switch to uv and remove old logo.svg

This commit is contained in:
maxDorninger
2025-05-29 21:44:26 +02:00
parent 727051611c
commit 88c72e3303
16 changed files with 1293 additions and 263 deletions

158
logo.svg
View File

@@ -1,158 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:svg="http://www.w3.org/2000/svg"
version="1.1"
id="svg1"
width="2000"
height="2000"
viewBox="0 0 2000 2000"
sodipodi:docname="logo.svg"
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1">
<path
d="M 0,1500 H 1500 V 0 H 0 Z"
id="path1"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath3">
<path
d="M 0,0 H 1500 V 1500 H 0 Z"
transform="matrix(1.3333333,0,0,-1.3333333,0,2000)"
id="path3"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4">
<path
d="M 162.861,1482.87 H 1561.64 V 291.538 H 162.861 Z"
transform="translate(-1227.7596,-574.95099)"
id="path4"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6">
<path
d="M 0,0 H 1500 V 1500 H 0 Z"
transform="matrix(1.3333333,0,0,-1.3333333,0,2000)"
id="path6"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath7">
<path
d="M 57.6551,1352.2 H 1456.43 V 160.865 H 57.6551 Z"
transform="translate(-1122.5541,-444.27759)"
id="path7"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath9">
<path
d="M 0,0 H 1500 V 1500 H 0 Z"
transform="matrix(1.3333333,0,0,-1.3333333,0,2000)"
id="path9"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath10">
<path
d="M -61.6302,1208.46 H 1337.15 V 17.1253 H -61.6302 Z"
transform="translate(-1003.2687,-300.53828)"
id="path10"/>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath12">
<path
d="M 0,0 H 1500 V 1500 H 0 Z"
transform="matrix(1.3333333,0,0,-1.3333333,0,2000)"
id="path12"/>
</clipPath>
</defs>
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.9075"
inkscape:cx="999.44904"
inkscape:cy="1000"
inkscape:window-width="3840"
inkscape:window-height="2054"
inkscape:window-x="3373"
inkscape:window-y="199"
inkscape:window-maximized="1"
inkscape:current-layer="g1">
<inkscape:page
x="0"
y="0"
inkscape:label="1"
id="page1"
width="2000"
height="2000"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<g
id="g1"
inkscape:groupmode="layer"
inkscape:label="1">
<g
id="g2"
clip-path="url(#clipPath3)">
<path
d="M 0,0 H 1500 V 1500 H 0 Z"
style="fill:#9ed8f7;fill-opacity:0;fill-rule:nonzero;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,0,2000)"
clip-path="url(#clipPath1)"
id="path2"/>
</g>
<g
opacity="0.720001"
id="g5"
clip-path="url(#clipPath6)">
<path
d="m 0,0 -662.988,-241.307 c -68.294,-24.856 -140.454,25.942 -140.088,98.618 l 3.371,669.629 c 0.22,43.692 27.626,82.623 68.683,97.567 L -68.034,865.813 C 0.26,890.67 72.42,839.872 72.054,767.196 L 68.683,97.566 C 68.463,53.876 41.057,14.943 0,0"
style="fill:#2842fc;fill-opacity:1;fill-rule:nonzero;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,1637.0128,1233.3987)"
clip-path="url(#clipPath4)"
id="path5"/>
</g>
<g
opacity="0.720001"
id="g8"
clip-path="url(#clipPath9)">
<path
d="m 0,0 -662.988,-241.307 c -68.293,-24.856 -140.454,25.942 -140.088,98.618 l 3.371,669.629 c 0.22,43.692 27.626,82.623 68.683,97.567 L -68.034,865.813 C 0.26,890.67 72.42,839.872 72.054,767.196 L 68.683,97.566 C 68.463,53.876 41.057,14.943 0,0"
style="fill:#ff5e00;fill-opacity:1;fill-rule:nonzero;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,1496.7387,1407.6299)"
clip-path="url(#clipPath7)"
id="path8"/>
</g>
<g
opacity="0.75"
id="g11"
clip-path="url(#clipPath12)">
<path
d="m 0,0 -662.988,-241.307 c -68.294,-24.856 -140.454,25.942 -140.088,98.618 l 3.371,669.629 c 0.22,43.692 27.626,82.623 68.683,97.567 L -68.034,865.814 C 0.26,890.67 72.42,839.872 72.054,767.196 L 68.683,97.566 C 68.463,53.876 41.057,14.943 0,0"
style="fill:#f20a4c;fill-opacity:1;fill-rule:nonzero;stroke:none"
transform="matrix(1.3333333,0,0,-1.3333333,1337.6916,1599.2823)"
clip-path="url(#clipPath10)"
id="path11"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.2 KiB

