diff --git a/python_rpc/http_downloader.py b/python_rpc/http_downloader.py index 40e30ccd..71e4b57e 100644 --- a/python_rpc/http_downloader.py +++ b/python_rpc/http_downloader.py @@ -11,11 +11,12 @@ class HttpDownloader: ) ) - def start_download(self, url: str, save_path: str, header: str): + def start_download(self, url: str, save_path: str, header: str, out: str = None): if self.download: self.aria2.resume([self.download]) else: - downloads = self.aria2.add(url, options={"header": header, "dir": save_path}) + downloads = self.aria2.add(url, options={"header": header, "dir": save_path, "out": out}) + self.download = downloads[0] def pause_download(self): diff --git a/python_rpc/main.py b/python_rpc/main.py index cc28d623..2deb2029 100644 --- a/python_rpc/main.py +++ b/python_rpc/main.py @@ -28,14 +28,14 @@ if start_download_payload: torrent_downloader = TorrentDownloader(torrent_session) downloads[initial_download['game_id']] = torrent_downloader try: - torrent_downloader.start_download(initial_download['url'], initial_download['save_path'], "") + torrent_downloader.start_download(initial_download['url'], initial_download['save_path']) except Exception as e: print("Error starting torrent download", e) else: http_downloader = HttpDownloader() downloads[initial_download['game_id']] = http_downloader try: - http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header')) + http_downloader.start_download(initial_download['url'], initial_download['save_path'], initial_download.get('header'), initial_download.get("out")) except Exception as e: print("Error starting http download", e) @@ -45,7 +45,7 @@ if start_seeding_payload: torrent_downloader = TorrentDownloader(torrent_session, lt.torrent_flags.upload_mode) downloads[seed['game_id']] = torrent_downloader try: - torrent_downloader.start_download(seed['url'], seed['save_path'], "") + torrent_downloader.start_download(seed['url'], seed['save_path']) except Exception as e: print("Error starting seeding", e) @@ -140,18 +140,18 @@ def action(): if url.startswith('magnet'): if existing_downloader and isinstance(existing_downloader, TorrentDownloader): - existing_downloader.start_download(url, data['save_path'], "") + existing_downloader.start_download(url, data['save_path']) else: torrent_downloader = TorrentDownloader(torrent_session) downloads[game_id] = torrent_downloader - torrent_downloader.start_download(url, data['save_path'], "") + torrent_downloader.start_download(url, data['save_path']) else: if existing_downloader and isinstance(existing_downloader, HttpDownloader): - existing_downloader.start_download(url, data['save_path'], data.get('header')) + existing_downloader.start_download(url, data['save_path'], data.get('header'), data.get('out')) else: http_downloader = HttpDownloader() downloads[game_id] = http_downloader - http_downloader.start_download(url, data['save_path'], data.get('header')) + http_downloader.start_download(url, data['save_path'], data.get('header'), data.get('out')) downloading_game_id = game_id @@ -167,7 +167,7 @@ def action(): elif action == 'resume_seeding': torrent_downloader = TorrentDownloader(torrent_session, lt.torrent_flags.upload_mode) downloads[game_id] = torrent_downloader - torrent_downloader.start_download(data['url'], data['save_path'], "") + torrent_downloader.start_download(data['url'], data['save_path']) elif action == 'pause_seeding': downloader = downloads.get(game_id) if downloader: diff --git a/python_rpc/torrent_downloader.py b/python_rpc/torrent_downloader.py index ca4c2fa8..8de8764e 100644 --- a/python_rpc/torrent_downloader.py +++ b/python_rpc/torrent_downloader.py @@ -102,7 +102,7 @@ class TorrentDownloader: "http://bvarf.tracker.sh:2086/announce", ] - def start_download(self, magnet: str, save_path: str, header: str): + def start_download(self, magnet: str, save_path: str): params = {'url': magnet, 'save_path': save_path, 'trackers': self.trackers, 'flags': self.flags} self.torrent_handle = self.session.add_torrent(params) self.torrent_handle.resume() diff --git a/src/locales/ar/translation.json b/src/locales/ar/translation.json index 15a24a7d..a12b3559 100644 --- a/src/locales/ar/translation.json +++ b/src/locales/ar/translation.json @@ -236,13 +236,13 @@ "behavior": "السلوك", "download_sources": "مصادر التنزيل", "language": "اللغة", - "real_debrid_api_token": "رمز API", + "api_token": "رمز API", "enable_real_debrid": "تفعيل Real-Debrid", "real_debrid_description": "Real-Debrid هو أداة تنزيل غير مقيدة تتيح لك تنزيل الملفات بسرعة، مقيدة فقط بسرعة الإنترنت لديك.", - "real_debrid_invalid_token": "رمز API غير صالح", - "real_debrid_api_token_hint": "يمكنك الحصول على رمز API الخاص بك <0>هنا", + "debrid_invalid_token": "رمز API غير صالح", + "debrid_api_token_hint": "يمكنك الحصول على رمز API الخاص بك <0>هنا", "real_debrid_free_account_error": "الحساب \"{{username}}\" هو حساب مجاني. يرجى الاشتراك في Real-Debrid", - "real_debrid_linked_message": "تم ربط الحساب \"{{username}}\"", + "debrid_linked_message": "تم ربط الحساب \"{{username}}\"", "save_changes": "حفظ التغييرات", "changes_saved": "تم حفظ التغييرات بنجاح", "download_sources_description": "سيقوم Hydra بجلب روابط التنزيل من هذه المصادر. يجب أن يكون عنوان URL المصدر رابطًا مباشرًا لملف .json يحتوي على روابط التنزيل.", diff --git a/src/locales/bg/translation.json b/src/locales/bg/translation.json index b68e60da..857d3ed4 100644 --- a/src/locales/bg/translation.json +++ b/src/locales/bg/translation.json @@ -230,13 +230,13 @@ "behavior": "Поведение", "download_sources": "Източници за изтегляне", "language": "Език", - "real_debrid_api_token": "API Токен", + "api_token": "API Токен", "enable_real_debrid": "Включи Real-Debrid", "real_debrid_description": "Real-Debrid е неограничен даунлоудър, който ви позволява бързо да изтегляте файлове, ограничени само от скоростта на интернет..", - "real_debrid_invalid_token": "Невалиден API токен", - "real_debrid_api_token_hint": "Вземете своя API токен <0>тук", + "debrid_invalid_token": "Невалиден API токен", + "debrid_api_token_hint": "Вземете своя API токен <0>тук", "real_debrid_free_account_error": "Акаунтът \"{{username}}\" е безплатен акаунт. Моля абонирай се за Real-Debrid", - "real_debrid_linked_message": "Акаунтът \"{{username}}\" е свързан", + "debrid_linked_message": "Акаунтът \"{{username}}\" е свързан", "save_changes": "Запази промените", "changes_saved": "Промените са успешно запазни", "download_sources_description": "Hydra ще извлича връзките за изтегляне от тези източници. URL адресът на източника трябва да е директна връзка към .json файл, съдържащ връзките за изтегляне.", diff --git a/src/locales/ca/translation.json b/src/locales/ca/translation.json index acf4b3c7..6d689f2b 100644 --- a/src/locales/ca/translation.json +++ b/src/locales/ca/translation.json @@ -161,13 +161,13 @@ "behavior": "Comportament", "download_sources": "Fonts de descàrrega", "language": "Idioma", - "real_debrid_api_token": "Testimoni API", + "api_token": "Testimoni API", "enable_real_debrid": "Activa el Real Debrid", "real_debrid_description": "Real-Debrid és un programa de descàrrega sense restriccions que us permet descarregar fitxers a l'instant i al màxim de la vostra velocitat d'Internet.", - "real_debrid_invalid_token": "Invalida el testimoni de l'API", - "real_debrid_api_token_hint": "Pots obtenir la teva clau de l'API <0>aquí.", + "debrid_invalid_token": "Invalida el testimoni de l'API", + "debrid_api_token_hint": "Pots obtenir la teva clau de l'API <0>aquí.", "real_debrid_free_account_error": "L'usuari \"{{username}}\" és un compte gratuït. Si us plau subscriu-te a Real-Debrid", - "real_debrid_linked_message": "Compte \"{{username}}\" vinculat", + "debrid_linked_message": "Compte \"{{username}}\" vinculat", "save_changes": "Desa els canvis", "changes_saved": "Els canvis s'han desat correctament", "download_sources_description": "Hydra buscarà els enllaços de descàrrega d'aquestes fonts. L'URL d'origen ha de ser un enllaç directe a un fitxer .json que contingui els enllaços de descàrrega.", diff --git a/src/locales/cs/translation.json b/src/locales/cs/translation.json index c1291444..b3543f94 100644 --- a/src/locales/cs/translation.json +++ b/src/locales/cs/translation.json @@ -214,13 +214,13 @@ "behavior": "Chování", "download_sources": "Zdroje stahování", "language": "Jazyk", - "real_debrid_api_token": "API Token", + "api_token": "API Token", "enable_real_debrid": "Povolit Real-Debrid", "real_debrid_description": "Real-Debrid je neomezený správce stahování, který umožňuje stahovat soubory v nejvyšší rychlosti vašeho internetu.", - "real_debrid_invalid_token": "Neplatný API token", - "real_debrid_api_token_hint": "API token můžeš sehnat <0>zde", + "debrid_invalid_token": "Neplatný API token", + "debrid_api_token_hint": "API token můžeš sehnat <0>zde", "real_debrid_free_account_error": "Účet \"{{username}}\" má základní úroveň. Prosím předplaťte si Real-Debrid", - "real_debrid_linked_message": "Účet \"{{username}}\" je propojen", + "debrid_linked_message": "Účet \"{{username}}\" je propojen", "save_changes": "Uložit změny", "changes_saved": "Změny úspěšně uloženy", "download_sources_description": "Hydra bude odsud sbírat soubory. Zdrojový odkaz musí být .json soubor obsahující odkazy na soubory.", diff --git a/src/locales/da/translation.json b/src/locales/da/translation.json index 711c81a3..9a7c700f 100644 --- a/src/locales/da/translation.json +++ b/src/locales/da/translation.json @@ -177,13 +177,13 @@ "behavior": "Opførsel", "download_sources": "Download kilder", "language": "Sprog", - "real_debrid_api_token": "API nøgle", + "api_token": "API nøgle", "enable_real_debrid": "Slå Real-Debrid til", "real_debrid_description": "Real-Debrid er en ubegrænset downloader der gør det muligt for dig at downloade filer med det samme og med den bedste udnyttelse af din internet hastighed.", - "real_debrid_invalid_token": "Ugyldig API nøgle", - "real_debrid_api_token_hint": "Du kan få din API nøgle <0>her", + "debrid_invalid_token": "Ugyldig API nøgle", + "debrid_api_token_hint": "Du kan få din API nøgle <0>her", "real_debrid_free_account_error": "Brugeren \"{{username}}\" er en gratis bruger. Venligst abbonér på Real-Debrid", - "real_debrid_linked_message": "Brugeren \"{{username}}\" er forbundet", + "debrid_linked_message": "Brugeren \"{{username}}\" er forbundet", "save_changes": "Gem ændringer", "changes_saved": "Ændringer gemt successfuldt", "download_sources_description": "Hydra vil hente download links fra disse kilder. Kilde URLen skal være et direkte link til en .json fil der indeholder download linkene.", diff --git a/src/locales/de/translation.json b/src/locales/de/translation.json index bf1eff60..c94b0913 100644 --- a/src/locales/de/translation.json +++ b/src/locales/de/translation.json @@ -161,13 +161,13 @@ "behavior": "Verhalten", "download_sources": "Download-Quellen", "language": "Sprache", - "real_debrid_api_token": "API Token", + "api_token": "API Token", "enable_real_debrid": "Real-Debrid aktivieren", "real_debrid_description": "Real-Debrid ist ein unrestriktiver Downloader, der es dir ermöglicht Dateien sofort und mit deiner maximalen Internetgeschwindigkeit herunterzuladen.", - "real_debrid_invalid_token": "API token nicht gültig", - "real_debrid_api_token_hint": "<0>Hier kannst du dir deinen API Token holen", + "debrid_invalid_token": "API token nicht gültig", + "debrid_api_token_hint": "<0>Hier kannst du dir deinen API Token holen", "real_debrid_free_account_error": "Das Konto \"{{username}}\" ist ein gratis account. Bitte abonniere Real-Debrid", - "real_debrid_linked_message": "Konto \"{{username}}\" verknüpft", + "debrid_linked_message": "Konto \"{{username}}\" verknüpft", "save_changes": "Änderungen speichern", "changes_saved": "Änderungen erfolgreich gespeichert", "download_sources_description": "Hydra wird die Download-Links von diesen Quellen abrufen. Die Quell-URL muss ein direkter Link zu einer .json Datei, welche die Download-Links enthält, sein.", diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5cb6ed1c..bbe922f2 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -240,13 +240,13 @@ "behavior": "Behavior", "download_sources": "Download sources", "language": "Language", - "real_debrid_api_token": "API Token", + "api_token": "API Token", "enable_real_debrid": "Enable Real-Debrid", "real_debrid_description": "Real-Debrid is an unrestricted downloader that allows you to quickly download files, only limited by your internet speed.", - "real_debrid_invalid_token": "Invalid API token", - "real_debrid_api_token_hint": "You can get your API token <0>here", + "debrid_invalid_token": "Invalid API token", + "debrid_api_token_hint": "You can get your API token <0>here", "real_debrid_free_account_error": "The account \"{{username}}\" is a free account. Please subscribe to Real-Debrid", - "real_debrid_linked_message": "Account \"{{username}}\" linked", + "debrid_linked_message": "Account \"{{username}}\" linked", "save_changes": "Save changes", "changes_saved": "Changes successfully saved", "download_sources_description": "Hydra will fetch the download links from these sources. The source URL must be a direct link to a .json file containing the download links.", @@ -300,7 +300,11 @@ "become_subscriber": "Be Hydra Cloud", "subscription_renew_cancelled": "Automatic renewal is disabled", "subscription_renews_on": "Your subscription renews on {{date}}", - "bill_sent_until": "Your next bill will be sent until this day" + "bill_sent_until": "Your next bill will be sent until this day", + "enable_torbox": "Enable Torbox", + "torbox_description": "TorBox is your premium seedbox service rivaling even the best servers on the market.", + "torbox_account_linked": "TorBox account linked", + "real_debrid_account_linked": "Real-Debrid account linked" }, "notifications": { "download_complete": "Download complete", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index c8667d6c..43839e9e 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -236,13 +236,13 @@ "behavior": "Otros", "download_sources": "Fuentes de descarga", "language": "Idioma", - "real_debrid_api_token": "Token API", + "api_token": "Token API", "enable_real_debrid": "Activar Real-Debrid", "real_debrid_description": "Real-Debrid es una forma de descargar sin restricciones archivos instantáneamente con la máxima velocidad de tu internet.", - "real_debrid_invalid_token": "Token de API inválido", - "real_debrid_api_token_hint": "Puedes obtener tu clave de API <0>aquí", + "debrid_invalid_token": "Token de API inválido", + "debrid_api_token_hint": "Puedes obtener tu clave de API <0>aquí", "real_debrid_free_account_error": "La cuenta \"{{username}}\" es una cuenta gratuita. Por favor, suscríbete a Real-Debrid", - "real_debrid_linked_message": "Cuenta \"{{username}}\" vinculada", + "debrid_linked_message": "Cuenta \"{{username}}\" vinculada", "save_changes": "Guardar cambios", "changes_saved": "Ajustes guardados exitosamente", "download_sources_description": "Hydra buscará los enlaces de descarga de estas fuentes. La URL de origen debe ser un enlace directo a un archivo .json que contenga los enlaces de descarga", diff --git a/src/locales/et/translation.json b/src/locales/et/translation.json index 91b4a63a..97e69a90 100644 --- a/src/locales/et/translation.json +++ b/src/locales/et/translation.json @@ -213,13 +213,13 @@ "behavior": "Käitumine", "download_sources": "Allalaadimise allikad", "language": "Keel", - "real_debrid_api_token": "API Võti", + "api_token": "API Võti", "enable_real_debrid": "Luba Real-Debrid", "real_debrid_description": "Real-Debrid on piiranguteta allalaadija, mis võimaldab sul faile alla laadida koheselt ja sinu internetiühenduse parima kiirusega.", - "real_debrid_invalid_token": "Vigane API võti", - "real_debrid_api_token_hint": "Sa saad oma API võtme <0>siit", + "debrid_invalid_token": "Vigane API võti", + "debrid_api_token_hint": "Sa saad oma API võtme <0>siit", "real_debrid_free_account_error": "Konto \"{{username}}\" on tasuta konto. Palun telli Real-Debrid", - "real_debrid_linked_message": "Konto \"{{username}}\" ühendatud", + "debrid_linked_message": "Konto \"{{username}}\" ühendatud", "save_changes": "Salvesta muudatused", "changes_saved": "Muudatused edukalt salvestatud", "download_sources_description": "Hydra laeb allalaadimise lingid nendest allikatest. Allika URL peab olema otsene link .json failile, mis sisaldab allalaadimise linke.", diff --git a/src/locales/fa/translation.json b/src/locales/fa/translation.json index 2409635f..9d4f7280 100644 --- a/src/locales/fa/translation.json +++ b/src/locales/fa/translation.json @@ -110,7 +110,7 @@ "general": "کلی", "behavior": "رفتار", "enable_real_debrid": "فعال‌سازی Real-Debrid", - "real_debrid_api_token_hint": "کلید API خود را از <ب0>اینجا بگیرید.", + "debrid_api_token_hint": "کلید API خود را از <ب0>اینجا بگیرید.", "save_changes": "ذخیره تغییرات" }, "notifications": { diff --git a/src/locales/id/translation.json b/src/locales/id/translation.json index ba4a06f1..a813d770 100644 --- a/src/locales/id/translation.json +++ b/src/locales/id/translation.json @@ -161,13 +161,13 @@ "behavior": "Perilaku", "download_sources": "Sumber unduhan", "language": "Bahasa", - "real_debrid_api_token": "Token API", + "api_token": "Token API", "enable_real_debrid": "Aktifkan Real-Debrid", "real_debrid_description": "Real-Debrid adalah downloader tanpa batas yang memungkinkan kamu untuk mengunduh file dengan cepat dan pada kecepatan terbaik dari Internet kamu.", - "real_debrid_invalid_token": "Token API tidak valid", - "real_debrid_api_token_hint": "Kamu bisa dapatkan token API di <0>sini", + "debrid_invalid_token": "Token API tidak valid", + "debrid_api_token_hint": "Kamu bisa dapatkan token API di <0>sini", "real_debrid_free_account_error": "Akun \"{{username}}\" adalah akun gratis. Silakan berlangganan Real-Debrid", - "real_debrid_linked_message": "Akun \"{{username}}\" terhubung", + "debrid_linked_message": "Akun \"{{username}}\" terhubung", "save_changes": "Simpan perubahan", "changes_saved": "Perubahan disimpan berhasil", "download_sources_description": "Hydra akan mencari link unduhan dari sini. URL harus menuju file .json dengan link unduhan.", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index cf763320..742f889f 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -118,7 +118,7 @@ "general": "Generale", "behavior": "Comportamento", "enable_real_debrid": "Abilita Real Debrid", - "real_debrid_api_token_hint": "Puoi trovare la tua chiave API <0>here", + "debrid_api_token_hint": "Puoi trovare la tua chiave API <0>here", "save_changes": "Salva modifiche" }, "notifications": { diff --git a/src/locales/kk/translation.json b/src/locales/kk/translation.json index 6d5d8404..e66cd5ed 100644 --- a/src/locales/kk/translation.json +++ b/src/locales/kk/translation.json @@ -159,13 +159,13 @@ "behavior": "Мінез-құлық", "download_sources": "Жүктеу көздері", "language": "Тіл", - "real_debrid_api_token": "API Кілті", + "api_token": "API Кілті", "enable_real_debrid": "Real-Debrid-ті қосу", "real_debrid_description": "Real-Debrid - бұл шектеусіз жүктеуші, ол интернетте орналастырылған файлдарды тез жүктеуге немесе жеке желі арқылы кез келген блоктарды айналып өтіп, оларды бірден плеерге беруге мүмкіндік береді.", - "real_debrid_invalid_token": "Қате API кілті", - "real_debrid_api_token_hint": "API кілтін <0>осы жерден алуға болады", + "debrid_invalid_token": "Қате API кілті", + "debrid_api_token_hint": "API кілтін <0>осы жерден алуға болады", "real_debrid_free_account_error": "\"{{username}}\" аккаунты жазылымға ие емес. Real-Debrid жазылымын алыңыз", - "real_debrid_linked_message": "\"{{username}}\" аккаунты байланған", + "debrid_linked_message": "\"{{username}}\" аккаунты байланған", "save_changes": "Өзгерістерді сақтау", "changes_saved": "Өзгерістер сәтті сақталды", "download_sources_description": "Hydra осы көздерден жүктеу сілтемелерін алады. URL-да жүктеу сілтемелері бар .json файлына тікелей сілтеме болуы керек.", diff --git a/src/locales/ko/translation.json b/src/locales/ko/translation.json index 2656bb45..bc8e6056 100644 --- a/src/locales/ko/translation.json +++ b/src/locales/ko/translation.json @@ -110,7 +110,7 @@ "general": "일반", "behavior": "행동", "enable_real_debrid": "Real-Debrid 활성화", - "real_debrid_api_token_hint": "API 키를 <0>이곳에서 얻으세요.", + "debrid_api_token_hint": "API 키를 <0>이곳에서 얻으세요.", "save_changes": "변경 사항 저장" }, "notifications": { diff --git a/src/locales/nb/translation.json b/src/locales/nb/translation.json index 5c5f6882..a6fb1bcc 100644 --- a/src/locales/nb/translation.json +++ b/src/locales/nb/translation.json @@ -177,13 +177,13 @@ "behavior": "Oppførsel", "download_sources": "Nedlastingskilder", "language": "Språk", - "real_debrid_api_token": "API nøkkel", + "api_token": "API nøkkel", "enable_real_debrid": "Slå på Real-Debrid", "real_debrid_description": "Real-Debrid er en ubegrenset nedlaster som gør det mulig for deg å laste ned filer med en gang og med den beste utnyttelsen av internethastigheten din.", - "real_debrid_invalid_token": "Ugyldig API nøkkel", - "real_debrid_api_token_hint": "Du kan få API nøkkelen din <0>her", + "debrid_invalid_token": "Ugyldig API nøkkel", + "debrid_api_token_hint": "Du kan få API nøkkelen din <0>her", "real_debrid_free_account_error": "Brukeren \"{{username}}\" er en gratis bruker. Vennligst abboner på Real-Debrid", - "real_debrid_linked_message": "Brukeren \"{{username}}\" er forbunnet", + "debrid_linked_message": "Brukeren \"{{username}}\" er forbunnet", "save_changes": "Lagre endringer", "changes_saved": "Lagring av endringer vellykket", "download_sources_description": "Hydra vil hente nedlastingslenker fra disse kildene. Kilde URLen skal være en direkte lenke til en .json fil som inneholder nedlastingslenkene.", diff --git a/src/locales/nl/translation.json b/src/locales/nl/translation.json index bb7abf59..6d9de5fa 100644 --- a/src/locales/nl/translation.json +++ b/src/locales/nl/translation.json @@ -111,7 +111,7 @@ "general": "Algemeen", "behavior": "Gedrag", "enable_real_debrid": "Enable Real-Debrid", - "real_debrid_api_token_hint": "U kunt uw API-sleutel <0>hier verkrijgen.", + "debrid_api_token_hint": "U kunt uw API-sleutel <0>hier verkrijgen.", "save_changes": "Wijzigingen opslaan" }, "notifications": { diff --git a/src/locales/pl/translation.json b/src/locales/pl/translation.json index 945c857a..bdaf822c 100644 --- a/src/locales/pl/translation.json +++ b/src/locales/pl/translation.json @@ -119,7 +119,7 @@ "behavior": "Zachowania", "language": "Język", "enable_real_debrid": "Włącz Real-Debrid", - "real_debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj", + "debrid_api_token_hint": "Możesz uzyskać swój klucz API <0>tutaj", "save_changes": "Zapisz zmiany" }, "notifications": { diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 3d1e5c15..b34f1874 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -229,13 +229,13 @@ "behavior": "Comportamento", "download_sources": "Fontes de download", "language": "Idioma", - "real_debrid_api_token": "Token de API", + "api_token": "Token de API", "enable_real_debrid": "Habilitar Real-Debrid", - "real_debrid_api_token_hint": "Você pode obter seu token de API <0>aqui", + "debrid_api_token_hint": "Você pode obter seu token de API <0>aqui", "real_debrid_description": "O Real-Debrid é um downloader sem restrições que permite baixar arquivos instantaneamente e com a melhor velocidade da sua Internet.", - "real_debrid_invalid_token": "Token de API inválido", + "debrid_invalid_token": "Token de API inválido", "real_debrid_free_account_error": "A conta \"{{username}}\" é uma conta gratuita. Por favor, assine a Real-Debrid", - "real_debrid_linked_message": "Conta \"{{username}}\" vinculada", + "debrid_linked_message": "Conta \"{{username}}\" vinculada", "save_changes": "Salvar mudanças", "changes_saved": "Ajustes salvos com sucesso", "download_sources_description": "Hydra vai buscar links de download em todas as fontes habilitadas. A URL da fonte deve ser um link direto para um arquivo .json contendo uma lista de links.", @@ -289,7 +289,11 @@ "become_subscriber": "Seja Hydra Cloud", "subscription_renew_cancelled": "A renovação automática está desativada", "subscription_renews_on": "Sua assinatura renova dia {{date}}", - "bill_sent_until": "Sua próxima cobrança será enviada até esse dia" + "bill_sent_until": "Sua próxima cobrança será enviada até esse dia", + "enable_torbox": "Habilitar Torbox", + "torbox_description": "TorBox é o seu serviço de seedbox premium que rivaliza até com os melhores servidores do mercado.", + "torbox_account_linked": "Conta do TorBox vinculada", + "real_debrid_account_linked": "Conta Real-Debrid associada" }, "notifications": { "download_complete": "Download concluído", diff --git a/src/locales/pt-PT/translation.json b/src/locales/pt-PT/translation.json index ce081b3f..3b8496ae 100644 --- a/src/locales/pt-PT/translation.json +++ b/src/locales/pt-PT/translation.json @@ -205,13 +205,13 @@ "behavior": "Comportamento", "download_sources": "Fontes de transferência", "language": "Idioma", - "real_debrid_api_token": "Token de API", + "api_token": "Token de API", "enable_real_debrid": "Ativar Real-Debrid", - "real_debrid_api_token_hint": "Podes obter o teu token de API <0>aqui", + "debrid_api_token_hint": "Podes obter o teu token de API <0>aqui", "real_debrid_description": "O Real-Debrid é um downloader sem restrições que permite descarregar ficheiros instantaneamente e com a melhor velocidade da tua Internet.", - "real_debrid_invalid_token": "Token de API inválido", + "debrid_invalid_token": "Token de API inválido", "real_debrid_free_account_error": "A conta \"{{username}}\" é uma conta gratuita. Por favor, subscreve o Real-Debrid", - "real_debrid_linked_message": "Conta \"{{username}}\" associada", + "debrid_linked_message": "Conta \"{{username}}\" associada", "save_changes": "Guardar alterações", "changes_saved": "Alterações guardadas com sucesso", "download_sources_description": "O Hydra vai procurar links de download em todas as fontes ativadas. O URL da fonte deve ser um link direto para um ficheiro .json que contenha uma lista de links.", diff --git a/src/locales/ro/translation.json b/src/locales/ro/translation.json index 69d14071..9003ecc6 100644 --- a/src/locales/ro/translation.json +++ b/src/locales/ro/translation.json @@ -124,13 +124,13 @@ "general": "General", "behavior": "Comportament", "language": "Limbă", - "real_debrid_api_token": "Token API", + "api_token": "Token API", "enable_real_debrid": "Activează Real-Debrid", "real_debrid_description": "Real-Debrid este un descărcător fără restricții care îți permite să descarci fișiere instantaneu și la cea mai bună viteză a internetului tău.", - "real_debrid_invalid_token": "Token API invalid", - "real_debrid_api_token_hint": "Poți obține token-ul tău API <0>aici", + "debrid_invalid_token": "Token API invalid", + "debrid_api_token_hint": "Poți obține token-ul tău API <0>aici", "real_debrid_free_account_error": "Contul \"{{username}}\" este un cont gratuit. Te rugăm să te abonezi la Real-Debrid", - "real_debrid_linked_message": "Contul \"{{username}}\" a fost legat", + "debrid_linked_message": "Contul \"{{username}}\" a fost legat", "save_changes": "Salvează modificările", "changes_saved": "Modificările au fost salvate cu succes" }, diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json index 1b48c5e0..18b8f1f5 100644 --- a/src/locales/ru/translation.json +++ b/src/locales/ru/translation.json @@ -237,13 +237,13 @@ "behavior": "Поведение", "download_sources": "Источники загрузки", "language": "Язык", - "real_debrid_api_token": "API Ключ", + "api_token": "API Ключ", "enable_real_debrid": "Включить Real-Debrid", "real_debrid_description": "Real-Debrid - это неограниченный загрузчик, который позволяет быстро скачивать файлы, размещенные в Интернете, или мгновенно передавать их в плеер через частную сеть, позволяющую обходить любые блокировки.", - "real_debrid_invalid_token": "Неверный API ключ", - "real_debrid_api_token_hint": "API ключ можно получить <0>здесь", + "debrid_invalid_token": "Неверный API ключ", + "debrid_api_token_hint": "API ключ можно получить <0>здесь", "real_debrid_free_account_error": "Аккаунт \"{{username}}\" - не имеет подписки. Пожалуйста, оформите подписку на Real-Debrid", - "real_debrid_linked_message": "Привязан аккаунт \"{{username}}\"", + "debrid_linked_message": "Привязан аккаунт \"{{username}}\"", "save_changes": "Сохранить изменения", "changes_saved": "Изменения успешно сохранены", "download_sources_description": "Hydra будет получать ссылки на загрузки из этих источников. URL должна содержать прямую ссылку на .json-файл с ссылками для загрузок.", diff --git a/src/locales/tr/translation.json b/src/locales/tr/translation.json index 6fa89c03..9095b693 100644 --- a/src/locales/tr/translation.json +++ b/src/locales/tr/translation.json @@ -236,13 +236,13 @@ "behavior": "Davranış", "download_sources": "İndirme kaynakları", "language": "Dil", - "real_debrid_api_token": "API Anahtarı", + "api_token": "API Anahtarı", "enable_real_debrid": "Real-Debrid'i Etkinleştir", "real_debrid_description": "Real-Debrid, yalnızca internet hızınızla sınırlı olarak hızlı dosya indirmenizi sağlayan sınırsız bir indirici.", - "real_debrid_invalid_token": "Geçersiz API anahtarı", - "real_debrid_api_token_hint": "API anahtarınızı <0>buradan alabilirsiniz", + "debrid_invalid_token": "Geçersiz API anahtarı", + "debrid_api_token_hint": "API anahtarınızı <0>buradan alabilirsiniz", "real_debrid_free_account_error": "\"{{username}}\" hesabı ücretsiz bir hesaptır. Lütfen Real-Debrid abonesi olun", - "real_debrid_linked_message": "\"{{username}}\" hesabı bağlandı", + "debrid_linked_message": "\"{{username}}\" hesabı bağlandı", "save_changes": "Değişiklikleri Kaydet", "changes_saved": "Değişiklikler başarıyla kaydedildi", "download_sources_description": "Hydra, indirme bağlantılarını bu kaynaklardan alacak. Kaynak URL, indirme bağlantılarını içeren bir .json dosyasına doğrudan bir bağlantı olmalıdır.", diff --git a/src/locales/uk/translation.json b/src/locales/uk/translation.json index ed4b3d58..174e768c 100644 --- a/src/locales/uk/translation.json +++ b/src/locales/uk/translation.json @@ -174,13 +174,13 @@ "import": "Імпортувати", "insert_valid_json_url": "Вставте дійсний URL JSON-файлу", "language": "Мова", - "real_debrid_api_token": "API-токен", - "real_debrid_api_token_hint": "API токен можливо отримати <0>тут", + "api_token": "API-токен", + "debrid_api_token_hint": "API токен можливо отримати <0>тут", "real_debrid_api_token_label": "Real-Debrid API-токен", "real_debrid_description": "Real-Debrid — це необмежений завантажувач, який дозволяє швидко завантажувати файли, розміщені в Інтернеті, або миттєво передавати їх у плеєр через приватну мережу, що дозволяє обходити будь-які блокування.", "real_debrid_free_account_error": "Акаунт \"{{username}}\" - не має наявної підписки. Будь ласка, оформіть підписку на Real-Debrid", - "real_debrid_invalid_token": "Невірний API-токен", - "real_debrid_linked_message": "Акаунт \"{{username}}\" привязаний", + "debrid_invalid_token": "Невірний API-токен", + "debrid_linked_message": "Акаунт \"{{username}}\" привязаний", "remove_download_source": "Видалити", "removed_download_source": "Джерело завантажень було видалено", "save_changes": "Зберегти зміни", diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index 664877fa..ba48a21b 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -213,13 +213,13 @@ "behavior": "行为", "download_sources": "下载源", "language": "语言", - "real_debrid_api_token": "API 令牌", + "api_token": "API 令牌", "enable_real_debrid": "启用 Real-Debrid", "real_debrid_description": "Real-Debrid 是一个无限制的下载器,允许您以最快的互联网速度即时下载文件。", - "real_debrid_invalid_token": "无效的 API 令牌", - "real_debrid_api_token_hint": "您可以从<0>这里获取API密钥.", + "debrid_invalid_token": "无效的 API 令牌", + "debrid_api_token_hint": "您可以从<0>这里获取API密钥.", "real_debrid_free_account_error": "账户 \"{{username}}\" 是免费账户。请订阅 Real-Debrid", - "real_debrid_linked_message": "账户 \"{{username}}\" 已链接", + "debrid_linked_message": "账户 \"{{username}}\" 已链接", "save_changes": "保存更改", "changes_saved": "更改已成功保存", "download_sources_description": "Hydra 将从这些源获取下载链接。源 URL 必须是直接链接到包含下载链接的 .json 文件。", diff --git a/src/main/events/auth/sign-out.ts b/src/main/events/auth/sign-out.ts index 4de9c285..2ab5e458 100644 --- a/src/main/events/auth/sign-out.ts +++ b/src/main/events/auth/sign-out.ts @@ -1,6 +1,5 @@ import { registerEvent } from "../register-event"; import { DownloadManager, HydraApi, gamesPlaytime } from "@main/services"; -import { PythonRPC } from "@main/services/python-rpc"; import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level"; const signOut = async (_event: Electron.IpcMainInvokeEvent) => { @@ -25,9 +24,6 @@ const signOut = async (_event: Electron.IpcMainInvokeEvent) => { /* Cancels any ongoing downloads */ DownloadManager.cancelDownload(); - /* Disconnects libtorrent */ - PythonRPC.kill(); - HydraApi.handleSignOut(); await Promise.all([ diff --git a/src/main/events/index.ts b/src/main/events/index.ts index 25882c3f..570fa378 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -46,6 +46,7 @@ import "./user-preferences/auto-launch"; import "./autoupdater/check-for-updates"; import "./autoupdater/restart-and-install-update"; import "./user-preferences/authenticate-real-debrid"; +import "./user-preferences/authenticate-torbox"; import "./download-sources/put-download-source"; import "./auth/sign-out"; import "./auth/open-auth-window"; diff --git a/src/main/events/torrenting/start-game-download.ts b/src/main/events/torrenting/start-game-download.ts index 96e3499a..8b5f1918 100644 --- a/src/main/events/torrenting/start-game-download.ts +++ b/src/main/events/torrenting/start-game-download.ts @@ -76,10 +76,10 @@ const startGameDownload = async ( queued: true, }; - await downloadsSublevel.put(gameKey, download); - try { - await DownloadManager.startDownload(download); + await DownloadManager.startDownload(download).then(() => { + return downloadsSublevel.put(gameKey, download); + }); const updatedGame = await gamesSublevel.get(gameKey); @@ -113,6 +113,10 @@ const startGameDownload = async ( error: DownloadError.RealDebridAccountNotAuthorized, }; } + + if (downloader === Downloader.TorBox) { + return { ok: false, error: err.response?.data?.detail }; + } } if (err instanceof Error) { diff --git a/src/main/events/user-preferences/authenticate-torbox.ts b/src/main/events/user-preferences/authenticate-torbox.ts new file mode 100644 index 00000000..87fc4ba8 --- /dev/null +++ b/src/main/events/user-preferences/authenticate-torbox.ts @@ -0,0 +1,14 @@ +import { registerEvent } from "../register-event"; +import { TorBoxClient } from "@main/services/download/torbox"; + +const authenticateTorBox = async ( + _event: Electron.IpcMainInvokeEvent, + apiToken: string +) => { + TorBoxClient.authorize(apiToken); + + const user = await TorBoxClient.getUser(); + return user; +}; + +registerEvent("authenticateTorBox", authenticateTorBox); diff --git a/src/main/events/user-preferences/get-user-preferences.ts b/src/main/events/user-preferences/get-user-preferences.ts index b40d6780..c67f72b9 100644 --- a/src/main/events/user-preferences/get-user-preferences.ts +++ b/src/main/events/user-preferences/get-user-preferences.ts @@ -15,6 +15,12 @@ const getUserPreferences = async () => ); } + if (userPreferences?.torBoxApiToken) { + userPreferences.torBoxApiToken = Crypto.decrypt( + userPreferences.torBoxApiToken + ); + } + return userPreferences; }); diff --git a/src/main/events/user-preferences/update-user-preferences.ts b/src/main/events/user-preferences/update-user-preferences.ts index 31193558..275a6f27 100644 --- a/src/main/events/user-preferences/update-user-preferences.ts +++ b/src/main/events/user-preferences/update-user-preferences.ts @@ -30,6 +30,10 @@ const updateUserPreferences = async ( ); } + if (preferences.torBoxApiToken) { + preferences.torBoxApiToken = Crypto.encrypt(preferences.torBoxApiToken); + } + if (!preferences.downloadsPath) { preferences.downloadsPath = null; } diff --git a/src/main/main.ts b/src/main/main.ts index 0777a28e..4824a1a5 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -20,6 +20,7 @@ import { } from "./level"; import { Auth, User, type UserPreferences } from "@types"; import { knexClient } from "./knex-client"; +import { TorBoxClient } from "./services/download/torbox"; export const loadState = async () => { const userPreferences = await migrateFromSqlite().then(async () => { @@ -42,6 +43,10 @@ export const loadState = async () => { ); } + if (userPreferences?.torBoxApiToken) { + TorBoxClient.authorize(Crypto.decrypt(userPreferences.torBoxApiToken)); + } + Ludusavi.addManifestToLudusaviConfig(); HydraApi.setupApi().then(() => { diff --git a/src/main/services/download/download-manager.ts b/src/main/services/download/download-manager.ts index 53389105..5c19c1b1 100644 --- a/src/main/services/download/download-manager.ts +++ b/src/main/services/download/download-manager.ts @@ -15,6 +15,7 @@ import path from "path"; import { logger } from "../logger"; import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level"; import { sortBy } from "lodash-es"; +import { TorBoxClient } from "./torbox"; export class DownloadManager { private static downloadingGameId: string | null = null; @@ -275,6 +276,7 @@ export class DownloadManager { } case Downloader.PixelDrain: { const id = download.uri.split("/").pop(); + return { action: "start", game_id: downloadId, @@ -329,6 +331,18 @@ export class DownloadManager { save_path: download.downloadPath, }; } + case Downloader.TorBox: { + const { name, url } = await TorBoxClient.getDownloadInfo(download.uri); + + if (!url) return; + return { + action: "start", + game_id: downloadId, + url, + save_path: download.downloadPath, + out: name, + }; + } } } diff --git a/src/main/services/download/torbox.ts b/src/main/services/download/torbox.ts index 3eade81d..8011cae8 100644 --- a/src/main/services/download/torbox.ts +++ b/src/main/services/download/torbox.ts @@ -6,24 +6,23 @@ import type { TorBoxAddTorrentRequest, TorBoxRequestLinkRequest, } from "@types"; -import { logger } from "../logger"; export class TorBoxClient { private static instance: AxiosInstance; private static readonly baseURL = "https://api.torbox.app/v1/api"; - public static apiToken: string; + private static apiToken: string; static authorize(apiToken: string) { + this.apiToken = apiToken; this.instance = axios.create({ baseURL: this.baseURL, headers: { Authorization: `Bearer ${apiToken}`, }, }); - this.apiToken = apiToken; } - static async addMagnet(magnet: string) { + private static async addMagnet(magnet: string) { const form = new FormData(); form.append("magnet", magnet); @@ -32,6 +31,10 @@ export class TorBoxClient { form ); + if (!response.data.success) { + throw new Error(response.data.detail); + } + return response.data.data; } @@ -55,22 +58,16 @@ export class TorBoxClient { } static async requestLink(id: number) { - const searchParams = new URLSearchParams({}); - - searchParams.set("token", this.apiToken); - searchParams.set("torrent_id", id.toString()); - searchParams.set("zip_link", "true"); + const searchParams = new URLSearchParams({ + token: this.apiToken, + torrent_id: id.toString(), + zip_link: "true", + }); const response = await this.instance.get( "/torrents/requestdl?" + searchParams.toString() ); - if (response.status !== 200) { - logger.error(response.data.error); - logger.error(response.data.detail); - return null; - } - return response.data.data; } @@ -81,7 +78,7 @@ export class TorBoxClient { return response.data.data; } - static async getTorrentId(magnetUri: string) { + private static async getTorrentIdAndName(magnetUri: string) { const userTorrents = await this.getAllTorrentsFromUser(); const { infoHash } = await parseTorrent(magnetUri); @@ -89,9 +86,18 @@ export class TorBoxClient { (userTorrent) => userTorrent.hash === infoHash ); - if (userTorrent) return userTorrent.id; + if (userTorrent) return { id: userTorrent.id, name: userTorrent.name }; const torrent = await this.addMagnet(magnetUri); - return torrent.torrent_id; + return { id: torrent.torrent_id, name: torrent.name }; + } + + static async getDownloadInfo(uri: string) { + const torrentData = await this.getTorrentIdAndName(uri); + const url = await this.requestLink(torrentData.id); + + const name = torrentData.name ? `${torrentData.name}.zip` : undefined; + + return { url, name }; } } diff --git a/src/preload/index.ts b/src/preload/index.ts index eac3c0a1..439327cd 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -92,6 +92,8 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("autoLaunch", autoLaunchProps), authenticateRealDebrid: (apiToken: string) => ipcRenderer.invoke("authenticateRealDebrid", apiToken), + authenticateTorBox: (apiToken: string) => + ipcRenderer.invoke("authenticateTorBox", apiToken), /* Download sources */ putDownloadSource: (objectIds: string[]) => diff --git a/src/renderer/src/assets/icons/torbox.webp b/src/renderer/src/assets/icons/torbox.webp new file mode 100644 index 00000000..68d68531 Binary files /dev/null and b/src/renderer/src/assets/icons/torbox.webp differ diff --git a/src/renderer/src/components/text-field/text-field.css.ts b/src/renderer/src/components/text-field/text-field.css.ts index f983508e..8c993993 100644 --- a/src/renderer/src/components/text-field/text-field.css.ts +++ b/src/renderer/src/components/text-field/text-field.css.ts @@ -14,7 +14,7 @@ export const textField = recipe({ base: { display: "inline-flex", transition: "all ease 0.2s", - width: "100%", + flex: 1, alignItems: "center", borderRadius: "8px", border: `solid 1px ${vars.color.border}`, diff --git a/src/renderer/src/constants.ts b/src/renderer/src/constants.ts index 8f20ad7a..1d7aa1b1 100644 --- a/src/renderer/src/constants.ts +++ b/src/renderer/src/constants.ts @@ -10,6 +10,7 @@ export const DOWNLOADER_NAME = { [Downloader.Qiwi]: "Qiwi", [Downloader.Datanodes]: "Datanodes", [Downloader.Mediafire]: "Mediafire", + [Downloader.TorBox]: "TorBox", }; export const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index a68db401..c1923562 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -28,6 +28,7 @@ import type { CatalogueSearchPayload, LibraryGame, GameRunning, + TorBoxUser, } from "@types"; import type { AxiosProgressEvent } from "axios"; import type disk from "diskusage"; @@ -144,6 +145,7 @@ declare global { minimized: boolean; }) => Promise; authenticateRealDebrid: (apiToken: string) => Promise; + authenticateTorBox: (apiToken: string) => Promise; onAchievementUnlocked: (cb: () => void) => () => Electron.IpcRenderer; /* Download sources */ diff --git a/src/renderer/src/pages/downloads/download-group.tsx b/src/renderer/src/pages/downloads/download-group.tsx index 8c61672c..d84d6601 100644 --- a/src/renderer/src/pages/downloads/download-group.tsx +++ b/src/renderer/src/pages/downloads/download-group.tsx @@ -30,6 +30,9 @@ import { XCircleIcon, } from "@primer/octicons-react"; +import torBoxLogo from "@renderer/assets/icons/torbox.webp"; +import { SPACING_UNIT, vars } from "@renderer/theme.css"; + export interface DownloadGroupProps { library: LibraryGame[]; title: string; @@ -235,12 +238,16 @@ export function DownloadGroup({ ]; } + const isResumeDisabled = + (download?.downloader === Downloader.RealDebrid && + !userPreferences?.realDebridApiToken) || + (download?.downloader === Downloader.TorBox && + !userPreferences?.torBoxApiToken); + return [ { label: t("resume"), - disabled: - download?.downloader === Downloader.RealDebrid && - !userPreferences?.realDebridApiToken, + disabled: isResumeDisabled, onClick: () => { resumeDownload(game.shop, game.objectId); }, @@ -279,13 +286,30 @@ export function DownloadGroup({ />
- - { - DOWNLOADER_NAME[ - game?.download?.downloader as Downloader - ] - } - + {game.download?.downloader === Downloader.TorBox ? ( +
+ TorBox + TorBox +
+ ) : ( + + {DOWNLOADER_NAME[game.download!.downloader]} + + )}
diff --git a/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx b/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx index 786c6793..fa6a9306 100644 --- a/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/download-settings-modal.tsx @@ -88,14 +88,14 @@ export function DownloadSettingsModal({ const filteredDownloaders = downloaders.filter((downloader) => { if (downloader === Downloader.RealDebrid) return userPreferences?.realDebridApiToken; + if (downloader === Downloader.TorBox) + return userPreferences?.torBoxApiToken; return true; }); - /* Gives preference to Real Debrid */ - const selectedDownloader = filteredDownloaders.includes( - Downloader.RealDebrid - ) - ? Downloader.RealDebrid + /* Gives preference to TorBox */ + const selectedDownloader = filteredDownloaders.includes(Downloader.TorBox) + ? Downloader.TorBox : filteredDownloaders[0]; setSelectedDownloader(selectedDownloader ?? null); diff --git a/src/renderer/src/pages/settings/settings-real-debrid.tsx b/src/renderer/src/pages/settings/settings-real-debrid.tsx index 35804664..0d4e5108 100644 --- a/src/renderer/src/pages/settings/settings-real-debrid.tsx +++ b/src/renderer/src/pages/settings/settings-real-debrid.tsx @@ -57,7 +57,8 @@ export function SettingsRealDebrid() { return; } else { showSuccessToast( - t("real_debrid_linked_message", { username: user.username }) + t("real_debrid_account_linked"), + t("debrid_linked_message", { username: user.username }) ); } } else { @@ -68,7 +69,7 @@ export function SettingsRealDebrid() { realDebridApiToken: form.useRealDebrid ? form.realDebridApiToken : null, }); } catch (err) { - showErrorToast(t("real_debrid_invalid_token")); + showErrorToast(t("debrid_invalid_token")); } finally { setIsLoading(false); } @@ -94,29 +95,30 @@ export function SettingsRealDebrid() { {form.useRealDebrid && ( setForm({ ...form, realDebridApiToken: event.target.value }) } placeholder="API Token" - containerProps={{ style: { marginTop: `${SPACING_UNIT}px` } }} + containerProps={{ + style: { + marginTop: `${SPACING_UNIT}px`, + }, + }} + rightContent={ + + } hint={ - + } /> )} - - ); } diff --git a/src/renderer/src/pages/settings/settings-torbox.css.ts b/src/renderer/src/pages/settings/settings-torbox.css.ts new file mode 100644 index 00000000..0dfc9d78 --- /dev/null +++ b/src/renderer/src/pages/settings/settings-torbox.css.ts @@ -0,0 +1,13 @@ +import { style } from "@vanilla-extract/css"; + +import { SPACING_UNIT } from "../../theme.css"; + +export const form = style({ + display: "flex", + flexDirection: "column", + gap: `${SPACING_UNIT}px`, +}); + +export const description = style({ + marginBottom: `${SPACING_UNIT * 2}px`, +}); diff --git a/src/renderer/src/pages/settings/settings-torbox.tsx b/src/renderer/src/pages/settings/settings-torbox.tsx new file mode 100644 index 00000000..ce4b5fcc --- /dev/null +++ b/src/renderer/src/pages/settings/settings-torbox.tsx @@ -0,0 +1,116 @@ +import { useContext, useEffect, useState } from "react"; +import { Trans, useTranslation } from "react-i18next"; + +import { Button, CheckboxField, Link, TextField } from "@renderer/components"; +import * as styles from "./settings-torbox.css"; + +import { useAppSelector, useToast } from "@renderer/hooks"; + +import { SPACING_UNIT } from "@renderer/theme.css"; +import { settingsContext } from "@renderer/context"; + +const TORBOX_API_TOKEN_URL = "https://torbox.app/settings"; + +export function SettingsTorbox() { + const userPreferences = useAppSelector( + (state) => state.userPreferences.value + ); + + const { updateUserPreferences } = useContext(settingsContext); + + const [isLoading, setIsLoading] = useState(false); + const [form, setForm] = useState({ + useTorBox: false, + torBoxApiToken: null as string | null, + }); + + const { showSuccessToast, showErrorToast } = useToast(); + + const { t } = useTranslation("settings"); + + useEffect(() => { + if (userPreferences) { + setForm({ + useTorBox: Boolean(userPreferences.torBoxApiToken), + torBoxApiToken: userPreferences.torBoxApiToken ?? null, + }); + } + }, [userPreferences]); + + const handleFormSubmit: React.FormEventHandler = async ( + event + ) => { + setIsLoading(true); + event.preventDefault(); + + try { + if (form.useTorBox) { + const user = await window.electron.authenticateTorBox( + form.torBoxApiToken! + ); + + showSuccessToast( + t("torbox_account_linked"), + t("debrid_linked_message", { username: user.email }) + ); + } else { + showSuccessToast(t("changes_saved")); + } + + updateUserPreferences({ + torBoxApiToken: form.useTorBox ? form.torBoxApiToken : null, + }); + } catch (err) { + showErrorToast(t("debrid_invalid_token")); + } finally { + setIsLoading(false); + } + }; + + const isButtonDisabled = + (form.useTorBox && !form.torBoxApiToken) || isLoading; + + return ( +
+

{t("torbox_description")}

+ + + setForm((prev) => ({ + ...prev, + useTorBox: !form.useTorBox, + })) + } + /> + + {form.useTorBox && ( + + setForm({ ...form, torBoxApiToken: event.target.value }) + } + placeholder="API Token" + containerProps={{ + style: { + marginTop: `${SPACING_UNIT}px`, + }, + }} + rightContent={ + + } + hint={ + + + + } + /> + )} + + ); +} diff --git a/src/renderer/src/pages/settings/settings.tsx b/src/renderer/src/pages/settings/settings.tsx index 5fba6c5d..a3a955e2 100644 --- a/src/renderer/src/pages/settings/settings.tsx +++ b/src/renderer/src/pages/settings/settings.tsx @@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next"; import { SettingsRealDebrid } from "./settings-real-debrid"; import { SettingsGeneral } from "./settings-general"; import { SettingsBehavior } from "./settings-behavior"; - +import torBoxLogo from "@renderer/assets/icons/torbox.webp"; import { SettingsDownloadSources } from "./settings-download-sources"; import { SettingsContextConsumer, @@ -14,6 +14,7 @@ import { import { SettingsAccount } from "./settings-account"; import { useUserDetails } from "@renderer/hooks"; import { useMemo } from "react"; +import { SettingsTorbox } from "./settings-torbox"; export default function Settings() { const { t } = useTranslation("settings"); @@ -22,13 +23,26 @@ export default function Settings() { const categories = useMemo(() => { const categories = [ - t("general"), - t("behavior"), - t("download_sources"), - "Real-Debrid", + { tabLabel: t("general"), contentTitle: t("general") }, + { tabLabel: t("behavior"), contentTitle: t("behavior") }, + { tabLabel: t("download_sources"), contentTitle: t("download_sources") }, + { + tabLabel: ( + <> + TorBox + Torbox + + ), + contentTitle: "TorBox", + }, + { tabLabel: "Real-Debrid", contentTitle: "Real-Debrid" }, ]; - if (userDetails) return [...categories, t("account")]; + if (userDetails) + return [ + ...categories, + { tabLabel: t("account"), contentTitle: t("account") }, + ]; return categories; }, [userDetails, t]); @@ -50,6 +64,10 @@ export default function Settings() { } if (currentCategoryIndex === 3) { + return ; + } + + if (currentCategoryIndex === 4) { return ; } @@ -62,18 +80,18 @@ export default function Settings() {
{categories.map((category, index) => ( ))}
-

{categories[currentCategoryIndex]}

+

{categories[currentCategoryIndex].contentTitle}

{renderCategory()} diff --git a/src/shared/constants.ts b/src/shared/constants.ts index f26128f5..550c1097 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -6,6 +6,7 @@ export enum Downloader { Qiwi, Datanodes, Mediafire, + TorBox, } export enum DownloadSourceStatus { diff --git a/src/shared/index.ts b/src/shared/index.ts index 1b9183b3..01d7cb06 100644 --- a/src/shared/index.ts +++ b/src/shared/index.ts @@ -95,7 +95,7 @@ export const getDownloadersForUri = (uri: string) => { return [Downloader.RealDebrid]; if (uri.startsWith("magnet:")) { - return [Downloader.Torrent, Downloader.RealDebrid]; + return [Downloader.Torrent, Downloader.TorBox, Downloader.RealDebrid]; } return []; diff --git a/src/types/level.types.ts b/src/types/level.types.ts index 28d8b0b6..aa28d9dd 100644 --- a/src/types/level.types.ts +++ b/src/types/level.types.ts @@ -69,6 +69,7 @@ export interface UserPreferences { downloadsPath?: string | null; language?: string; realDebridApiToken?: string | null; + torBoxApiToken?: string | null; preferQuitInsteadOfHiding?: boolean; runAtStartup?: boolean; startMinimized?: boolean;