This commit is contained in:
Arkadiusz Fal 2022-06-30 01:31:51 +02:00
parent 5439e53639
commit 6e63cd0be7
6 changed files with 68 additions and 3 deletions

View File

@ -215,6 +215,10 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
nil nil
} }
func channelByUsername(_: String) -> Resource? {
nil
}
func channelVideos(_ id: String) -> Resource { func channelVideos(_ id: String) -> Resource {
resource(baseURL: account.url, path: basePathAppending("channels/\(id)/latest")) resource(baseURL: account.url, path: basePathAppending("channels/\(id)/latest"))
} }

View File

@ -44,6 +44,10 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
self.extractChannel(from: content.json) self.extractChannel(from: content.json)
} }
configureTransformer(pathPattern("user/*")) { (content: Entity<JSON>) -> Channel? in
self.extractChannel(from: content.json)
}
configureTransformer(pathPattern("playlists/*")) { (content: Entity<JSON>) -> ChannelPlaylist? in configureTransformer(pathPattern("playlists/*")) { (content: Entity<JSON>) -> ChannelPlaylist? in
self.extractChannelPlaylist(from: content.json) self.extractChannelPlaylist(from: content.json)
} }
@ -133,6 +137,10 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
resource(baseURL: account.url, path: "c/\(name)") resource(baseURL: account.url, path: "c/\(name)")
} }
func channelByUsername(_ username: String) -> Resource? {
resource(baseURL: account.url, path: "user/\(username)")
}
func channelVideos(_ id: String) -> Resource { func channelVideos(_ id: String) -> Resource {
channel(id) channel(id)
} }

View File

@ -8,6 +8,7 @@ protocol VideosAPI {
func channel(_ id: String) -> Resource func channel(_ id: String) -> Resource
func channelByName(_ name: String) -> Resource? func channelByName(_ name: String) -> Resource?
func channelByUsername(_ username: String) -> Resource?
func channelVideos(_ id: String) -> Resource func channelVideos(_ id: String) -> Resource
func trending(country: Country, category: TrendingCategory?) -> Resource func trending(country: Country, category: TrendingCategory?) -> Resource
func search(_ query: SearchQuery, page: String?) -> Resource func search(_ query: SearchQuery, page: String?) -> Resource

View File

@ -16,6 +16,11 @@ final class URLParserTests: XCTestCase {
"c/ABCDE": "ABCDE" "c/ABCDE": "ABCDE"
] ]
private static let users: [String: String] = [
"https://m.youtube.com/user/ARD": "ARD",
"m.youtube.com/user/ARD": "ARD"
]
private static let channelsByID: [String: String] = [ private static let channelsByID: [String: String] = [
"https://piped.kavin.rocks/channel/UCbcxFkd6B9xUU54InHv4Tig": "UCbcxFkd6B9xUU54InHv4Tig", "https://piped.kavin.rocks/channel/UCbcxFkd6B9xUU54InHv4Tig": "UCbcxFkd6B9xUU54InHv4Tig",
"youtube.com/channel/UCbcxFkd6B9xUU54InHv4Tig": "UCbcxFkd6B9xUU54InHv4Tig", "youtube.com/channel/UCbcxFkd6B9xUU54InHv4Tig": "UCbcxFkd6B9xUU54InHv4Tig",
@ -68,6 +73,16 @@ final class URLParserTests: XCTestCase {
} }
} }
func testUsersParsing() throws {
Self.users.forEach { url, user in
let parser = URLParser(url: URL(string: url)!)
XCTAssertEqual(parser.destination, .channel)
XCTAssertNil(parser.channelID)
XCTAssertNil(parser.channelName)
XCTAssertEqual(parser.username, user)
}
}
func testPlaylistsParsing() throws { func testPlaylistsParsing() throws {
Self.playlists.forEach { url, id in Self.playlists.forEach { url, id in
let parser = URLParser(url: URL(string: url)!) let parser = URLParser(url: URL(string: url)!)

View File

@ -180,6 +180,10 @@ struct OpenURLHandler {
return accounts.api.channel(id) return accounts.api.channel(id)
} }
if let resource = resourceForUsernameUrl(parser) {
return resource
}
guard let name = parser.channelName else { guard let name = parser.channelName else {
return nil return nil
} }
@ -195,6 +199,20 @@ struct OpenURLHandler {
return nil return nil
} }
private func resourceForUsernameUrl(_ parser: URLParser) -> Resource? {
guard let username = parser.username else { return nil }
if accounts.app.supportsOpeningChannelsByName {
return accounts.api.channelByUsername(username)
}
if let instance = InstancesModel.all.first(where: { $0.app.supportsOpeningChannelsByName }) {
return instance.anonymous.channelByUsername(username)
}
return nil
}
private func handleSearchUrlOpen(_ parser: URLParser) { private func handleSearchUrlOpen(_ parser: URLParser) {
#if os(macOS) #if os(macOS)
if alertIfNoMainWindowOpen() { return } if alertIfNoMainWindowOpen() { return }

View File

@ -4,7 +4,7 @@ import Foundation
struct URLParser { struct URLParser {
static let prefixes: [Destination: [String]] = [ static let prefixes: [Destination: [String]] = [
.playlist: ["/playlist", "playlist"], .playlist: ["/playlist", "playlist"],
.channel: ["/c", "c", "/channel", "channel"], .channel: ["/c", "c", "/channel", "channel", "/user", "user"],
.search: ["/results", "search"] .search: ["/results", "search"]
] ]
@ -13,6 +13,21 @@ struct URLParser {
case favorites, subscriptions, popular, trending case favorites, subscriptions, popular, trending
} }
var url: URL
init(url: URL) {
self.url = url
let urlString = url.absoluteString
let scheme = urlComponents?.scheme
if scheme == nil,
urlString.contains("youtube.com"),
let url = URL(string: "https://\(urlString)"
)
{
self.url = url
}
}
var destination: Destination? { var destination: Destination? {
if hasAnyOfPrefixes(path, ["favorites"]) { return .favorites } if hasAnyOfPrefixes(path, ["favorites"]) { return .favorites }
if hasAnyOfPrefixes(path, ["subscriptions"]) { return .subscriptions } if hasAnyOfPrefixes(path, ["subscriptions"]) { return .subscriptions }
@ -34,8 +49,6 @@ struct URLParser {
return .video return .video
} }
var url: URL
var videoID: String? { var videoID: String? {
if host == "youtu.be", !path.isEmpty { if host == "youtu.be", !path.isEmpty {
return String(path.suffix(from: path.index(path.startIndex, offsetBy: 1))) return String(path.suffix(from: path.index(path.startIndex, offsetBy: 1)))
@ -85,6 +98,12 @@ struct URLParser {
return removePrefixes(path, Self.prefixes[.channel]!.map { [$0, "/"].joined() }) return removePrefixes(path, Self.prefixes[.channel]!.map { [$0, "/"].joined() })
} }
var username: String? {
guard hasAnyOfPrefixes(path, ["user/", "/user/"]) else { return nil }
return removePrefixes(path, ["user/", "/user/"])
}
private var host: String { private var host: String {
urlComponents?.host ?? "" urlComponents?.host ?? ""
} }