183 lines
6.1 KiB
Swift
183 lines
6.1 KiB
Swift
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
|
|
|
import Foundation
|
|
import CoreDataStack
|
|
import MastodonSDK
|
|
|
|
public struct MastodonAuthentication: Codable, Hashable, UserIdentifier {
|
|
public static let fallbackCharactersReservedPerURL = 23
|
|
|
|
public enum InstanceConfiguration: Codable, Hashable {
|
|
case v1(Mastodon.Entity.Instance)
|
|
case v2(Mastodon.Entity.V2.Instance, TranslationLanguages)
|
|
|
|
public func canTranslateFrom(_ sourceLocale: String, to targetLanguage: String) -> Bool {
|
|
switch self {
|
|
case .v1:
|
|
return false
|
|
case let .v2(instance, translationLanguages):
|
|
guard instance.configuration?.translation?.enabled == true else { return false }
|
|
return translationLanguages[sourceLocale]?.contains(targetLanguage) == true
|
|
}
|
|
}
|
|
|
|
public var instanceConfigLimitingProperties: InstanceConfigLimitingPropertyContaining? {
|
|
switch self {
|
|
case let .v1(instance):
|
|
return instance.configuration
|
|
case let .v2(instance, _):
|
|
return instance.configuration
|
|
}
|
|
}
|
|
|
|
public var canFollowTags: Bool {
|
|
let version: String?
|
|
switch self {
|
|
case let .v1(instance):
|
|
version = instance.version
|
|
case let .v2(instance, _):
|
|
version = instance.version
|
|
}
|
|
return version?.majorServerVersion(greaterThanOrEquals: 4) ?? false // following Tags is support beginning with Mastodon v4.0.0
|
|
}
|
|
|
|
public var charactersReservedPerURL: Int {
|
|
switch self {
|
|
case let .v1(instance):
|
|
return instance.configuration?.statuses?.charactersReservedPerURL ?? fallbackCharactersReservedPerURL
|
|
case let .v2(instance, _):
|
|
return instance.configuration?.statuses?.charactersReservedPerURL ?? fallbackCharactersReservedPerURL
|
|
}
|
|
}
|
|
}
|
|
|
|
public typealias ID = UUID
|
|
|
|
public private(set) var identifier: ID
|
|
public private(set) var domain: String
|
|
public private(set) var username: String
|
|
|
|
public private(set) var appAccessToken: String
|
|
public private(set) var userAccessToken: String
|
|
public private(set) var clientID: String
|
|
public private(set) var clientSecret: String
|
|
|
|
public private(set) var createdAt: Date
|
|
public private(set) var updatedAt: Date
|
|
public private(set) var activedAt: Date
|
|
|
|
public private(set) var userID: String
|
|
|
|
public private(set) var instanceConfiguration: InstanceConfiguration?
|
|
|
|
public var persistenceIdentifier: String {
|
|
"\(username)@\(domain)"
|
|
}
|
|
|
|
public static func createFrom(
|
|
domain: String,
|
|
userID: String,
|
|
username: String,
|
|
appAccessToken: String,
|
|
userAccessToken: String,
|
|
clientID: String,
|
|
clientSecret: String
|
|
) -> Self {
|
|
let now = Date()
|
|
return MastodonAuthentication(
|
|
identifier: .init(),
|
|
domain: domain,
|
|
username: username,
|
|
appAccessToken: appAccessToken,
|
|
userAccessToken: userAccessToken,
|
|
clientID: clientID,
|
|
clientSecret: clientSecret,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
activedAt: now,
|
|
userID: userID,
|
|
instanceConfiguration: nil
|
|
)
|
|
}
|
|
|
|
func copy(
|
|
identifier: ID? = nil,
|
|
domain: String? = nil,
|
|
username: String? = nil,
|
|
appAccessToken: String? = nil,
|
|
userAccessToken: String? = nil,
|
|
clientID: String? = nil,
|
|
clientSecret: String? = nil,
|
|
createdAt: Date? = nil,
|
|
updatedAt: Date? = nil,
|
|
activedAt: Date? = nil,
|
|
userID: String? = nil,
|
|
instanceConfiguration: InstanceConfiguration? = nil
|
|
) -> Self {
|
|
MastodonAuthentication(
|
|
identifier: identifier ?? self.identifier,
|
|
domain: domain ?? self.domain,
|
|
username: username ?? self.username,
|
|
appAccessToken: appAccessToken ?? self.appAccessToken,
|
|
userAccessToken: userAccessToken ?? self.userAccessToken,
|
|
clientID: clientID ?? self.clientID,
|
|
clientSecret: clientSecret ?? self.clientSecret,
|
|
createdAt: createdAt ?? self.createdAt,
|
|
updatedAt: updatedAt ?? self.updatedAt,
|
|
activedAt: activedAt ?? self.activedAt,
|
|
userID: userID ?? self.userID,
|
|
instanceConfiguration: instanceConfiguration ?? self.instanceConfiguration
|
|
)
|
|
}
|
|
|
|
public func account() -> Mastodon.Entity.Account? {
|
|
|
|
let account = FileManager
|
|
.default
|
|
.accounts(for: self.userIdentifier())
|
|
.first(where: { $0.id == userID })
|
|
|
|
return account
|
|
}
|
|
|
|
public func userIdentifier() -> MastodonUserIdentifier {
|
|
MastodonUserIdentifier(domain: domain, userID: userID)
|
|
}
|
|
|
|
@MainActor
|
|
func updating(instanceV1 instance: Mastodon.Entity.Instance) -> Self {
|
|
return copy(instanceConfiguration: .v1(instance))
|
|
}
|
|
|
|
@MainActor
|
|
func updating(instanceV2 instance: Mastodon.Entity.V2.Instance) -> Self {
|
|
guard
|
|
let instanceConfiguration,
|
|
case let InstanceConfiguration.v2(_, translationLanguages) = instanceConfiguration
|
|
else {
|
|
return copy(instanceConfiguration: .v2(instance, [:]))
|
|
}
|
|
return copy(instanceConfiguration: .v2(instance, translationLanguages))
|
|
}
|
|
|
|
@MainActor
|
|
func updating(translationLanguages: TranslationLanguages) -> Self {
|
|
switch self.instanceConfiguration {
|
|
case .v1(let instance):
|
|
return copy(instanceConfiguration: .v1(instance))
|
|
case .v2(let instance, _):
|
|
return copy(instanceConfiguration: .v2(instance, translationLanguages))
|
|
case .none:
|
|
return self
|
|
}
|
|
}
|
|
|
|
func updating(activatedAt: Date) -> Self {
|
|
copy(activedAt: activatedAt)
|
|
}
|
|
|
|
var authorization: Mastodon.API.OAuth.Authorization {
|
|
.init(accessToken: userAccessToken)
|
|
}
|
|
}
|