mirror of
https://github.com/nimbold/Firelink.git
synced 2026-07-26 12:08:27 +00:00
87 lines
3.6 KiB
Swift
87 lines
3.6 KiB
Swift
import Foundation
|
|
|
|
enum FileClassifier {
|
|
private static let musicExtensions: Set<String> = [
|
|
"aac", "aif", "aiff", "alac", "amr", "ape", "au", "caf", "flac", "m4a",
|
|
"m4b", "mid", "midi", "mp3", "oga", "ogg", "opus", "ra", "wav", "weba",
|
|
"wma"
|
|
]
|
|
|
|
private static let movieExtensions: Set<String> = [
|
|
"3g2", "3gp", "avi", "divx", "f4v", "flv", "m2ts", "m4v", "mkv", "mov",
|
|
"mp4", "mpeg", "mpg", "mts", "ogm", "ogv", "rm", "rmvb", "ts", "vob",
|
|
"webm", "wmv"
|
|
]
|
|
|
|
private static let compressedExtensions: Set<String> = [
|
|
"7z", "ace", "alz", "apk", "appx", "ar", "arc", "arj", "bz", "bz2",
|
|
"cab", "cpio", "deb", "dmg", "gz", "gzip", "iso", "jar", "lha", "lzh",
|
|
"lz", "lz4", "lzip", "lzma", "pak", "pkg", "rar", "rpm", "sit", "sitx",
|
|
"tar", "tbz", "tbz2", "tgz", "tlz", "txz", "war", "whl", "xar", "xz",
|
|
"z", "zip", "zipx", "zst"
|
|
]
|
|
|
|
private static let pictureExtensions: Set<String> = [
|
|
"ai", "apng", "avif", "bmp", "cr2", "cr3", "dng", "emf", "eps", "gif",
|
|
"heic", "heif", "ico", "indd", "jfif", "jpeg", "jpg", "jxl", "nef",
|
|
"orf", "pbm", "pgm", "png", "pnm", "ppm", "psd", "raw", "rw2",
|
|
"svg", "tga", "tif", "tiff", "webp", "wmf"
|
|
]
|
|
|
|
private static let documentExtensions: Set<String> = [
|
|
"azw", "azw3", "csv", "djvu", "doc", "docm", "docx", "dot", "dotx",
|
|
"epub", "fb2", "htm", "html", "ics", "key", "log", "md", "mobi", "pdf",
|
|
"numbers", "odp", "ods", "odt", "pages", "pot", "potx", "pps", "ppsx",
|
|
"ppt", "pptm", "pptx", "rtf", "tex", "txt", "vcf", "xls", "xlsm",
|
|
"xlsx", "xml", "xps", "yaml", "yml"
|
|
]
|
|
|
|
static func category(forFileName fileName: String) -> DownloadCategory {
|
|
let ext = (fileName as NSString).pathExtension.lowercased()
|
|
guard !ext.isEmpty else { return .other }
|
|
|
|
if musicExtensions.contains(ext) { return .musics }
|
|
if movieExtensions.contains(ext) { return .movies }
|
|
if compressedExtensions.contains(ext) { return .compressed }
|
|
if pictureExtensions.contains(ext) { return .pictures }
|
|
if documentExtensions.contains(ext) { return .documents }
|
|
return .other
|
|
}
|
|
|
|
static func destinationDirectory(for category: DownloadCategory) -> URL {
|
|
let downloads = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
|
|
?? URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Downloads")
|
|
return downloads.appendingPathComponent(category.rawValue, isDirectory: true)
|
|
}
|
|
|
|
static func fileName(from url: URL) -> String {
|
|
let pathName = url.lastPathComponent.removingPercentEncoding ?? url.lastPathComponent
|
|
if !pathName.isEmpty, pathName != "/" {
|
|
return sanitizedFileName(pathName)
|
|
}
|
|
|
|
let host = url.host(percentEncoded: false) ?? "download"
|
|
return sanitizedFileName("\(host)-download")
|
|
}
|
|
|
|
static func sanitizedFileName(_ rawValue: String, fallback: String = "download") -> String {
|
|
let separators = CharacterSet(charactersIn: "/\\")
|
|
let invalidCharacters = separators
|
|
.union(.newlines)
|
|
.union(.controlCharacters)
|
|
|
|
let components = rawValue
|
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
.components(separatedBy: invalidCharacters)
|
|
.filter { !$0.isEmpty }
|
|
let clean = components.joined(separator: "_")
|
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
guard !clean.isEmpty, clean != ".", clean != ".." else {
|
|
return fallback
|
|
}
|
|
|
|
return String(clean.prefix(255))
|
|
}
|
|
}
|