View File

View File

@@ -1,4 +1,3 @@
from pydantic import EmailStr
from pydantic_settings import BaseSettings, SettingsConfigDict

View File

@@ -1,6 +1,6 @@
from sqlalchemy.orm import Session
import indexer.repository
import media_manager.indexer.repository
from media_manager.indexer import IndexerQueryResult, log, indexers
from media_manager.indexer.repository import save_result
from media_manager.indexer.schemas import IndexerQueryResultId
@@ -22,4 +22,4 @@ def search(query: str, db: Session) -> list[IndexerQueryResult]:
def get_indexer_query_result(
result_id: IndexerQueryResultId, db: Session
) -> IndexerQueryResult:
return indexer.repository.get_result(result_id=result_id, db=db)
return media_manager.indexer.repository.get_result(result_id=result_id, db=db)

View File

@@ -1,8 +1,8 @@
import logging
from cachetools import TTLCache, cached
import metadataProvider.tmdb
import metadataProvider.tvdb
import media_manager.metadataProvider.tmdb
import media_manager.metadataProvider.tvdb
from media_manager.metadataProvider.abstractMetaDataProvider import metadata_providers
from media_manager.metadataProvider.schemas import MetaDataProviderShowSearchResult
from media_manager.tv.schemas import Show

View File

@@ -1,7 +1,7 @@
import logging
from abc import ABC, abstractmethod
import config
import media_manager.config
from media_manager.metadataProvider.schemas import MetaDataProviderShowSearchResult
from media_manager.tv.schemas import Show
@@ -9,7 +9,7 @@ log = logging.getLogger(__name__)
class AbstractMetadataProvider(ABC):
storage_path = config.BasicConfig().image_directory
storage_path = media_manager.config.BasicConfig().image_directory
@property
@abstractmethod

View File

