diff --git a/Ferrite/API/AllDebridWrapper.swift b/Ferrite/API/AllDebridWrapper.swift index eaa9133..438bdac 100644 --- a/Ferrite/API/AllDebridWrapper.swift +++ b/Ferrite/API/AllDebridWrapper.swift @@ -7,19 +7,18 @@ import Foundation -// TODO: Fix errors -public class AllDebrid: PollingDebridSource, ObservableObject { - public let id = "AllDebrid" - public let abbreviation = "AD" - public let website = "https://alldebrid.com" - public var authTask: Task? +class AllDebrid: PollingDebridSource, ObservableObject { + let id = "AllDebrid" + let abbreviation = "AD" + let website = "https://alldebrid.com" + var authTask: Task? - public var authProcessing: Bool = false - public var isLoggedIn: Bool { + var authProcessing: Bool = false + var isLoggedIn: Bool { getToken() != nil } - public var manualToken: String? { + var manualToken: String? { if UserDefaults.standard.bool(forKey: "AllDebrid.UseManualKey") { return getToken() } else { @@ -27,20 +26,20 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } } - @Published public var IAValues: [DebridIA] = [] - @Published public var cloudDownloads: [DebridCloudDownload] = [] - @Published public var cloudTorrents: [DebridCloudTorrent] = [] - public var cloudTTL: Double = 0.0 + @Published var IAValues: [DebridIA] = [] + @Published var cloudDownloads: [DebridCloudDownload] = [] + @Published var cloudTorrents: [DebridCloudTorrent] = [] + var cloudTTL: Double = 0.0 - let baseApiUrl = "https://api.alldebrid.com/v4" - let appName = "Ferrite" + private let baseApiUrl = "https://api.alldebrid.com/v4" + private let appName = "Ferrite" - let jsonDecoder = JSONDecoder() + private let jsonDecoder = JSONDecoder() // MARK: - Auth // Fetches information for PIN auth - public func getAuthUrl() async throws -> URL { + func getAuthUrl() async throws -> URL { let url = try buildRequestURL(urlString: "\(baseApiUrl)/pin/get") let request = URLRequest(url: url) @@ -66,7 +65,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } // Fetches API keys - public func getApiKey(checkID: String, pin: String) async throws { + func getApiKey(checkID: String, pin: String) async throws { let queryItems = [ URLQueryItem(name: "agent", value: appName), URLQueryItem(name: "check", value: checkID), @@ -109,17 +108,17 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } // Adds a manual API key instead of web auth - public func setApiKey(_ key: String) { + func setApiKey(_ key: String) { FerriteKeychain.shared.set(key, forKey: "AllDebrid.ApiKey") UserDefaults.standard.set(true, forKey: "AllDebrid.UseManualKey") } - public func getToken() -> String? { + func getToken() -> String? { FerriteKeychain.shared.get("AllDebrid.ApiKey") } // Clears tokens. No endpoint to deregister a device - public func logout() { + func logout() { FerriteKeychain.shared.delete("AllDebrid.ApiKey") UserDefaults.standard.removeObject(forKey: "AllDebrid.UseManualKey") } @@ -150,7 +149,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } // Builds a URL for further requests - private func buildRequestURL(urlString: String, queryItems: [URLQueryItem] = []) throws -> URL { + func buildRequestURL(urlString: String, queryItems: [URLQueryItem] = []) throws -> URL { guard var components = URLComponents(string: urlString) else { throw DebridError.InvalidUrl } @@ -168,7 +167,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { // MARK: - Instant availability - public func instantAvailability(magnets: [Magnet]) async throws { + func instantAvailability(magnets: [Magnet]) async throws { let now = Date().timeIntervalSince1970 let sendMagnets = magnets.filter { magnet in @@ -215,7 +214,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { // MARK: - Downloading // Wrapper function to fetch a download link from the API - public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { + func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { let selectedMagnetId: String if let existingMagnet = cloudTorrents.first(where: { $0.hash == magnet.hash && $0.status == "Ready" }) { @@ -237,7 +236,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } // Adds a magnet link to the user's AD account - public func addMagnet(magnet: Magnet) async throws -> Int { + func addMagnet(magnet: Magnet) async throws -> Int { guard let magnetLink = magnet.link else { throw DebridError.FailedRequest(description: "The magnet link is invalid") } @@ -263,7 +262,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } } - public func fetchMagnetStatus(magnetId: String, selectedIndex: Int?) async throws -> String { + func fetchMagnetStatus(magnetId: String, selectedIndex: Int?) async throws -> String { let queryItems = [ URLQueryItem(name: "id", value: magnetId) ] @@ -280,7 +279,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } } - public func unlockLink(lockedLink: String) async throws -> String { + func unlockLink(lockedLink: String) async throws -> String { let queryItems = [ URLQueryItem(name: "link", value: lockedLink) ] @@ -292,7 +291,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { return rawResponse.link } - public func saveLink(link: String) async throws { + func saveLink(link: String) async throws { let queryItems = [ URLQueryItem(name: "links[]", value: link) ] @@ -304,7 +303,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { // MARK: - Cloud methods // Referred to as "User magnets" in AllDebrid's API - public func getUserTorrents() async throws { + func getUserTorrents() async throws { var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/status")) let data = try await performRequest(request: &request, requestName: #function) @@ -326,7 +325,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } } - public func deleteTorrent(torrentId: String?) async throws { + func deleteTorrent(torrentId: String?) async throws { guard let torrentId else { throw DebridError.FailedRequest(description: "The torrentID \(String(describing: torrentId)) is invalid") } @@ -339,7 +338,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { try await performRequest(request: &request, requestName: #function) } - public func getUserDownloads() async throws { + func getUserDownloads() async throws { var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/user/links")) let data = try await performRequest(request: &request, requestName: #function) @@ -358,12 +357,12 @@ public class AllDebrid: PollingDebridSource, ObservableObject { } // Not used - public func checkUserDownloads(link: String) async throws -> String? { + func checkUserDownloads(link: String) async throws -> String? { nil } // The downloadId is actually the download link - public func deleteDownload(downloadId: String) async throws { + func deleteDownload(downloadId: String) async throws { let queryItems = [ URLQueryItem(name: "link", value: downloadId) ] diff --git a/Ferrite/API/GithubWrapper.swift b/Ferrite/API/GithubWrapper.swift index 01c0dc5..ef97dbe 100644 --- a/Ferrite/API/GithubWrapper.swift +++ b/Ferrite/API/GithubWrapper.swift @@ -7,8 +7,8 @@ import Foundation -public class Github { - public func fetchLatestRelease() async throws -> Release? { +class Github { + func fetchLatestRelease() async throws -> Release? { let url = URL(string: "https://api.github.com/repos/Ferrite-iOS/Ferrite/releases/latest")! let (data, _) = try await URLSession.shared.data(from: url) @@ -17,7 +17,7 @@ public class Github { return rawResponse } - public func fetchReleases() async throws -> [Release]? { + func fetchReleases() async throws -> [Release]? { let url = URL(string: "https://api.github.com/repos/Ferrite-iOS/Ferrite/releases")! let (data, _) = try await URLSession.shared.data(from: url) diff --git a/Ferrite/API/KodiWrapper.swift b/Ferrite/API/KodiWrapper.swift index 95bc23f..74130b3 100644 --- a/Ferrite/API/KodiWrapper.swift +++ b/Ferrite/API/KodiWrapper.swift @@ -7,11 +7,11 @@ import Foundation -public class Kodi { - let encoder = JSONEncoder() +class Kodi { + private let encoder = JSONEncoder() // Used to add server to CoreData. Not part of API - public func addServer(urlString: String, + func addServer(urlString: String, friendlyName: String?, username: String?, password: String?, @@ -65,7 +65,7 @@ public class Kodi { try backgroundContext.save() } - public func ping(server: KodiServer) async throws { + func ping(server: KodiServer) async throws { var request = URLRequest(url: URL(string: "\(server.urlString)/jsonrpc")!) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") @@ -94,7 +94,7 @@ public class Kodi { } } - public func sendVideoUrl(urlString: String, server: KodiServer) async throws { + func sendVideoUrl(urlString: String, server: KodiServer) async throws { if URL(string: urlString) == nil { throw KodiError.InvalidPlaybackUrl } diff --git a/Ferrite/API/PremiumizeWrapper.swift b/Ferrite/API/PremiumizeWrapper.swift index 4f1803e..12e7b02 100644 --- a/Ferrite/API/PremiumizeWrapper.swift +++ b/Ferrite/API/PremiumizeWrapper.swift @@ -7,16 +7,17 @@ import Foundation -public class Premiumize: OAuthDebridSource, ObservableObject { - public let id = "Premiumize" - public let abbreviation = "PM" - public let website = "https://premiumize.me" - @Published public var authProcessing: Bool = false - public var isLoggedIn: Bool { +class Premiumize: OAuthDebridSource, ObservableObject { + let id = "Premiumize" + let abbreviation = "PM" + let website = "https://premiumize.me" + + @Published var authProcessing: Bool = false + var isLoggedIn: Bool { getToken() != nil } - public var manualToken: String? { + var manualToken: String? { if UserDefaults.standard.bool(forKey: "Premiumize.UseManualKey") { return getToken() } else { @@ -24,20 +25,20 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } } - @Published public var IAValues: [DebridIA] = [] - @Published public var cloudDownloads: [DebridCloudDownload] = [] - @Published public var cloudTorrents: [DebridCloudTorrent] = [] - public var cloudTTL: Double = 0.0 + @Published var IAValues: [DebridIA] = [] + @Published var cloudDownloads: [DebridCloudDownload] = [] + @Published var cloudTorrents: [DebridCloudTorrent] = [] + var cloudTTL: Double = 0.0 - let baseAuthUrl = "https://www.premiumize.me/authorize" - let baseApiUrl = "https://www.premiumize.me/api" - let clientId = "791565696" + private let baseAuthUrl = "https://www.premiumize.me/authorize" + private let baseApiUrl = "https://www.premiumize.me/api" + private let clientId = "791565696" - let jsonDecoder = JSONDecoder() + private let jsonDecoder = JSONDecoder() // MARK: - Auth - public func getAuthUrl() throws -> URL { + func getAuthUrl() throws -> URL { var urlComponents = URLComponents(string: baseAuthUrl)! urlComponents.queryItems = [ URLQueryItem(name: "client_id", value: clientId), @@ -52,7 +53,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } } - public func handleAuthCallback(url: URL) throws { + func handleAuthCallback(url: URL) throws { let callbackComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) guard let callbackFragment = callbackComponents?.fragment else { @@ -70,17 +71,17 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } // Adds a manual API key instead of web auth - public func setApiKey(_ key: String) { + func setApiKey(_ key: String) { FerriteKeychain.shared.set(key, forKey: "Premiumize.AccessToken") UserDefaults.standard.set(true, forKey: "Premiumize.UseManualKey") } - public func getToken() -> String? { + func getToken() -> String? { FerriteKeychain.shared.get("Premiumize.AccessToken") } // Clears tokens. No endpoint to deregister a device - public func logout() { + func logout() { FerriteKeychain.shared.delete("Premiumize.AccessToken") UserDefaults.standard.removeObject(forKey: "Premiumize.UseManualKey") } @@ -132,7 +133,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { // MARK: - Instant availability - public func instantAvailability(magnets: [Magnet]) async throws { + func instantAvailability(magnets: [Magnet]) async throws { let now = Date().timeIntervalSince1970 // Remove magnets that don't have an associated link for PM along with existing TTL logic @@ -168,7 +169,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { // Function to divide and execute DDL endpoint requests in parallel // Calls this for 10 requests at a time to not overwhelm API servers - public func divideDDLRequests(magnetChunk: [Magnet]) async throws -> [DebridIA] { + func divideDDLRequests(magnetChunk: [Magnet]) async throws -> [DebridIA] { let tempIA = try await withThrowingTaskGroup(of: DebridIA.self) { group in for magnet in magnetChunk { group.addTask { @@ -187,7 +188,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } // Grabs DDL links - func fetchDDL(magnet: Magnet) async throws -> DebridIA { + private func fetchDDL(magnet: Magnet) async throws -> DebridIA { if magnet.hash == nil { throw DebridError.EmptyData } @@ -227,7 +228,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { // Function to divide and execute cache endpoint requests in parallel // Calls this for 100 hashes at a time due to API limits - public func divideCacheRequests(magnets: [Magnet]) async throws -> [Magnet] { + func divideCacheRequests(magnets: [Magnet]) async throws -> [Magnet] { let availableMagnets = try await withThrowingTaskGroup(of: [Magnet].self) { group in for chunk in magnets.chunked(into: 100) { group.addTask { @@ -247,7 +248,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } // Parent function for initial checking of the cache - func checkCache(magnets: [Magnet]) async throws -> [Magnet] { + private func checkCache(magnets: [Magnet]) async throws -> [Magnet] { var urlComponents = URLComponents(string: "\(baseApiUrl)/cache/check")! urlComponents.queryItems = magnets.map { URLQueryItem(name: "items[]", value: $0.hash) } guard let url = urlComponents.url else { @@ -277,7 +278,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { // MARK: - Downloading // Wrapper function to fetch a DDL link from the API - public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { + func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { // Store the item in PM cloud for later use try await createTransfer(magnet: magnet) @@ -290,7 +291,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } } - func createTransfer(magnet: Magnet) async throws { + private func createTransfer(magnet: Magnet) async throws { guard let magnetLink = magnet.link else { throw DebridError.FailedRequest(description: "The magnet link is invalid") } @@ -309,7 +310,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { // MARK: - Cloud methods - public func getUserDownloads() async throws { + func getUserDownloads() async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/listall")!) let data = try await performRequest(request: &request, requestName: #function) @@ -325,7 +326,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } } - func itemDetails(itemID: String) async throws -> ItemDetailsResponse { + private func itemDetails(itemID: String) async throws -> ItemDetailsResponse { var urlComponents = URLComponents(string: "\(baseApiUrl)/item/details")! urlComponents.queryItems = [URLQueryItem(name: "id", value: itemID)] guard let url = urlComponents.url else { @@ -340,12 +341,12 @@ public class Premiumize: OAuthDebridSource, ObservableObject { return rawResponse } - public func checkUserDownloads(link: String) async throws -> String? { + func checkUserDownloads(link: String) async throws -> String? { // Link is the cloud item ID try await itemDetails(itemID: link).link } - public func deleteDownload(downloadId: String) async throws { + func deleteDownload(downloadId: String) async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/delete")!) request.httpMethod = "POST" request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") @@ -359,7 +360,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } // No user torrents for Premiumize - public func getUserTorrents() async throws {} + func getUserTorrents() async throws {} - public func deleteTorrent(torrentId: String?) async throws {} + func deleteTorrent(torrentId: String?) async throws {} } diff --git a/Ferrite/API/RealDebridWrapper.swift b/Ferrite/API/RealDebridWrapper.swift index fdeccab..08f69ee 100644 --- a/Ferrite/API/RealDebridWrapper.swift +++ b/Ferrite/API/RealDebridWrapper.swift @@ -7,20 +7,20 @@ import Foundation -public class RealDebrid: PollingDebridSource, ObservableObject { - public let id = "RealDebrid" - public let abbreviation = "RD" - public let website = "https://real-debrid.com" - public var authTask: Task? +class RealDebrid: PollingDebridSource, ObservableObject { + let id = "RealDebrid" + let abbreviation = "RD" + let website = "https://real-debrid.com" + var authTask: Task? - @Published public var authProcessing: Bool = false + @Published var authProcessing: Bool = false // Check the manual token since getTokens() is async - public var isLoggedIn: Bool { + var isLoggedIn: Bool { FerriteKeychain.shared.get("RealDebrid.AccessToken") != nil } - public var manualToken: String? { + var manualToken: String? { if UserDefaults.standard.bool(forKey: "RealDebrid.UseManualKey") { return FerriteKeychain.shared.get("RealDebrid.AccessToken") } else { @@ -28,31 +28,31 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } } - @Published public var IAValues: [DebridIA] = [] - @Published public var cloudDownloads: [DebridCloudDownload] = [] - @Published public var cloudTorrents: [DebridCloudTorrent] = [] - public var cloudTTL: Double = 0.0 + @Published var IAValues: [DebridIA] = [] + @Published var cloudDownloads: [DebridCloudDownload] = [] + @Published var cloudTorrents: [DebridCloudTorrent] = [] + var cloudTTL: Double = 0.0 - let baseAuthUrl = "https://api.real-debrid.com/oauth/v2" - let baseApiUrl = "https://api.real-debrid.com/rest/1.0" - let openSourceClientId = "X245A4XAIBGVM" + private let baseAuthUrl = "https://api.real-debrid.com/oauth/v2" + private let baseApiUrl = "https://api.real-debrid.com/rest/1.0" + private let openSourceClientId = "X245A4XAIBGVM" - let jsonDecoder = JSONDecoder() + private let jsonDecoder = JSONDecoder() @MainActor - func setUserDefaultsValue(_ value: Any, forKey: String) { + private func setUserDefaultsValue(_ value: Any, forKey: String) { UserDefaults.standard.set(value, forKey: forKey) } @MainActor - func removeUserDefaultsValue(forKey: String) { + private func removeUserDefaultsValue(forKey: String) { UserDefaults.standard.removeObject(forKey: forKey) } // MARK: - Auth // Fetches the device code from RD - public func getAuthUrl() async throws -> URL { + func getAuthUrl() async throws -> URL { var urlComponents = URLComponents(string: "\(baseAuthUrl)/device/code")! urlComponents.queryItems = [ URLQueryItem(name: "client_id", value: openSourceClientId), @@ -86,7 +86,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Fetches the user's client ID and secret - public func getDeviceCredentials(deviceCode: String) async throws { + func getDeviceCredentials(deviceCode: String) async throws { var urlComponents = URLComponents(string: "\(baseAuthUrl)/device/credentials")! urlComponents.queryItems = [ URLQueryItem(name: "client_id", value: openSourceClientId), @@ -130,7 +130,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Fetch all tokens for the user and store in FerriteKeychain.shared - public func getApiTokens(deviceCode: String) async throws { + func getApiTokens(deviceCode: String) async throws { guard let clientId = UserDefaults.standard.string(forKey: "RealDebrid.ClientId") else { throw DebridError.EmptyData } @@ -164,7 +164,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { await setUserDefaultsValue(accessTimestamp, forKey: "RealDebrid.AccessTokenStamp") } - public func getToken() async -> String? { + func getToken() async -> String? { let accessTokenStamp = UserDefaults.standard.double(forKey: "RealDebrid.AccessTokenStamp") if Date().timeIntervalSince1970 > accessTokenStamp { @@ -183,7 +183,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { // Adds a manual API key instead of web auth // Clear out existing refresh tokens and timestamps - public func setApiKey(_ key: String) { + func setApiKey(_ key: String) { FerriteKeychain.shared.set(key, forKey: "RealDebrid.AccessToken") FerriteKeychain.shared.delete("RealDebrid.RefreshToken") FerriteKeychain.shared.delete("RealDebrid.AccessTokenStamp") @@ -192,7 +192,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Deletes tokens from device and RD's servers - public func logout() async { + func logout() async { FerriteKeychain.shared.delete("RealDebrid.RefreshToken") FerriteKeychain.shared.delete("RealDebrid.ClientSecret") await removeUserDefaultsValue(forKey: "RealDebrid.ClientId") @@ -237,7 +237,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { // MARK: - Instant availability // Checks if the magnet is streamable on RD - public func instantAvailability(magnets: [Magnet]) async throws { + func instantAvailability(magnets: [Magnet]) async throws { let now = Date().timeIntervalSince1970 let sendMagnets = magnets.filter { magnet in @@ -328,7 +328,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { // MARK: - Downloading // Wrapper function to fetch a download link from the API - public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { + func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { var selectedMagnetId = "" do { @@ -360,7 +360,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Adds a magnet link to the user's RD account - public func addMagnet(magnet: Magnet) async throws -> String { + func addMagnet(magnet: Magnet) async throws -> String { guard let magnetLink = magnet.link else { throw DebridError.FailedRequest(description: "The magnet link is invalid") } @@ -381,7 +381,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Queues the magnet link for downloading - public func selectFiles(debridID: String, fileIds: [Int]) async throws { + func selectFiles(debridID: String, fileIds: [Int]) async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/selectFiles/\(debridID)")!) request.httpMethod = "POST" request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") @@ -401,7 +401,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Gets the info of a torrent from a given ID - public func torrentInfo(debridID: String, selectedFileId: Int?) async throws -> String { + func torrentInfo(debridID: String, selectedFileId: Int?) async throws -> String { var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/info/\(debridID)")!) let data = try await performRequest(request: &request, requestName: #function) @@ -420,7 +420,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Downloads link from selectFiles for playback - public func unrestrictLink(debridDownloadLink: String) async throws -> String { + func unrestrictLink(debridDownloadLink: String) async throws -> String { var request = URLRequest(url: URL(string: "\(baseApiUrl)/unrestrict/link")!) request.httpMethod = "POST" request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") @@ -439,7 +439,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { // MARK: - Cloud methods // Gets the user's torrent library - public func getUserTorrents() async throws { + func getUserTorrents() async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents")!) let data = try await performRequest(request: &request, requestName: #function) @@ -457,7 +457,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Deletes a torrent download from RD - public func deleteTorrent(torrentId: String?) async throws { + func deleteTorrent(torrentId: String?) async throws { let deleteId: String if let torrentId { @@ -480,7 +480,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Gets the user's downloads - public func getUserDownloads() async throws { + func getUserDownloads() async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads")!) let data = try await performRequest(request: &request, requestName: #function) @@ -491,11 +491,11 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Not used - public func checkUserDownloads(link: String) -> String? { + func checkUserDownloads(link: String) -> String? { nil } - public func deleteDownload(downloadId: String) async throws { + func deleteDownload(downloadId: String) async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads/delete/\(downloadId)")!) request.httpMethod = "DELETE" diff --git a/Ferrite/DataManagement/Classes/Bookmark+CoreDataClass.swift b/Ferrite/DataManagement/Classes/Bookmark+CoreDataClass.swift index 730fbdb..37dbaf8 100644 --- a/Ferrite/DataManagement/Classes/Bookmark+CoreDataClass.swift +++ b/Ferrite/DataManagement/Classes/Bookmark+CoreDataClass.swift @@ -10,4 +10,4 @@ import CoreData import Foundation @objc(Bookmark) -public class Bookmark: NSManagedObject {} +class Bookmark: NSManagedObject {} diff --git a/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift b/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift index 39a6268..c242630 100644 --- a/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift +++ b/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift @@ -9,7 +9,7 @@ import CoreData import Foundation -public extension Bookmark { +extension Bookmark { @nonobjc class func fetchRequest() -> NSFetchRequest { NSFetchRequest(entityName: "Bookmark") } diff --git a/Ferrite/Extensions/Color.swift b/Ferrite/Extensions/Color.swift index 8d28825..3cfe031 100644 --- a/Ferrite/Extensions/Color.swift +++ b/Ferrite/Extensions/Color.swift @@ -7,7 +7,7 @@ import SwiftUI -public extension Color { +extension Color { init(hex: String) { let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) var int: UInt64 = 0 diff --git a/Ferrite/Extensions/View.swift b/Ferrite/Extensions/View.swift index 73bafca..6126b97 100644 --- a/Ferrite/Extensions/View.swift +++ b/Ferrite/Extensions/View.swift @@ -11,7 +11,7 @@ import SwiftUI extension View { // Modifies properties of a view. Works the same way as a ViewModifier // From: https://github.com/SwiftUIX/SwiftUIX/blob/master/Sources/Intermodular/Extensions/SwiftUI/View%2B%2B.swift#L10 - public func modifyViewProp(_ body: (inout Self) -> Void) -> Self { + func modifyViewProp(_ body: (inout Self) -> Void) -> Self { var result = self body(&result) diff --git a/Ferrite/Models/ActionModels.swift b/Ferrite/Models/ActionModels.swift index 59dd4f2..eb73c30 100644 --- a/Ferrite/Models/ActionModels.swift +++ b/Ferrite/Models/ActionModels.swift @@ -7,20 +7,20 @@ import Foundation -public struct ActionJson: Codable, Hashable, PluginJson { - public let name: String - public let version: Int16 +struct ActionJson: Codable, Hashable, PluginJson { + let name: String + let version: Int16 let minVersion: String? let about: String? let website: String? let requires: [ActionRequirement] let deeplink: [DeeplinkActionJson]? - public let author: String? - public let listId: UUID? - public let listName: String? - public let tags: [PluginTagJson]? + let author: String? + let listId: UUID? + let listName: String? + let tags: [PluginTagJson]? - public init(name: String, + init(name: String, version: Int16, minVersion: String?, about: String?, @@ -45,7 +45,7 @@ public struct ActionJson: Codable, Hashable, PluginJson { self.tags = tags } - public init(from decoder: Decoder) throws { + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) name = try container.decode(String.self, forKey: .name) version = try container.decode(Int16.self, forKey: .version) @@ -68,7 +68,7 @@ public struct ActionJson: Codable, Hashable, PluginJson { } } -public struct DeeplinkActionJson: Codable, Hashable { +struct DeeplinkActionJson: Codable, Hashable { let os: [String] let scheme: String @@ -77,7 +77,7 @@ public struct DeeplinkActionJson: Codable, Hashable { self.scheme = scheme } - public init(from decoder: Decoder) throws { + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if let os = try? container.decode(String.self, forKey: .os) { @@ -92,7 +92,7 @@ public struct DeeplinkActionJson: Codable, Hashable { } } -public extension ActionJson { +extension ActionJson { // Fetches all tags without optional requirement // Avoids the need for extra tag additions in DB func getTags() -> [PluginTagJson] { @@ -100,7 +100,7 @@ public extension ActionJson { } } -public enum ActionRequirement: String, Codable { +enum ActionRequirement: String, Codable { case magnet case debrid } diff --git a/Ferrite/Models/AllDebridModels.swift b/Ferrite/Models/AllDebridModels.swift index 3ec1d0e..ff28617 100644 --- a/Ferrite/Models/AllDebridModels.swift +++ b/Ferrite/Models/AllDebridModels.swift @@ -7,7 +7,7 @@ import Foundation -public extension AllDebrid { +extension AllDebrid { // MARK: - Generic AllDebrid response // Uses a generic parametr for whatever underlying response is present @@ -71,7 +71,7 @@ public extension AllDebrid { struct MagnetStatusResponse: Codable { let magnets: [MagnetStatusData] - public init(from decoder: Decoder) throws { + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if let data = try? container.decode(MagnetStatusData.self, forKey: .magnets) { diff --git a/Ferrite/Models/BackupModels.swift b/Ferrite/Models/BackupModels.swift index 3ebefcc..b35c898 100644 --- a/Ferrite/Models/BackupModels.swift +++ b/Ferrite/Models/BackupModels.swift @@ -8,7 +8,7 @@ import Foundation // Version is optional until v1 is phased out -public struct Backup: Codable { +struct Backup: Codable { let version: Int? var bookmarks: [BookmarkJson]? var history: [HistoryJson]? diff --git a/Ferrite/Models/DebridManagerModels.swift b/Ferrite/Models/DebridManagerModels.swift index 17bc43c..ad4cff6 100644 --- a/Ferrite/Models/DebridManagerModels.swift +++ b/Ferrite/Models/DebridManagerModels.swift @@ -10,7 +10,7 @@ import Foundation // MARK: - Universal IA enum (IA = InstantAvailability) -public enum IAStatus: String, Codable, Hashable, Sendable, CaseIterable { +enum IAStatus: String, Codable, Hashable, Sendable, CaseIterable { case full = "Cached" case partial = "Batch" case none = "Uncached" @@ -18,7 +18,7 @@ public enum IAStatus: String, Codable, Hashable, Sendable, CaseIterable { // MARK: - Enum for debrid differentiation. 0 is nil -public enum DebridType: Int, Codable, Hashable, CaseIterable { +enum DebridType: Int, Codable, Hashable, CaseIterable { case realDebrid = 1 case allDebrid = 2 case premiumize = 3 @@ -47,7 +47,7 @@ public enum DebridType: Int, Codable, Hashable, CaseIterable { } // Wrapper struct for magnet links to contain both the link and hash for easy access -public struct Magnet: Codable, Hashable, Sendable { +struct Magnet: Codable, Hashable, Sendable { var hash: String? var link: String? diff --git a/Ferrite/Models/DebridModels.swift b/Ferrite/Models/DebridModels.swift index 31ea356..50f9d27 100644 --- a/Ferrite/Models/DebridModels.swift +++ b/Ferrite/Models/DebridModels.swift @@ -7,14 +7,14 @@ import Foundation -public struct DebridIA: Hashable, Sendable { +struct DebridIA: Hashable, Sendable { let magnet: Magnet let source: String let expiryTimeStamp: Double var files: [DebridIAFile] } -public struct DebridIAFile: Hashable, Sendable { +struct DebridIAFile: Hashable, Sendable { let fileId: Int let name: String let streamUrlString: String? @@ -28,14 +28,14 @@ public struct DebridIAFile: Hashable, Sendable { } } -public struct DebridCloudDownload: Hashable, Sendable { +struct DebridCloudDownload: Hashable, Sendable { let downloadId: String let source: String let fileName: String let link: String } -public struct DebridCloudTorrent: Hashable, Sendable { +struct DebridCloudTorrent: Hashable, Sendable { let torrentId: String let source: String let fileName: String @@ -44,7 +44,7 @@ public struct DebridCloudTorrent: Hashable, Sendable { let links: [String] } -public enum DebridError: Error { +enum DebridError: Error { case InvalidUrl case InvalidPostBody case InvalidResponse diff --git a/Ferrite/Models/GithubModels.swift b/Ferrite/Models/GithubModels.swift index 08e007e..0533694 100644 --- a/Ferrite/Models/GithubModels.swift +++ b/Ferrite/Models/GithubModels.swift @@ -7,7 +7,7 @@ import Foundation -public extension Github { +extension Github { struct Release: Codable, Hashable, Sendable { let htmlUrl: String let tagName: String diff --git a/Ferrite/Models/PluginModels.swift b/Ferrite/Models/PluginModels.swift index 83ae8a5..e3dbdcd 100644 --- a/Ferrite/Models/PluginModels.swift +++ b/Ferrite/Models/PluginModels.swift @@ -7,7 +7,7 @@ import Foundation -public struct PluginListJson: Codable { +struct PluginListJson: Codable { let name: String let author: String var sources: [SourceJson]? @@ -16,8 +16,8 @@ public struct PluginListJson: Codable { // Color: Hex value public struct PluginTagJson: Codable, Hashable, Sendable { - public let name: String - public let colorHex: String? + let name: String + let colorHex: String? enum CodingKeys: String, CodingKey { case name diff --git a/Ferrite/Models/PremiumizeModels.swift b/Ferrite/Models/PremiumizeModels.swift index d160c11..927702c 100644 --- a/Ferrite/Models/PremiumizeModels.swift +++ b/Ferrite/Models/PremiumizeModels.swift @@ -7,7 +7,7 @@ import Foundation -public extension Premiumize { +extension Premiumize { // MARK: - CacheCheckResponse struct CacheCheckResponse: Codable { diff --git a/Ferrite/Models/RealDebridModels.swift b/Ferrite/Models/RealDebridModels.swift index d72ad40..1374058 100644 --- a/Ferrite/Models/RealDebridModels.swift +++ b/Ferrite/Models/RealDebridModels.swift @@ -8,7 +8,7 @@ import Foundation -public extension RealDebrid { +extension RealDebrid { // MARK: - device code endpoint struct DeviceCodeResponse: Codable, Sendable { @@ -58,7 +58,7 @@ public extension RealDebrid { struct InstantAvailabilityResponse: Codable, Sendable { var data: InstantAvailabilityData? - public init(from decoder: Decoder) throws { + init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let data = try? container.decode(InstantAvailabilityData.self) { diff --git a/Ferrite/Models/SearchModels.swift b/Ferrite/Models/SearchModels.swift index e2a9598..49ef182 100644 --- a/Ferrite/Models/SearchModels.swift +++ b/Ferrite/Models/SearchModels.swift @@ -8,7 +8,7 @@ import Foundation // A raw search result structure displayed on the UI -public struct SearchResult: Codable, Hashable, Sendable { +struct SearchResult: Codable, Hashable, Sendable { let title: String? let source: String let size: String? diff --git a/Ferrite/Models/SourceModels.swift b/Ferrite/Models/SourceModels.swift index efa0efb..ee5e5d9 100644 --- a/Ferrite/Models/SourceModels.swift +++ b/Ferrite/Models/SourceModels.swift @@ -7,14 +7,14 @@ import Foundation -public enum ApiCredentialResponseType: String, Codable, Hashable, Sendable { +enum ApiCredentialResponseType: String, Codable, Hashable, Sendable { case json case text } -public struct SourceJson: Codable, Hashable, Sendable, PluginJson { - public let name: String - public let version: Int16 +struct SourceJson: Codable, Hashable, Sendable, PluginJson { + let name: String + let version: Int16 let minVersion: String? let about: String? let website: String? @@ -25,33 +25,33 @@ public struct SourceJson: Codable, Hashable, Sendable, PluginJson { let jsonParser: SourceJsonParserJson? let rssParser: SourceRssParserJson? let htmlParser: SourceHtmlParserJson? - public let author: String? - public let listId: UUID? - public let listName: String? - public let tags: [PluginTagJson]? + let author: String? + let listId: UUID? + let listName: String? + let tags: [PluginTagJson]? } -public extension SourceJson { +extension SourceJson { // Fetches all tags without optional requirement func getTags() -> [PluginTagJson] { tags ?? [] } } -public enum SourcePreferredParser: Int16, CaseIterable, Sendable { +enum SourcePreferredParser: Int16, CaseIterable, Sendable { // case none = 0 case scraping = 1 case rss = 2 case siteApi = 3 } -public struct SourceApiJson: Codable, Hashable, Sendable { +struct SourceApiJson: Codable, Hashable, Sendable { let apiUrl: String? let clientId: SourceApiCredentialJson? let clientSecret: SourceApiCredentialJson? } -public struct SourceApiCredentialJson: Codable, Hashable, Sendable { +struct SourceApiCredentialJson: Codable, Hashable, Sendable { let query: String? let value: String? let dynamic: Bool? @@ -60,7 +60,7 @@ public struct SourceApiCredentialJson: Codable, Hashable, Sendable { let expiryLength: Double? } -public struct SourceJsonParserJson: Codable, Hashable, Sendable { +struct SourceJsonParserJson: Codable, Hashable, Sendable { let searchUrl: String let request: SourceRequestJson? let results: String? @@ -73,7 +73,7 @@ public struct SourceJsonParserJson: Codable, Hashable, Sendable { let sl: SourceSLJson? } -public struct SourceRssParserJson: Codable, Hashable, Sendable { +struct SourceRssParserJson: Codable, Hashable, Sendable { let rssUrl: String? let searchUrl: String let request: SourceRequestJson? @@ -86,7 +86,7 @@ public struct SourceRssParserJson: Codable, Hashable, Sendable { let sl: SourceSLJson? } -public struct SourceHtmlParserJson: Codable, Hashable, Sendable { +struct SourceHtmlParserJson: Codable, Hashable, Sendable { let searchUrl: String? let request: SourceRequestJson? let rows: String @@ -97,21 +97,21 @@ public struct SourceHtmlParserJson: Codable, Hashable, Sendable { let sl: SourceSLJson? } -public struct SourceComplexQueryJson: Codable, Hashable, Sendable { +struct SourceComplexQueryJson: Codable, Hashable, Sendable { let query: String let discriminator: String? let attribute: String? let regex: String? } -public struct SourceMagnetJson: Codable, Hashable, Sendable { +struct SourceMagnetJson: Codable, Hashable, Sendable { let query: String let attribute: String let regex: String? let externalLinkQuery: String? } -public struct SourceSLJson: Codable, Hashable, Sendable { +struct SourceSLJson: Codable, Hashable, Sendable { let seeders: String? let leechers: String? let combined: String? @@ -121,7 +121,7 @@ public struct SourceSLJson: Codable, Hashable, Sendable { let leecherRegex: String? } -public struct SourceRequestJson: Codable, Hashable, Sendable { +struct SourceRequestJson: Codable, Hashable, Sendable { let method: String? let headers: [String: String]? let body: String? diff --git a/Ferrite/Protocols/Debrid.swift b/Ferrite/Protocols/Debrid.swift index fb24d7d..0ec910f 100644 --- a/Ferrite/Protocols/Debrid.swift +++ b/Ferrite/Protocols/Debrid.swift @@ -7,7 +7,7 @@ import Foundation -public protocol DebridSource: AnyObservableObject { +protocol DebridSource: AnyObservableObject { // ID of the service // var id: DebridInfo { get } var id: String { get } @@ -51,7 +51,7 @@ public protocol DebridSource: AnyObservableObject { func deleteTorrent(torrentId: String?) async throws } -public protocol PollingDebridSource: DebridSource { +protocol PollingDebridSource: DebridSource { // Task reference for polling var authTask: Task? { get set } @@ -59,7 +59,7 @@ public protocol PollingDebridSource: DebridSource { func getAuthUrl() async throws -> URL } -public protocol OAuthDebridSource: DebridSource { +protocol OAuthDebridSource: DebridSource { // Fetches the auth URL func getAuthUrl() throws -> URL diff --git a/Ferrite/Protocols/Plugin.swift b/Ferrite/Protocols/Plugin.swift index adbe1ee..65cc4bf 100644 --- a/Ferrite/Protocols/Plugin.swift +++ b/Ferrite/Protocols/Plugin.swift @@ -8,7 +8,7 @@ import CoreData import Foundation -public protocol Plugin: ObservableObject, NSManagedObject { +protocol Plugin: ObservableObject, NSManagedObject { var id: UUID { get set } var listId: UUID? { get set } var name: String { get set } @@ -27,7 +27,7 @@ extension Plugin { } } -public protocol PluginJson: Hashable { +protocol PluginJson: Hashable { var name: String { get } var version: Int16 { get } var author: String? { get } diff --git a/Ferrite/Utils/Application.swift b/Ferrite/Utils/Application.swift index d27584e..e125246 100644 --- a/Ferrite/Utils/Application.swift +++ b/Ferrite/Utils/Application.swift @@ -9,7 +9,7 @@ import Foundation -public class Application { +class Application { static let shared = Application() // OS name for Plugins to read. Lowercase for ease of use diff --git a/Ferrite/Utils/Store.swift b/Ferrite/Utils/Store.swift index 34cd3b2..395e45b 100644 --- a/Ferrite/Utils/Store.swift +++ b/Ferrite/Utils/Store.swift @@ -27,7 +27,7 @@ class ErasedObservableObject: ObservableObject { } } -public protocol AnyObservableObject: AnyObject { +protocol AnyObservableObject: AnyObject { var objectWillChange: ObservableObjectPublisher { get } } @@ -59,14 +59,14 @@ public protocol AnyObservableObject: AnyObject { /// Not all injected objects need this property wrapper. See the example projects for examples each /// way. @propertyWrapper -public struct Store { +struct Store { /// The underlying object being stored. - public let wrappedValue: ObjectType + let wrappedValue: ObjectType // See https://github.com/Tiny-Home-Consulting/Dependiject/issues/38 fileprivate var _observableObject: ObservedObject - @MainActor internal var observableObject: ErasedObservableObject { + @MainActor var observableObject: ErasedObservableObject { _observableObject.wrappedValue } @@ -83,14 +83,14 @@ public struct Store { /// } /// } /// ``` - public var projectedValue: Wrapper { + var projectedValue: Wrapper { Wrapper(self) } /// Create a stored value on a custom scheduler. /// /// Use this init to schedule updates on a specific scheduler other than `DispatchQueue.main`. - public init(wrappedValue: ObjectType, + init(wrappedValue: ObjectType, on scheduler: S, schedulerOptions: S.SchedulerOptions? = nil) { @@ -112,7 +112,7 @@ public struct Store { /// Create a stored value which publishes on the main thread. /// /// To control when updates are published, see ``init(wrappedValue:on:schedulerOptions:)``. - public init(wrappedValue: ObjectType) { + init(wrappedValue: ObjectType) { self.init(wrappedValue: wrappedValue, on: DispatchQueue.main) } @@ -120,15 +120,15 @@ public struct Store { /// [`ObservedObject.Wrapper`](https://developer.apple.com/documentation/swiftui/observedobject/wrapper) /// type. @dynamicMemberLookup - public struct Wrapper { + struct Wrapper { private var store: Store - internal init(_ store: Store) { + init(_ store: Store) { self.store = store } /// Returns a binding to the resulting value of a given key path. - public subscript( + subscript( dynamicMember keyPath: ReferenceWritableKeyPath ) -> Binding { Binding { @@ -141,7 +141,7 @@ public struct Store { } extension Store: DynamicProperty { - public nonisolated mutating func update() { + nonisolated mutating func update() { _observableObject.update() } } diff --git a/Ferrite/ViewModels/BackupManager.swift b/Ferrite/ViewModels/BackupManager.swift index 588c1ac..bfbafce 100644 --- a/Ferrite/ViewModels/BackupManager.swift +++ b/Ferrite/ViewModels/BackupManager.swift @@ -7,9 +7,9 @@ import Foundation -public class BackupManager: ObservableObject { +class BackupManager: ObservableObject { // Constant variable for backup versions - let latestBackupVersion: Int = 2 + private let latestBackupVersion: Int = 2 var logManager: LoggingManager? @@ -21,17 +21,17 @@ public class BackupManager: ObservableObject { @Published var selectedBackupUrl: URL? @MainActor - func updateRestoreCompletedMessage(newString: String) { + private func updateRestoreCompletedMessage(newString: String) { restoreCompletedMessage.append(newString) } @MainActor - func toggleRestoreCompletedAlert() { + private func toggleRestoreCompletedAlert() { showRestoreCompletedAlert.toggle() } @MainActor - func updateBackupUrls(newUrl: URL) { + private func updateBackupUrls(newUrl: URL) { backupUrls.append(newUrl) } diff --git a/Ferrite/ViewModels/DebridManager.swift b/Ferrite/ViewModels/DebridManager.swift index a113407..fcbd8a0 100644 --- a/Ferrite/ViewModels/DebridManager.swift +++ b/Ferrite/ViewModels/DebridManager.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI @MainActor -public class DebridManager: ObservableObject { +class DebridManager: ObservableObject { // Linked classes var logManager: LoggingManager? @Published var realDebrid: RealDebrid = .init() @@ -40,7 +40,7 @@ public class DebridManager: ObservableObject { var selectedDebridFile: DebridIAFile? // TODO: Figure out a way to remove this var - var selectedOAuthDebridSource: OAuthDebridSource? + private var selectedOAuthDebridSource: OAuthDebridSource? @Published var filteredIAStatus: Set = [] @@ -48,17 +48,8 @@ public class DebridManager: ObservableObject { var downloadUrl: String = "" var authUrl: URL? - // RealDebrid auth variables - var realDebridAuthProcessing: Bool = false - @Published var showDeleteAlert: Bool = false - // AllDebrid auth variables - var allDebridAuthProcessing: Bool = false - - // Premiumize auth variables - var premiumizeAuthProcessing: Bool = false - init() { // Set the preferred service. Contains migration logic for earlier versions if let rawPreferredService = UserDefaults.standard.string(forKey: "Debrid.PreferredService") { @@ -83,7 +74,7 @@ public class DebridManager: ObservableObject { // TODO: Remove after v0.8.0 // Function to migrate the preferred service to the new string ID format - public func migratePreferredService(_ idInt: Int) -> String? { + private func migratePreferredService(_ idInt: Int) -> String? { // Undo the EnabledDebrids key UserDefaults.standard.removeObject(forKey: "Debrid.EnabledArray") @@ -92,7 +83,7 @@ public class DebridManager: ObservableObject { // Wrapper function to match error descriptions // Error can be suppressed to end user but must be printed in logs - func sendDebridError( + private func sendDebridError( _ error: Error, prefix: String, presentError: Bool = true, @@ -119,20 +110,20 @@ public class DebridManager: ObservableObject { } // Cleans all cached IA values in the event of a full IA refresh - public func clearIAValues() { + func clearIAValues() { for debridSource in debridSources { debridSource.IAValues = [] } } // Clears all selected files and items - public func clearSelectedDebridItems() { + func clearSelectedDebridItems() { selectedDebridItem = nil selectedDebridFile = nil } // Common function to populate hashes for debrid services - public func populateDebridIA(_ resultMagnets: [Magnet]) async { + func populateDebridIA(_ resultMagnets: [Magnet]) async { for debridSource in debridSources { if !debridSource.isLoggedIn { continue @@ -148,7 +139,7 @@ public class DebridManager: ObservableObject { } // Common function to match a magnet hash with a provided debrid service - public func matchMagnetHash(_ magnet: Magnet) -> IAStatus { + func matchMagnetHash(_ magnet: Magnet) -> IAStatus { guard let magnetHash = magnet.hash else { return .none } @@ -162,7 +153,7 @@ public class DebridManager: ObservableObject { } } - public func selectDebridResult(magnet: Magnet) -> Bool { + func selectDebridResult(magnet: Magnet) -> Bool { guard let magnetHash = magnet.hash else { logManager?.error("DebridManager: Could not find the torrent magnet hash") return false @@ -184,7 +175,7 @@ public class DebridManager: ObservableObject { // MARK: - Authentication UI linked functions // Common function to delegate what debrid service to authenticate with - public func authenticateDebrid(_ debridSource: some DebridSource, apiKey: String?) async { + func authenticateDebrid(_ debridSource: some DebridSource, apiKey: String?) async { defer { // Don't cancel processing if using OAuth if !(debridSource is OAuthDebridSource) { @@ -253,7 +244,7 @@ public class DebridManager: ObservableObject { } // Wrapper function to validate and present an auth URL to the user - @discardableResult func validateAuthUrl(_ url: URL?, useAuthSession: Bool = false) -> Bool { + @discardableResult private func validateAuthUrl(_ url: URL?, useAuthSession: Bool = false) -> Bool { guard let url else { logManager?.error("DebridManager: Authentication: Invalid URL created: \(String(describing: url))") return false @@ -270,7 +261,7 @@ public class DebridManager: ObservableObject { } // Currently handles Premiumize callback - public func handleAuthCallback(url: URL?, error: Error?) async { + func handleAuthCallback(url: URL?, error: Error?) async { defer { if enabledDebridCount == 1 { selectedDebridSource = selectedOAuthDebridSource @@ -300,7 +291,7 @@ public class DebridManager: ObservableObject { // MARK: - Logout UI functions - public func logout(_ debridSource: some DebridSource) async { + func logout(_ debridSource: some DebridSource) async { await debridSource.logout() if selectedDebridSource?.id == debridSource.id { @@ -312,7 +303,7 @@ public class DebridManager: ObservableObject { // Common function to delegate what debrid service to fetch from // Cloudinfo is used for any extra information provided by debrid cloud - public func fetchDebridDownload(magnet: Magnet?, cloudInfo: String? = nil) async { + func fetchDebridDownload(magnet: Magnet?, cloudInfo: String? = nil) async { defer { currentDebridTask = nil logManager?.hideIndeterminateToast() @@ -359,7 +350,7 @@ public class DebridManager: ObservableObject { } // Wrapper to handle cloud fetching - public func fetchDebridCloud(bypassTTL: Bool = false) async { + func fetchDebridCloud(bypassTTL: Bool = false) async { guard let selectedSource = selectedDebridSource else { return } @@ -381,7 +372,7 @@ public class DebridManager: ObservableObject { } } - public func deleteCloudDownload(_ download: DebridCloudDownload) async { + func deleteCloudDownload(_ download: DebridCloudDownload) async { guard let selectedSource = selectedDebridSource else { return } @@ -395,7 +386,7 @@ public class DebridManager: ObservableObject { } } - public func deleteCloudTorrent(_ torrent: DebridCloudTorrent) async { + func deleteCloudTorrent(_ torrent: DebridCloudTorrent) async { guard let selectedSource = selectedDebridSource else { return } diff --git a/Ferrite/ViewModels/LoggingManager.swift b/Ferrite/ViewModels/LoggingManager.swift index 86c7334..9abf814 100644 --- a/Ferrite/ViewModels/LoggingManager.swift +++ b/Ferrite/ViewModels/LoggingManager.swift @@ -70,7 +70,7 @@ class LoggingManager: ObservableObject { // TODO: Maybe append to a constant logfile? - public func info(_ message: String, + func info(_ message: String, description: String? = nil) { let log = Log( @@ -88,7 +88,7 @@ class LoggingManager: ObservableObject { print("LOG: \(log.toMessage())") } - public func warn(_ message: String, + func warn(_ message: String, description: String? = nil) { let log = Log( @@ -106,7 +106,7 @@ class LoggingManager: ObservableObject { print("LOG: \(log.toMessage())") } - public func error(_ message: String, + func error(_ message: String, description: String? = nil, showToast: Bool = true) { @@ -132,7 +132,7 @@ class LoggingManager: ObservableObject { // MARK: - Indeterminate functions - public func updateIndeterminateToast(_ description: String, cancelAction: (() -> Void)?) { + func updateIndeterminateToast(_ description: String, cancelAction: (() -> Void)?) { indeterminateToastDescription = description if let cancelAction { @@ -144,13 +144,13 @@ class LoggingManager: ObservableObject { } } - public func hideIndeterminateToast() { + func hideIndeterminateToast() { showIndeterminateToast = false indeterminateToastDescription = "" indeterminateCancelAction = nil } - public func exportLogs() { + func exportLogs() { logFormatter.dateFormat = "yyyy-MM-dd-HHmmss" let logFileName = "ferrite_session_\(logFormatter.string(from: Date())).txt" let logFolderPath = FileManager.default.appDirectory.appendingPathComponent("Logs") diff --git a/Ferrite/ViewModels/NavigationViewModel.swift b/Ferrite/ViewModels/NavigationViewModel.swift index 910ce27..1095b85 100644 --- a/Ferrite/ViewModels/NavigationViewModel.swift +++ b/Ferrite/ViewModels/NavigationViewModel.swift @@ -8,12 +8,12 @@ import SwiftUI @MainActor -public class NavigationViewModel: ObservableObject { +class NavigationViewModel: ObservableObject { var logManager: LoggingManager? // Used between SearchResultsView and MagnetChoiceView - public enum ChoiceSheetType: Identifiable { - public var id: Int { + enum ChoiceSheetType: Identifiable { + var id: Int { hashValue } @@ -53,7 +53,7 @@ public class NavigationViewModel: ObservableObject { @Published var currentSortFilter: SortFilter? @Published var currentSortOrder: SortOrder = .forward - public func compareSearchResult(lhs: SearchResult, rhs: SearchResult) -> Bool { + func compareSearchResult(lhs: SearchResult, rhs: SearchResult) -> Bool { switch currentSortFilter { case .leechers: guard let lhsLeechers = lhs.leechers, let rhsLeechers = rhs.leechers else { @@ -97,7 +97,7 @@ public class NavigationViewModel: ObservableObject { @Published var searchPrompt: String = "Search" @Published var lastSearchPromptIndex: Int = -1 - let searchBarTextArray: [String] = [ + private let searchBarTextArray: [String] = [ "What's on your mind?", "Discover something interesting", "Find an engaging show", diff --git a/Ferrite/ViewModels/PluginManager.swift b/Ferrite/ViewModels/PluginManager.swift index bf46181..58c57ab 100644 --- a/Ferrite/ViewModels/PluginManager.swift +++ b/Ferrite/ViewModels/PluginManager.swift @@ -9,7 +9,7 @@ import Foundation import SwiftUI import Yams -public class PluginManager: ObservableObject { +class PluginManager: ObservableObject { var logManager: LoggingManager? let kodi: Kodi = .init() @@ -25,18 +25,18 @@ public class PluginManager: ObservableObject { @Published var actionSuccessAlertMessage: String = "" @MainActor - func cleanAvailablePlugins() { + private func cleanAvailablePlugins() { availableSources = [] availableActions = [] } @MainActor - func updateAvailablePlugins(_ newPlugins: AvailablePlugins) { + private func updateAvailablePlugins(_ newPlugins: AvailablePlugins) { availableSources += newPlugins.availableSources availableActions += newPlugins.availableActions } - public func fetchPluginsFromUrl() async { + func fetchPluginsFromUrl() async { let pluginListRequest = PluginList.fetchRequest() guard let pluginLists = try? PersistenceController.shared.backgroundContext.fetch(pluginListRequest) else { await logManager?.error("PluginManager: No plugin lists found") @@ -97,7 +97,7 @@ public class PluginManager: ObservableObject { await logManager?.info("Plugin list fetch finished") } - func fetchPluginList(pluginList: PluginList, url: URL) async throws -> AvailablePlugins? { + private func fetchPluginList(pluginList: PluginList, url: URL) async throws -> AvailablePlugins? { var tempSources: [SourceJson] = [] var tempActions: [ActionJson] = [] @@ -176,7 +176,7 @@ public class PluginManager: ObservableObject { } // Checks if a deeplink action is present and if there's a single action for the OS (or fallback) - func getFilteredDeeplinks(_ deeplinks: [DeeplinkActionJson]) -> [DeeplinkActionJson]? { + private func getFilteredDeeplinks(_ deeplinks: [DeeplinkActionJson]) -> [DeeplinkActionJson]? { let osArray = deeplinks.filter { deeplink in deeplink.os.contains(where: { $0.lowercased() == Application.shared.os.lowercased() }) } @@ -244,7 +244,7 @@ public class PluginManager: ObservableObject { } } - func fetchCastedPlugins(_ forType: PJ.Type) -> [PJ] { + private func fetchCastedPlugins(_ forType: PJ.Type) -> [PJ] { switch String(describing: PJ.self) { case "SourceJson": return availableSources as? [PJ] ?? [] @@ -256,7 +256,7 @@ public class PluginManager: ObservableObject { } // Checks if the current app version is supported by the source - func checkAppVersion(minVersion: String?) -> Bool { + private func checkAppVersion(minVersion: String?) -> Bool { // If there's no min version, assume that every version is supported guard let minVersion else { return true @@ -266,7 +266,7 @@ public class PluginManager: ObservableObject { } // Fetches sources using the background context - public func fetchInstalledSources(searchResultsEmpty: Bool) -> [Source] { + func fetchInstalledSources(searchResultsEmpty: Bool) -> [Source] { let backgroundContext = PersistenceController.shared.backgroundContext if !filteredInstalledSources.isEmpty, !searchResultsEmpty { @@ -279,7 +279,7 @@ public class PluginManager: ObservableObject { } @MainActor - public func runDefaultAction(urlString: String?, navModel: NavigationViewModel) { + func runDefaultAction(urlString: String?, navModel: NavigationViewModel) { let context = PersistenceController.shared.backgroundContext guard let urlString else { @@ -332,7 +332,7 @@ public class PluginManager: ObservableObject { // The iOS version of Ferrite only runs deeplink actions @MainActor - public func runDeeplinkAction(_ action: Action, urlString: String?) { + func runDeeplinkAction(_ action: Action, urlString: String?) { guard let deeplink = action.deeplink, let urlString else { actionErrorAlertMessage = "Could not run action: \(action.name) since there is no deeplink to execute. Contact the action dev!" showActionErrorAlert.toggle() @@ -355,7 +355,7 @@ public class PluginManager: ObservableObject { } @MainActor - public func sendToKodi(urlString: String?, server: KodiServer) async { + func sendToKodi(urlString: String?, server: KodiServer) async { guard let urlString else { actionErrorAlertMessage = "Could not send URL to Kodi since there is no playback URL to send" showActionErrorAlert.toggle() @@ -380,7 +380,7 @@ public class PluginManager: ObservableObject { } } - public func installAction(actionJson: ActionJson?, doUpsert: Bool = false) async { + func installAction(actionJson: ActionJson?, doUpsert: Bool = false) async { guard let actionJson else { await logManager?.error("Action addition: No action present. Contact the app dev!") return @@ -448,7 +448,7 @@ public class PluginManager: ObservableObject { } } - public func installSource(sourceJson: SourceJson?, doUpsert: Bool = false) async { + func installSource(sourceJson: SourceJson?, doUpsert: Bool = false) async { guard let sourceJson else { await logManager?.error("Source addition: No source present. Contact the app dev!") return @@ -535,7 +535,7 @@ public class PluginManager: ObservableObject { } } - func addSourceApi(newSource: Source, apiJson: SourceApiJson) { + private func addSourceApi(newSource: Source, apiJson: SourceApiJson) { let backgroundContext = PersistenceController.shared.backgroundContext let newSourceApi = SourceApi(context: backgroundContext) @@ -571,7 +571,7 @@ public class PluginManager: ObservableObject { } // TODO: Migrate parser addition to a common protocol - func addJsonParser(newSource: Source, jsonParserJson: SourceJsonParserJson) { + private func addJsonParser(newSource: Source, jsonParserJson: SourceJsonParserJson) { let backgroundContext = PersistenceController.shared.backgroundContext let newSourceJsonParser = SourceJsonParser(context: backgroundContext) @@ -646,7 +646,7 @@ public class PluginManager: ObservableObject { newSource.jsonParser = newSourceJsonParser } - func addRssParser(newSource: Source, rssParserJson: SourceRssParserJson) { + private func addRssParser(newSource: Source, rssParserJson: SourceRssParserJson) { let backgroundContext = PersistenceController.shared.backgroundContext let newSourceRssParser = SourceRssParser(context: backgroundContext) @@ -725,7 +725,7 @@ public class PluginManager: ObservableObject { newSource.rssParser = newSourceRssParser } - func addHtmlParser(newSource: Source, htmlParserJson: SourceHtmlParserJson) { + private func addHtmlParser(newSource: Source, htmlParserJson: SourceHtmlParserJson) { let backgroundContext = PersistenceController.shared.backgroundContext let newSourceHtmlParser = SourceHtmlParser(context: backgroundContext) @@ -795,7 +795,7 @@ public class PluginManager: ObservableObject { // Adds a plugin list // Can move this to PersistenceController if needed - public func addPluginList(_ urlString: String, isSheet: Bool = false, existingPluginList: PluginList? = nil) async throws { + func addPluginList(_ urlString: String, isSheet: Bool = false, existingPluginList: PluginList? = nil) async throws { let backgroundContext = PersistenceController.shared.backgroundContext if urlString.isEmpty || !urlString.starts(with: "https://") && !urlString.starts(with: "http://") { diff --git a/Ferrite/ViewModels/ScrapingViewModel.swift b/Ferrite/ViewModels/ScrapingViewModel.swift index 94d30cc..964fcc8 100644 --- a/Ferrite/ViewModels/ScrapingViewModel.swift +++ b/Ferrite/ViewModels/ScrapingViewModel.swift @@ -27,18 +27,18 @@ class ScrapingViewModel: ObservableObject { // Only add results with valid magnet hashes to the search results array @MainActor - func updateSearchResults(newResults: [SearchResult]) { + private func updateSearchResults(newResults: [SearchResult]) { searchResults += newResults } @MainActor - func clearSearchResults() { + private func clearSearchResults() { searchResults = [] } @Published var currentSourceNames: Set = [] @MainActor - func updateCurrentSourceNames(_ newName: String) { + private func updateCurrentSourceNames(_ newName: String) { currentSourceNames.insert(newName) logManager?.updateIndeterminateToast( "Loading \(currentSourceNames.joined(separator: ", "))", @@ -47,7 +47,7 @@ class ScrapingViewModel: ObservableObject { } @MainActor - func removeCurrentSourceName(_ removedName: String) { + private func removeCurrentSourceName(_ removedName: String) { currentSourceNames.remove(removedName) logManager?.updateIndeterminateToast( "Loading \(currentSourceNames.joined(separator: ", "))", @@ -56,18 +56,18 @@ class ScrapingViewModel: ObservableObject { } @MainActor - func clearCurrentSourceNames() { + private func clearCurrentSourceNames() { currentSourceNames = [] logManager?.updateIndeterminateToast("Loading sources", cancelAction: nil) } // Utility function to print source specific errors - func sendSourceError(_ description: String) async { + private func sendSourceError(_ description: String) async { await logManager?.error(description, showToast: false) } // Substitutes the given string with an arbitrary parameter dictionary - func substituteParams(_ input: String, with params: [String: String]) -> String { + private func substituteParams(_ input: String, with params: [String: String]) -> String { let replaced = params.reduce(input) { result, param -> String in result.replacingOccurrences(of: "{\(param.key)}", with: param.value) } @@ -76,7 +76,7 @@ class ScrapingViewModel: ObservableObject { } // Cleans a SourceRequest's body and headers to be substituted - func cleanRequest(request: SourceRequest, params: [String: String]) -> SourceRequest { + private func cleanRequest(request: SourceRequest, params: [String: String]) -> SourceRequest { if let body = request.body { request.body = substituteParams(body, with: params) } @@ -88,7 +88,7 @@ class ScrapingViewModel: ObservableObject { return request } - public func scanSources(sources: [Source], searchText: String, debridManager: DebridManager) async { + func scanSources(sources: [Source], searchText: String, debridManager: DebridManager) async { await logManager?.info("Started scanning sources for query \"\(searchText)\"") if sources.isEmpty { @@ -166,7 +166,7 @@ class ScrapingViewModel: ObservableObject { } } - func executeParser(source: Source) async -> SearchRequestResult? { + private func executeParser(source: Source) async -> SearchRequestResult? { guard let website = source.website else { await logManager?.error("Scraping: The base URL could not be found for source \(source.name)") @@ -294,7 +294,7 @@ class ScrapingViewModel: ObservableObject { } // Checks the base URL for any website data then iterates through the fallback URLs - func handleUrls(website: String, replacedSearchUrl: String?, fallbackUrls: [String]?, sourceName: String, requestParams: SourceRequest?) async -> Data? { + private func handleUrls(website: String, replacedSearchUrl: String?, fallbackUrls: [String]?, sourceName: String, requestParams: SourceRequest?) async -> Data? { let fetchUrl = website + (replacedSearchUrl.map { $0 } ?? "") if let data = await fetchWebsiteData(urlString: fetchUrl, sourceName: sourceName, requestParams: requestParams) { return data @@ -312,7 +312,7 @@ class ScrapingViewModel: ObservableObject { return nil } - public func handleApiCredential(_ credential: SourceApiCredential, + private func handleApiCredential(_ credential: SourceApiCredential, replacement: String, searchUrl: String, apiUrl: String?, @@ -353,7 +353,7 @@ class ScrapingViewModel: ObservableObject { return nil } - public func fetchApiCredential(urlString: String, + private func fetchApiCredential(urlString: String, credential: SourceApiCredential, sourceName: String) async -> String? { @@ -399,7 +399,7 @@ class ScrapingViewModel: ObservableObject { } // Fetches the data for a URL - public func fetchWebsiteData(urlString: String, sourceName: String, requestParams: SourceRequest?) async -> Data? { + private func fetchWebsiteData(urlString: String, sourceName: String, requestParams: SourceRequest?) async -> Data? { guard let url = URL(string: urlString.trimmingCharacters(in: .whitespacesAndNewlines)) else { await sendSourceError("\(sourceName): Source doesn't contain a valid URL, contact the source dev!") @@ -446,7 +446,7 @@ class ScrapingViewModel: ObservableObject { } } - public func scrapeJson(source: Source, jsonData: Data) async -> SearchRequestResult? { + private func scrapeJson(source: Source, jsonData: Data) async -> SearchRequestResult? { guard let jsonParser = source.jsonParser else { return nil } @@ -521,7 +521,7 @@ class ScrapingViewModel: ObservableObject { } // TODO: Add regex parsing for API - public func parseJsonResult(_ result: JSON, + private func parseJsonResult(_ result: JSON, jsonParser: SourceJsonParser, source: Source, existingSearchResult: SearchResult? = nil) -> SearchResult? @@ -615,7 +615,7 @@ class ScrapingViewModel: ObservableObject { } // RSS feed scraper - public func scrapeRss(source: Source, rss: String) async -> SearchRequestResult? { + private func scrapeRss(source: Source, rss: String) async -> SearchRequestResult? { guard let rssParser = source.rssParser else { return nil } @@ -750,7 +750,7 @@ class ScrapingViewModel: ObservableObject { } // Complex query parsing for RSS scraping - func runRssComplexQuery(item: Element, + private func runRssComplexQuery(item: Element, query: String, attribute: String, discriminator: String?, @@ -783,7 +783,7 @@ class ScrapingViewModel: ObservableObject { } // HTML scraper - public func scrapeHtml(source: Source, website: String, html: String) async -> SearchRequestResult? { + private func scrapeHtml(source: Source, website: String, html: String) async -> SearchRequestResult? { guard let htmlParser = source.htmlParser else { return nil } @@ -955,7 +955,7 @@ class ScrapingViewModel: ObservableObject { } // Complex query parsing for HTML scraping - func runHtmlComplexQuery(row: Element, + private func runHtmlComplexQuery(row: Element, query: String, attribute: String, regexString: String?) throws -> String? @@ -980,7 +980,7 @@ class ScrapingViewModel: ObservableObject { } } - func runRegex(parsedValue: String, regexString: String) -> String? { + private func runRegex(parsedValue: String, regexString: String) -> String? { // TODO: Maybe dynamically parse flags let replacedRegexString = regexString .replacingOccurrences(of: "{query}", with: cleanedSearchText) @@ -1003,7 +1003,7 @@ class ScrapingViewModel: ObservableObject { } } - func parseSizeString(sizeString: String) -> String? { + private func parseSizeString(sizeString: String) -> String? { // Test if the string can be a full integer guard let size = Int(sizeString) else { return nil @@ -1025,7 +1025,7 @@ class ScrapingViewModel: ObservableObject { } } - func cleanApiCreds(api: SourceApi, sourceName: String) async { + private func cleanApiCreds(api: SourceApi, sourceName: String) async { let backgroundContext = PersistenceController.shared.backgroundContext let hasCredentials = api.clientId != nil || api.clientSecret != nil diff --git a/Ferrite/Views/CommonViews/HybridSecureField.swift b/Ferrite/Views/CommonViews/HybridSecureField.swift index 665623e..981859f 100644 --- a/Ferrite/Views/CommonViews/HybridSecureField.swift +++ b/Ferrite/Views/CommonViews/HybridSecureField.swift @@ -56,7 +56,7 @@ struct HybridSecureField: View { } extension HybridSecureField { - public func fieldDisabled(_ isFieldDisabled: Bool) -> Self { + func fieldDisabled(_ isFieldDisabled: Bool) -> Self { modifyViewProp { $0.isFieldDisabled = isFieldDisabled } } } diff --git a/Ferrite/Views/RepresentableViews/ExpandedSearchable.swift b/Ferrite/Views/RepresentableViews/ExpandedSearchable.swift index e361f07..58b1748 100644 --- a/Ferrite/Views/RepresentableViews/ExpandedSearchable.swift +++ b/Ferrite/Views/RepresentableViews/ExpandedSearchable.swift @@ -7,7 +7,7 @@ import SwiftUI -public extension View { +extension View { // A dismissAction must be added in the parent view struct due to lifecycle issues func expandedSearchable(text: Binding, isSearching: Binding? = nil,