Debrid: Order API implementations

Reorder everything and mark off where different functions are located.

Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
kingbri 2024-06-03 16:00:40 -04:00
parent 9e306eff1e
commit 37ef64224e
3 changed files with 102 additions and 72 deletions

View file

@ -19,6 +19,8 @@ public class AllDebrid: PollingDebridSource {
let jsonDecoder = JSONDecoder()
// MARK: - Auth
// Fetches information for PIN auth
public func getAuthUrl() async throws -> URL {
let url = try buildRequestURL(urlString: "\(baseApiUrl)/pin/get")
@ -106,6 +108,8 @@ public class AllDebrid: PollingDebridSource {
UserDefaults.standard.removeObject(forKey: "AllDebrid.UseManualKey")
}
// MARK: - Common request
// Wrapper request function which matches the responses and returns data
@discardableResult private func performRequest(request: inout URLRequest, requestName: String) async throws -> Data {
guard let token = getToken() else {
@ -147,6 +151,34 @@ public class AllDebrid: PollingDebridSource {
}
}
// MARK: - Instant availability
public func instantAvailability(magnets: [Magnet]) async throws -> [DebridIA] {
let queryItems = magnets.map { URLQueryItem(name: "magnets[]", value: $0.hash) }
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/instant", queryItems: queryItems))
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode(ADResponse<InstantAvailabilityResponse>.self, from: data).data
let filteredMagnets = rawResponse.magnets.filter { $0.instant == true && $0.files != nil }
let availableHashes = filteredMagnets.map { magnetResp in
// Force unwrap is OK here since the filter caught any nil values
let files = magnetResp.files!.enumerated().map { index, magnetFile in
DebridIAFile(fileId: index, name: magnetFile.name)
}
return DebridIA(
magnet: Magnet(hash: magnetResp.hash, link: magnetResp.magnet),
expiryTimeStamp: Date().timeIntervalSince1970 + 300,
files: files
)
}
return availableHashes
}
// MARK: - Downloading
// Wrapper function to fetch a download link from the API
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String {
let magnetID = try await addMagnet(magnet: magnet)
@ -226,6 +258,8 @@ public class AllDebrid: PollingDebridSource {
try await performRequest(request: &request, requestName: #function)
}
// MARK: - Cloud methods
// Referred to as "User magnets" in AllDebrid's API
public func getUserTorrents() async throws -> [DebridCloudTorrent] {
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/status"))
@ -288,28 +322,4 @@ public class AllDebrid: PollingDebridSource {
try await performRequest(request: &request, requestName: #function)
}
public func instantAvailability(magnets: [Magnet]) async throws -> [DebridIA] {
let queryItems = magnets.map { URLQueryItem(name: "magnets[]", value: $0.hash) }
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/instant", queryItems: queryItems))
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode(ADResponse<InstantAvailabilityResponse>.self, from: data).data
let filteredMagnets = rawResponse.magnets.filter { $0.instant == true && $0.files != nil }
let availableHashes = filteredMagnets.map { magnetResp in
// Force unwrap is OK here since the filter caught any nil values
let files = magnetResp.files!.enumerated().map { index, magnetFile in
DebridIAFile(fileId: index, name: magnetFile.name)
}
return DebridIA(
magnet: Magnet(hash: magnetResp.hash, link: magnetResp.magnet),
expiryTimeStamp: Date().timeIntervalSince1970 + 300,
files: files
)
}
return availableHashes
}
}

View file

@ -18,6 +18,8 @@ public class Premiumize: OAuthDebridSource {
let jsonDecoder = JSONDecoder()
// MARK: - Auth
public func getAuthUrl() throws -> URL {
var urlComponents = URLComponents(string: baseAuthUrl)!
urlComponents.queryItems = [
@ -68,6 +70,8 @@ public class Premiumize: OAuthDebridSource {
UserDefaults.standard.removeObject(forKey: "Premiumize.UseManualKey")
}
// MARK: - Common request
// Wrapper request function which matches the responses and returns data
@discardableResult private func performRequest(request: inout URLRequest, requestName: String) async throws -> Data {
guard let token = getToken() else {
@ -112,54 +116,7 @@ public class Premiumize: OAuthDebridSource {
}
}
// 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] {
let availableMagnets = try await withThrowingTaskGroup(of: [Magnet].self) { group in
for chunk in magnets.chunked(into: 100) {
group.addTask {
try await self.checkCache(magnets: chunk)
}
}
var chunkedMagnets: [Magnet] = []
for try await magnetArray in group {
chunkedMagnets += magnetArray
}
return chunkedMagnets
}
return availableMagnets
}
// Parent function for initial checking of the cache
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 {
throw PMError.InvalidUrl
}
var request = URLRequest(url: url)
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode(CacheCheckResponse.self, from: data)
if rawResponse.response.isEmpty {
throw PMError.EmptyData
} else {
let availableMagnets = magnets.enumerated().compactMap { index, magnet in
if rawResponse.response[safe: index] == true {
return magnet
} else {
return nil
}
}
return availableMagnets
}
}
// MARK: - Instant availability
// Function to divide and execute DDL endpoint requests in parallel
// Calls this for 10 requests at a time to not overwhelm API servers
@ -218,6 +175,57 @@ public class Premiumize: OAuthDebridSource {
}
}
// 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] {
let availableMagnets = try await withThrowingTaskGroup(of: [Magnet].self) { group in
for chunk in magnets.chunked(into: 100) {
group.addTask {
try await self.checkCache(magnets: chunk)
}
}
var chunkedMagnets: [Magnet] = []
for try await magnetArray in group {
chunkedMagnets += magnetArray
}
return chunkedMagnets
}
return availableMagnets
}
// Parent function for initial checking of the cache
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 {
throw PMError.InvalidUrl
}
var request = URLRequest(url: url)
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode(CacheCheckResponse.self, from: data)
if rawResponse.response.isEmpty {
throw PMError.EmptyData
} else {
let availableMagnets = magnets.enumerated().compactMap { index, magnet in
if rawResponse.response[safe: index] == true {
return magnet
} else {
return nil
}
}
return availableMagnets
}
}
// MARK: - Downloading
// Wrapper function to fetch a DDL link from the API
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String {
// Store the item in PM cloud for later use
@ -249,6 +257,8 @@ public class Premiumize: OAuthDebridSource {
try await performRequest(request: &request, requestName: #function)
}
// MARK: - Cloud methods
public func getUserDownloads() async throws -> [DebridCloudDownload] {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/listall")!)

View file

@ -29,6 +29,8 @@ public class RealDebrid: PollingDebridSource {
UserDefaults.standard.removeObject(forKey: forKey)
}
// MARK: - Auth
// Fetches the device code from RD
public func getAuthUrl() async throws -> URL {
var urlComponents = URLComponents(string: "\(baseAuthUrl)/device/code")!
@ -189,6 +191,8 @@ public class RealDebrid: PollingDebridSource {
}
}
// MARK: - Common request
// Wrapper request function which matches the responses and returns data
@discardableResult private func performRequest(request: inout URLRequest, requestName: String) async throws -> Data {
guard let token = await fetchToken() else {
@ -213,6 +217,8 @@ public class RealDebrid: PollingDebridSource {
}
}
// MARK: - Instant availability
// Checks if the magnet is streamable on RD
public func instantAvailability(magnets: [Magnet]) async throws -> [DebridIA] {
var availableHashes: [DebridIA] = []
@ -284,6 +290,8 @@ public class RealDebrid: PollingDebridSource {
return availableHashes
}
// MARK: - Downloading
// Wrapper function to fetch a download link from the API
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String {
let selectedMagnetId = try await addMagnet(magnet: magnet)
@ -376,6 +384,8 @@ public class RealDebrid: PollingDebridSource {
return rawResponse.download
}
// MARK: - Cloud methods
// Gets the user's torrent library
public func getUserTorrents() async throws -> [DebridCloudTorrent] {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents")!)