passepartout-apple/PassepartoutLibrary/Sources/PassepartoutProviders/Managers/ProviderManager.swift

142 lines
5.1 KiB
Swift
Raw Normal View History

2022-04-12 13:09:14 +00:00
//
// ProviderManager.swift
// Passepartout
//
// Created by Davide De Rosa on 3/13/22.
2023-03-17 15:56:19 +00:00
// Copyright (c) 2023 Davide De Rosa. All rights reserved.
2022-04-12 13:09:14 +00:00
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import Combine
import Foundation
2022-06-23 21:31:01 +00:00
import PassepartoutCore
2022-04-12 13:09:14 +00:00
@MainActor
public final class ProviderManager: ObservableObject, RateLimited {
2023-05-24 16:19:47 +00:00
private let localProvidersRepository: LocalProvidersRepository
2023-03-17 20:55:47 +00:00
2023-05-24 16:19:47 +00:00
private let remoteProvidersStrategy: RemoteProvidersStrategy
2022-04-12 13:09:14 +00:00
public let didUpdateProviders = PassthroughSubject<Void, Never>()
2023-05-24 16:19:47 +00:00
public init(
localProvidersRepository: LocalProvidersRepository,
remoteProvidersStrategy: RemoteProvidersStrategy
) {
self.localProvidersRepository = localProvidersRepository
self.remoteProvidersStrategy = remoteProvidersStrategy
2022-04-12 13:09:14 +00:00
_ = allProviders()
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
// MARK: Queries
public func allProviders() -> [ProviderMetadata] {
2023-05-24 16:19:47 +00:00
localProvidersRepository.allProviders()
2022-04-12 13:09:14 +00:00
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public func provider(withName name: ProviderName) -> ProviderMetadata? {
2023-05-24 16:19:47 +00:00
localProvidersRepository.provider(withName: name)
2022-04-12 13:09:14 +00:00
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public func isAvailable(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> Bool {
2023-05-24 16:19:47 +00:00
localProvidersRepository.lastInfrastructureUpdate(withName: name, vpnProtocol: vpnProtocol) != nil
2022-04-12 13:09:14 +00:00
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public func defaultUsername(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> String? {
2023-05-24 16:19:47 +00:00
localProvidersRepository.defaultUsername(forProviderWithName: name, vpnProtocol: vpnProtocol)
2022-04-12 13:09:14 +00:00
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public func lastUpdate(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> Date? {
2023-05-24 16:19:47 +00:00
localProvidersRepository.lastInfrastructureUpdate(withName: name, vpnProtocol: vpnProtocol)
2022-04-12 13:09:14 +00:00
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public func categories(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> [ProviderCategory] {
2023-05-24 16:19:47 +00:00
localProvidersRepository.categories(forProviderWithName: name, vpnProtocol: vpnProtocol)
2022-04-12 13:09:14 +00:00
}
public func servers(forLocation location: ProviderLocation) -> [ProviderServer] {
2023-05-24 16:19:47 +00:00
localProvidersRepository.servers(forLocation: location)
2022-04-12 13:09:14 +00:00
}
public func server(_ name: ProviderName, vpnProtocol: VPNProtocolType, apiId: String) -> ProviderServer? {
2023-05-24 16:19:47 +00:00
localProvidersRepository.server(forProviderWithName: name, vpnProtocol: vpnProtocol, apiId: apiId)
2022-04-12 13:09:14 +00:00
}
public func anyDefaultServer(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> ProviderServer? {
2023-05-24 16:19:47 +00:00
localProvidersRepository.anyDefaultServer(forProviderWithName: name, vpnProtocol: vpnProtocol)
2022-04-12 13:09:14 +00:00
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public func server(withId id: String) -> ProviderServer? {
2023-05-24 16:19:47 +00:00
localProvidersRepository.server(withId: id)
2022-04-12 13:09:14 +00:00
}
// MARK: Modification
2023-07-02 10:51:50 +00:00
public func fetchProvidersIndexPublisher(priority: RemoteProvidersPriority) -> AnyPublisher<Void, Passepartout.ProviderError> {
2022-04-12 13:09:14 +00:00
guard !isRateLimited(indexActionName) else {
return Just(())
2023-07-02 10:51:50 +00:00
.setFailureType(to: Passepartout.ProviderError.self)
2022-04-12 13:09:14 +00:00
.eraseToAnyPublisher()
}
2023-03-17 20:55:47 +00:00
2023-05-24 16:19:47 +00:00
let savePublisher = remoteProvidersStrategy.saveIndex(priority: priority) {
self.saveLastAction(self.indexActionName)
}
return savePublisher
.map {
self.didUpdateProviders.send()
2023-07-02 10:51:50 +00:00
}.mapError {
.fetchFailure(error: $0)
2022-04-12 13:09:14 +00:00
}.eraseToAnyPublisher()
}
2023-03-17 20:55:47 +00:00
2023-07-02 10:51:50 +00:00
public func fetchProviderPublisher(withName providerName: ProviderName, vpnProtocol: VPNProtocolType, priority: RemoteProvidersPriority) -> AnyPublisher<Void, Passepartout.ProviderError> {
2022-04-12 13:09:14 +00:00
guard !isRateLimited(providerName) else {
return Just(())
2023-07-02 10:51:50 +00:00
.setFailureType(to: Passepartout.ProviderError.self)
2022-04-12 13:09:14 +00:00
.eraseToAnyPublisher()
}
2023-05-24 16:19:47 +00:00
let lastUpdate = localProvidersRepository.lastInfrastructureUpdate(withName: providerName, vpnProtocol: vpnProtocol)
let savePublisher = remoteProvidersStrategy.saveProvider(
withName: providerName,
vpnProtocol: vpnProtocol,
lastUpdate: lastUpdate,
priority: priority
) {
self.saveLastAction(providerName)
}
return savePublisher
.map {
self.didUpdateProviders.send()
2023-07-02 10:51:50 +00:00
}.mapError {
.fetchFailure(error: $0)
2022-04-12 13:09:14 +00:00
}.eraseToAnyPublisher()
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
// MARK: RateLimited
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
private let indexActionName = ""
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public var lastActionDate: [String: Date] = [:]
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
public var rateLimitMilliseconds: Int?
}