Files
Backports
Extensions
Fixtures
Model
Accounts
Account.swift
AccountValidator.swift
AccountsBridge.swift
AccountsModel.swift
Instance.swift
InstancesBridge.swift
InstancesModel.swift
Applications
Player
Search
SponsorBlock
Channel.swift
ChannelPlaylist.swift
Comment.swift
CommentsModel.swift
CommentsPage.swift
ContentItem.swift
Country.swift
FavoriteItem.swift
FavoritesModel.swift
MenuModel.swift
NavigationModel.swift
Playlist.swift
PlaylistsModel.swift
RecentsModel.swift
Segment.swift
SingleAssetStream.swift
Store.swift
Stream.swift
SubscriptionsModel.swift
Thumbnail.swift
ThumbnailsModel.swift
TrendingCategory.swift
Video.swift
Open in Yattee
Shared
Tests Apple TV
Tests iOS
Tests macOS
Yattee.xcodeproj
iOS
macOS
tvOS
.gitignore
.swift-version
.swiftformat
.swiftlint.yml
LICENSE
README.md
yattee/Model/Accounts/AccountValidator.swift
2021-11-15 18:58:45 +01:00

159 lines
4.4 KiB
Swift

import Foundation
import Siesta
import SwiftUI
final class AccountValidator: Service {
let app: Binding<VideosApp>
let url: String
let account: Account!
var formObjectID: Binding<String>
var isValid: Binding<Bool>
var isValidated: Binding<Bool>
var isValidating: Binding<Bool>
var error: Binding<String?>?
init(
app: Binding<VideosApp>,
url: String,
account: Account? = nil,
id: Binding<String>,
isValid: Binding<Bool>,
isValidated: Binding<Bool>,
isValidating: Binding<Bool>,
error: Binding<String?>? = nil
) {
self.app = app
self.url = url
self.account = account
formObjectID = id
self.isValid = isValid
self.isValidated = isValidated
self.isValidating = isValidating
self.error = error
super.init(baseURL: url)
configure()
}
func configure() {
configure {
$0.pipeline[.parsing].add(SwiftyJSONTransformer, contentTypes: ["*/json"])
}
configure("/api/v1/auth/feed", requestMethods: [.get]) {
guard self.account != nil else {
return
}
$0.headers["Cookie"] = self.invidiousCookieHeader
}
configure("/login", requestMethods: [.post]) {
$0.headers["Content-Type"] = "application/json"
}
}
func validateInstance() {
reset()
neverGonnaGiveYouUp
.load()
.onSuccess { response in
guard self.url == self.formObjectID.wrappedValue else {
return
}
let json = response.json.dictionaryValue
let author = self.app.wrappedValue == .invidious ? json["author"] : json["uploader"]
if author == "Rick Astley" {
self.isValid.wrappedValue = true
self.error?.wrappedValue = nil
} else {
self.isValid.wrappedValue = false
}
}
.onFailure { error in
guard self.url == self.formObjectID.wrappedValue else {
return
}
self.isValid.wrappedValue = false
self.error?.wrappedValue = error.userMessage
}
.onCompletion { _ in
self.isValidated.wrappedValue = true
self.isValidating.wrappedValue = false
}
}
func validateAccount() {
reset()
accountRequest
.onSuccess { response in
guard self.account!.username == self.formObjectID.wrappedValue else {
return
}
switch self.app.wrappedValue {
case .invidious:
self.isValid.wrappedValue = true
case .piped:
let error = response.json.dictionaryValue["error"]?.string
let token = response.json.dictionaryValue["token"]?.string
self.isValid.wrappedValue = error?.isEmpty ?? !(token?.isEmpty ?? true)
self.error!.wrappedValue = error
}
}
.onFailure { _ in
guard self.account!.username == self.formObjectID.wrappedValue else {
return
}
self.isValid.wrappedValue = false
}
.onCompletion { _ in
self.isValidated.wrappedValue = true
self.isValidating.wrappedValue = false
}
}
var accountRequest: Request {
switch app.wrappedValue {
case .invidious:
return feed.load()
case .piped:
return login.request(.post, json: ["username": account.username, "password": account.password])
}
}
func reset() {
isValid.wrappedValue = false
isValidated.wrappedValue = false
isValidating.wrappedValue = false
error?.wrappedValue = nil
}
var invidiousCookieHeader: String {
"SID=\(account.username)"
}
var login: Resource {
resource("/login")
}
var feed: Resource {
resource("/api/v1/auth/feed")
}
var videoResourceBasePath: String {
app.wrappedValue == .invidious ? "/api/v1/videos" : "/streams"
}
var neverGonnaGiveYouUp: Resource {
resource("\(videoResourceBasePath)/dQw4w9WgXcQ")
}
}