diff --git a/app/download.py b/app/download.py index 5771959..7fd2e52 100644 --- a/app/download.py +++ b/app/download.py @@ -107,7 +107,7 @@ class grab(): print("Downloaded MP4 but no thumbnail found.") class dropout(): - def show(show, season, episode_start): + def show(show, season, archive, episode_start): directory = f'/tv/{show}/Season {season}/' if not os.path.exists(directory): os.makedirs(directory) @@ -167,6 +167,8 @@ class dropout(): 'subtitleslangs': ['en'], 'outtmpl': filename_template, } + if archive: + dl_opts['skip_download'] = True with yt_dlp.YoutubeDL(dl_opts) as ydl: ydl.download([entry['webpage_url']]) diff --git a/app/main.py b/app/main.py index 3ff0dbb..7737b50 100644 --- a/app/main.py +++ b/app/main.py @@ -73,7 +73,7 @@ async def ebookDownload( background_tasks: BackgroundTasks, url: str = Form(...), author: str = Form(...) -): + ): try: background_tasks.add_task(download.ebook,url,author) # download.dropout.show(show,season,episode) @@ -126,26 +126,64 @@ def get_latest_season(item): return None @app.post("/dropout/download", description="Download an entire season from episode 1. Ignores behind the scenes and trailers.") -async def dropoutDownload( +async def dropout_download( background_tasks: BackgroundTasks, show: str = Form(...), season: Optional[int] = Form(None), - latest: bool = Form(False) - ): + latest: bool = Form(False), + archive: bool = Form(False) +): try: - if latest is not False and season is None: - item = await get_show_data(show,True) - if not item: - return JSONResponse(status_code=404, content={"status": "error", "message": "Show not found"}) - season = get_latest_season(item) + # Resolve latest season if requested + if latest and season is None: + show_data = await get_show_data(show, True) + if not show_data: + return JSONResponse( + status_code=404, + content={"status": "error", "message": "Show not found"} + ) + + season = get_latest_season(show_data) if season is None: - return JSONResponse(status_code=400, content={"status": "error", "message": "No valid seasons found"}) - logger.info(f'message=Received download request for season {season} of {show}.') - background_tasks.add_task(download.dropout.show, show, season, None) - return JSONResponse(status_code=200, content={"status": "success", "message": f"Series download started for season {season}."}) + return JSONResponse( + status_code=400, + content={"status": "error", "message": "No valid seasons found"} + ) + + # Ensure season is specified by now + if season is None: + return JSONResponse( + status_code=400, + content={"status": "error", "message": "Season is required unless 'latest' is used."} + ) + + + task_msg = f"{'Adding to archive' if archive else 'Starting download'} for show '{show}', season {season}." + logger.info(f"message={task_msg}") + + # Schedule the background task + background_tasks.add_task(download.dropout.show, show, season, archive, None) + + return JSONResponse( + status_code=200, + content={ + "status": "success", + "message": ( + f"Series is being added to the completed archive for '{show}', season {season}." + if archive else + f"Series download started for '{show}', season {season}." + ) + } + ) + + except Exception as e: - return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) + logger.exception(f"Unhandled exception during /dropout/download: {e}") + return JSONResponse( + status_code=500, + content={"status": "error", "message": "An unexpected error occurred."} + ) @app.post("/dropout/download/specials", description="Downloads a seasons behind the scenes and trailers, ignores main episodes.") async def dropoutDownload(