Debrid: Add common functions for existing magnets/downloads
This fixes cloud magnet fetching and also doesn't duplicate magnets inside the cloud service. Unrestricted links don't get duplicated, so no need to check against those. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
273403b711
commit
0caf8a8120
8 changed files with 88 additions and 94 deletions
|
|
@ -181,10 +181,18 @@ public class AllDebrid: PollingDebridSource {
|
|||
// 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)
|
||||
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?, userTorrents: [DebridCloudTorrent] = []) async throws -> String {
|
||||
let selectedMagnetId: String
|
||||
|
||||
if let existingMagnet = userTorrents.first(where: { $0.hash == magnet.hash && $0.status == "Ready" }) {
|
||||
selectedMagnetId = existingMagnet.torrentId
|
||||
} else {
|
||||
let magnetId = try await addMagnet(magnet: magnet)
|
||||
selectedMagnetId = String(magnetId)
|
||||
}
|
||||
|
||||
let lockedLink = try await fetchMagnetStatus(
|
||||
magnetId: magnetID,
|
||||
magnetId: selectedMagnetId,
|
||||
selectedIndex: iaFile?.fileId ?? 0
|
||||
)
|
||||
|
||||
|
|
@ -221,9 +229,9 @@ public class AllDebrid: PollingDebridSource {
|
|||
}
|
||||
}
|
||||
|
||||
public func fetchMagnetStatus(magnetId: Int, selectedIndex: Int?) async throws -> String {
|
||||
public func fetchMagnetStatus(magnetId: String, selectedIndex: Int?) async throws -> String {
|
||||
let queryItems = [
|
||||
URLQueryItem(name: "id", value: String(magnetId))
|
||||
URLQueryItem(name: "id", value: magnetId)
|
||||
]
|
||||
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/status", queryItems: queryItems))
|
||||
|
||||
|
|
@ -315,6 +323,11 @@ public class AllDebrid: PollingDebridSource {
|
|||
return downloads
|
||||
}
|
||||
|
||||
// Not used
|
||||
public func checkUserDownloads(link: String, userDownloads: [DebridCloudDownload]) async throws -> String? {
|
||||
nil
|
||||
}
|
||||
|
||||
// The downloadId is actually the download link
|
||||
public func deleteDownload(downloadId: String) async throws {
|
||||
let queryItems = [
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ public class Premiumize: OAuthDebridSource {
|
|||
// MARK: - Downloading
|
||||
|
||||
// Wrapper function to fetch a DDL link from the API
|
||||
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String {
|
||||
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?, userTorrents: [DebridCloudTorrent] = []) async throws -> String {
|
||||
// Store the item in PM cloud for later use
|
||||
try await createTransfer(magnet: magnet)
|
||||
|
||||
|
|
@ -316,6 +316,11 @@ public class Premiumize: OAuthDebridSource {
|
|||
return rawResponse
|
||||
}
|
||||
|
||||
public func checkUserDownloads(link: String, userDownloads: [DebridCloudDownload]) async throws -> String? {
|
||||
// Link is the cloud item ID
|
||||
try await itemDetails(itemID: link).link
|
||||
}
|
||||
|
||||
public func deleteDownload(downloadId: String) async throws {
|
||||
var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/delete")!)
|
||||
request.httpMethod = "POST"
|
||||
|
|
|
|||
|
|
@ -295,14 +295,22 @@ public class RealDebrid: PollingDebridSource {
|
|||
// 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)
|
||||
public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?, userTorrents: [DebridCloudTorrent] = []) async throws -> String {
|
||||
let selectedMagnetId: String
|
||||
|
||||
try await selectFiles(debridID: selectedMagnetId, fileIds: iaFile?.batchIds ?? [])
|
||||
// Don't queue a new job if the torrent already exists
|
||||
if let existingTorrent = userTorrents.first(where: { $0.hash == magnet.hash && $0.status == "downloaded" }) {
|
||||
selectedMagnetId = existingTorrent.torrentId
|
||||
} else {
|
||||
selectedMagnetId = try await addMagnet(magnet: magnet)
|
||||
|
||||
try await selectFiles(debridID: selectedMagnetId, fileIds: iaFile?.batchIds ?? [])
|
||||
}
|
||||
|
||||
// RealDebrid has 1 as the first ID for a file
|
||||
let torrentLink = try await torrentInfo(
|
||||
debridID: selectedMagnetId,
|
||||
selectedIndex: iaFile?.fileId ?? 0
|
||||
selectedFileId: iaFile?.fileId ?? 1
|
||||
)
|
||||
let downloadLink = try await unrestrictLink(debridDownloadLink: torrentLink)
|
||||
|
||||
|
|
@ -351,13 +359,13 @@ public class RealDebrid: PollingDebridSource {
|
|||
}
|
||||
|
||||
// Gets the info of a torrent from a given ID
|
||||
public func torrentInfo(debridID: String, selectedIndex: Int?) async throws -> String {
|
||||
public 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)
|
||||
let rawResponse = try jsonDecoder.decode(TorrentInfoResponse.self, from: data)
|
||||
let filteredFiles = rawResponse.files.filter { $0.selected == 1 }
|
||||
let linkIndex = filteredFiles.firstIndex(where: { $0.id == selectedIndex })
|
||||
let linkIndex = filteredFiles.firstIndex(where: { $0.id == selectedFileId })
|
||||
|
||||
// Let the user know if a torrent is downloading
|
||||
if let torrentLink = rawResponse.links[safe: linkIndex ?? -1], rawResponse.status == "downloaded" {
|
||||
|
|
@ -429,6 +437,11 @@ public class RealDebrid: PollingDebridSource {
|
|||
return downloads
|
||||
}
|
||||
|
||||
// Not used
|
||||
public func checkUserDownloads(link: String, userDownloads: [DebridCloudDownload]) -> String? {
|
||||
nil
|
||||
}
|
||||
|
||||
public func deleteDownload(downloadId: String) async throws {
|
||||
var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads/delete/\(downloadId)")!)
|
||||
request.httpMethod = "DELETE"
|
||||
|
|
|
|||
|
|
@ -21,14 +21,16 @@ public protocol DebridSource {
|
|||
|
||||
// Fetches a download link from a source
|
||||
// Include the instant availability information with the args
|
||||
func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String
|
||||
// Torrents also checked here
|
||||
func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?, userTorrents: [DebridCloudTorrent]) async throws -> String
|
||||
|
||||
// Fetches cloud information from the service
|
||||
// User downloads functions
|
||||
func getUserDownloads() async throws -> [DebridCloudDownload]
|
||||
func getUserTorrents() async throws -> [DebridCloudTorrent]
|
||||
|
||||
// Deletes information from the service
|
||||
func checkUserDownloads(link: String, userDownloads: [DebridCloudDownload]) async throws -> String?
|
||||
func deleteDownload(downloadId: String) async throws
|
||||
|
||||
// User torrent functions
|
||||
func getUserTorrents() async throws -> [DebridCloudTorrent]
|
||||
func deleteTorrent(torrentId: String) async throws
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -559,42 +559,21 @@ public class DebridManager: ObservableObject {
|
|||
|
||||
switch selectedDebridType {
|
||||
case .realDebrid:
|
||||
await fetchRdDownload(magnet: magnet, existingLink: cloudInfo)
|
||||
await fetchRdDownload(magnet: magnet, cloudInfo: cloudInfo)
|
||||
case .allDebrid:
|
||||
await fetchAdDownload(magnet: magnet, existingLockedLink: cloudInfo)
|
||||
await fetchAdDownload(magnet: magnet, cloudInfo: cloudInfo)
|
||||
case .premiumize:
|
||||
await fetchPmDownload(magnet: magnet, cloudItemId: cloudInfo)
|
||||
await fetchPmDownload(magnet: magnet, cloudInfo: cloudInfo)
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func fetchRdDownload(magnet: Magnet?, existingLink: String?) async {
|
||||
// If an existing link is passed in args, set it to that. Otherwise, find one from RD cloud.
|
||||
/*
|
||||
let torrentLink: String?
|
||||
if let existingLink {
|
||||
torrentLink = existingLink
|
||||
} else {
|
||||
// Bypass the TTL for up to date information
|
||||
await fetchRdCloud(bypassTTL: true)
|
||||
|
||||
let existingTorrent = realDebridCloudTorrents.first { $0.hash == selectedRealDebridItem?.magnet.hash && $0.status == "downloaded" }
|
||||
torrentLink = existingTorrent?.links[safe: selectedRealDebridFile?.batchFileIndex ?? 0]
|
||||
}
|
||||
*/
|
||||
|
||||
func fetchRdDownload(magnet: Magnet?, cloudInfo: String?) async {
|
||||
do {
|
||||
// If the links match from a user's downloads, no need to re-run a download
|
||||
/*
|
||||
if let torrentLink,
|
||||
let downloadLink = await checkRdUserDownloads(userTorrentLink: torrentLink)
|
||||
{
|
||||
downloadUrl = downloadLink
|
||||
} else */
|
||||
if let magnet {
|
||||
let downloadLink = try await realDebrid.getDownloadLink(
|
||||
magnet: magnet, ia: selectedRealDebridItem, iaFile: selectedRealDebridFile
|
||||
magnet: magnet, ia: selectedRealDebridItem, iaFile: selectedRealDebridFile, userTorrents: realDebridCloudTorrents
|
||||
)
|
||||
|
||||
// Update the UI
|
||||
|
|
@ -612,7 +591,9 @@ public class DebridManager: ObservableObject {
|
|||
default:
|
||||
await sendDebridError(error, prefix: "RealDebrid download error", cancelString: "Download cancelled")
|
||||
|
||||
// await deleteRdTorrent(torrentID: selectedRealDebridID, presentError: false)
|
||||
if let torrentId = selectedRealDebridID {
|
||||
try? await realDebrid.deleteTorrent(torrentId: torrentId)
|
||||
}
|
||||
}
|
||||
|
||||
logManager?.hideIndeterminateToast()
|
||||
|
|
@ -685,32 +666,11 @@ public class DebridManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func fetchAdDownload(magnet: Magnet?, existingLockedLink: String?) async {
|
||||
// If an existing link is passed in args, set it to that. Otherwise, find one from AD cloud.
|
||||
/*
|
||||
let lockedLink: String?
|
||||
if let existingLockedLink {
|
||||
lockedLink = existingLockedLink
|
||||
} else {
|
||||
// Bypass the TTL for up to date information
|
||||
await fetchAdCloud(bypassTTL: true)
|
||||
|
||||
let existingMagnet = allDebridCloudMagnets.first { $0.hash == selectedAllDebridItem?.magnet.hash && $0.status == "Ready" }
|
||||
lockedLink = existingMagnet?.links[safe: selectedAllDebridFile?.fileId ?? 0]?.link
|
||||
}
|
||||
*/
|
||||
|
||||
func fetchAdDownload(magnet: Magnet?, cloudInfo: String?) async {
|
||||
do {
|
||||
/*
|
||||
if let lockedLink,
|
||||
let unlockedLink = await checkAdUserLinks(lockedLink: lockedLink)
|
||||
{
|
||||
downloadUrl = unlockedLink
|
||||
} else if let magnet {
|
||||
*/
|
||||
if let magnet {
|
||||
let downloadLink = try await allDebrid.getDownloadLink(
|
||||
magnet: magnet, ia: selectedAllDebridItem, iaFile: selectedAllDebridFile
|
||||
magnet: magnet, ia: selectedAllDebridItem, iaFile: selectedAllDebridFile, userTorrents: allDebridCloudMagnets
|
||||
)
|
||||
|
||||
// Update UI
|
||||
|
|
@ -777,11 +737,14 @@ public class DebridManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func fetchPmDownload(magnet: Magnet?, cloudItemId: String? = nil) async {
|
||||
func fetchPmDownload(magnet: Magnet?, cloudInfo: String? = nil) async {
|
||||
do {
|
||||
if let cloudItemId {
|
||||
downloadUrl = try await premiumize.itemDetails(itemID: cloudItemId).link
|
||||
} else if let magnet {
|
||||
if let cloudInfo {
|
||||
downloadUrl = try await premiumize.checkUserDownloads(link: cloudInfo, userDownloads: premiumizeCloudItems) ?? ""
|
||||
return
|
||||
}
|
||||
|
||||
if let magnet {
|
||||
let downloadLink = try await premiumize.getDownloadLink(
|
||||
magnet: magnet, ia: selectedPremiumizeItem, iaFile: selectedPremiumizeFile
|
||||
)
|
||||
|
|
|
|||
|
|
@ -67,9 +67,14 @@ struct AllDebridCloudView: View {
|
|||
)
|
||||
|
||||
Task {
|
||||
if cloudTorrent.links.count == 1 {
|
||||
if let torrentLink = cloudTorrent.links[safe: 0] {
|
||||
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: torrentLink)
|
||||
let magnet = Magnet(hash: cloudTorrent.hash, link: nil)
|
||||
await debridManager.populateDebridIA([magnet])
|
||||
if debridManager.selectDebridResult(magnet: magnet) {
|
||||
// Is this a batch?
|
||||
|
||||
if cloudTorrent.links.count == 1 {
|
||||
await debridManager.fetchDebridDownload(magnet: magnet)
|
||||
|
||||
if !debridManager.downloadUrl.isEmpty {
|
||||
historyInfo.url = debridManager.downloadUrl
|
||||
PersistenceController.shared.createHistory(historyInfo, performSave: true)
|
||||
|
|
@ -79,14 +84,8 @@ struct AllDebridCloudView: View {
|
|||
navModel: navModel
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let magnet = Magnet(hash: cloudTorrent.hash, link: nil)
|
||||
|
||||
// Do not clear old IA values
|
||||
await debridManager.populateDebridIA([magnet])
|
||||
|
||||
if debridManager.selectDebridResult(magnet: magnet) {
|
||||
} else {
|
||||
navModel.selectedMagnet = magnet
|
||||
navModel.selectedHistoryInfo = historyInfo
|
||||
navModel.currentChoiceSheet = .batch
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,9 +68,14 @@ struct RealDebridCloudView: View {
|
|||
)
|
||||
|
||||
Task {
|
||||
if cloudTorrent.links.count == 1 {
|
||||
if let torrentLink = cloudTorrent.links[safe: 0] {
|
||||
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: torrentLink)
|
||||
let magnet = Magnet(hash: cloudTorrent.hash, link: nil)
|
||||
await debridManager.populateDebridIA([magnet])
|
||||
if debridManager.selectDebridResult(magnet: magnet) {
|
||||
// Is this a batch?
|
||||
|
||||
if cloudTorrent.links.count == 1 {
|
||||
await debridManager.fetchDebridDownload(magnet: magnet)
|
||||
|
||||
if !debridManager.downloadUrl.isEmpty {
|
||||
historyInfo.url = debridManager.downloadUrl
|
||||
PersistenceController.shared.createHistory(historyInfo, performSave: true)
|
||||
|
|
@ -80,14 +85,8 @@ struct RealDebridCloudView: View {
|
|||
navModel: navModel
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let magnet = Magnet(hash: cloudTorrent.hash, link: nil)
|
||||
|
||||
// Do not clear old IA values
|
||||
await debridManager.populateDebridIA([magnet])
|
||||
|
||||
if debridManager.selectDebridResult(magnet: magnet) {
|
||||
} else {
|
||||
navModel.selectedMagnet = magnet
|
||||
navModel.selectedHistoryInfo = historyInfo
|
||||
navModel.currentChoiceSheet = .batch
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ struct BatchChoiceView: View {
|
|||
// Common function to communicate betwen VMs and queue/display a download
|
||||
func queueCommonDownload(fileName: String) {
|
||||
debridManager.currentDebridTask = Task {
|
||||
await debridManager.fetchDebridDownload(magnet: navModel.resultFromCloud ? nil : navModel.selectedMagnet)
|
||||
await debridManager.fetchDebridDownload(magnet: navModel.selectedMagnet)
|
||||
|
||||
if !debridManager.downloadUrl.isEmpty {
|
||||
try? await Task.sleep(seconds: 1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue