Debrid: Add protocol for cloud handling

Cloud downloads and torrents are now unified under their own
protocol and models. Downloads and torrents are separated.

Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
kingbri 2024-06-03 15:46:18 -04:00
parent 37450ef979
commit 9e306eff1e
9 changed files with 204 additions and 129 deletions

View file

@ -10,6 +10,8 @@ import Foundation
// TODO: Fix errors
public class AllDebrid: PollingDebridSource {
public let id = "AllDebrid"
public let abbreviation = "AD"
public let website = "https://alldebrid.com"
public var authTask: Task<Void, Error>?
let baseApiUrl = "https://api.alldebrid.com/v4"
@ -203,28 +205,6 @@ public class AllDebrid: PollingDebridSource {
}
}
public func userMagnets() async throws -> [MagnetStatusData] {
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/status"))
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode(ADResponse<MagnetStatusResponse>.self, from: data).data
if rawResponse.magnets.isEmpty {
throw ADError.EmptyData
} else {
return rawResponse.magnets
}
}
public func deleteMagnet(magnetId: Int) async throws {
let queryItems = [
URLQueryItem(name: "id", value: String(magnetId))
]
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/delete", queryItems: queryItems))
try await performRequest(request: &request, requestName: #function)
}
public func unlockLink(lockedLink: String) async throws -> String {
let queryItems = [
URLQueryItem(name: "link", value: lockedLink)
@ -246,7 +226,40 @@ public class AllDebrid: PollingDebridSource {
try await performRequest(request: &request, requestName: #function)
}
public func savedLinks() async throws -> [SavedLink] {
// 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"))
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode(ADResponse<MagnetStatusResponse>.self, from: data).data
if rawResponse.magnets.isEmpty {
throw ADError.EmptyData
}
let torrents = rawResponse.magnets.map { magnetResponse in
DebridCloudTorrent(
torrentId: String(magnetResponse.id),
fileName: magnetResponse.filename,
status: magnetResponse.status,
hash: magnetResponse.hash,
links: magnetResponse.links.map { $0.link }
)
}
return torrents
}
public func deleteTorrent(torrentId: String) async throws {
let queryItems = [
URLQueryItem(name: "id", value: torrentId)
]
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/delete", queryItems: queryItems))
try await performRequest(request: &request, requestName: #function)
}
public func getUserDownloads() async throws -> [DebridCloudDownload] {
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/user/links"))
let data = try await performRequest(request: &request, requestName: #function)
@ -254,14 +267,22 @@ public class AllDebrid: PollingDebridSource {
if rawResponse.links.isEmpty {
throw ADError.EmptyData
} else {
return rawResponse.links
}
// The link is also the ID
let downloads = rawResponse.links.map { link in
DebridCloudDownload(
downloadId: link.link, fileName: link.filename, link: link.link
)
}
return downloads
}
public func deleteLink(link: String) async throws {
// The downloadId is actually the download link
public func deleteDownload(downloadId: String) async throws {
let queryItems = [
URLQueryItem(name: "link", value: link)
URLQueryItem(name: "link", value: downloadId)
]
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/user/links/delete", queryItems: queryItems))

View file

@ -9,6 +9,8 @@ import Foundation
public class Premiumize: OAuthDebridSource {
public let id = "Premiumize"
public let abbreviation = "PM"
public let website = "https://premiumize.me"
let baseAuthUrl = "https://www.premiumize.me/authorize"
let baseApiUrl = "https://www.premiumize.me/api"
@ -247,7 +249,7 @@ public class Premiumize: OAuthDebridSource {
try await performRequest(request: &request, requestName: #function)
}
func userItems() async throws -> [UserItem] {
public func getUserDownloads() async throws -> [DebridCloudDownload] {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/listall")!)
let data = try await performRequest(request: &request, requestName: #function)
@ -257,7 +259,12 @@ public class Premiumize: OAuthDebridSource {
throw PMError.EmptyData
}
return rawResponse.files
// The "link" is the ID for Premiumize
let downloads = rawResponse.files.map { file in
DebridCloudDownload(downloadId: file.id, fileName: file.name, link: file.id)
}
return downloads
}
func itemDetails(itemID: String) async throws -> ItemDetailsResponse {
@ -275,16 +282,25 @@ public class Premiumize: OAuthDebridSource {
return rawResponse
}
func deleteItem(itemID: String) async throws {
public 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")
var bodyComponents = URLComponents()
bodyComponents.queryItems = [URLQueryItem(name: "id", value: itemID)]
bodyComponents.queryItems = [URLQueryItem(name: "id", value: downloadId)]
request.httpBody = bodyComponents.query?.data(using: .utf8)
try await performRequest(request: &request, requestName: #function)
}
// No user torrents for Premiumize
public func getUserTorrents() async throws -> [DebridCloudTorrent] {
return []
}
public func deleteTorrent(torrentId: String) async throws {
return
}
}

View file

@ -9,6 +9,8 @@ import Foundation
public class RealDebrid: PollingDebridSource {
public let id = "RealDebrid"
public let abbreviation = "RD"
public let website = "https://real-debrid.com"
public var authTask: Task<Void, Error>?
let baseAuthUrl = "https://api.real-debrid.com/oauth/v2"
@ -357,24 +359,6 @@ public class RealDebrid: PollingDebridSource {
}
}
// Gets the user's torrent library
public func userTorrents() async throws -> [UserTorrentsResponse] {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents")!)
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode([UserTorrentsResponse].self, from: data)
return rawResponse
}
// Deletes a torrent download from RD
public func deleteTorrent(debridID: String) async throws {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/delete/\(debridID)")!)
request.httpMethod = "DELETE"
try await performRequest(request: &request, requestName: #function)
}
// Downloads link from selectFiles for playback
public func unrestrictLink(debridDownloadLink: String) async throws -> String {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/unrestrict/link")!)
@ -392,18 +376,48 @@ public class RealDebrid: PollingDebridSource {
return rawResponse.download
}
// Gets the user's torrent library
public func getUserTorrents() async throws -> [DebridCloudTorrent] {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents")!)
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode([UserTorrentsResponse].self, from: data)
let torrents = rawResponse.map { response in
DebridCloudTorrent(
torrentId: response.id,
fileName: response.filename,
status: response.status,
hash: response.hash,
links: response.links
)
}
return torrents
}
// Deletes a torrent download from RD
public func deleteTorrent(torrentId: String) async throws {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/delete/\(torrentId)")!)
request.httpMethod = "DELETE"
try await performRequest(request: &request, requestName: #function)
}
// Gets the user's downloads
public func userDownloads() async throws -> [UserDownloadsResponse] {
public func getUserDownloads() async throws -> [DebridCloudDownload] {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads")!)
let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode([UserDownloadsResponse].self, from: data)
let downloads = rawResponse.map { response in
DebridCloudDownload(downloadId: response.id, fileName: response.filename, link: response.download)
}
return rawResponse
return downloads
}
public func deleteDownload(debridID: String) async throws {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads/delete/\(debridID)")!)
public func deleteDownload(downloadId: String) async throws {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads/delete/\(downloadId)")!)
request.httpMethod = "DELETE"
try await performRequest(request: &request, requestName: #function)

View file

@ -7,7 +7,7 @@
import Foundation
public struct DebridIA: Sendable, Hashable {
public struct DebridIA: Hashable, Sendable {
let magnet: Magnet
let expiryTimeStamp: Double
var files: [DebridIAFile]
@ -27,4 +27,16 @@ public struct DebridIAFile: Hashable, Sendable {
}
}
public struct DebridCloudFile {}
public struct DebridCloudDownload: Hashable, Sendable {
let downloadId: String
let fileName: String
let link: String
}
public struct DebridCloudTorrent: Hashable, Sendable {
let torrentId: String
let fileName: String
let status: String
let hash: String
let links: [String]
}

View file

@ -10,6 +10,8 @@ import Foundation
public protocol DebridSource {
// ID of the service
var id: String { get }
var abbreviation: String { get }
var website: String { get }
// Common authentication functions
func setApiKey(_ key: String) -> Bool
@ -18,6 +20,14 @@ 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
// Fetches cloud information from the service
func getUserDownloads() async throws -> [DebridCloudDownload]
func getUserTorrents() async throws -> [DebridCloudTorrent]
// Deletes information from the service
func deleteDownload(downloadId: String) async throws
func deleteTorrent(torrentId: String) async throws
}
public protocol PollingDebridSource: DebridSource {

View file

@ -69,8 +69,8 @@ public class DebridManager: ObservableObject {
// TODO: Maybe make these generic?
// RealDebrid cloud variables
@Published var realDebridCloudTorrents: [RealDebrid.UserTorrentsResponse] = []
@Published var realDebridCloudDownloads: [RealDebrid.UserDownloadsResponse] = []
@Published var realDebridCloudTorrents: [DebridCloudTorrent] = []
@Published var realDebridCloudDownloads: [DebridCloudDownload] = []
var realDebridCloudTTL: Double = 0.0
// AllDebrid auth variables
@ -83,8 +83,8 @@ public class DebridManager: ObservableObject {
var selectedAllDebridFile: DebridIAFile?
// AllDebrid cloud variables
@Published var allDebridCloudMagnets: [AllDebrid.MagnetStatusData] = []
@Published var allDebridCloudLinks: [AllDebrid.SavedLink] = []
@Published var allDebridCloudMagnets: [DebridCloudTorrent] = []
@Published var allDebridCloudLinks: [DebridCloudDownload] = []
var allDebridCloudTTL: Double = 0.0
// Premiumize auth variables
@ -97,7 +97,7 @@ public class DebridManager: ObservableObject {
var selectedPremiumizeFile: DebridIAFile?
// Premiumize cloud variables
@Published var premiumizeCloudItems: [Premiumize.UserItem] = []
@Published var premiumizeCloudItems: [DebridCloudDownload] = []
var premiumizeCloudTTL: Double = 0.0
init() {
@ -651,8 +651,8 @@ public class DebridManager: ObservableObject {
public func fetchRdCloud(bypassTTL: Bool = false) async {
if bypassTTL || Date().timeIntervalSince1970 > realDebridCloudTTL {
do {
realDebridCloudTorrents = try await realDebrid.userTorrents()
realDebridCloudDownloads = try await realDebrid.userDownloads()
realDebridCloudTorrents = try await realDebrid.getUserTorrents()
realDebridCloudDownloads = try await realDebrid.getUserDownloads()
// 5 minutes
realDebridCloudTTL = Date().timeIntervalSince1970 + 300
@ -664,7 +664,7 @@ public class DebridManager: ObservableObject {
func deleteRdDownload(downloadID: String) async {
do {
try await realDebrid.deleteDownload(debridID: downloadID)
try await realDebrid.deleteDownload(downloadId: downloadID)
// Bypass TTL to get current RD values
await fetchRdCloud(bypassTTL: true)
@ -676,7 +676,7 @@ public class DebridManager: ObservableObject {
func deleteRdTorrent(torrentID: String? = nil, presentError: Bool = true) async {
do {
if let torrentID {
try await realDebrid.deleteTorrent(debridID: torrentID)
try await realDebrid.deleteTorrent(torrentId: torrentID)
} else {
throw RealDebrid.RDError.FailedRequest(description: "No torrent ID was provided")
}
@ -688,7 +688,7 @@ public class DebridManager: ObservableObject {
func checkRdUserDownloads(userTorrentLink: String) async -> String? {
do {
let existingLinks = realDebridCloudDownloads.first { $0.link == userTorrentLink }
if let existingLink = existingLinks?.download {
if let existingLink = existingLinks?.fileName {
return existingLink
} else {
return try await realDebrid.unrestrictLink(debridDownloadLink: userTorrentLink)
@ -761,8 +761,8 @@ public class DebridManager: ObservableObject {
public func fetchAdCloud(bypassTTL: Bool = false) async {
if bypassTTL || Date().timeIntervalSince1970 > allDebridCloudTTL {
do {
allDebridCloudMagnets = try await allDebrid.userMagnets()
allDebridCloudLinks = try await allDebrid.savedLinks()
allDebridCloudMagnets = try await allDebrid.getUserTorrents()
allDebridCloudLinks = try await allDebrid.getUserDownloads()
// 5 minutes
allDebridCloudTTL = Date().timeIntervalSince1970 + 300
@ -774,7 +774,7 @@ public class DebridManager: ObservableObject {
func deleteAdLink(link: String) async {
do {
try await allDebrid.deleteLink(link: link)
try await allDebrid.deleteDownload(downloadId: link)
await fetchAdCloud(bypassTTL: true)
} catch {
@ -782,9 +782,9 @@ public class DebridManager: ObservableObject {
}
}
func deleteAdMagnet(magnetId: Int) async {
func deleteAdMagnet(magnetId: String) async {
do {
try await allDebrid.deleteMagnet(magnetId: magnetId)
try await allDebrid.deleteTorrent(torrentId: magnetId)
await fetchAdCloud(bypassTTL: true)
} catch {
@ -817,7 +817,7 @@ public class DebridManager: ObservableObject {
public func fetchPmCloud(bypassTTL: Bool = false) async {
if bypassTTL || Date().timeIntervalSince1970 > premiumizeCloudTTL {
do {
let userItems = try await premiumize.userItems()
let userItems = try await premiumize.getUserDownloads()
withAnimation {
premiumizeCloudItems = userItems
}
@ -835,7 +835,7 @@ public class DebridManager: ObservableObject {
public func deletePmItem(id: String) async {
do {
try await premiumize.deleteItem(itemID: id)
try await premiumize.deleteDownload(downloadId: id)
// Bypass TTL to get current RD values
await fetchPmCloud(bypassTTL: true)

View file

@ -17,17 +17,17 @@ struct AllDebridCloudView: View {
var body: some View {
DisclosureGroup("Links") {
ForEach(debridManager.allDebridCloudLinks.filter {
searchText.isEmpty ? true : $0.filename.lowercased().contains(searchText.lowercased())
}, id: \.self) { downloadResponse in
Button(downloadResponse.filename) {
searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased())
}, id: \.self) { cloudDownload in
Button(cloudDownload.fileName) {
navModel.resultFromCloud = true
navModel.selectedTitle = downloadResponse.filename
debridManager.downloadUrl = downloadResponse.link
navModel.selectedTitle = cloudDownload.fileName
debridManager.downloadUrl = cloudDownload.link
PersistenceController.shared.createHistory(
HistoryEntryJson(
name: downloadResponse.filename,
url: downloadResponse.link,
name: cloudDownload.fileName,
url: cloudDownload.link,
source: DebridType.allDebrid.toString()
),
performSave: true
@ -43,9 +43,9 @@ struct AllDebridCloudView: View {
}
.onDelete { offsets in
for index in offsets {
if let savedLink = debridManager.allDebridCloudLinks[safe: index] {
if let cloudDownload = debridManager.allDebridCloudLinks[safe: index] {
Task {
await debridManager.deleteAdLink(link: savedLink.link)
await debridManager.deleteAdLink(link: cloudDownload.downloadId)
}
}
}
@ -54,26 +54,26 @@ struct AllDebridCloudView: View {
DisclosureGroup("Magnets") {
ForEach(debridManager.allDebridCloudMagnets.filter {
searchText.isEmpty ? true : $0.filename.lowercased().contains(searchText.lowercased())
}, id: \.id) { magnet in
searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased())
}, id: \.self) { cloudTorrent in
Button {
if magnet.status == "Ready", !magnet.links.isEmpty {
if cloudTorrent.status == "Ready", !cloudTorrent.links.isEmpty {
navModel.resultFromCloud = true
navModel.selectedTitle = magnet.filename
navModel.selectedTitle = cloudTorrent.fileName
var historyInfo = HistoryEntryJson(
name: magnet.filename,
name: cloudTorrent.fileName,
source: DebridType.allDebrid.toString()
)
Task {
if magnet.links.count == 1 {
if let lockedLink = magnet.links[safe: 0]?.link {
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: lockedLink)
if cloudTorrent.links.count == 1 {
if let torrentLink = cloudTorrent.links[safe: 0] {
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: torrentLink)
if !debridManager.downloadUrl.isEmpty {
historyInfo.url = debridManager.downloadUrl
PersistenceController.shared.createHistory(historyInfo, performSave: true)
pluginManager.runDefaultAction(
urlString: debridManager.downloadUrl,
navModel: navModel
@ -81,7 +81,7 @@ struct AllDebridCloudView: View {
}
}
} else {
let magnet = Magnet(hash: magnet.hash, link: nil)
let magnet = Magnet(hash: cloudTorrent.hash, link: nil)
// Do not clear old IA values
await debridManager.populateDebridIA([magnet])
@ -93,27 +93,29 @@ struct AllDebridCloudView: View {
}
}
}
} label: {
VStack(alignment: .leading, spacing: 10) {
Text(magnet.filename)
Text(cloudTorrent.fileName)
.font(.callout)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(4)
HStack {
Text(magnet.status)
Text(cloudTorrent.status.capitalizingFirstLetter())
Spacer()
DebridLabelView(cloudLinks: magnet.links.map(\.link))
DebridLabelView(cloudLinks: cloudTorrent.links)
}
.font(.caption)
}
}
.disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.9, animation: .easeOut(duration: 0.2))
.disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.7, animation: .easeOut(duration: 0.2))
.tint(.primary)
}
.onDelete { offsets in
for index in offsets {
if let magnet = debridManager.allDebridCloudMagnets[safe: index] {
if let cloudTorrent = debridManager.allDebridCloudMagnets[safe: index] {
Task {
await debridManager.deleteAdMagnet(magnetId: magnet.id)
await debridManager.deleteAdMagnet(magnetId: cloudTorrent.torrentId)
}
}
}

View file

@ -17,20 +17,20 @@ struct PremiumizeCloudView: View {
var body: some View {
DisclosureGroup("Items") {
ForEach(debridManager.premiumizeCloudItems.filter {
searchText.isEmpty ? true : $0.name.lowercased().contains(searchText.lowercased())
}, id: \.id) { item in
Button(item.name) {
searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased())
}, id: \.self) { cloudDownload in
Button(cloudDownload.fileName) {
Task {
navModel.resultFromCloud = true
navModel.selectedTitle = item.name
navModel.selectedTitle = cloudDownload.fileName
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: item.id)
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: cloudDownload.downloadId)
if !debridManager.downloadUrl.isEmpty {
PersistenceController.shared.createHistory(
HistoryEntryJson(
name: item.name,
url: debridManager.downloadUrl,
name: cloudDownload.fileName,
url: cloudDownload.link,
source: DebridType.premiumize.toString()
),
performSave: true
@ -48,9 +48,9 @@ struct PremiumizeCloudView: View {
}
.onDelete { offsets in
for index in offsets {
if let item = debridManager.premiumizeCloudItems[safe: index] {
if let cloudDownload = debridManager.premiumizeCloudItems[safe: index] {
Task {
await debridManager.deletePmItem(id: item.id)
await debridManager.deletePmItem(id: cloudDownload.downloadId)
}
}
}

View file

@ -18,17 +18,17 @@ struct RealDebridCloudView: View {
Group {
DisclosureGroup("Downloads") {
ForEach(debridManager.realDebridCloudDownloads.filter {
searchText.isEmpty ? true : $0.filename.lowercased().contains(searchText.lowercased())
}, id: \.self) { downloadResponse in
Button(downloadResponse.filename) {
searchText.isEmpty ? true : $0.fileName .lowercased().contains(searchText.lowercased())
}, id: \.self) { cloudDownload in
Button(cloudDownload.fileName) {
navModel.resultFromCloud = true
navModel.selectedTitle = downloadResponse.filename
debridManager.downloadUrl = downloadResponse.download
navModel.selectedTitle = cloudDownload.fileName
debridManager.downloadUrl = cloudDownload.link
PersistenceController.shared.createHistory(
HistoryEntryJson(
name: downloadResponse.filename,
url: downloadResponse.download,
name: cloudDownload.fileName,
url: cloudDownload.link,
source: DebridType.realDebrid.toString()
),
performSave: true
@ -44,9 +44,9 @@ struct RealDebridCloudView: View {
}
.onDelete { offsets in
for index in offsets {
if let downloadResponse = debridManager.realDebridCloudDownloads[safe: index] {
if let cloudDownload = debridManager.realDebridCloudDownloads[safe: index] {
Task {
await debridManager.deleteRdDownload(downloadID: downloadResponse.id)
await debridManager.deleteRdDownload(downloadID: cloudDownload.downloadId)
}
}
}
@ -55,21 +55,21 @@ struct RealDebridCloudView: View {
DisclosureGroup("Torrents") {
ForEach(debridManager.realDebridCloudTorrents.filter {
searchText.isEmpty ? true : $0.filename.lowercased().contains(searchText.lowercased())
}, id: \.self) { torrentResponse in
searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased())
}, id: \.self) { cloudTorrent in
Button {
if torrentResponse.status == "downloaded", !torrentResponse.links.isEmpty {
if cloudTorrent.status == "downloaded", !cloudTorrent.links.isEmpty {
navModel.resultFromCloud = true
navModel.selectedTitle = torrentResponse.filename
navModel.selectedTitle = cloudTorrent.fileName
var historyInfo = HistoryEntryJson(
name: torrentResponse.filename,
name: cloudTorrent.fileName,
source: DebridType.realDebrid.toString()
)
Task {
if torrentResponse.links.count == 1 {
if let torrentLink = torrentResponse.links[safe: 0] {
if cloudTorrent.links.count == 1 {
if let torrentLink = cloudTorrent.links[safe: 0] {
await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: torrentLink)
if !debridManager.downloadUrl.isEmpty {
historyInfo.url = debridManager.downloadUrl
@ -82,7 +82,7 @@ struct RealDebridCloudView: View {
}
}
} else {
let magnet = Magnet(hash: torrentResponse.hash, link: nil)
let magnet = Magnet(hash: cloudTorrent.hash, link: nil)
// Do not clear old IA values
await debridManager.populateDebridIA([magnet])
@ -96,15 +96,15 @@ struct RealDebridCloudView: View {
}
} label: {
VStack(alignment: .leading, spacing: 10) {
Text(torrentResponse.filename)
Text(cloudTorrent.fileName)
.font(.callout)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(4)
HStack {
Text(torrentResponse.status.capitalizingFirstLetter())
Text(cloudTorrent.status.capitalizingFirstLetter())
Spacer()
DebridLabelView(cloudLinks: torrentResponse.links)
DebridLabelView(cloudLinks: cloudTorrent.links)
}
.font(.caption)
}
@ -114,9 +114,9 @@ struct RealDebridCloudView: View {
}
.onDelete { offsets in
for index in offsets {
if let torrentResponse = debridManager.realDebridCloudTorrents[safe: index] {
if let cloudTorrent = debridManager.realDebridCloudTorrents[safe: index] {
Task {
await debridManager.deleteRdTorrent(torrentID: torrentResponse.id)
await debridManager.deleteRdTorrent(torrentID: cloudTorrent.torrentId)
}
}
}