mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-17 23:53:58 +02:00
feat: enhance season request management with CRUD operations and update schemas
This commit is contained in:
@@ -2,7 +2,7 @@ from sqlalchemy import String, Integer
|
||||
from sqlalchemy.dialects.postgresql import ARRAY
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from database import Base
|
||||
from backend.src.database import Base
|
||||
from indexer.schemas import IndexerQueryResultId
|
||||
from torrent.schemas import Quality
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ from auth.users import bearer_auth_backend, fastapi_users, cookie_auth_backend
|
||||
|
||||
from config import BasicConfig
|
||||
from auth.users import oauth_client
|
||||
import auth.db # registering user table for sqlalchemy
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
@@ -73,7 +74,7 @@ else:
|
||||
log.info("Development Mode not activated!")
|
||||
|
||||
database.init_db()
|
||||
|
||||
log.info("Database initialized")
|
||||
app = FastAPI(root_path="/api/v1")
|
||||
|
||||
if basic_config.DEVELOPMENT:
|
||||
|
||||
@@ -2,7 +2,7 @@ from uuid import UUID
|
||||
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from database import Base
|
||||
from backend.src.database import Base
|
||||
from torrent.schemas import Quality, TorrentStatus
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from uuid import UUID
|
||||
from sqlalchemy import ForeignKey, PrimaryKeyConstraint, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from database import Base
|
||||
from backend.src.database import Base
|
||||
from torrent.models import Quality
|
||||
|
||||
|
||||
@@ -69,8 +69,9 @@ class SeasonFile(Base):
|
||||
class SeasonRequest(Base):
|
||||
__tablename__ = "season_request"
|
||||
__table_args__ = (
|
||||
PrimaryKeyConstraint("season_id", "wanted_quality"),
|
||||
UniqueConstraint("season_id", "wanted_quality"),
|
||||
)
|
||||
id: Mapped[UUID] = mapped_column(primary_key=True)
|
||||
season_id: Mapped[UUID] = mapped_column(ForeignKey(column="season.id", ondelete="CASCADE"), )
|
||||
wanted_quality: Mapped[Quality]
|
||||
min_quality: Mapped[Quality]
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
from sqlalchemy import select, delete
|
||||
import pprint
|
||||
|
||||
from sqlalchemy import select, delete, update
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
|
||||
import database
|
||||
from torrent.models import Torrent
|
||||
from torrent.schemas import TorrentId, Torrent as TorrentSchema
|
||||
from tv.models import Season, Show, Episode, SeasonRequest, SeasonFile
|
||||
from tv.schemas import Season as SeasonSchema, SeasonId, Show as ShowSchema, ShowId, \
|
||||
SeasonRequest as SeasonRequestSchema, SeasonFile as SeasonFileSchema, SeasonNumber
|
||||
SeasonRequest as SeasonRequestSchema, SeasonFile as SeasonFileSchema, SeasonNumber, SeasonRequestId, \
|
||||
RichSeasonRequest as RichSeasonRequestSchema
|
||||
|
||||
|
||||
def get_show(show_id: ShowId, db: Session) -> ShowSchema | None:
|
||||
@@ -17,13 +21,7 @@ def get_show(show_id: ShowId, db: Session) -> ShowSchema | None:
|
||||
:param db: The database session.
|
||||
:return: A ShowSchema object if found, otherwise None.
|
||||
"""
|
||||
stmt = (
|
||||
select(Show)
|
||||
.where(Show.id == show_id)
|
||||
.options(
|
||||
joinedload(Show.seasons).joinedload(Season.episodes)
|
||||
)
|
||||
)
|
||||
stmt = (select(Show).where(Show.id == show_id).options(joinedload(Show.seasons).joinedload(Season.episodes)))
|
||||
|
||||
result = db.execute(stmt).unique().scalar_one_or_none()
|
||||
if not result:
|
||||
@@ -31,6 +29,7 @@ def get_show(show_id: ShowId, db: Session) -> ShowSchema | None:
|
||||
|
||||
return ShowSchema.model_validate(result)
|
||||
|
||||
|
||||
def get_show_by_external_id(external_id: int, db: Session, metadata_provider: str) -> ShowSchema | None:
|
||||
"""
|
||||
Retrieve a show by its external ID, including nested seasons and episodes.
|
||||
@@ -41,21 +40,14 @@ def get_show_by_external_id(external_id: int, db: Session, metadata_provider: st
|
||||
:return: A ShowSchema object if found, otherwise None.
|
||||
"""
|
||||
stmt = (
|
||||
select(Show)
|
||||
.where(Show.external_id == external_id)
|
||||
.where(Show.metadata_provider == metadata_provider)
|
||||
.options(
|
||||
joinedload(Show.seasons).joinedload(Season.episodes)
|
||||
)
|
||||
)
|
||||
select(Show).where(Show.external_id == external_id).where(Show.metadata_provider == metadata_provider).options(
|
||||
joinedload(Show.seasons).joinedload(Season.episodes)))
|
||||
|
||||
result = db.execute(stmt).unique().scalar_one_or_none()
|
||||
if not result:
|
||||
return None
|
||||
|
||||
return ShowSchema(
|
||||
**result.__dict__
|
||||
)
|
||||
return ShowSchema(**result.__dict__)
|
||||
|
||||
|
||||
def get_shows(db: Session) -> list[ShowSchema]:
|
||||
@@ -81,33 +73,12 @@ def save_show(show: ShowSchema, db: Session) -> ShowSchema:
|
||||
:return: The saved ShowSchema object.
|
||||
:raises ValueError: If a show with the same primary key already exists.
|
||||
"""
|
||||
db_show = Show(
|
||||
id=show.id,
|
||||
external_id=show.external_id,
|
||||
metadata_provider=show.metadata_provider,
|
||||
name=show.name,
|
||||
overview=show.overview,
|
||||
year=show.year,
|
||||
seasons=[
|
||||
Season(
|
||||
id=season.id,
|
||||
show_id=show.id,
|
||||
number=season.number,
|
||||
external_id=season.external_id,
|
||||
name=season.name,
|
||||
overview=season.overview,
|
||||
episodes=[
|
||||
Episode(
|
||||
id=episode.id,
|
||||
season_id=season.id,
|
||||
number=episode.number,
|
||||
external_id=episode.external_id,
|
||||
title=episode.title
|
||||
) for episode in season.episodes
|
||||
]
|
||||
) for season in show.seasons
|
||||
]
|
||||
)
|
||||
db_show = Show(id=show.id, external_id=show.external_id, metadata_provider=show.metadata_provider, name=show.name,
|
||||
overview=show.overview, year=show.year, seasons=[
|
||||
Season(id=season.id, show_id=show.id, number=season.number, external_id=season.external_id,
|
||||
name=season.name, overview=season.overview, episodes=[
|
||||
Episode(id=episode.id, season_id=season.id, number=episode.number, external_id=episode.external_id,
|
||||
title=episode.title) for episode in season.episodes]) for season in show.seasons])
|
||||
|
||||
db.add(db_show)
|
||||
try:
|
||||
@@ -161,24 +132,17 @@ def remove_season_from_requested_list(season_request: SeasonRequestSchema, db: S
|
||||
|
||||
|
||||
def get_season_by_number(db: Session, season_number: int, show_id: ShowId) -> SeasonSchema:
|
||||
stmt = (
|
||||
select(Season).
|
||||
where(Season.show_id == show_id).
|
||||
where(Season.number == season_number).
|
||||
options(
|
||||
joinedload(Season.episodes),
|
||||
joinedload(Season.show)
|
||||
)
|
||||
)
|
||||
stmt = (select(Season).where(Season.show_id == show_id).where(Season.number == season_number).options(
|
||||
joinedload(Season.episodes), joinedload(Season.show)))
|
||||
result = db.execute(stmt).unique().scalar_one_or_none()
|
||||
return SeasonSchema.model_validate(result)
|
||||
|
||||
|
||||
def get_season_requests(db: Session) -> list[SeasonRequestSchema]:
|
||||
stmt = select(SeasonRequest)
|
||||
def get_season_requests(db: Session) -> list[RichSeasonRequestSchema]:
|
||||
stmt = select(SeasonRequest).join(Season, Season.id == SeasonRequest.season_id).join(Show,
|
||||
Season.show_id == Show.id)
|
||||
result = db.execute(stmt).scalars().all()
|
||||
return [SeasonRequestSchema.model_validate(season) for season in result]
|
||||
|
||||
return [RichSeasonRequestSchema.model_validate(season) for season in result]
|
||||
|
||||
def add_season_file(db: Session, season_file: SeasonFileSchema) -> SeasonFileSchema:
|
||||
db.add(SeasonFile(**season_file.model_dump()))
|
||||
@@ -187,31 +151,26 @@ def add_season_file(db: Session, season_file: SeasonFileSchema) -> SeasonFileSch
|
||||
|
||||
|
||||
def remove_season_files_by_torrent_id(db: Session, torrent_id: TorrentId):
|
||||
stmt = (
|
||||
delete(SeasonFile).
|
||||
where(SeasonFile.torrent_id == torrent_id)
|
||||
)
|
||||
stmt = (delete(SeasonFile).where(SeasonFile.torrent_id == torrent_id))
|
||||
db.execute(stmt)
|
||||
|
||||
|
||||
def get_season_files_by_season_id(db: Session, season_id: SeasonId):
|
||||
stmt = (
|
||||
select(SeasonFile).
|
||||
where(SeasonFile.season_id == season_id)
|
||||
)
|
||||
stmt = (select(SeasonFile).where(SeasonFile.season_id == season_id))
|
||||
result = db.execute(stmt).scalars().all()
|
||||
return [SeasonFileSchema.model_validate(season_file) for season_file in result]
|
||||
|
||||
|
||||
def get_torrents_by_show_id(db: Session, show_id: ShowId) -> list[TorrentSchema]:
|
||||
stmt = (
|
||||
select(Torrent)
|
||||
.distinct()
|
||||
.join(SeasonFile, SeasonFile.torrent_id == Torrent.id)
|
||||
.join(Season, Season.id == SeasonFile.season_id)
|
||||
.where(Season.show_id == show_id)
|
||||
)
|
||||
stmt = (select(Torrent)
|
||||
.distinct()
|
||||
.join(SeasonFile, SeasonFile.torrent_id == Torrent.id)
|
||||
.join(Season, Season.id == SeasonFile.season_id)
|
||||
.where(Season.show_id == show_id))
|
||||
result = db.execute(stmt).scalars().unique().all()
|
||||
return [TorrentSchema.model_validate(torrent) for torrent in result]
|
||||
|
||||
|
||||
def get_all_shows_with_torrents(db: Session) -> list[ShowSchema]:
|
||||
"""
|
||||
Retrieve all shows that are associated with a torrent alphabetically from the database.
|
||||
@@ -219,29 +178,40 @@ def get_all_shows_with_torrents(db: Session) -> list[ShowSchema]:
|
||||
:param db: The database session.
|
||||
:return: A list of ShowSchema objects.
|
||||
"""
|
||||
stmt = (
|
||||
select(Show)
|
||||
.distinct()
|
||||
.join(Season, Show.id == Season.show_id)
|
||||
.join(SeasonFile, Season.id == SeasonFile.season_id)
|
||||
.join(Torrent, SeasonFile.torrent_id == Torrent.id)
|
||||
.options(joinedload(Show.seasons).joinedload(Season.episodes))
|
||||
.order_by(Show.name)
|
||||
)
|
||||
stmt = (select(Show)
|
||||
.distinct()
|
||||
.join(Season, Show.id == Season.show_id)
|
||||
.join(SeasonFile, Season.id == SeasonFile.season_id)
|
||||
.join(Torrent, SeasonFile.torrent_id == Torrent.id)
|
||||
.options(joinedload(Show.seasons).joinedload(Season.episodes))
|
||||
.order_by(Show.name))
|
||||
|
||||
results = db.execute(stmt).scalars().unique().all()
|
||||
|
||||
return [ShowSchema.model_validate(show) for show in results]
|
||||
|
||||
|
||||
def get_seasons_by_torrent_id(db: Session, torrent_id: TorrentId) -> list[SeasonNumber]:
|
||||
stmt = (
|
||||
select(Season.number)
|
||||
.distinct()
|
||||
.join(SeasonFile, SeasonFile.torrent_id == Torrent.id)
|
||||
.join(Season, Season.id == SeasonFile.season_id)
|
||||
.where(Torrent.id == torrent_id)
|
||||
.select_from(Torrent)
|
||||
)
|
||||
stmt = (select(Season.number)
|
||||
.distinct()
|
||||
.join(SeasonFile, SeasonFile.torrent_id == Torrent.id)
|
||||
.join(Season, Season.id == SeasonFile.season_id).where(
|
||||
Torrent.id == torrent_id).select_from(Torrent))
|
||||
result = db.execute(stmt).scalars().unique().all()
|
||||
|
||||
return [SeasonNumber(x) for x in result]
|
||||
return [SeasonNumber(x) for x in result]
|
||||
|
||||
|
||||
def get_season_request(db: Session, season_request_id: SeasonRequestId) -> SeasonRequestSchema:
|
||||
return SeasonRequestSchema.model_validate(db.get(SeasonRequest, season_request_id))
|
||||
|
||||
|
||||
def update_season_request(db: Session, season_request: SeasonRequestSchema) -> None:
|
||||
db.delete(db.get(SeasonRequest, season_request.id))
|
||||
db.add(SeasonRequest(**season_request.model_dump()))
|
||||
db.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
session = database.sessionmaker(autocommit=False, autoflush=False, bind=database.engine)()
|
||||
pprint.pprint(get_season_requests(db=session))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import logging
|
||||
import pprint
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
import metadataProvider
|
||||
import tv.repository
|
||||
import tv.service
|
||||
from auth.users import current_active_user, current_superuser
|
||||
from database import DbSessionDependency
|
||||
@@ -12,8 +11,9 @@ from indexer.schemas import PublicIndexerQueryResult, IndexerQueryResultId
|
||||
from metadataProvider.schemas import MetaDataProviderShowSearchResult
|
||||
from torrent.schemas import Torrent
|
||||
from tv.exceptions import MediaAlreadyExists
|
||||
from tv.schemas import Show, SeasonRequest, ShowId, RichShowTorrent, PublicShow, SeasonId, SeasonFile, PublicSeasonFile, \
|
||||
SeasonNumber
|
||||
from tv.schemas import Show, SeasonRequest, ShowId, RichShowTorrent, PublicShow, PublicSeasonFile, SeasonNumber, \
|
||||
CreateSeasonRequest, SeasonRequestId, UpdateSeasonRequest, RichSeasonRequest
|
||||
from auth.db import User
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -23,10 +23,8 @@ router = APIRouter()
|
||||
# --------------------------------
|
||||
|
||||
@router.post("/shows", status_code=status.HTTP_201_CREATED, dependencies=[Depends(current_active_user)],
|
||||
responses={
|
||||
status.HTTP_201_CREATED: {"model": Show, "description": "Successfully created show"},
|
||||
status.HTTP_409_CONFLICT: {"model": str, "description": "Show already exists"},
|
||||
})
|
||||
responses={status.HTTP_201_CREATED: {"model": Show, "description": "Successfully created show"},
|
||||
status.HTTP_409_CONFLICT: {"model": str, "description": "Show already exists"}, })
|
||||
def add_a_show(db: DbSessionDependency, show_id: int, metadata_provider: str = "tmdb"):
|
||||
try:
|
||||
show = tv.service.add_show(db=db, external_id=show_id, metadata_provider=metadata_provider, )
|
||||
@@ -52,6 +50,7 @@ def get_all_shows(db: DbSessionDependency, external_id: int = None, metadata_pro
|
||||
else:
|
||||
return tv.service.get_all_shows(db=db)
|
||||
|
||||
|
||||
@router.get("/shows/torrents", dependencies=[Depends(current_active_user)], response_model=list[RichShowTorrent])
|
||||
def get_shows_with_torrents(db: DbSessionDependency):
|
||||
"""
|
||||
@@ -61,6 +60,7 @@ def get_shows_with_torrents(db: DbSessionDependency):
|
||||
result = tv.service.get_all_shows_with_torrents(db=db)
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/shows/{show_id}", dependencies=[Depends(current_active_user)], response_model=PublicShow)
|
||||
def get_a_show(db: DbSessionDependency, show_id: ShowId):
|
||||
return tv.service.get_public_show_by_id(db=db, show_id=show_id)
|
||||
@@ -71,21 +71,34 @@ def get_a_shows_torrents(db: DbSessionDependency, show_id: ShowId):
|
||||
return tv.service.get_torrents_for_show(db=db, show=tv.service.get_show_by_id(db=db, show_id=show_id))
|
||||
|
||||
|
||||
# TODO: replace by route with season_id rather than show_id and season_number
|
||||
@router.get("/shows/{show_id}/{season_number}/files", status_code=status.HTTP_200_OK,
|
||||
dependencies=[Depends(current_active_user)])
|
||||
def get_season_files(db: DbSessionDependency, season_number: SeasonNumber, show_id: ShowId) -> list[PublicSeasonFile]:
|
||||
return tv.service.get_public_season_files_by_season_number(db=db, season_number=season_number, show_id=show_id)
|
||||
|
||||
|
||||
@router.get("/shows/{show_id}/{season_number}/requests", status_code=status.HTTP_200_OK,
|
||||
dependencies=[Depends(current_active_user)], response_model=list[RichSeasonRequest])
|
||||
def get_season_files(db: DbSessionDependency, season_number: SeasonNumber, show_id: ShowId) -> list[RichSeasonRequest]:
|
||||
return None
|
||||
|
||||
|
||||
# --------------------------------
|
||||
# MANAGE REQUESTS
|
||||
# --------------------------------
|
||||
|
||||
@router.post("/seasons/requests", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)])
|
||||
def request_a_season(db: DbSessionDependency, season_request: SeasonRequest):
|
||||
@router.post("/seasons/requests", status_code=status.HTTP_200_OK, response_model=RichSeasonRequest)
|
||||
def request_a_season(db: DbSessionDependency, user: Annotated[User, Depends(current_active_user)],
|
||||
season_request: CreateSeasonRequest):
|
||||
"""
|
||||
adds request flag to a season
|
||||
"""
|
||||
tv.service.request_season(db=db, season_request=season_request)
|
||||
request: SeasonRequest = SeasonRequest.model_validate(season_request)
|
||||
request.requested_by = user.id
|
||||
|
||||
tv.service.request_season(db=db, season_request=request)
|
||||
return request
|
||||
|
||||
|
||||
@router.get("/seasons/requests", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)])
|
||||
@@ -93,20 +106,34 @@ def get_requested_seasons(db: DbSessionDependency) -> list[SeasonRequest]:
|
||||
return tv.service.get_all_requested_seasons(db=db)
|
||||
|
||||
|
||||
@router.delete("/seasons/requests", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)])
|
||||
def unrequest_season(db: DbSessionDependency, request: SeasonRequest):
|
||||
@router.patch("/seasons/requests/{season_request_id}", status_code=status.HTTP_200_OK, response_model=SeasonRequest)
|
||||
def authorize_request(db: DbSessionDependency, user: Annotated[User, Depends(current_superuser)],
|
||||
season_request_id: SeasonRequestId, authorized_status: bool = False):
|
||||
"""
|
||||
updates the request flag to true
|
||||
"""
|
||||
season_request: SeasonRequest = tv.repository.get_season_request(db=db, season_request_id=season_request_id)
|
||||
season_request.authorized_by = user.id
|
||||
season_request.authorized = authorized_status
|
||||
tv.service.update_season_request(db=db, season_request=season_request)
|
||||
return season_request
|
||||
|
||||
|
||||
@router.put("/seasons/requests/{season_request_id}", status_code=status.HTTP_200_OK, response_model=SeasonRequest)
|
||||
def update_request(db: DbSessionDependency, user: Annotated[User, Depends(current_superuser)],
|
||||
season_request: UpdateSeasonRequest):
|
||||
season_request: SeasonRequest = SeasonRequest.model_validate(season_request)
|
||||
season_request.requested_by = user.id
|
||||
tv.service.update_season_request(db=db, season_request=season_request)
|
||||
return season_request
|
||||
|
||||
|
||||
@router.delete("/seasons/requests/{season_request_id}", status_code=status.HTTP_204_NO_CONTENT,
|
||||
dependencies=[Depends(current_active_user)])
|
||||
def delete_season_request(db: DbSessionDependency, request: SeasonRequest):
|
||||
tv.service.unrequest_season(db=db, season_request=request)
|
||||
|
||||
|
||||
# --------------------------------
|
||||
# MANAGE SEASON FILES
|
||||
# --------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# --------------------------------
|
||||
# MANAGE TORRENTS
|
||||
# --------------------------------
|
||||
@@ -128,6 +155,7 @@ def download_a_torrent(db: DbSessionDependency, public_indexer_result_id: Indexe
|
||||
return tv.service.download_torrent(db=db, public_indexer_result_id=public_indexer_result_id, show_id=show_id,
|
||||
override_show_file_path_suffix=override_file_path_suffix)
|
||||
|
||||
|
||||
# --------------------------------
|
||||
# SEARCH SHOWS ON METADATA PROVIDERS
|
||||
# --------------------------------
|
||||
|
||||
@@ -3,6 +3,7 @@ import uuid
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field, ConfigDict
|
||||
from tvdb_v4_official import Request
|
||||
|
||||
from torrent.models import Quality
|
||||
from torrent.schemas import TorrentId, TorrentStatus
|
||||
@@ -13,7 +14,7 @@ EpisodeId = typing.NewType("EpisodeId", UUID)
|
||||
|
||||
SeasonNumber = typing.NewType("SeasonNumber", int)
|
||||
EpisodeNumber = typing.NewType("EpisodeNumber", int)
|
||||
|
||||
SeasonRequestId = typing.NewType("SeasonRequestId", UUID)
|
||||
|
||||
class Episode(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -53,14 +54,36 @@ class Show(BaseModel):
|
||||
seasons: list[Season]
|
||||
|
||||
|
||||
class SeasonRequest(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
class SeasonRequestBase(BaseModel):
|
||||
season_id: SeasonId
|
||||
min_quality: Quality
|
||||
wanted_quality: Quality
|
||||
|
||||
|
||||
class CreateSeasonRequest(SeasonRequestBase):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateSeasonRequest(SeasonRequestBase):
|
||||
id: SeasonRequestId
|
||||
|
||||
|
||||
class SeasonRequest(SeasonRequestBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: SeasonRequestId = Field(default_factory=uuid.uuid4)
|
||||
|
||||
requested_by: UUID | None = None
|
||||
authorized: bool = False
|
||||
authorized_by: UUID | None = None
|
||||
|
||||
|
||||
class RichSeasonRequest(SeasonRequest):
|
||||
show_id: ShowId
|
||||
show_name: str
|
||||
show_year: int | None
|
||||
season_number: SeasonNumber
|
||||
|
||||
class SeasonFile(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@@ -73,6 +96,7 @@ class SeasonFile(BaseModel):
|
||||
class PublicSeasonFile(SeasonFile):
|
||||
downloaded: bool = False
|
||||
|
||||
|
||||
class RichSeasonTorrent(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@@ -85,6 +109,7 @@ class RichSeasonTorrent(BaseModel):
|
||||
file_path_suffix: str
|
||||
seasons: list[SeasonNumber]
|
||||
|
||||
|
||||
class RichShowTorrent(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from pydantic.v1 import UUID4
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import indexer.service
|
||||
@@ -14,7 +15,7 @@ from tv import log
|
||||
from tv.exceptions import MediaAlreadyExists
|
||||
from tv.repository import add_season_file, get_season_files_by_season_id
|
||||
from tv.schemas import Show, ShowId, SeasonRequest, SeasonFile, SeasonId, Season, RichShowTorrent, RichSeasonTorrent, \
|
||||
PublicSeason, PublicShow, PublicSeasonFile, SeasonNumber
|
||||
PublicSeason, PublicShow, PublicSeasonFile, SeasonNumber, SeasonRequestId
|
||||
|
||||
|
||||
def add_show(db: Session, external_id: int, metadata_provider: str) -> Show | None:
|
||||
@@ -30,6 +31,9 @@ def request_season(db: Session, season_request: SeasonRequest) -> None:
|
||||
tv.repository.add_season_to_requested_list(db=db, season_request=season_request)
|
||||
|
||||
|
||||
def update_season_request(db: Session, season_request: SeasonRequest) -> None:
|
||||
tv.repository.update_season_request(db=db, season_request=season_request)
|
||||
|
||||
def unrequest_season(db: Session, season_request: SeasonRequest) -> None:
|
||||
tv.repository.remove_season_from_requested_list(db=db, season_request=season_request)
|
||||
|
||||
@@ -181,3 +185,11 @@ def download_torrent(db: Session, public_indexer_result_id: IndexerQueryResultId
|
||||
file_path_suffix=override_show_file_path_suffix)
|
||||
add_season_file(db=db, season_file=season_file)
|
||||
return show_torrent
|
||||
|
||||
|
||||
def get_season_requests_by_season_id(db: Session, season_id: SeasonId) -> list[SeasonRequest]:
|
||||
return [x for x in tv.repository.get_season_requests(db=db) if x.season_id == season_id]
|
||||
|
||||
|
||||
def get_season_requests_by_show_id(db: Session, show_id: ShowId) -> list[SeasonRequest]:
|
||||
return [x for x in tv.repository.get_season_requests(db=db) if x.show_id == show_id]
|
||||
|
||||
Reference in New Issue
Block a user