Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/alldebrid support #517

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions backend/program/downloaders/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
from .realdebrid import Debrid
from .torbox import TorBoxDownloader
from .realdebrid import RealDebridDownloader
from .alldebrid import AllDebridDownloader
from .torbox import TorBoxDownloader
from program.media.item import MediaItem


class Downloader:
def __init__(self, hash_cache):
self.key = "downloader"
self.initialized = False
services = [
RealDebridDownloader(hash_cache),
TorBoxDownloader(hash_cache),
AllDebridDownloader(hash_cache),
]
self.service = next(service for service in services if service.initialized)
self.initialized = self.validate()

def validate(self):
return self.service is not None

def run(self, item: MediaItem):
yield next(self.service.run(item))
669 changes: 669 additions & 0 deletions backend/program/downloaders/alldebrid.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion backend/program/downloaders/realdebrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
RD_BASE_URL = "https://api.real-debrid.com/rest/1.0"


class Debrid:
class RealDebridDownloader:
"""Real-Debrid API Wrapper"""

def __init__(self, hash_cache):
Expand Down
4 changes: 2 additions & 2 deletions backend/program/downloaders/torbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def validate(self) -> bool:
return False

def run(self, item: MediaItem) -> Generator[MediaItem, None, None]:
"""Download media item from TorBox"""
"""Download media item from TorBox"""
logger.info(f"Downloading {item.log_string} from TorBox")
if self.is_cached(item):
self.download(item)
Expand Down Expand Up @@ -97,4 +97,4 @@ def create_torrent(self, hash) -> int:

def get_torrent_list(self) -> list:
response = get(f"{self.base_url}/torrents/mylist", additional_headers=self.headers, response_type=dict)
return response.data["data"]
return response.data["data"]
14 changes: 3 additions & 11 deletions backend/program/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

from apscheduler.schedulers.background import BackgroundScheduler
from program.content import Listrr, Mdblist, Overseerr, PlexWatchlist, TraktContent
from program.downloaders.realdebrid import Debrid
from program.downloaders.torbox import TorBoxDownloader
from program.downloaders import Downloader
from program.indexers.trakt import TraktIndexer
from program.libraries import SymlinkLibrary
from program.media.item import Episode, MediaItem, Movie, Season, Show
Expand Down Expand Up @@ -71,10 +70,7 @@ def initialize_services(self):
Scraping: Scraping(),
Symlinker: Symlinker(),
Updater: Updater(),
}
self.downloader_services = {
Debrid: Debrid(hash_cache),
TorBoxDownloader: TorBoxDownloader(hash_cache),
Downloader: Downloader(hash_cache),
}
# Depends on Symlinker having created the file structure so needs
# to run after it
Expand All @@ -83,8 +79,6 @@ def initialize_services(self):
}
if not any(s.initialized for s in self.requesting_services.values()):
logger.error("No Requesting service initialized, you must select at least one.")
if not any(s.initialized for s in self.downloader_services.values()):
logger.error("No Downloader service initialized, you must select at least one.")
if not self.processing_services.get(Scraping).initialized:
logger.error("No Scraping service initialized, you must select at least one.")

Expand All @@ -93,7 +87,6 @@ def initialize_services(self):
**self.indexing_services,
**self.requesting_services,
**self.processing_services,
**self.downloader_services,
}

if self.enable_trace:
Expand All @@ -107,7 +100,6 @@ def validate(self) -> bool:
any(s.initialized for s in self.library_services.values()),
any(s.initialized for s in self.indexing_services.values()),
all(s.initialized for s in self.processing_services.values()),
any(s.initialized for s in self.downloader_services.values()),
)
)

Expand Down Expand Up @@ -425,4 +417,4 @@ def clear_queue(self):
self.event_queue.task_done()
except Empty:
break
logger.log("PROGRAM", "Cleared the event queue")
logger.log("PROGRAM", "Cleared the event queue")
13 changes: 10 additions & 3 deletions backend/program/settings/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ def __setattr__(self, name, value):

# Download Services

class DebridModel(Observable):
class RealDebridModel(Observable):
enabled: bool = False
api_key: str = ""
proxy_enabled: bool = False
proxy_url: str = ""

