diff --git a/app/download.py b/app/download.py index 97d6ac5..3bde26f 100644 --- a/app/download.py +++ b/app/download.py @@ -7,7 +7,7 @@ logger = logging.getLogger("syllabus") # Global or outer-scope tracking dictionary last_logged_percent = {} -def my_hook(d): +def my_hook(d): #logging hook status = d.get('status') filename = d.get('filename') @@ -39,26 +39,26 @@ def my_hook(d): -def ebook(url, author): - destination = f"/ebooks/{author}" - os.makedirs(destination, exist_ok=True) # Create the folder if it doesn't exist +# def ebook(url, author): +# destination = f"/ebooks/{author}" +# os.makedirs(destination, exist_ok=True) # Create the folder if it doesn't exist - response = requests.get(url, stream=True) - response.raise_for_status() # Good practice to raise error on bad status +# response = requests.get(url, stream=True) +# response.raise_for_status() # Good practice to raise error on bad status - # Try to extract filename from the headers - cd = response.headers.get('Content-Disposition') - if cd and 'filename=' in cd: - filename = cd.split('filename=')[1].strip('";') - else: - # Fallback: get the last part of the URL - filename = os.path.basename(url) +# # Try to extract filename from the headers +# cd = response.headers.get('Content-Disposition') +# if cd and 'filename=' in cd: +# filename = cd.split('filename=')[1].strip('";') +# else: +# # Fallback: get the last part of the URL +# filename = os.path.basename(url) - file_path = os.path.join(destination, filename) +# file_path = os.path.join(destination, filename) - with open(file_path, 'wb') as f: - for chunk in response.iter_content(chunk_size=8192): - f.write(chunk) +# with open(file_path, 'wb') as f: +# for chunk in response.iter_content(chunk_size=8192): +# f.write(chunk) class grab(): def season(url): diff --git a/app/main.py b/app/main.py index 4ddf033..384568f 100644 --- a/app/main.py +++ b/app/main.py @@ -42,6 +42,31 @@ loop = asyncio.get_event_loop() # Optional cache cached_data = None + +async def get_show_data(show: str): + global cached_data + if cached_data is None: + await dropoutUpdate() + + for item in cached_data: + if show == item['LINK']: + if "SEASONS" not in item: + item['SEASONS'] = download.grab.season(item['URL']) + return item + return None + +def get_latest_season(item): + if item and item.get("SEASONS"): + try: + seasons = item["SEASONS"].keys() + numeric_seasons = [int(s) for s in seasons if str(s).isdigit()] + if numeric_seasons: + return max(numeric_seasons) + except Exception as e: + logger.info(f"Error getting latest season: {e}") + return None + + # Middleware @app.middleware("http") async def log_requests(request: Request, call_next): @@ -60,7 +85,11 @@ async def log_requests(request: Request, call_next): f"status_code={response.status_code}" ) return response - + + + + + # api @app.post("/ebook/download", description="Download an ebook via a url.") async def ebookDownload( @@ -96,17 +125,26 @@ async def dropoutSeries(): @app.post("/dropout/download", description="Download an entire season from episode 1. Ignores behind the scenes and trailers.") async def dropoutDownload( - # request: Request, background_tasks: BackgroundTasks, show: str = Form(...), - season: int = Form(...) - ): + season: Optional[int] = Form(None), + latest: bool = Form(False) +): try: - background_tasks.add_task(download.dropout.show,show,season,None) - # download.dropout.show(show,season,episode) - return JSONResponse(status_code=200, content={"status": "success", "message": "Series downloaded."}) + if latest is not False and season is None: + item = await get_show_data(show) + if not item: + return JSONResponse(status_code=404, content={"status": "error", "message": "Show not found"}) + season = get_latest_season(item) + if season is None: + return JSONResponse(status_code=400, content={"status": "error", "message": "No valid seasons found"}) + + 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}."}) + except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) + @app.post("/dropout/download/specials", description="Downloads a seasons behind the scenes and trailers, ignores main episodes.") async def dropoutDownload( @@ -132,6 +170,10 @@ async def ydl(background_tasks: BackgroundTasks, url: str = Form(...), location: except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) + + + + #web ui @app.get("/", include_in_schema=False, response_class=HTMLResponse) async def index(request: Request): @@ -144,19 +186,13 @@ async def index(request: Request): return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) @app.get("/show/{show}", include_in_schema=False, response_class=HTMLResponse) -async def index(request: Request, show = str): +async def index(request: Request, show: str): try: - global cached_data - if cached_data is None: - await dropoutUpdate() - try: - for item in cached_data: - if show == item['LINK']: - if "SEASONS" not in item: - item['SEASONS'] = download.grab.season(item['URL']) - return templates.TemplateResponse("show.html", {"request": request, "show": item}) - except Exception as e: - return JSONResponse(status_code=500, content={"status": "error", "message": str(e)}) + item = await get_show_data(show) + if item: + return templates.TemplateResponse("show.html", {"request": request, "show": item}) + else: + return JSONResponse(status_code=404, content={"status": "error", "message": "Show not found"}) except Exception as e: return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})