diff options
| author | Fuwn <[email protected]> | 2025-02-20 19:33:19 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-02-20 19:33:19 -0800 |
| commit | e23a8714f6cdc1b55ef96f6bc0f024af049ce299 (patch) | |
| tree | 8496471c3e0a455dc0d0c5c16a3c03964509934e /Sora/Data/Booru/BooruPostXMLParser.swift | |
| parent | feat: Development commit (diff) | |
| download | sora-testing-e23a8714f6cdc1b55ef96f6bc0f024af049ce299.tar.xz sora-testing-e23a8714f6cdc1b55ef96f6bc0f024af049ce299.zip | |
feat: Development commit
Diffstat (limited to 'Sora/Data/Booru/BooruPostXMLParser.swift')
| -rw-r--r-- | Sora/Data/Booru/BooruPostXMLParser.swift | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/Sora/Data/Booru/BooruPostXMLParser.swift b/Sora/Data/Booru/BooruPostXMLParser.swift new file mode 100644 index 0000000..30207bc --- /dev/null +++ b/Sora/Data/Booru/BooruPostXMLParser.swift @@ -0,0 +1,116 @@ +import Foundation + +class BooruPostXMLParser: NSObject, XMLParserDelegate { + private var posts: [BooruPost] = [] + private var currentPost: BooruPost? + private var parser: XMLParser + + init(data: Data) { + parser = XMLParser(data: data) + + super.init() + + parser.delegate = self + } + + func parse() -> [BooruPost] { + parser.parse() + + return posts + } + + func parser(_: XMLParser, didStartElement elementName: String, namespaceURI _: String?, qualifiedName _: String?, attributes attributeDict: [String: String] = [:]) { + if elementName == "post" { + guard let id = attributeDict["id"], + let heightStr = attributeDict["height"], + let height = Int(heightStr), + let score = attributeDict["score"], + let fileUrl = attributeDict["file_url"], + let parentId = attributeDict["parent_id"], + let sampleUrl = attributeDict["sample_url"], + let sampleWidthStr = attributeDict["sample_width"], + let sampleWidth = Int(sampleWidthStr), + let sampleHeightStr = attributeDict["sample_height"], + let sampleHeight = Int(sampleHeightStr), + let previewUrl = attributeDict["preview_url"], + let rating = attributeDict["rating"], + let tags = attributeDict["tags"], + let widthStr = attributeDict["width"], + let width = Int(widthStr), + let change = attributeDict["change"], + let md5 = attributeDict["md5"], + let creatorId = attributeDict["creator_id"], + let hasChildrenStr = attributeDict["has_children"], + let createdAt = attributeDict["created_at"], + let status = attributeDict["status"], + let source = attributeDict["source"], + let previewWidthStr = attributeDict["preview_width"], + let previewWidth = Int(previewWidthStr), + let previewHeightStr = attributeDict["preview_height"], + let previewHeight = Int(previewHeightStr) + else { + return + } + + let hasNotesStr = attributeDict["has_notes"] ?? "false" + let hasCommentsStr = attributeDict["has_comments"] ?? "false" + + currentPost = BooruPost( + id: id, + height: height, + score: score, + fileURL: URL(string: fileUrl)!, + parentID: parentId, + sampleURL: URL(string: sampleUrl)!, + sampleWidth: sampleWidth, + sampleHeight: sampleHeight, + previewURL: URL(string: previewUrl)!, + rating: rating, + tags: tags.components(separatedBy: " ").filter { !$0.isEmpty }, + width: width, + change: change, + md5: md5, + creatorID: creatorId, + hasChildren: hasChildrenStr == "true", + createdAt: parseCreatedAt(createdAt)!, + status: status, + source: source, + hasNotes: hasNotesStr == "true", + hasComments: hasCommentsStr == "true", + previewWidth: previewWidth, + previewHeight: previewHeight + ) + } + } + + func parser(_: XMLParser, didEndElement elementName: String, namespaceURI _: String?, qualifiedName _: String?) { + if elementName == "post", let post = currentPost { + posts.append(post) + + currentPost = nil + } + } + + #if DEBUG + func parser(_: XMLParser, parseErrorOccurred parseError: any Error) { + print("parser: \(parseError)") + } + #endif + + func parseCreatedAt(_ input: String) -> Date? { + let dateFormatter = DateFormatter() + + dateFormatter.dateFormat = "EEE MMM dd HH:mm:ss Z yyyy" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + + if let date = dateFormatter.date(from: input) { + return date + } + + if let timestamp = Double(input) { + return Date(timeIntervalSince1970: timestamp) + } + + return nil + } +} |