summaryrefslogtreecommitdiff
path: root/Sora/Data/Booru
diff options
context:
space:
mode:
Diffstat (limited to 'Sora/Data/Booru')
-rw-r--r--Sora/Data/Booru/BooruManager.swift40
-rw-r--r--Sora/Data/Booru/Tag/GelbooruAutocompleteTagParser.swift83
2 files changed, 104 insertions, 19 deletions
diff --git a/Sora/Data/Booru/BooruManager.swift b/Sora/Data/Booru/BooruManager.swift
index 8f055af..0909885 100644
--- a/Sora/Data/Booru/BooruManager.swift
+++ b/Sora/Data/Booru/BooruManager.swift
@@ -309,9 +309,13 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
guard !Task.isCancelled else { return [] }
let parsedTags =
- flavor == .danbooru
- ? DanbooruTagParser(data: data).parse()
- : BooruTagXMLParser(data: data).parse()
+ if flavor == .danbooru {
+ DanbooruTagParser(data: data).parse()
+ } else if flavor == .gelbooru, provider != .safebooru {
+ GelbooruAutocompleteTagParser(data: data).parse()
+ } else {
+ BooruTagXMLParser(data: data).parse()
+ }
return parsedTags.sorted { $0.count > $1.count }
} catch {
@@ -500,24 +504,22 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
components.host = domain
components.path = "/index.php"
- var queryItems = [
- URLQueryItem(name: "page", value: "dapi"),
- URLQueryItem(name: "s", value: "tag"),
- URLQueryItem(name: "q", value: "index"),
- URLQueryItem(name: "name_pattern", value: "%\(name)%"),
- URLQueryItem(name: "orderby", value: "count"),
- ]
-
- if let validCredentials = credentials,
- !validCredentials.apiKey.isEmpty,
- validCredentials.userID != 0
- {
- queryItems.append(URLQueryItem(name: "api_key", value: validCredentials.apiKey))
- queryItems.append(URLQueryItem(name: "user_id", value: String(validCredentials.userID)))
+ if provider == .safebooru {
+ components.queryItems = [
+ URLQueryItem(name: "page", value: "dapi"),
+ URLQueryItem(name: "s", value: "tag"),
+ URLQueryItem(name: "q", value: "index"),
+ URLQueryItem(name: "name_pattern", value: "%\(name)%"),
+ URLQueryItem(name: "orderby", value: "count"),
+ ]
+ } else {
+ components.queryItems = [
+ URLQueryItem(name: "page", value: "autocomplete2"),
+ URLQueryItem(name: "type", value: "tag_query"),
+ URLQueryItem(name: "term", value: name),
+ ]
}
- components.queryItems = queryItems
-
return components.url
case .danbooru:
diff --git a/Sora/Data/Booru/Tag/GelbooruAutocompleteTagParser.swift b/Sora/Data/Booru/Tag/GelbooruAutocompleteTagParser.swift
new file mode 100644
index 0000000..c69cd9b
--- /dev/null
+++ b/Sora/Data/Booru/Tag/GelbooruAutocompleteTagParser.swift
@@ -0,0 +1,83 @@
+import Foundation
+
+nonisolated class GelbooruAutocompleteTagParser {
+ 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("GelbooruAutocompleteTagParser.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 name = tag["value"] as? String, !name.isEmpty else {
+ droppedRecordCount += 1
+
+ continue
+ }
+
+ let count: Int
+
+ if let postCount = tag["post_count"] as? String {
+ count = Int(postCount) ?? 0
+ } else if let postCount = tag["post_count"] as? Int {
+ count = postCount
+ } else {
+ count = 0
+ }
+
+ parsedTags.append(
+ BooruTag(
+ id: name,
+ name: name,
+ count: count,
+ type: tagType(for: tag["category"] as? String),
+ ambiguous: false
+ )
+ )
+ }
+
+ if droppedRecordCount > 0 {
+ debugPrint(
+ "GelbooruAutocompleteTagParser.parse: dropped \(droppedRecordCount) malformed records while decoding tags."
+ )
+ }
+
+ return parsedTags
+ } catch {
+ debugPrint("GelbooruAutocompleteTagParser.parse: failed to decode response: \(error)")
+
+ return []
+ }
+ }
+
+ private func tagType(for category: String?) -> Int {
+ switch category?.lowercased() {
+ case "artist":
+ 1
+
+ case "copyright":
+ 3
+
+ case "character":
+ 4
+
+ case "metadata", "meta":
+ 5
+
+ default:
+ 0
+ }
+ }
+}