import asyncio import json import os from ast import literal_eval import uvicorn from aio_pika import connect, Message, DeliveryMode from fastapi import FastAPI, Request, Form, HTTPException from starlette.middleware.cors import CORSMiddleware from starlette.responses import JSONResponse, FileResponse, StreamingResponse from starlette.templating import Jinja2Templates from src.core.redis_client import RedisClient app = FastAPI( title="video_downloader", openapi_url=f"/api/v1/openapi.json" ) templates = Jinja2Templates(directory="templates") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/") async def index(request: Request): return templates.TemplateResponse("index.html", {"request": request}) @app.post('/submit/') async def get_url_for_download_video(request: Request, link: str = Form(...)): connection = await connect("amqp://guest:guest@localhost/") async with connection: # Creating a channel channel = await connection.channel() body = [ { "link": link, "parser": "base", "format": "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best", "merge_output_format": "mp4", "outtmpl": f"downloads/%(extractor_key)s/%(id)s_%(width)sp.%(ext)s", }, ] # Sending the message for link in body: if "mail" in link["link"]: link["parser"] = "MyMailRu" elif "yappy" in link["link"]: link["parser"] = "Yappy" message = Message( json.dumps(link, indent=4).encode('utf-8'), delivery_mode=DeliveryMode.PERSISTENT, ) await channel.default_exchange.publish( message, routing_key='hello', ) print(f" [x] Sent '{link}'") red = RedisClient() while True: try: mes = await red.get_task_done_queue() task = literal_eval(list(mes)[0].decode('utf-8')) if task["link"] == link["link"]: await red.del_task_from_task_done_queue(task) break await asyncio.sleep(5) except (AttributeError, IndexError): await asyncio.sleep(5) continue link_to_download_video = str(request.base_url) + "get/?file_path=" + task["result"] return JSONResponse({"result": link_to_download_video}) @app.get('/get/', response_class=FileResponse, status_code=200) async def download_video(file_path): base = os.path.dirname(os.path.dirname(os.path.abspath(file_path))) base_download_dir = os.path.join(base, os.pardir, os.pardir, "downloads") def iterfile(): with open(base_download_dir + f'/{file_path}', mode="rb") as file_like: yield from file_like return StreamingResponse(iterfile(), media_type="video/mp4") if __name__ == '__main__': uvicorn.run("src.web.main:app", host="localhost", log_level="info")