@@ -1,12 +1,10 @@
import logging
import mimetypes
import requests
import tmdbsimple
from pydantic_settings import BaseSettings
from tmdbsimple import TV, TV_Seasons
import metadataProvider.utils
import media_manager.metadataProvider.utils
from media_manager.metadataProvider.abstractMetaDataProvider import (
AbstractMetadataProvider,
register_metadata_provider,
@@ -62,7 +60,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
)
)
year = metadataProvider.utils.get_year_from_first_air_date(
year = media_manager.metadataProvider.utils.get_year_from_first_air_date(
show_metadata["first_air_date"]
)
@@ -81,7 +79,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
poster_url = (
"https://image.tmdb.org/t/p/original" + show_metadata["poster_path"]
)
if metadataProvider.utils.download_poster_image(
if media_manager.metadataProvider.utils.download_poster_image(
storage_path=self.storage_path, poster_url=poster_url, show=show
):
log.info("Successfully downloaded poster image for show " + show.name)
@@ -130,7 +128,7 @@ class TmdbMetadataProvider(AbstractMetadataProvider):
overview=result["overview"],
name=result["name"],
external_id=result["id"],
year=metadataProvider.utils.get_year_from_first_air_date(
year=media_manager.metadataProvider.utils.get_year_from_first_air_date(
result["first_air_date"]
),
metadata_provider=self.name,

View File

@@ -1,22 +1,17 @@
import pprint
from functools import cache
import tvdb_v4_official
import logging
import mimetypes
import requests
import tmdbsimple
from pydantic_settings import BaseSettings
from tmdbsimple import TV, TV_Seasons
import metadataProvider.utils
import media_manager.metadataProvider.utils
from media_manager.metadataProvider.abstractMetaDataProvider import (
AbstractMetadataProvider,
register_metadata_provider,
)
from media_manager.metadataProvider.schemas import MetaDataProviderShowSearchResult
from media_manager.tv.schemas import Episode, Season, Show, SeasonNumber, EpisodeNumber
from media_manager.tv.schemas import Episode, Season, Show
class TvdbConfig(BaseSettings):
@@ -77,7 +72,7 @@ class TvdbMetadataProvider(AbstractMetadataProvider):
)
if series["image"] is not None:
metadataProvider.utils.download_poster_image(
media_manager.metadataProvider.utils.download_poster_image(
storage_path=self.storage_path, poster_url=series["image"], show=show
)
else:

View File

@@ -12,10 +12,10 @@ from fastapi_utils.tasks import repeat_every
from pydantic_settings import BaseSettings, SettingsConfigDict
from sqlalchemy.orm import Session
import torrent.repository
import tv.repository
import tv.service
from config import BasicConfig
import media_manager.torrent.repository
import media_manager.tv.repository
import media_manager.tv.service
from media_manager.config import BasicConfig
from media_manager.indexer import IndexerQueryResult
from media_manager.torrent.repository import (
get_seasons_files_of_torrent,
@@ -215,7 +215,9 @@ class TorrentService:
# creating directories and hard linking files
for season_file in season_files:
season = tv.service.get_season(db=self.db, season_id=season_file.season_id)
season = media_manager.tv.service.get_season(
db=self.db, season_id=season_file.season_id
)
season_path = show_file_path / Path(f"Season {season.number}")
try:
@@ -286,21 +288,25 @@ class TorrentService:
def get_all_torrents(self) -> list[Torrent]:
return [
self.get_torrent_status(x)
for x in torrent.repository.get_all_torrents(db=self.db)
for x in media_manager.torrent.repository.get_all_torrents(db=self.db)
]
def get_torrent_by_id(self, id: TorrentId) -> Torrent:
return self.get_torrent_status(
torrent.repository.get_torrent_by_id(torrent_id=id, db=self.db)
media_manager.torrent.repository.get_torrent_by_id(
torrent_id=id, db=self.db
)
)
def delete_torrent(self, torrent_id: TorrentId):
t = torrent.repository.get_torrent_by_id(torrent_id=torrent_id, db=self.db)
t = media_manager.torrent.repository.get_torrent_by_id(
torrent_id=torrent_id, db=self.db
)
if not t.imported:
tv.repository.remove_season_files_by_torrent_id(
media_manager.tv.repository.remove_season_files_by_torrent_id(
db=self.db, torrent_id=torrent_id
)
torrent.repository.delete_torrent(db=self.db, torrent_id=t.id)
media_manager.torrent.repository.delete_torrent(db=self.db, torrent_id=t.id)
@repeat_every(seconds=3600)
def import_all_torrents(self) -> list[Torrent]:

View File

@@ -4,7 +4,7 @@ from pathlib import Path
import patoolib
from config import BasicConfig
from media_manager.config import BasicConfig
from media_manager.torrent.schemas import Torrent
log = logging.getLogger(__name__)

View File

@@ -3,8 +3,8 @@ from typing import Annotated
from fastapi import APIRouter, Depends, status
from fastapi.responses import JSONResponse
import tv.repository
import tv.service
import media_manager.tv.repository
import media_manager.tv.service
from media_manager.auth.db import User
from media_manager.auth.schemas import UserRead
from media_manager.auth.users import current_active_user, current_superuser
@@ -50,7 +50,7 @@ router = APIRouter()
)
def add_a_show(db: DbSessionDependency, show_id: int, metadata_provider: str = "tmdb"):
try:
show = tv.service.add_show(
show = media_manager.tv.service.add_show(
db=db,
external_id=show_id,
metadata_provider=metadata_provider,
@@ -84,11 +84,11 @@ def get_all_shows(
db: DbSessionDependency, external_id: int = None, metadata_provider: str = "tmdb"
):
if external_id is not None:
return tv.service.get_show_by_external_id(
return media_manager.tv.service.get_show_by_external_id(
db=db, external_id=external_id, metadata_provider=metadata_provider
)
else:
return tv.service.get_all_shows(db=db)
return media_manager.tv.service.get_all_shows(db=db)
@router.get(
@@ -101,7 +101,7 @@ def get_shows_with_torrents(db: DbSessionDependency):
get all shows that are associated with torrents
:return: A list of shows with all their torrents
"""
result = tv.service.get_all_shows_with_torrents(db=db)
result = media_manager.tv.service.get_all_shows_with_torrents(db=db)
return result
@@ -111,7 +111,7 @@ def get_shows_with_torrents(db: DbSessionDependency):
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)
return media_manager.tv.service.get_public_show_by_id(db=db, show_id=show_id)
@router.get(
@@ -120,8 +120,8 @@ def get_a_show(db: DbSessionDependency, show_id: ShowId):
response_model=RichShowTorrent,
)
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)
return media_manager.tv.service.get_torrents_for_show(
db=db, show=media_manager.tv.service.get_show_by_id(db=db, show_id=show_id)
)
@@ -134,7 +134,7 @@ def get_a_shows_torrents(db: DbSessionDependency, show_id: ShowId):
def get_season_files(
db: DbSessionDependency, season_number: SeasonNumber, show_id: ShowId
) -> list[PublicSeasonFile]:
return tv.service.get_public_season_files_by_season_number(
return media_manager.tv.service.get_public_season_files_by_season_number(
db=db, season_number=season_number, show_id=show_id
)
@@ -158,7 +158,7 @@ def request_a_season(
if user.is_superuser:
request.authorized = True
request.authorized_by = user
tv.service.add_season_request(db=db, season_request=request)
media_manager.tv.service.add_season_request(db=db, season_request=request)
return
@@ -169,7 +169,7 @@ def request_a_season(
response_model=list[RichSeasonRequest],
)
def get_season_requests(db: DbSessionDependency) -> list[RichSeasonRequest]:
return tv.service.get_all_season_requests(db=db)
return media_manager.tv.service.get_all_season_requests(db=db)
@router.delete(
@@ -181,9 +181,13 @@ def delete_season_request(
user: Annotated[User, Depends(current_active_user)],
request_id: SeasonRequestId,
):
request = tv.service.get_season_request_by_id(db=db, season_request_id=request_id)
request = media_manager.tv.service.get_season_request_by_id(
db=db, season_request_id=request_id
)
if user.is_superuser or request.requested_by.id == user.id:
tv.service.delete_season_request(db=db, season_request_id=request_id)
media_manager.tv.service.delete_season_request(
db=db, season_request_id=request_id
)
log.info(f"User {user.id} deleted season request {request_id}.")
else:
log.warning(
@@ -207,14 +211,14 @@ def authorize_request(
"""
updates the request flag to true
"""
season_request: SeasonRequest = tv.repository.get_season_request(
season_request: SeasonRequest = media_manager.tv.repository.get_season_request(
db=db, season_request_id=season_request_id
)
season_request.authorized_by = UserRead.model_validate(user)
season_request.authorized = authorized_status
if not authorized_status:
season_request.authorized_by = None
tv.service.update_season_request(db=db, season_request=season_request)
media_manager.tv.service.update_season_request(db=db, season_request=season_request)
return
@@ -225,12 +229,14 @@ def update_request(
season_request: UpdateSeasonRequest,
):
season_request: SeasonRequest = SeasonRequest.model_validate(season_request)
request = tv.service.get_season_request_by_id(
request = media_manager.tv.service.get_season_request_by_id(
db=db, season_request_id=season_request.id
)
if request.requested_by.id == user.id or user.is_superuser:
season_request.requested_by = UserRead.model_validate(user)
tv.service.update_season_request(db=db, season_request=season_request)
media_manager.tv.service.update_season_request(
db=db, season_request=season_request
)
return
@@ -252,7 +258,7 @@ def get_torrents_for_a_season(
season_number: int = 1,
search_query_override: str = None,
):
return tv.service.get_all_available_torrents_for_a_season(
return media_manager.tv.service.get_all_available_torrents_for_a_season(
db=db,
season_number=season_number,
show_id=show_id,
@@ -273,7 +279,7 @@ def download_a_torrent(
show_id: ShowId,
override_file_path_suffix: str = "",
):
return tv.service.download_torrent(
return media_manager.tv.service.download_torrent(
db=db,
public_indexer_result_id=public_indexer_result_id,
show_id=show_id,
@@ -294,7 +300,7 @@ def download_a_torrent(
def search_metadata_providers_for_a_show(
db: DbSessionDependency, query: str, metadata_provider: str = "tmdb"
):
return tv.service.search_for_show(
return media_manager.tv.service.search_for_show(
query=query, metadata_provider=metadata_provider, db=db
)
@@ -304,7 +310,7 @@ def search_metadata_providers_for_a_show(
dependencies=[Depends(current_active_user)],
response_model=list[MetaDataProviderShowSearchResult],
)
def search_metadata_providers_for_a_show(
db: DbSessionDependency, metadata_provider: str = "tmdb"
):
return tv.service.get_popular_shows(metadata_provider=metadata_provider, db=db)
def get_recommended_shows(db: DbSessionDependency, metadata_provider: str = "tmdb"):
return media_manager.tv.service.get_popular_shows(
metadata_provider=metadata_provider, db=db
)

View File

@@ -3,7 +3,6 @@ import uuid
from uuid import UUID
from pydantic import BaseModel, Field, ConfigDict, model_validator
from tvdb_v4_official import Request
from media_manager.auth.schemas import UserRead
from media_manager.torrent.models import Quality

View File

@@ -1,10 +1,9 @@
from pydantic.v1 import UUID4
from sqlalchemy.orm import Session
import indexer.service
import metadataProvider
import torrent.repository
import tv.repository
import media_manager.indexer.service
import media_manager.metadataProvider
import media_manager.torrent.repository
import media_manager.tv.repository
from media_manager.indexer import IndexerQueryResult
from media_manager.indexer.schemas import IndexerQueryResultId
from media_manager.metadataProvider.schemas import MetaDataProviderShowSearchResult
@@ -40,30 +39,36 @@ def add_show(db: Session, external_id: int, metadata_provider: str) -> Show | No
f"Show with external ID {external_id} and"
+ f" metadata provider {metadata_provider} already exists"
)
show_with_metadata = metadataProvider.get_show_metadata(
show_with_metadata = media_manager.metadataProvider.get_show_metadata(
id=external_id, provider=metadata_provider
)
saved_show = tv.repository.save_show(db=db, show=show_with_metadata)
saved_show = media_manager.tv.repository.save_show(db=db, show=show_with_metadata)
return saved_show
def add_season_request(db: Session, season_request: SeasonRequest) -> None:
tv.repository.add_season_request(db=db, season_request=season_request)
media_manager.tv.repository.add_season_request(db=db, season_request=season_request)
def get_season_request_by_id(
db: Session, season_request_id: SeasonRequestId
) -> SeasonRequest | None:
return tv.repository.get_season_request(db=db, season_request_id=season_request_id)
return media_manager.tv.repository.get_season_request(
db=db, season_request_id=season_request_id
)
def update_season_request(db: Session, season_request: SeasonRequest) -> None:
tv.repository.delete_season_request(db=db, season_request_id=season_request.id)
tv.repository.add_season_request(db=db, season_request=season_request)
media_manager.tv.repository.delete_season_request(
db=db, season_request_id=season_request.id
)
media_manager.tv.repository.add_season_request(db=db, season_request=season_request)
def delete_season_request(db: Session, season_request_id: SeasonRequestId) -> None:
tv.repository.delete_season_request(db=db, season_request_id=season_request_id)
media_manager.tv.repository.delete_season_request(
db=db, season_request_id=season_request_id
)
def get_public_season_files_by_season_id(
@@ -82,7 +87,7 @@ def get_public_season_files_by_season_id(
def get_public_season_files_by_season_number(
db: Session, season_number: SeasonNumber, show_id: ShowId
) -> list[PublicSeasonFile]:
season = tv.repository.get_season_by_number(
season = media_manager.tv.repository.get_season_by_number(
db=db, season_number=season_number, show_id=show_id
)
return get_public_season_files_by_season_id(db=db, season_id=season.id)
@@ -95,14 +100,14 @@ def check_if_show_exists(
show_id: ShowId = None,
) -> bool:
if external_id and metadata_provider:
if tv.repository.get_show_by_external_id(
if media_manager.tv.repository.get_show_by_external_id(
external_id=external_id, metadata_provider=metadata_provider, db=db
):
return True
else:
return False
elif show_id:
if tv.repository.get_show(show_id=show_id, db=db):
if media_manager.tv.repository.get_show(show_id=show_id, db=db):
return True
else:
return False
@@ -118,13 +123,13 @@ def get_all_available_torrents_for_a_season(
log.debug(
f"getting all available torrents for season {season_number} for show {show_id}"
)
show = tv.repository.get_show(show_id=show_id, db=db)
show = media_manager.tv.repository.get_show(show_id=show_id, db=db)
if search_query_override:
search_query = search_query_override
else:
# TODO: add more Search query strings and combine all the results, like "season 3", "s03", "s3"
search_query = show.name + " s" + str(season_number).zfill(2)
torrents: list[IndexerQueryResult] = indexer.service.search(
torrents: list[IndexerQueryResult] = media_manager.indexer.service.search(
query=search_query, db=db
)
if search_query_override:
@@ -141,13 +146,13 @@ def get_all_available_torrents_for_a_season(
def get_all_shows(db: Session) -> list[Show]:
return tv.repository.get_shows(db=db)
return media_manager.tv.repository.get_shows(db=db)
def search_for_show(
query: str, metadata_provider: str, db: Session
) -> list[MetaDataProviderShowSearchResult]:
results = metadataProvider.search_show(query, metadata_provider)
results = media_manager.metadataProvider.search_show(query, metadata_provider)
for result in results:
if check_if_show_exists(
db=db, external_id=result.external_id, metadata_provider=metadata_provider
@@ -157,8 +162,8 @@ def search_for_show(
def get_popular_shows(metadata_provider: str, db: Session):
results: list[MetaDataProviderShowSearchResult] = metadataProvider.search_show(
provider=metadata_provider
results: list[MetaDataProviderShowSearchResult] = (
media_manager.metadataProvider.search_show(provider=metadata_provider)
)
for result in results:
@@ -170,7 +175,7 @@ def get_popular_shows(metadata_provider: str, db: Session):
def get_public_show_by_id(db: Session, show_id: ShowId) -> PublicShow:
show = tv.repository.get_show(show_id=show_id, db=db)
show = media_manager.tv.repository.get_show(show_id=show_id, db=db)
seasons = [PublicSeason.model_validate(season) for season in show.seasons]
for season in seasons:
season.downloaded = is_season_downloaded(db=db, season_id=season.id)
@@ -180,7 +185,7 @@ def get_public_show_by_id(db: Session, show_id: ShowId) -> PublicShow:
def get_show_by_id(db: Session, show_id: ShowId) -> Show:
return tv.repository.get_show(show_id=show_id, db=db)
return media_manager.tv.repository.get_show(show_id=show_id, db=db)
def is_season_downloaded(db: Session, season_id: SeasonId) -> bool:
@@ -196,7 +201,7 @@ def season_file_exists_on_file(db: Session, season_file: SeasonFile) -> bool:
if season_file.torrent_id is None:
return True
else:
torrent_file = torrent.repository.get_torrent_by_id(
torrent_file = media_manager.torrent.repository.get_torrent_by_id(
db=db, torrent_id=season_file.torrent_id
)
if torrent_file.imported:
@@ -208,24 +213,26 @@ def season_file_exists_on_file(db: Session, season_file: SeasonFile) -> bool:
def get_show_by_external_id(
db: Session, external_id: int, metadata_provider: str
) -> Show | None:
return tv.repository.get_show_by_external_id(
return media_manager.tv.repository.get_show_by_external_id(
external_id=external_id, metadata_provider=metadata_provider, db=db
)
def get_season(db: Session, season_id: SeasonId) -> Season:
return tv.repository.get_season(season_id=season_id, db=db)
return media_manager.tv.repository.get_season(season_id=season_id, db=db)
def get_all_season_requests(db: Session) -> list[RichSeasonRequest]:
return tv.repository.get_season_requests(db=db)
return media_manager.tv.repository.get_season_requests(db=db)
def get_torrents_for_show(db: Session, show: Show) -> RichShowTorrent:
show_torrents = tv.repository.get_torrents_by_show_id(db=db, show_id=show.id)
show_torrents = media_manager.tv.repository.get_torrents_by_show_id(
db=db, show_id=show.id
)
rich_season_torrents = []
for show_torrent in show_torrents:
seasons = tv.repository.get_seasons_by_torrent_id(
seasons = media_manager.tv.repository.get_seasons_by_torrent_id(
db=db, torrent_id=show_torrent.id
)
season_files = get_seasons_files_of_torrent(db=db, torrent_id=show_torrent.id)
@@ -250,7 +257,7 @@ def get_torrents_for_show(db: Session, show: Show) -> RichShowTorrent:
def get_all_shows_with_torrents(db: Session) -> list[RichShowTorrent]:
shows = tv.repository.get_all_shows_with_torrents(db=db)
shows = media_manager.tv.repository.get_all_shows_with_torrents(db=db)
return [get_torrents_for_show(show=show, db=db) for show in shows]
@@ -260,13 +267,13 @@ def download_torrent(
show_id: ShowId,
override_show_file_path_suffix: str = "",
) -> Torrent:
indexer_result = indexer.service.get_indexer_query_result(
indexer_result = media_manager.indexer.service.get_indexer_query_result(
db=db, result_id=public_indexer_result_id
)
show_torrent = TorrentService(db=db).download(indexer_result=indexer_result)
for season_number in indexer_result.season:
season = tv.repository.get_season_by_number(
season = media_manager.tv.repository.get_season_by_number(
db=db, season_number=season_number, show_id=show_id
)
season_file = SeasonFile(

28
pyproject.toml Normal file
View File

@@ -0,0 +1,28 @@
[project]
name = "mediamanager"
version = "0.1.0"
description = "Add your description here"
requires-python = ">=3.13"
dependencies = [
"bencoder>=0.2.0",
"cachetools>=6.0.0",
"fastapi[standard]>=0.115.12",
"fastapi-restful[all]>=0.6.0",
"fastapi-users[sqlalchemy]>=14.0.1",
"httpx>=0.28.1",
"httpx-oauth>=0.16.1",
"jsonschema>=4.24.0",
"patool>=4.0.1",
"psycopg[binary]>=3.2.9",
"pydantic>=2.11.5",
"pydantic-settings>=2.9.1",
"python-json-logger>=3.3.0",
"qbittorrent-api>=2025.5.0",
"requests>=2.32.3",
"sqlalchemy>=2.0.41",
"starlette>=0.46.2",
"tmdbsimple>=2.9.1",
"tvdb-v4-official>=1.1.0",
"typing-inspect>=0.9.0",
"uvicorn>=0.34.2",
]

View File

@@ -1,15 +0,0 @@
fastapi==0.115.12
ollama==0.4.7
psycopg==3.2.4
pydantic==2.11.0
pydantic_settings==2.8.1
PyJWT==2.10.1
PyJWT==2.10.1
python_bcrypt==0.3.2
qbittorrent_api==2025.2.0
Requests==2.32.3
SQLAlchemy==2.0.38
sqlmodel==0.0.24
starlette==0.46.1
tmdbsimple==2.9.1
uvicorn==0.34.0

1165
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff