2018-08-16 07:46:19 -04:00
|
|
|
//
|
|
|
|
// MastodonController.swift
|
|
|
|
// Tusker
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 8/15/18.
|
|
|
|
// Copyright © 2018 Shadowfacts. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
2018-09-11 10:52:21 -04:00
|
|
|
import Pachyderm
|
2018-08-16 07:46:19 -04:00
|
|
|
|
2018-08-16 18:55:40 -04:00
|
|
|
class MastodonController {
|
2020-01-07 21:29:15 -05:00
|
|
|
|
|
|
|
static private(set) var all = [LocalData.UserAccountInfo: MastodonController]()
|
|
|
|
|
|
|
|
@available(*, message: "do something less dumb")
|
|
|
|
static var first: MastodonController { all.first!.value }
|
2018-08-16 07:46:19 -04:00
|
|
|
|
2020-01-07 21:29:15 -05:00
|
|
|
static func getForAccount(_ account: LocalData.UserAccountInfo) -> MastodonController {
|
|
|
|
if let controller = all[account] {
|
|
|
|
return controller
|
|
|
|
} else {
|
|
|
|
let controller = MastodonController(instanceURL: account.instanceURL)
|
|
|
|
controller.accountInfo = account
|
|
|
|
controller.client.clientID = account.clientID
|
|
|
|
controller.client.clientSecret = account.clientSecret
|
|
|
|
controller.client.accessToken = account.accessToken
|
|
|
|
all[account] = controller
|
|
|
|
return controller
|
|
|
|
}
|
|
|
|
}
|
2018-08-16 18:55:40 -04:00
|
|
|
|
2020-05-13 18:58:11 -04:00
|
|
|
static func resetAll() {
|
|
|
|
all = [:]
|
|
|
|
}
|
|
|
|
|
2020-05-11 17:57:50 -04:00
|
|
|
private let transient: Bool
|
|
|
|
private(set) lazy var persistentContainer = MastodonCachePersistentStore(for: accountInfo, transient: transient)
|
2020-04-12 11:14:10 -04:00
|
|
|
|
2020-01-07 21:29:15 -05:00
|
|
|
let instanceURL: URL
|
2020-04-12 11:14:10 -04:00
|
|
|
var accountInfo: LocalData.UserAccountInfo?
|
2020-01-07 21:29:15 -05:00
|
|
|
|
|
|
|
let client: Client!
|
2018-08-16 07:46:19 -04:00
|
|
|
|
2020-01-05 15:25:07 -05:00
|
|
|
var account: Account!
|
|
|
|
var instance: Instance!
|
2020-09-13 15:51:06 -04:00
|
|
|
|
|
|
|
var loggedIn: Bool {
|
|
|
|
accountInfo != nil
|
|
|
|
}
|
2020-01-07 21:29:15 -05:00
|
|
|
|
2020-05-11 17:57:50 -04:00
|
|
|
init(instanceURL: URL, transient: Bool = false) {
|
2020-01-07 21:29:15 -05:00
|
|
|
self.instanceURL = instanceURL
|
|
|
|
self.accountInfo = nil
|
|
|
|
self.client = Client(baseURL: instanceURL)
|
2020-05-11 17:57:50 -04:00
|
|
|
self.transient = transient
|
2018-08-16 18:55:40 -04:00
|
|
|
}
|
|
|
|
|
2020-01-05 15:25:07 -05:00
|
|
|
func run<Result>(_ request: Request<Result>, completion: @escaping Client.Callback<Result>) {
|
2020-01-05 14:00:39 -05:00
|
|
|
client.run(request, completion: completion)
|
|
|
|
}
|
|
|
|
|
2020-01-07 21:29:15 -05:00
|
|
|
func registerApp(completion: @escaping (_ clientID: String, _ clientSecret: String) -> Void) {
|
|
|
|
guard client.clientID == nil,
|
|
|
|
client.clientSecret == nil else {
|
|
|
|
|
|
|
|
completion(client.clientID!, client.clientSecret!)
|
2018-08-19 16:14:04 -04:00
|
|
|
return
|
|
|
|
}
|
2020-01-07 21:29:15 -05:00
|
|
|
|
2018-09-11 10:52:21 -04:00
|
|
|
client.registerApp(name: "Tusker", redirectURI: "tusker://oauth", scopes: [.read, .write, .follow]) { response in
|
|
|
|
guard case let .success(app, _) = response else { fatalError() }
|
2020-01-07 21:29:15 -05:00
|
|
|
self.client.clientID = app.clientID
|
|
|
|
self.client.clientSecret = app.clientSecret
|
|
|
|
completion(app.clientID, app.clientSecret)
|
2018-08-16 18:55:40 -04:00
|
|
|
}
|
2018-08-16 20:11:56 -04:00
|
|
|
}
|
|
|
|
|
2020-01-07 21:29:15 -05:00
|
|
|
func authorize(authorizationCode: String, completion: @escaping (_ accessToken: String) -> Void) {
|
2018-09-11 10:52:21 -04:00
|
|
|
client.getAccessToken(authorizationCode: authorizationCode, redirectURI: "tusker://oauth") { response in
|
|
|
|
guard case let .success(settings, _) = response else { fatalError() }
|
2020-01-07 21:29:15 -05:00
|
|
|
self.client.accessToken = settings.accessToken
|
|
|
|
completion(settings.accessToken)
|
2018-08-16 07:46:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-16 17:52:00 -04:00
|
|
|
func getOwnAccount(completion: ((Result<Account, Client.Error>) -> Void)? = nil) {
|
2018-10-02 19:23:50 -04:00
|
|
|
if account != nil {
|
2020-09-16 17:52:00 -04:00
|
|
|
completion?(.success(account))
|
2018-10-02 19:23:50 -04:00
|
|
|
} else {
|
2020-01-05 14:00:39 -05:00
|
|
|
let request = Client.getSelfAccount()
|
|
|
|
run(request) { response in
|
2020-09-16 17:52:00 -04:00
|
|
|
switch response {
|
|
|
|
case let .failure(error):
|
|
|
|
completion?(.failure(error))
|
|
|
|
|
|
|
|
case let .success(account, _):
|
|
|
|
self.account = account
|
|
|
|
self.persistentContainer.backgroundContext.perform {
|
|
|
|
if let accountMO = self.persistentContainer.account(for: account.id, in: self.persistentContainer.backgroundContext) {
|
|
|
|
accountMO.updateFrom(apiAccount: account, container: self.persistentContainer)
|
|
|
|
} else {
|
|
|
|
// the first time the user's account is added to the store,
|
|
|
|
// increment its reference count so that it's never removed
|
|
|
|
self.persistentContainer.addOrUpdate(account: account, incrementReferenceCount: true)
|
|
|
|
}
|
|
|
|
completion?(.success(account))
|
2020-05-11 21:59:46 -04:00
|
|
|
}
|
|
|
|
}
|
2018-10-02 19:23:50 -04:00
|
|
|
}
|
2018-08-30 22:30:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-16 19:07:30 -04:00
|
|
|
func getOwnInstance(completion: ((Instance) -> Void)? = nil) {
|
|
|
|
if let instance = self.instance {
|
|
|
|
completion?(instance)
|
|
|
|
} else {
|
|
|
|
let request = Client.getInstance()
|
|
|
|
run(request) { (response) in
|
|
|
|
guard case let .success(instance, _) = response else { fatalError() }
|
|
|
|
self.instance = instance
|
|
|
|
completion?(instance)
|
|
|
|
}
|
2018-09-29 22:20:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-16 07:46:19 -04:00
|
|
|
}
|
2020-08-31 19:28:50 -04:00
|
|
|
|
|
|
|
// ObservableObject so that SwiftUI views can receive it through @EnvironmentObject
|
|
|
|
extension MastodonController: ObservableObject {}
|