Add Invidious comments support

This commit is contained in:
Arkadiusz Fal
2022-07-02 00:14:04 +02:00
parent 4fcf57d755
commit 7c4ee9bf35
7 changed files with 43 additions and 70 deletions

View File

@@ -157,6 +157,15 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
configureTransformer(pathPattern("videos/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> Video in
self.extractVideo(from: content.json)
}
configureTransformer(pathPattern("comments/*")) { (content: Entity<JSON>) -> CommentsPage in
let details = content.json.dictionaryValue
let comments = details["comments"]?.arrayValue.compactMap { self.extractComment(from: $0) } ?? []
let nextPage = details["continuation"]?.string
let disabled = !details["error"].isNil
return CommentsPage(comments: comments, nextPage: nextPage, disabled: disabled)
}
}
private func pathPattern(_ path: String) -> String {
@@ -337,7 +346,12 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
.withParam("q", query.lowercased())
}
func comments(_: Video.ID, page _: String?) -> Resource? { nil }
func comments(_ id: Video.ID, page: String?) -> Resource? {
let resource = resource(baseURL: account.url, path: basePathAppending("comments/\(id)"))
guard let page = page else { return resource }
return resource.withParam("continuation", page)
}
private func searchQuery(_ query: String) -> String {
var searchQuery = query
@@ -533,4 +547,23 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
videos: content["videos"].arrayValue.map { extractVideo(from: $0) }
)
}
private func extractComment(from content: JSON) -> Comment? {
let details = content.dictionaryValue
let author = details["author"]?.string ?? ""
let channelId = details["authorId"]?.string ?? UUID().uuidString
let authorAvatarURL = details["authorThumbnails"]?.arrayValue.last?.dictionaryValue["url"]?.string ?? ""
return Comment(
id: UUID().uuidString,
author: author,
authorAvatarURL: authorAvatarURL,
time: details["publishedText"]?.string ?? "",
pinned: false,
hearted: false,
likeCount: details["likeCount"]?.int ?? 0,
text: details["content"]?.string ?? "",
repliesPage: details["replies"]?.dictionaryValue["continuation"]?.string,
channel: Channel(id: channelId, name: author)
)
}
}

View File

@@ -51,10 +51,6 @@ enum VideosApp: String, CaseIterable {
self == .piped
}
var supportsComments: Bool {
self == .piped
}
var searchUsesIndexedPages: Bool {
self == .invidious
}

View File

@@ -17,38 +17,16 @@ final class CommentsModel: ObservableObject {
var player: PlayerModel!
static var instance: Instance? {
InstancesModel.find(Defaults[.commentsInstanceID])
var instance: Instance? {
player.accounts.current?.instance
}
var api: VideosAPI? {
Self.instance.isNil ? nil : PipedAPI(account: Self.instance!.anonymousAccount)
}
static var enabled: Bool {
!instance.isNil
}
#if !os(tvOS)
static var placement: CommentsPlacement {
Defaults[.commentsPlacement]
}
#endif
var nextPageAvailable: Bool {
!(nextPage?.isEmpty ?? true)
}
func load(page: String? = nil) {
guard Self.enabled, !loaded else {
return
}
guard !Self.instance.isNil,
let video = player.currentVideo
else {
return
}
guard let video = player.currentVideo else { return }
if !firstPage && !nextPageAvailable {
return
@@ -56,7 +34,7 @@ final class CommentsModel: ObservableObject {
firstPage = page.isNil || page!.isEmpty
api?.comments(video.videoID, page: page)?
player.accounts.api.comments(video.videoID, page: page)?
.load()
.onSuccess { [weak self] response in
if let page: CommentsPage = response.typedContent() {
@@ -65,6 +43,9 @@ final class CommentsModel: ObservableObject {
self?.disabled = page.disabled
}
}
.onFailure { [weak self] requestError in
self?.disabled = !requestError.json.dictionaryValue["error"].isNil
}
.onCompletion { [weak self] _ in
self?.loaded = true
}
@@ -94,7 +75,7 @@ final class CommentsModel: ObservableObject {
repliesPageID = page
repliesLoaded = false
api?.comments(player.currentVideo!.videoID, page: page)?
player.accounts.api.comments(player.currentVideo!.videoID, page: page)?
.load()
.onSuccess { [weak self] response in
if let page: CommentsPage = response.typedContent() {