diff options
Diffstat (limited to 'Sora/Data/Booru')
| -rw-r--r-- | Sora/Data/Booru/BooruManager.swift | 19 | ||||
| -rw-r--r-- | Sora/Data/Booru/Tag/DanbooruTagParser.swift | 58 |
2 files changed, 75 insertions, 2 deletions
diff --git a/Sora/Data/Booru/BooruManager.swift b/Sora/Data/Booru/BooruManager.swift index 7d11158..8f055af 100644 --- a/Sora/Data/Booru/BooruManager.swift +++ b/Sora/Data/Booru/BooruManager.swift @@ -308,7 +308,12 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng guard !Task.isCancelled else { return [] } - return BooruTagXMLParser(data: data).parse().sorted { $0.count > $1.count } + let parsedTags = + flavor == .danbooru + ? DanbooruTagParser(data: data).parse() + : BooruTagXMLParser(data: data).parse() + + return parsedTags.sorted { $0.count > $1.count } } catch { if (error as? URLError)?.code != .cancelled { debugPrint("BooruManager.searchTags: \(error)") @@ -516,7 +521,17 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng return components.url case .danbooru: - return nil + var components = URLComponents() + + components.scheme = "https" + components.host = domain + components.path = "/tags.json" + components.queryItems = [ + URLQueryItem(name: "search[name_matches]", value: "\(name)*"), + URLQueryItem(name: "limit", value: "50"), + ] + + return components.url } } diff --git a/Sora/Data/Booru/Tag/DanbooruTagParser.swift b/Sora/Data/Booru/Tag/DanbooruTagParser.swift new file mode 100644 index 0000000..3da165a --- /dev/null +++ b/Sora/Data/Booru/Tag/DanbooruTagParser.swift @@ -0,0 +1,58 @@ +import Foundation + +nonisolated class DanbooruTagParser { + private let data: Data + + init(data: Data) { + self.data = data + } + + func parse() -> [BooruTag] { + do { + guard let decodedTags = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] else { + debugPrint("DanbooruTagParser.parse: failed to decode top-level tag array.") + + return [] + } + + var parsedTags: [BooruTag] = [] + var droppedRecordCount = 0 + + parsedTags.reserveCapacity(decodedTags.count) + + for tag in decodedTags { + guard let id = tag["id"] as? Int, + let name = tag["name"] as? String, + let postCount = tag["post_count"] as? Int, + let category = tag["category"] as? Int + else { + droppedRecordCount += 1 + + continue + } + + parsedTags.append( + BooruTag( + id: String(id), + name: name, + count: postCount, + type: category, + ambiguous: false + ) + ) + } + + if droppedRecordCount > 0 { + debugPrint( + "DanbooruTagParser.parse: dropped \(droppedRecordCount) malformed records while decoding tags." + ) + } + + return parsedTags + } catch { + debugPrint("DanbooruTagParser.parse: failed to decode response: \(error)") + + return [] + } + } +} |