diff options
| author | Fuwn <[email protected]> | 2026-02-23 09:51:09 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-23 13:33:42 -0800 |
| commit | 33cbce7af9dd26e40e9dd6ba825499eff9abd707 (patch) | |
| tree | 2a5ab11e3e3c1cbd74bf0634970fcf6e817be0b4 /Sora/Data/Booru | |
| parent | chore: add login localization key (diff) | |
| download | sora-testing-33cbce7af9dd26e40e9dd6ba825499eff9abd707.tar.xz sora-testing-33cbce7af9dd26e40e9dd6ba825499eff9abd707.zip | |
feat: add moebooru held-post visibility setting
Diffstat (limited to 'Sora/Data/Booru')
| -rw-r--r-- | Sora/Data/Booru/BooruManager.swift | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/Sora/Data/Booru/BooruManager.swift b/Sora/Data/Booru/BooruManager.swift index 5753089..3c4374e 100644 --- a/Sora/Data/Booru/BooruManager.swift +++ b/Sora/Data/Booru/BooruManager.swift @@ -27,6 +27,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng private let cacheDuration: TimeInterval private let credentials: BooruProviderCredentials? private let userAgent: String + private let showHeldMoebooruPosts: Bool private var urlCache: [String: URL] = [:] private var lastPostCount = 0 @@ -45,13 +46,15 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng init( _ provider: BooruProvider, credentials: BooruProviderCredentials? = nil, - cacheDuration: TimeInterval = BooruPageCacheEntry.defaultExpiration + cacheDuration: TimeInterval = BooruPageCacheEntry.defaultExpiration, + showHeldMoebooruPosts: Bool = false ) { self.provider = provider self.flavor = BooruProviderFlavor(provider: provider) self.domain = provider.domain self.credentials = credentials self.cacheDuration = cacheDuration + self.showHeldMoebooruPosts = showHeldMoebooruPosts pageCache.countLimit = 50 pageCache.totalCostLimit = 50 * 1_024 * 1_024 @@ -134,7 +137,6 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng flavor: flavor, provider: provider ) - .sorted { $0.createdAt > $1.createdAt } continuation.resume(returning: parsedPosts) } @@ -312,8 +314,31 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng } // MARK: - Private Methods - private func danbooruPageToken(for page: Int) -> String { + private func moebooruTagString(for tags: [String]) -> String { + let hasExplicitHoldsFilter = tags.contains { tag in + tag.lowercased().hasPrefix("holds:") + } + + if hasExplicitHoldsFilter { + return tags.joined(separator: "+") + } + + guard !showHeldMoebooruPosts else { + return tags.joined(separator: "+") + } + + return (tags + ["holds:false"]).joined(separator: "+") + } + + private func hasExplicitSortTag(in tags: [String]) -> Bool { + tags.contains { tag in + tag.lowercased().hasPrefix("order:") + } + } + + private func danbooruPageToken(for page: Int, tags: [String]) -> String { guard page > 1 else { return "1" } + guard !hasExplicitSortTag(in: tags) else { return String(page) } guard let minimumPostID = posts.lazy.compactMap({ Int($0.id) }).min() else { return String(page) @@ -324,7 +349,8 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng func url(forPosts page: Int, limit: Int, tags: [String]) -> URL? { let tagString = tags.joined(separator: "+") - let pageCacheValue = flavor == .danbooru ? danbooruPageToken(for: page) : String(page) + let pageCacheValue = + flavor == .danbooru ? danbooruPageToken(for: page, tags: tags) : String(page) let cacheKey = "posts_\(pageCacheValue)_\(limit)_\(tagString.hashValue)" if let cachedURL = urlCache[cacheKey] { @@ -342,7 +368,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng components.path = "/posts.json" var queryItems = [ - URLQueryItem(name: "page", value: danbooruPageToken(for: page)), + URLQueryItem(name: "page", value: danbooruPageToken(for: page, tags: tags)), URLQueryItem(name: "limit", value: String(limit)), URLQueryItem(name: "tags", value: tagString), ] @@ -361,6 +387,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng case .moebooru: var components = URLComponents() + let moebooruTags = moebooruTagString(for: tags) components.scheme = "https" components.host = domain @@ -368,7 +395,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng components.queryItems = [ URLQueryItem(name: "page", value: String(page)), URLQueryItem(name: "limit", value: String(limit)), - URLQueryItem(name: "tags", value: tagString), + URLQueryItem(name: "tags", value: moebooruTags), ] url = components.url @@ -499,13 +526,15 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng flavor == .danbooru ? DanbooruPostParser(data: data).parse() : BooruPostXMLParser(data: data, provider: provider).parse() - var uniquePosts: [String: BooruPost] = [:] - for post in parsedPosts { - uniquePosts[post.id] = post + var seenPostIDs = Set<String>() + var orderedUniquePosts: [BooruPost] = [] + + for post in parsedPosts where seenPostIDs.insert(post.id).inserted { + orderedUniquePosts.append(post) } - return Array(uniquePosts.values) + return orderedUniquePosts } private func updatePosts(_ newPosts: [BooruPost], replace: Bool) { |