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 // TODO: Fix errors
public class AllDebrid: PollingDebridSource { public class AllDebrid: PollingDebridSource {
public let id = "AllDebrid" public let id = "AllDebrid"
public let abbreviation = "AD"
public let website = "https://alldebrid.com"
public var authTask: Task<Void, Error>? public var authTask: Task<Void, Error>?
let baseApiUrl = "https://api.alldebrid.com/v4" 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 { public func unlockLink(lockedLink: String) async throws -> String {
let queryItems = [ let queryItems = [
URLQueryItem(name: "link", value: lockedLink) URLQueryItem(name: "link", value: lockedLink)
@ -246,7 +226,40 @@ public class AllDebrid: PollingDebridSource {
try await performRequest(request: &request, requestName: #function) 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")) var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/user/links"))
let data = try await performRequest(request: &request, requestName: #function) let data = try await performRequest(request: &request, requestName: #function)
@ -254,14 +267,22 @@ public class AllDebrid: PollingDebridSource {
if rawResponse.links.isEmpty { if rawResponse.links.isEmpty {
throw ADError.EmptyData 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 = [ 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)) 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 class Premiumize: OAuthDebridSource {
public let id = "Premiumize" public let id = "Premiumize"
public let abbreviation = "PM"
public let website = "https://premiumize.me"
let baseAuthUrl = "https://www.premiumize.me/authorize" let baseAuthUrl = "https://www.premiumize.me/authorize"
let baseApiUrl = "https://www.premiumize.me/api" let baseApiUrl = "https://www.premiumize.me/api"
@ -247,7 +249,7 @@ public class Premiumize: OAuthDebridSource {
try await performRequest(request: &request, requestName: #function) 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")!) var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/listall")!)
let data = try await performRequest(request: &request, requestName: #function) let data = try await performRequest(request: &request, requestName: #function)
@ -257,7 +259,12 @@ public class Premiumize: OAuthDebridSource {
throw PMError.EmptyData 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 { func itemDetails(itemID: String) async throws -> ItemDetailsResponse {
@ -275,16 +282,25 @@ public class Premiumize: OAuthDebridSource {
return rawResponse return rawResponse
} }
func deleteItem(itemID: String) async throws { public func deleteDownload(downloadId: String) async throws {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/delete")!) var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/delete")!)
request.httpMethod = "POST" request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
var bodyComponents = URLComponents() var bodyComponents = URLComponents()
bodyComponents.queryItems = [URLQueryItem(name: "id", value: itemID)] bodyComponents.queryItems = [URLQueryItem(name: "id", value: downloadId)]
request.httpBody = bodyComponents.query?.data(using: .utf8) request.httpBody = bodyComponents.query?.data(using: .utf8)
try await performRequest(request: &request, requestName: #function) 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 class RealDebrid: PollingDebridSource {
public let id = "RealDebrid" public let id = "RealDebrid"
public let abbreviation = "RD"
public let website = "https://real-debrid.com"
public var authTask: Task<Void, Error>? public var authTask: Task<Void, Error>?
let baseAuthUrl = "https://api.real-debrid.com/oauth/v2" 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 // Downloads link from selectFiles for playback
public func unrestrictLink(debridDownloadLink: String) async throws -> String { public func unrestrictLink(debridDownloadLink: String) async throws -> String {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/unrestrict/link")!) var request = URLRequest(url: URL(string: "\(baseApiUrl)/unrestrict/link")!)
@ -392,18 +376,48 @@ public class RealDebrid: PollingDebridSource {
return rawResponse.download 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 // 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")!) var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads")!)
let data = try await performRequest(request: &request, requestName: #function) let data = try await performRequest(request: &request, requestName: #function)
let rawResponse = try jsonDecoder.decode([UserDownloadsResponse].self, from: data) 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 { public func deleteDownload(downloadId: String) async throws {
var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads/delete/\(debridID)")!) var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads/delete/\(downloadId)")!)
request.httpMethod = "DELETE" request.httpMethod = "DELETE"
try await performRequest(request: &request, requestName: #function) try await performRequest(request: &request, requestName: #function)

View file

@ -7,7 +7,7 @@
import Foundation import Foundation
public struct DebridIA: Sendable, Hashable { public struct DebridIA: Hashable, Sendable {
let magnet: Magnet let magnet: Magnet
let expiryTimeStamp: Double let expiryTimeStamp: Double
var files: [DebridIAFile] 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 { public protocol DebridSource {
// ID of the service // ID of the service
var id: String { get } var id: String { get }
var abbreviation: String { get }
var website: String { get }
// Common authentication functions // Common authentication functions
func setApiKey(_ key: String) -> Bool func setApiKey(_ key: String) -> Bool
@ -18,6 +20,14 @@ public protocol DebridSource {
// Fetches a download link from a source // Fetches a download link from a source
// Include the instant availability information with the args // Include the instant availability information with the args
func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String 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 { public protocol PollingDebridSource: DebridSource {

View file

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

View file

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

View file

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