mirror of
https://github.com/Livinglist/Hacki.git
synced 2025-08-06 18:24:42 +08:00
131 lines
4.8 KiB
Swift
131 lines
4.8 KiB
Swift
import Foundation
|
|
import Alamofire
|
|
|
|
public class StoryRepository {
|
|
public static let shared: StoryRepository = .init()
|
|
|
|
private let baseUrl: String = "https://hacker-news.firebaseio.com/v0/"
|
|
|
|
private init() {}
|
|
|
|
// MARK: - Story related.
|
|
|
|
public func fetchAllStories(from storyType: StoryType, onStoryFetched: @escaping (Story) -> Void) async -> Void {
|
|
let storyIds = await fetchStoryIds(from: storyType)
|
|
for id in storyIds {
|
|
let story = await self.fetchStory(id)
|
|
if let story = story {
|
|
onStoryFetched(story)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func fetchStoryIds(from storyType: StoryType) async -> [Int] {
|
|
let response = await AF.request("\(self.baseUrl)\(storyType.rawValue)stories.json").serializingString().response
|
|
guard response.data != nil else { return [Int]() }
|
|
let storyIds = try? JSONDecoder().decode([Int].self, from: response.data!)
|
|
return storyIds ?? [Int]()
|
|
}
|
|
|
|
public func fetchStoryIds(from storyType: String) async -> [Int] {
|
|
let response = await AF.request("\(self.baseUrl)\(storyType)stories.json").serializingString().response
|
|
guard response.data != nil else { return [Int]() }
|
|
let storyIds = try? JSONDecoder().decode([Int].self, from: response.data!)
|
|
return storyIds ?? [Int]()
|
|
}
|
|
|
|
public func fetchStories(ids: [Int], onStoryFetched: @escaping (Story) -> Void) async -> Void {
|
|
for id in ids {
|
|
let story = await fetchStory(id)
|
|
if let story = story {
|
|
onStoryFetched(story)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func fetchStory(_ id: Int) async -> Story?{
|
|
let response = await AF.request("\(self.baseUrl)item/\(id).json").serializingString().response
|
|
if let data = response.data,
|
|
var story = try? JSONDecoder().decode(Story.self, from: data) {
|
|
let formattedText = story.text.htmlStripped
|
|
story = story.copyWith(text: formattedText)
|
|
return story
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// MARK: - Comment related.
|
|
|
|
public func fetchComments(ids: [Int], onCommentFetched: @escaping (Comment) -> Void) async -> Void {
|
|
for id in ids {
|
|
let comment = await fetchComment(id)
|
|
if let comment = comment {
|
|
onCommentFetched(comment)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func fetchComment(_ id: Int) async -> Comment? {
|
|
let response = await AF.request("\(self.baseUrl)item/\(id).json").serializingString().response
|
|
if let data = response.data,
|
|
var comment = try? JSONDecoder().decode(Comment.self, from: data) {
|
|
let formattedText = comment.text.htmlStripped
|
|
comment = comment.copyWith(text: formattedText)
|
|
return comment
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// MARK: - Item related.
|
|
|
|
public func fetchItems(ids: [Int], filtered: Bool = true, onItemFetched: @escaping (any Item) -> Void) async -> Void {
|
|
for id in ids {
|
|
let item = await fetchItem(id)
|
|
guard let item = item else { continue }
|
|
if let story = item as? Story {
|
|
onItemFetched(story)
|
|
} else if let cmt = item as? Comment {
|
|
onItemFetched(cmt)
|
|
}
|
|
}
|
|
}
|
|
|
|
public func fetchItem(_ id: Int) async -> (any Item)? {
|
|
let response = await AF.request("\(self.baseUrl)item/\(id).json").serializingString().response
|
|
if let data = response.data,
|
|
let result = try? response.result.get(),
|
|
let map = result.toJSON() as? [String: AnyObject],
|
|
let type = map["type"] as? String {
|
|
switch type {
|
|
case "story":
|
|
let story = try? JSONDecoder().decode(Story.self, from: data)
|
|
let formattedText = story?.text.htmlStripped
|
|
return story?.copyWith(text: formattedText)
|
|
case "comment":
|
|
let comment = try? JSONDecoder().decode(Comment.self, from: data)
|
|
let formattedText = comment?.text.htmlStripped
|
|
return comment?.copyWith(text: formattedText)
|
|
default:
|
|
return nil
|
|
}
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// MARK: - User related.
|
|
|
|
public func fetchUser(_ id: String) async -> User? {
|
|
let response = await AF.request("\(self.baseUrl)/user/\(id).json").serializingString().response
|
|
if let data = response.data,
|
|
let user = try? JSONDecoder().decode(User.self, from: data) {
|
|
let formattedText = user.about.orEmpty.htmlStripped
|
|
return user.copyWith(about: formattedText)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|