mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Fix #203
This commit is contained in:
parent
25ef0a4383
commit
f8fe2961ca
@ -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"))
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)!)
|
||||||
|
@ -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 }
|
||||||
|
@ -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 ?? ""
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user