mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-21 16:25:36 +02:00
add ability to add different versions of the same show
This commit is contained in:
@@ -8,7 +8,7 @@ from database.torrents import TorrentMixin
|
|||||||
|
|
||||||
|
|
||||||
class Show(SQLModel, table=True):
|
class Show(SQLModel, table=True):
|
||||||
__table_args__ = (UniqueConstraint("external_id", "metadata_provider"),)
|
__table_args__ = (UniqueConstraint("external_id", "metadata_provider", "version"),)
|
||||||
id: UUID = Field(primary_key=True, default_factory=uuid.uuid4)
|
id: UUID = Field(primary_key=True, default_factory=uuid.uuid4)
|
||||||
external_id: int
|
external_id: int
|
||||||
metadata_provider: str
|
metadata_provider: str
|
||||||
@@ -16,6 +16,7 @@ class Show(SQLModel, table=True):
|
|||||||
overview: str
|
overview: str
|
||||||
# For some shows the first_air_date isn't known, therefore it needs to be nullable
|
# For some shows the first_air_date isn't known, therefore it needs to be nullable
|
||||||
year: int | None
|
year: int | None
|
||||||
|
version: str = Field(default="")
|
||||||
|
|
||||||
seasons: list["Season"] = Relationship(back_populates="show", cascade_delete=True)
|
seasons: list["Season"] = Relationship(back_populates="show", cascade_delete=True)
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
import tmdbsimple as tmdb
|
|
||||||
|
|
||||||
from config import TvConfig
|
|
||||||
|
|
||||||
config = TvConfig()
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
tmdb.API_KEY = config.api_key
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
import pprint
|
import pprint
|
||||||
from typing import List
|
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
import psycopg.errors
|
import psycopg.errors
|
||||||
@@ -8,17 +7,17 @@ from fastapi import APIRouter, Depends, status
|
|||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlmodel import select
|
from sqlmodel import select
|
||||||
from tmdbsimple import TV, TV_Seasons
|
|
||||||
|
|
||||||
import auth
|
import auth
|
||||||
import dowloadClients
|
import dowloadClients
|
||||||
import indexer
|
import indexer
|
||||||
|
import metadataProvider
|
||||||
from database import SessionDependency
|
from database import SessionDependency
|
||||||
from database.torrents import Torrent
|
from database.torrents import Torrent
|
||||||
from database.tv import Episode, Season, Show
|
from database.tv import Season, Show
|
||||||
from indexer import IndexerQueryResult
|
from indexer import IndexerQueryResult
|
||||||
from routers.users import Message
|
from routers.users import Message
|
||||||
from tv import log, tmdb
|
from tv import log
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/tv",
|
prefix="/tv",
|
||||||
@@ -35,48 +34,19 @@ class ShowDetails(BaseModel):
|
|||||||
status.HTTP_201_CREATED: {"model": Show, "description": "Successfully created show"},
|
status.HTTP_201_CREATED: {"model": Show, "description": "Successfully created show"},
|
||||||
status.HTTP_409_CONFLICT: {"model": Message, "description": "Show already exists"},
|
status.HTTP_409_CONFLICT: {"model": Message, "description": "Show already exists"},
|
||||||
})
|
})
|
||||||
def add_show(db: SessionDependency, show_id: int, metadata_provider: str = "tmdb"):
|
def add_show(db: SessionDependency, show_id: int, metadata_provider: str = "tmdb", version: str = ""):
|
||||||
show_metadata = TV(show_id).info()
|
res = db.exec(select(Show).
|
||||||
|
where(Show.external_id == show_id).
|
||||||
|
where(Show.metadata_provider == metadata_provider).
|
||||||
|
where(Show.version == version)).first()
|
||||||
|
|
||||||
# For some shows the first_air_date isn't known, therefore it needs to be nullable
|
if res is not None:
|
||||||
year: str | None = show_metadata["first_air_date"]
|
return JSONResponse(status_code=status.HTTP_409_CONFLICT, content={"message": "Show already exists"})
|
||||||
if year:
|
|
||||||
year: int = int(year.split('-')[0])
|
|
||||||
else:
|
|
||||||
year = None
|
|
||||||
|
|
||||||
show = Show(
|
|
||||||
external_id=show_id,
|
|
||||||
metadata_provider=metadata_provider,
|
|
||||||
name=show_metadata["name"],
|
|
||||||
overview=show_metadata["overview"],
|
|
||||||
year=year,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
show = metadataProvider.get_show_metadata(id=show_id, provider=metadata_provider)
|
||||||
|
show.version = version
|
||||||
log.info("Adding show: " + json.dumps(show.model_dump(), default=str))
|
log.info("Adding show: " + json.dumps(show.model_dump(), default=str))
|
||||||
db.add(show)
|
db.add(show)
|
||||||
db.commit()
|
|
||||||
|
|
||||||
for season in show_metadata["seasons"]:
|
|
||||||
season_metadata = TV_Seasons(tv_id=show_metadata["id"], season_number=season["season_number"]).info()
|
|
||||||
db.add(Season(
|
|
||||||
show_id=show.id,
|
|
||||||
number=int(season_metadata["season_number"]),
|
|
||||||
name=season_metadata["name"],
|
|
||||||
overview=season_metadata["overview"],
|
|
||||||
external_id=int(season_metadata["id"]))
|
|
||||||
)
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
for episode in season_metadata["episodes"]:
|
|
||||||
db.add(Episode(
|
|
||||||
show_id=show.id,
|
|
||||||
season_number=int(season_metadata["season_number"]),
|
|
||||||
title=episode["name"],
|
|
||||||
number=int(episode["episode_number"]),
|
|
||||||
external_id=int(episode["id"]),
|
|
||||||
))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(show)
|
db.refresh(show)
|
||||||
@@ -151,8 +121,17 @@ def get_season_torrents(db: SessionDependency, show_id: UUID, season_id: UUID):
|
|||||||
|
|
||||||
@router.post("/{show_id}/torrent", status_code=status.HTTP_200_OK, dependencies=[Depends(
|
@router.post("/{show_id}/torrent", status_code=status.HTTP_200_OK, dependencies=[Depends(
|
||||||
auth.get_current_user)], response_model=list[Season])
|
auth.get_current_user)], response_model=list[Season])
|
||||||
def download_seasons_torrent(db: SessionDependency, show_id: UUID, torrent: IndexerQueryResult, ):
|
def download_seasons_torrent(db: SessionDependency, show_id: UUID, torrent_id: UUID):
|
||||||
seasons: list[Season] = []
|
"""
|
||||||
|
downloads torrents for a show season, links the torrent for all seasons the torrent contains
|
||||||
|
|
||||||
|
"""
|
||||||
|
torrent = db.get(Torrent, torrent_id)
|
||||||
|
|
||||||
|
if torrent is None:
|
||||||
|
return JSONResponse(status_code=status.HTTP_404_NOT_FOUND, content={"message": "Torrent not found"})
|
||||||
|
|
||||||
|
seasons = []
|
||||||
for season_number in torrent.season:
|
for season_number in torrent.season:
|
||||||
seasons.append(
|
seasons.append(
|
||||||
db.exec(select(Season)
|
db.exec(select(Season)
|
||||||
@@ -172,13 +151,55 @@ def download_seasons_torrent(db: SessionDependency, show_id: UUID, torrent: Inde
|
|||||||
return seasons
|
return seasons
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", dependencies=[Depends(auth.get_current_user)], response_model=List[Show])
|
@router.post("/{show_id}/{season_id}/torrent", status_code=status.HTTP_200_OK, dependencies=[Depends(
|
||||||
|
auth.get_current_user)], response_model=list[Season])
|
||||||
|
def download_seasons_torrent(db: SessionDependency, show_id: UUID, season_id: UUID, torrent_id: UUID):
|
||||||
|
"""
|
||||||
|
downloads torrents for a season, links the torrent only to the specified season
|
||||||
|
this means that multiple torrents can contain a season but you can choose from one which the content should be
|
||||||
|
imported
|
||||||
|
|
||||||
|
"""
|
||||||
|
torrent = db.get(Torrent, torrent_id)
|
||||||
|
|
||||||
|
if torrent is None:
|
||||||
|
return JSONResponse(status_code=status.HTTP_404_NOT_FOUND, content={"message": "Torrent not found"})
|
||||||
|
|
||||||
|
seasons = []
|
||||||
|
for season_number in torrent.season:
|
||||||
|
seasons.append(
|
||||||
|
db.exec(select(Season)
|
||||||
|
.where(Season.show_id == show_id)
|
||||||
|
.where(Season.number == season_number)
|
||||||
|
).first()
|
||||||
|
)
|
||||||
|
|
||||||
|
torrent = torrent.download()
|
||||||
|
|
||||||
|
dowloadClients.client.download(Torrent)
|
||||||
|
|
||||||
|
for season in seasons:
|
||||||
|
season.requested = True
|
||||||
|
season.torrent_id = torrent.id
|
||||||
|
|
||||||
|
return seasons
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/", dependencies=[Depends(auth.get_current_user)], response_model=list[Show])
|
||||||
def get_shows(db: SessionDependency):
|
def get_shows(db: SessionDependency):
|
||||||
|
""""""
|
||||||
return db.exec(select(Show)).unique().fetchall()
|
return db.exec(select(Show)).unique().fetchall()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{show_id}", dependencies=[Depends(auth.get_current_user)], response_model=ShowDetails)
|
@router.get("/{show_id}", dependencies=[Depends(auth.get_current_user)], response_model=ShowDetails)
|
||||||
def get_show(db: SessionDependency, show_id: UUID):
|
def get_show(db: SessionDependency, show_id: UUID):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param show_id:
|
||||||
|
:type show_id:
|
||||||
|
:return:
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
shows = db.execute(select(Show, Season).where(Show.id == show_id).join(Season).order_by(Season.number)).fetchall()
|
shows = db.execute(select(Show, Season).where(Show.id == show_id).join(Season).order_by(Season.number)).fetchall()
|
||||||
seasons = []
|
seasons = []
|
||||||
for show in shows:
|
for show in shows:
|
||||||
@@ -191,5 +212,11 @@ def get_show(db: SessionDependency, show_id: UUID):
|
|||||||
|
|
||||||
@router.get("/search")
|
@router.get("/search")
|
||||||
def search_show(query: str):
|
def search_show(query: str):
|
||||||
|
"""
|
||||||
|
Searches for shows by title in the metadata provider.
|
||||||
|
:param query: The search query string.
|
||||||
|
:param db: The database connection object.
|
||||||
|
:return: A list of show objects that match the query.
|
||||||
|
"""
|
||||||
search = tmdb.Search()
|
search = tmdb.Search()
|
||||||
return search.tv(query=query)
|
return search.tv(query=query)
|
||||||
|
|||||||
Reference in New Issue
Block a user