class AllDebridModel(Observable):
enabled: bool = False
api_key: str = ""
proxy_enabled: bool = False
Expand All @@ -43,7 +49,8 @@ class DownloadersModel(Observable):
movie_filesize_max: int = -1 # MB (-1 is no limit)
episode_filesize_min: int = 40 # MB
episode_filesize_max: int = -1 # MB (-1 is no limit)
real_debrid: DebridModel = DebridModel()
real_debrid: RealDebridModel = RealDebridModel()
all_debrid: AllDebridModel = AllDebridModel()
torbox: TorboxModel = TorboxModel()


Expand Down Expand Up @@ -324,4 +331,4 @@ class AppModel(Observable):
scraping: ScraperModel = ScraperModel()
ranking: RTNSettingsModel = RTNSettingsModel()
indexer: IndexerModel = IndexerModel()
database: DatabaseModel = DatabaseModel()
database: DatabaseModel = DatabaseModel()
5 changes: 2 additions & 3 deletions backend/program/state_transition.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from program.content import Listrr, Mdblist, Overseerr, PlexWatchlist
from program.content.trakt import TraktContent
from program.downloaders.realdebrid import Debrid
from program.downloaders.torbox import TorBoxDownloader
from program.downloaders import Downloader
from program.indexers.trakt import TraktIndexer
from program.libraries import SymlinkLibrary
from program.media import Episode, MediaItem, Movie, Season, Show, States
Expand Down Expand Up @@ -43,7 +42,7 @@ def process_event(existing_item: MediaItem | None, emitted_by: Service, item: Me
items_to_submit = [item] if Scraping.can_we_scrape(item) else []

elif item.state == States.Scraped:
next_service = Debrid or TorBoxDownloader
next_service = Downloader
items_to_submit = [item]

elif item.state == States.Downloaded:
Expand Down
6 changes: 3 additions & 3 deletions backend/program/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Generator, Union

from program.content import Listrr, Mdblist, Overseerr, PlexWatchlist, TraktContent
from program.downloaders import Debrid, TorBoxDownloader
from program.downloaders import RealDebridDownloader, TorBoxDownloader, AllDebridDownloader
from program.libraries import SymlinkLibrary
from program.media.item import MediaItem
from program.scrapers import (
Expand All @@ -22,7 +22,7 @@
# Typehint classes
Scraper = Union[Scraping, Torrentio, Knightcrawler, Mediafusion, Orionoid, Jackett, Annatar, TorBoxScraper, Zilean]
Content = Union[Overseerr, PlexWatchlist, Listrr, Mdblist, TraktContent]
Downloader = Union[Debrid, TorBoxDownloader]
Downloader = Union[RealDebridDownloader, TorBoxDownloader, AllDebridDownloader]
Service = Union[Content, SymlinkLibrary, Scraper, Downloader, Symlinker, Updater]
MediaItemGenerator = Generator[MediaItem, None, MediaItem | None]
ProcessedEvent = (MediaItem, Service, list[MediaItem])
Expand All @@ -31,4 +31,4 @@
@dataclass
class Event:
emitted_by: Service
item: MediaItem
item: MediaItem
16 changes: 8 additions & 8 deletions backend/tests/test_states_processing.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from program.downloaders.realdebrid import Debrid
from program.downloaders.realdebrid import RealDebridDownloader
from program.indexers.trakt import TraktIndexer
from program.media.item import Episode, MediaItem, Movie, Season, Show
from program.media.state import States
Expand Down Expand Up @@ -126,8 +126,8 @@ def test_show_state_transitions(show):
(States.Unknown, Program, TraktIndexer),
# (States.Requested, TraktIndexer, TraktIndexer),
(States.Indexed, TraktIndexer, Scraping),
(States.Scraped, Scraping, Debrid),
(States.Downloaded, Debrid, Symlinker),
(States.Scraped, Scraping, RealDebridDownloader),
(States.Downloaded, RealDebridDownloader, Symlinker),
(States.Symlinked, Symlinker, PlexUpdater),
(States.Completed, PlexUpdater, None)
])
Expand All @@ -150,8 +150,8 @@ def test_process_event_transitions_movie(state, service, next_service, movie):
(States.Unknown, Program, TraktIndexer),
# (States.Requested, TraktIndexer, TraktIndexer),
(States.Indexed, TraktIndexer, Scraping),
(States.Scraped, Scraping, Debrid),
(States.Downloaded, Debrid, Symlinker),
(States.Scraped, Scraping, RealDebridDownloader),
(States.Downloaded, RealDebridDownloader, Symlinker),
(States.Symlinked, Symlinker, PlexUpdater),
(States.Completed, PlexUpdater, None)
])
Expand Down Expand Up @@ -181,8 +181,8 @@ def test_process_event_transition_shows(state, service, next_service, show):
(States.Unknown, Program, TraktIndexer),
# (States.Requested, TraktIndexer, TraktIndexer),
(States.Indexed, TraktIndexer, Scraping),
(States.Scraped, Scraping, Debrid),
(States.Downloaded, Debrid, Symlinker),
(States.Scraped, Scraping, RealDebridDownloader),
(States.Downloaded, RealDebridDownloader, Symlinker),
(States.Symlinked, Symlinker, PlexUpdater),
(States.Completed, PlexUpdater, None)
])
Expand Down Expand Up @@ -225,4 +225,4 @@ def test_process_event_transitions_media_item_movie(state, service, next_service
# if next_service is None:
# assert next_service_result is None, f"Next service should be None for {service}"
# else:
# assert next_service_result == next_service, f"Next service should be {next_service} for {service}"
# assert next_service_result == next_service, f"Next service should be {next_service} for {service}"
2 changes: 2 additions & 0 deletions backend/utils/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ def ping(
timeout=10,
additional_headers=None,
proxies=None,
params=None,
specific_rate_limiter: Optional[RateLimiter] = None,
overall_rate_limiter: Optional[RateLimiter] = None):
return get(
url,
additional_headers=additional_headers,
params=params,
timeout=timeout,
proxies=proxies,
specific_rate_limiter=specific_rate_limiter,
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/lib/forms/general-form.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,28 @@
{/if}
{/if}

{#if $formData.alldebrid_enabled}
<div transition:slide>
<TextField {form} name="alldebrid_api_key" {formData} isProtected={true} />
</div>

<div transition:slide>
<CheckboxField
{form}
name="alldebrid_proxy_enabled"
label="All-Debrid Proxy"
{formData}
fieldDescription="Use proxy for All-Debrid API"
/>
</div>

{#if $formData.alldebrid_proxy_enabled}
<div transition:slide>
<TextField {form} name="alldebrid_proxy_url" {formData} />
</div>
{/if}
{/if}

{#if $formData.torbox_enabled}
<div transition:slide>
<TextField {form} name="torbox_api_key" {formData} />
Expand Down
16 changes: 15 additions & 1 deletion frontend/src/lib/forms/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export const generalSettingsSchema = z.object({
realdebrid_api_key: z.string().optional().default(''),
realdebrid_proxy_enabled: z.boolean().default(false),
realdebrid_proxy_url: z.string().optional().default(''),
alldebrid_enabled: z.boolean().default(false),
alldebrid_api_key: z.string().optional().default(''),
alldebrid_proxy_enabled: z.boolean().default(false),
alldebrid_proxy_url: z.string().optional().default(''),
torbox_enabled: z.boolean().default(false),
torbox_api_key: z.string().optional().default('')
});
Expand All @@ -77,8 +81,12 @@ export function generalSettingsToPass(data: any) {
realdebrid_api_key: data.data.downloaders.real_debrid?.api_key || '',
realdebrid_proxy_enabled: data.data.downloaders.real_debrid?.proxy_enabled || false,
realdebrid_proxy_url: data.data.downloaders.real_debrid?.proxy_url || '',
alldebrid_enabled: data.data.downloaders.all_debrid.enabled,
alldebrid_api_key: data.data.downloaders.all_debrid?.api_key || '',
alldebrid_proxy_enabled: data.data.downloaders.all_debrid?.proxy_enabled || false,
alldebrid_proxy_url: data.data.downloaders.all_debrid?.proxy_url || '',
torbox_enabled: data.data.downloaders.torbox.enabled,
torbox_api_key: data.data.downloaders.torbox?.api_key || ''
torbox_api_key: data.data.downloaders.torbox?.api_key || '',
};
}

Expand Down Expand Up @@ -113,6 +121,12 @@ export function generalSettingsToSet(form: SuperValidated<Infer<GeneralSettingsS
proxy_enabled: form.data.realdebrid_proxy_enabled,
proxy_url: form.data.realdebrid_proxy_url
},
all_debrid: {
enabled: form.data.alldebrid_enabled,
api_key: form.data.alldebrid_api_key,
proxy_enabled: form.data.alldebrid_proxy_enabled,
proxy_url: form.data.alldebrid_proxy_url
},
torbox: {
enabled: form.data.torbox_enabled,
api_key: form.data.torbox_api_key
Expand Down