diff --git a/MediaManager/src/database/torrents.py b/MediaManager/src/database/torrents.py index 58f6d5d..9edba9f 100644 --- a/MediaManager/src/database/torrents.py +++ b/MediaManager/src/database/torrents.py @@ -16,12 +16,11 @@ class Quality(Enum): unknown = 5 -# TODO: make system to detect quality more sophisticated class QualityMixin: title: str - @property @computed_field + @property def quality(self) -> Quality: high_quality_pattern = r'\b(4k|4K)\b' medium_quality_pattern = r'\b(1080p|1080P)\b' @@ -39,7 +38,6 @@ class QualityMixin: else: return Quality.unknown - class TorrentMixin: torrent_id: UUID | None = Field(default=None, foreign_key="torrent.id") @@ -53,4 +51,4 @@ class Torrent(SQLModel, QualityMixin, table=True): @property @computed_field def torrent_filepath(self) -> str: - return f"{self.id}.torrent" + return f"{self.id}.torrent" \ No newline at end of file diff --git a/MediaManager/src/indexer/__init__.py b/MediaManager/src/indexer/__init__.py index 3c38a49..f1c6d9d 100644 --- a/MediaManager/src/indexer/__init__.py +++ b/MediaManager/src/indexer/__init__.py @@ -13,6 +13,7 @@ def search(query: str | Season) -> list[IndexerQueryResult]: if isinstance(query, Season): query = query.show.name + " s" + query.number.__str__() + log.debug(f"Searching for Season {query}") for indexer in indexers: results.extend(indexer.get_search_results(query)) diff --git a/MediaManager/src/indexer/generic.py b/MediaManager/src/indexer/generic.py index 5692491..8eef87f 100644 --- a/MediaManager/src/indexer/generic.py +++ b/MediaManager/src/indexer/generic.py @@ -1,15 +1,33 @@ import re +from uuid import UUID, uuid4 +import pydantic from pydantic import BaseModel, computed_field from database.torrents import QualityMixin, Torrent class IndexerQueryResult(BaseModel, QualityMixin): + id: UUID = pydantic.Field(default_factory=uuid4) title: str - download_url: str + _download_url: str seeders: int - flags: list[str] + flags: set[str] + + @computed_field + @property + def season(self) -> set[int]: + pattern = r"\b[sS](\d+)\b" + matches = re.findall(pattern, self.title, re.IGNORECASE) + if matches.__len__() == 2: + result = set() + for i in range(int(matches[0]), int(matches[1]) + 1): + result.add(i) + elif matches.__len__() == 1: + result = {int(matches[0])} + else: + result = {} + return result def __gt__(self, other) -> bool: if self.quality.value != other.quality.value: @@ -35,22 +53,6 @@ class IndexerQueryResult(BaseModel, QualityMixin): return Torrent(torrent_title=self.title) - @computed_field - @property - def season(self) -> list[int]: - pattern = r"\b[sS](\d+)\b" - matches = re.findall(pattern, self.title, re.IGNORECASE) - if matches.__len__() == 2: - result = [] - for i in range(int(matches[0]), int(matches[1]) + 1): - result.append(i) - elif matches.__len__() == 1: - result = [int(matches[0])] - else: - result = [] - return result - - class GenericIndexer(object): name: str diff --git a/MediaManager/src/indexer/prowlarr.py b/MediaManager/src/indexer/prowlarr.py index b56d7bd..30f57bf 100644 --- a/MediaManager/src/indexer/prowlarr.py +++ b/MediaManager/src/indexer/prowlarr.py @@ -40,14 +40,13 @@ class Prowlarr(GenericIndexer): log.debug("torrent result: " + result.__str__()) result_list.append( IndexerQueryResult( - download_url=result['downloadUrl'], + _download_url=result['downloadUrl'], title=result['sortTitle'], seeders=result['seeders'], - flags=[] + flags=result['indexerFlags'], ) ) return result_list else: print(f'Error: {response.status_code}') return [] - diff --git a/MediaManager/src/tv/router.py b/MediaManager/src/tv/router.py index 02742a4..135e515 100644 --- a/MediaManager/src/tv/router.py +++ b/MediaManager/src/tv/router.py @@ -102,22 +102,6 @@ def add_season(db: SessionDependency, season_id: UUID): """ season = db.get(Season, season_id) season.requested = True - - # if season.requested == True and season.torrent_status is None: - # torrents = indexer.search(season.show.name + " " + season.number.__str__()) - # log.info("Found torrents: " + pprint.pformat(json.dumps(torrents, default=str))) - # torrents.sort() - # log.info("Found torrents: " + pprint.pformat(json.dumps(torrents, default=str))) - # - # torrent_filepath = torrents[0].download() - # season.torrent_filepath = torrent_filepath - # - # db.add(season) - # db.commit() - # db.refresh(season) - # log.info("Selected Torrent: " + pprint.pformat(json.dumps(torrents[0], default=str))) - # season = dowloadClients.client.download(torrent=season) - db.add(season) db.commit() db.refresh(season) @@ -139,19 +123,27 @@ def delete_season(db: SessionDependency, show_id: UUID, season: int): return season -@router.get("/{show_id}/torrent", status_code=status.HTTP_200_OK, dependencies=[Depends( +@router.get("/{show_id}/{season_id}/torrent", status_code=status.HTTP_200_OK, dependencies=[Depends( auth.get_current_user)], response_model=list[IndexerQueryResult]) -def get_season_torrents(db: SessionDependency, show_id: UUID, season_number: int): - season = db.exec(select(Season).where(Season.show_id == show_id).where(Season.number == season_number)).first() +def get_season_torrents(db: SessionDependency, show_id: UUID, season_id: UUID): + season = db.get(Season, season_id) - torrents = indexer.search(season) + if season is None: + return JSONResponse(status_code=status.HTTP_404_NOT_FOUND, content={"message": "Season not found"}) + + torrents: list[IndexerQueryResult] = indexer.search(season) result = [] for torrent in torrents: - if season_number in torrent.season: + if season.number in torrent.season: result.append(torrent) + + db.commit() + if len(result) == 0: + return result result.sort() - log.info(f"Found {torrents.__len__()} torrents for show {season.show.name} season {season_number}, of which " + + log.info(f"Found {torrents.__len__()} torrents for show {season.show.name} season {season.number}, of which " f"{result.__len__()} torrents fit the query") log.debug(f"unfiltered torrents: \n{pprint.pformat(torrents)}\nfiltered torrents: \n{pprint.pformat(result)}") return result @@ -169,9 +161,13 @@ def download_seasons_torrent(db: SessionDependency, show_id: UUID, torrent: Inde ).first() ) - filepath = torrent.download() + torrent = torrent.download() - status = dowloadClients.client.download(Torrent()) + dowloadClients.client.download(Torrent) + + for season in seasons: + season.requested = True + season.torrent_id = torrent.id return seasons