mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-28 03:39:34 +02:00
it's working!?
This commit is contained in:
@@ -85,3 +85,4 @@ cookie_auth_backend = AuthenticationBackend(
|
||||
fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [bearer_auth_backend, cookie_auth_backend])
|
||||
|
||||
current_active_user = fastapi_users.current_user(active=True)
|
||||
current_superuser = fastapi_users.current_user(active=True, superuser=True)
|
||||
|
||||
@@ -4,7 +4,7 @@ from pydantic_settings import BaseSettings
|
||||
|
||||
|
||||
class BasicConfig(BaseSettings):
|
||||
storage_directory: Path = "./data"
|
||||
image_directory: Path = "./data"
|
||||
tv_directory: Path = "./tv"
|
||||
movie_directory: Path = "./movie"
|
||||
torrent_directory: Path = "./torrent"
|
||||
|
||||
@@ -62,7 +62,7 @@ if basic_config.DEVELOPMENT:
|
||||
basic_config.torrent_directory.mkdir(parents=True, exist_ok=True)
|
||||
basic_config.tv_directory.mkdir(parents=True, exist_ok=True)
|
||||
basic_config.movie_directory.mkdir(parents=True, exist_ok=True)
|
||||
basic_config.storage_directory.mkdir(parents=True, exist_ok=True)
|
||||
basic_config.image_directory.mkdir(parents=True, exist_ok=True)
|
||||
log.warning("Development Mode activated!")
|
||||
else:
|
||||
log.info("Development Mode not activated!")
|
||||
|
||||
@@ -8,7 +8,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AbstractMetadataProvider(ABC):
|
||||
storage_path = config.BasicConfig().storage_directory
|
||||
storage_path = config.BasicConfig().image_directory
|
||||
@property
|
||||
@abstractmethod
|
||||
def name(self) -> str:
|
||||
|
||||
@@ -2,13 +2,18 @@ from fastapi import APIRouter
|
||||
from fastapi import status
|
||||
from fastapi.params import Depends
|
||||
|
||||
from auth.users import current_active_user
|
||||
from auth.users import current_active_user, current_superuser
|
||||
from torrent.dependencies import TorrentServiceDependency
|
||||
from torrent.schemas import TorrentId, Torrent
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/{torrent_id}", status_code=status.HTTP_200_OK, response_model=Torrent)
|
||||
def get_torrent(service: TorrentServiceDependency, torrent_id: TorrentId):
|
||||
return service.get_torrent_by_id(id=torrent_id)
|
||||
|
||||
|
||||
@router.get("/", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)],
|
||||
response_model=list[Torrent])
|
||||
def get_all_torrents(service: TorrentServiceDependency, ):
|
||||
@@ -27,11 +32,6 @@ def import_all_torrents(service: TorrentServiceDependency):
|
||||
return service.import_all_torrents()
|
||||
|
||||
|
||||
@router.get("/{torrent_id}", status_code=status.HTTP_200_OK, response_model=Torrent)
|
||||
def get_torrent(service: TorrentServiceDependency, torrent_id: TorrentId):
|
||||
return service.get_torrent_by_id(id=torrent_id)
|
||||
|
||||
|
||||
@router.delete("/torrents", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)])
|
||||
@router.delete("/{torrent_id}", status_code=status.HTTP_200_OK, dependencies=[Depends(current_superuser)])
|
||||
def delete_torrent(service: TorrentServiceDependency, torrent_id: TorrentId):
|
||||
service.delete_torrent(torrent_id=torrent_id)
|
||||
|
||||
@@ -19,7 +19,7 @@ from config import BasicConfig
|
||||
from indexer import IndexerQueryResult
|
||||
from torrent.repository import get_seasons_files_of_torrent, get_show_of_torrent, save_torrent
|
||||
from torrent.schemas import Torrent, TorrentStatus, TorrentId
|
||||
from torrent.utils import list_files_recursively, get_torrent_filepath
|
||||
from torrent.utils import list_files_recursively, get_torrent_filepath, import_file
|
||||
from tv.schemas import SeasonFile, Show
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -139,21 +139,25 @@ class TorrentService:
|
||||
self.api_client.torrents_resume(torrent_hashes=torrent.hash)
|
||||
return self.get_torrent_status(torrent=torrent)
|
||||
|
||||
# TODO: add function to differentiate between .srt files and stuff
|
||||
# TODO: add function to import .srt files
|
||||
def import_torrent(self, torrent: Torrent) -> Torrent:
|
||||
log.info(f"importing torrent {torrent}")
|
||||
all_files = list_files_recursively(path=get_torrent_filepath(torrent=torrent))
|
||||
log.debug(f"Found {len(all_files)} files downloaded by the torrent")
|
||||
files = []
|
||||
subtitle_files = []
|
||||
for file in all_files:
|
||||
file_type = mimetypes.guess_file_type(file)
|
||||
if file_type[0] is not None:
|
||||
if file_type[0].startswith("video"):
|
||||
files.append(file)
|
||||
log.debug(f"File is a video, it will be imported: {file}")
|
||||
elif file_type[0].startswith("text") and file.suffix == ".srt":
|
||||
subtitle_files.append(file)
|
||||
log.debug(f"File is a subtitle, it will be imported: {file}")
|
||||
else:
|
||||
log.debug(f"File is not a video, will not be imported: {file}")
|
||||
log.debug(f"Importing these {len(files)} files:\n" + pprint.pformat(files))
|
||||
log.info(f"Importing these {len(files)} files:\n" + pprint.pformat(files))
|
||||
|
||||
show: Show = get_show_of_torrent(db=self.db, torrent_id=torrent.id)
|
||||
show_file_path = BasicConfig().tv_directory / f"{show.name} ({show.year}) [{show.metadata_provider}id-{show.external_id}]"
|
||||
@@ -162,26 +166,42 @@ class TorrentService:
|
||||
for season_file in season_files:
|
||||
season = tv.service.get_season(db=self.db, season_id=season_file.season_id)
|
||||
season_path = show_file_path / Path(f"Season {season.number}")
|
||||
|
||||
try:
|
||||
season_path.mkdir(parents=True)
|
||||
except FileExistsError:
|
||||
log.warning(f"Path already exists: {season_path}")
|
||||
|
||||
for episode in season.episodes:
|
||||
episode_file_name = f"{show.name} S{season.number:02d}E{episode.number:02d}"
|
||||
if season_file.file_path_suffix != "":
|
||||
episode_file_name += f" - {season_file.file_path_suffix}"
|
||||
target_file = season_path / episode_file_name
|
||||
|
||||
pattern = r'.*[.]S0?' + str(season.number) + r'E0?' + str(episode.number) + r"[.].*"
|
||||
subtitle_pattern = pattern + r"[.]([A-Za-z]{2})[.]srt"
|
||||
target_file_name = season_path / episode_file_name
|
||||
|
||||
# import subtitles
|
||||
for subtitle_file in subtitle_files:
|
||||
log.debug(f"Searching for pattern {subtitle_pattern} in subtitle file: {subtitle_file.name}")
|
||||
regex_result = re.search(subtitle_pattern, subtitle_file.name)
|
||||
if regex_result:
|
||||
language_code = regex_result.group(1)
|
||||
log.debug(
|
||||
f"Found matching pattern: {subtitle_pattern} in subtitle file: {subtitle_file.name}," +
|
||||
f" extracted language code: {language_code}")
|
||||
target_subtitle_file = target_file_name.with_suffix(f".{language_code}.srt")
|
||||
import_file(target_file=target_subtitle_file, source_file=subtitle_file)
|
||||
else:
|
||||
log.debug(f"Didn't find any pattern {subtitle_pattern} in subtitle file: {subtitle_file.name}")
|
||||
|
||||
# import episode videos
|
||||
for file in files:
|
||||
pattern = r'.*[.]S0?' + str(season.number) + r'E0?' + str(episode.number) + r"[.].*"
|
||||
# NOTE: irgendwos passt mit file.name glauwi ned????
|
||||
log.debug(f"Searching for pattern {pattern} in file: {file.name}")
|
||||
log.debug(f"Searching for pattern {pattern} in video file: {file.name}")
|
||||
if re.search(pattern, file.name):
|
||||
log.debug(f"Found matching pattern: {pattern} in file {file.name}")
|
||||
target_file = target_file.with_suffix(file.suffix)
|
||||
if target_file.exists():
|
||||
target_file.unlink()
|
||||
|
||||
target_file.hardlink_to(file)
|
||||
target_video_file = target_file_name.with_suffix(file.suffix)
|
||||
import_file(target_file=target_video_file, source_file=file)
|
||||
break
|
||||
else:
|
||||
log.warning(f"S{season.number}E{episode.number} in Torrent {torrent.title}'s files not found.")
|
||||
|
||||
@@ -22,3 +22,9 @@ def list_files_recursively(path: Path = Path(".")) -> list[Path]:
|
||||
|
||||
def get_torrent_filepath(torrent: Torrent):
|
||||
return BasicConfig().torrent_directory / torrent.title
|
||||
|
||||
|
||||
def import_file(target_file: Path, source_file: Path):
|
||||
if target_file.exists():
|
||||
target_file.unlink()
|
||||
target_file.hardlink_to(source_file)
|
||||
|
||||
@@ -3,7 +3,7 @@ from fastapi.responses import JSONResponse
|
||||
|
||||
import metadataProvider
|
||||
import tv.service
|
||||
from auth.users import current_active_user
|
||||
from auth.users import current_active_user, current_superuser
|
||||
from database import DbSessionDependency
|
||||
from indexer.schemas import PublicIndexerQueryResult, IndexerQueryResultId
|
||||
from tv.exceptions import MediaAlreadyExists
|
||||
@@ -87,12 +87,14 @@ def unrequest_season(db: DbSessionDependency, request: SeasonRequest):
|
||||
# 1 is the default for season_number because it returns multi season torrents
|
||||
@router.get("/torrents", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)],
|
||||
response_model=list[PublicIndexerQueryResult])
|
||||
def get_torrents_for_a_season(db: DbSessionDependency, show_id: ShowId, season_number: int = 1):
|
||||
return tv.service.get_all_available_torrents_for_a_season(db=db, season_number=season_number, show_id=show_id)
|
||||
def get_torrents_for_a_season(db: DbSessionDependency, show_id: ShowId, season_number: int = 1,
|
||||
search_query_override: str = None):
|
||||
return tv.service.get_all_available_torrents_for_a_season(db=db, season_number=season_number, show_id=show_id,
|
||||
search_query_override=search_query_override)
|
||||
|
||||
|
||||
# download a torrent
|
||||
@router.post("/torrents", status_code=status.HTTP_200_OK, dependencies=[Depends(current_active_user)])
|
||||
@router.post("/torrents", status_code=status.HTTP_200_OK, dependencies=[Depends(current_superuser)])
|
||||
def download_a_torrent(db: DbSessionDependency, public_indexer_result_id: IndexerQueryResultId, show_id: ShowId,
|
||||
override_file_path_suffix: str = ""):
|
||||
return tv.service.download_torrent(db=db, public_indexer_result_id=public_indexer_result_id, show_id=show_id,
|
||||
|
||||
@@ -48,11 +48,16 @@ def check_if_show_exists(db: Session,
|
||||
raise ValueError("External ID and metadata provider or Show ID must be provided")
|
||||
|
||||
|
||||
def get_all_available_torrents_for_a_season(db: Session, season_number: int, show_id: ShowId) -> list[
|
||||
def get_all_available_torrents_for_a_season(db: Session, season_number: int, show_id: ShowId,
|
||||
search_query_override: str = None) -> list[
|
||||
IndexerQueryResult]:
|
||||
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)
|
||||
torrents: list[IndexerQueryResult] = indexer.service.search(query=show.name + " S" + str(season_number), db=db)
|
||||
if search_query_override is not None:
|
||||
search_query = search_query_override
|
||||
else:
|
||||
search_query = show.name + " Season " + str(season_number)
|
||||
torrents: list[IndexerQueryResult] = indexer.service.search(query=search_query, db=db)
|
||||
result: list[IndexerQueryResult] = []
|
||||
for torrent in torrents:
|
||||
if season_number in torrent.season:
|
||||
|
||||
Reference in New Issue
Block a user