Spaces:
Running
Running
import os | |
import json | |
import logging | |
import asyncio | |
import traceback | |
import aiohttp_cors | |
from aiohttp import web | |
from pyrogram import raw | |
from bson import ObjectId | |
from bson.json_util import dumps | |
from aiohttp.http_exceptions import BadStatusLine | |
#---------------------Local Imports----------------------------------# | |
from FileStream.bot import req_client | |
from FileStream.config import Telegram, Server | |
from FileStream.Database import Database | |
from FileStream.TMDB.Endpoint import search_tmdb_any, search_tmdb_tv, search_tmdb_movies | |
from FileStream.server.exceptions import FIleNotFound, InvalidHash | |
from .Functions.downloader import media_streamer | |
CORS_HEADERS = { | |
"Access-Control-Allow-Origin": "*", | |
"Access-Control-Allow-Headers": "*" | |
} | |
async def handle_v2(request): | |
return web.Response(text="Hello from app api!") | |
# API endpoint to list 10 files (pagination optimization) | |
async def list_10_all_files_db(request): | |
db = Database(Telegram.DATABASE_URL, Telegram.SESSION_NAME) | |
files, total_files = await db.find_all_files([1, 10]) | |
return web.json_response([dict(file) async for file in files], headers=CORS_HEADERS) | |
# API endpoint to list all files in database | |
async def list_all_files_db(request): | |
db = Database(Telegram.DATABASE_URL, Telegram.SESSION_NAME) | |
files = await db.get_all_files_api() # Ensure `get_all_files_api` is optimized for performance | |
return web.json_response(json.loads(dumps(files)), headers=CORS_HEADERS) | |
# API endpoint to list all TMDB movies related to files in the database | |
async def list_all_tmdb_movies_from_db(request): | |
db = Database(Telegram.DATABASE_URL, Telegram.SESSION_NAME) | |
files = await db.get_all_files() | |
response = [] | |
for row in files: | |
try: | |
resp = search_tmdb_movies(str(row['file']['caption']) if row['file']['caption'] else str(row['file']['file_name'])) | |
if resp: | |
response.append(resp) | |
except Exception as e: | |
logging.error(f"Error while fetching TMDB movie for {row['file']['caption']}: {e}") | |
return web.json_response(json.loads(dumps(response)), headers=CORS_HEADERS) | |
# API endpoint to list all TMDB TV shows related to files in the database | |
async def list_all_tmdb_tv_from_db(request): | |
db = Database(Telegram.DATABASE_URL, Telegram.SESSION_NAME) | |
files = await db.get_all_files() | |
response = [] | |
for row in files: | |
try: | |
resp = search_tmdb_tv(str(row['file']['caption']) if row['file']['caption'] else str(row['file']['file_name'])) | |
if resp: | |
response.append(resp) | |
except Exception as e: | |
logging.error(f"Error while fetching TMDB TV show for {row['file']['caption']}: {e}") | |
return web.json_response(json.loads(dumps(response)), headers=CORS_HEADERS) | |
# API endpoint to list all TMDB results, streaming them to the client | |
async def list_all_files_tmdb(request): | |
db = Database(Telegram.DATABASE_URL, Telegram.SESSION_NAME) | |
files = await db.get_all_files() | |
async def data_generator(): | |
for row in files: | |
try: | |
resp = search_tmdb_any(str(row['file']['caption']) if row['file']['caption'] else str(row['file']['file_name'])) | |
if resp: | |
yield json.dumps(resp) + '\n' # Streaming data to client in chunks | |
except Exception as e: | |
logging.error(f"Error while fetching TMDB data for {row['file']['caption']}: {e}") | |
return web.Response(body=data_generator(), content_type='application/json', headers=CORS_HEADERS) | |
# API endpoint to list all files for a simple response | |
async def list_all_files(request): | |
db = Database(Telegram.DATABASE_URL, Telegram.SESSION_NAME) | |
files = await db.get_all_files_api() | |
resp = [{ | |
"adult": False, | |
"backdrop_path": "/c1bz69r0v065TGFA5nqBiKzPDys.jpg", | |
"genre_ids": [35, 10751, 10402], | |
"id": f"{row['_id']}", | |
"original_language": "en-hi", | |
"original_title": f"{str(row['file']['caption'])}", | |
"overview": "XRepo Movies", | |
"popularity": 1710.176, | |
"poster_path": "/irIS5Tn3TXjNi1R9BpWvGAN4CZ1.jpg", | |
"release_date": "2022-10-07", | |
"title": f"{str(row['file']['caption'])}", | |
"link": f"{Server.URL}api/dl/{row['_id']}", | |
"vote_average": 7.8, | |
"vote_count": 122, | |
} for row in files] | |
return web.json_response(json.loads(dumps(resp)), headers=CORS_HEADERS) | |
# Upload endpoint with optimization (not reading entire file into memory) | |
async def upload_file(request: web.Request): | |
data = await request.post() | |
file = data.get('file').file | |
chunk = file.read() # Read the file in chunks to avoid memory overload | |
file_details = dict( | |
user_id="thebinary1", | |
dropzone_id=str(data["dzuuid"]), | |
file=dict( | |
file_id=str(data["dzuuid"]), | |
file_unique_id=str(data["dzuuid"]), | |
file_name=str(data.get('file').filename), | |
file_size=int(data["dztotalfilesize"]), | |
mime_type=mime_identifier(str(data.get('file').filename)), | |
part_size=int(data["dzchunksize"]), | |
file_part=int(data["dzchunkindex"]), | |
total_parts=int(data["dztotalchunkcount"]) | |
), | |
time=Time_ISTKolNow(), | |
user_type="WEB", | |
privacy_type="PRIVATE" | |
) | |
client_req = await req_client() # Ensure client request is fast and optimized | |
tg_connect = TeleUploader(client_req["client"]) | |
main = await tg_connect.upload_web_file(file_details, chunk) | |
return web.json_response({ | |
"status": main.get("status"), | |
"message": main.get("message") | |
}) | |
# Stream file handler with optimized error handling | |
async def stream_handler(request: web.Request): | |
try: | |
path = request.match_info["path"] | |
return await media_streamer(request, path, "FAST") | |
except InvalidHash as e: | |
raise web.HTTPForbidden(text=e.message) | |
except FIleNotFound as e: | |
raise web.HTTPNotFound(text=e.message) | |
except (AttributeError, BadStatusLine, ConnectionResetError): | |
pass # Handle expected errors silently | |
except Exception as e: | |
logging.error(f"Error while streaming file: {str(e)}") | |
traceback.print_exc() | |
raise web.HTTPInternalServerError(text=str(e)) | |
# Web server setup with optimized CORS handling | |
api = web.Application() | |
cors = aiohttp_cors.setup(api, defaults={"*": aiohttp_cors.ResourceOptions( | |
allow_credentials=False, | |
expose_headers="*", | |
allow_headers="*", | |
allow_methods="*" | |
)}) | |
cors.add(api.router.add_get('/', handle_v2)) | |
api.router.add_get('/files', list_all_files_db) | |
api.router.add_get('/files/mix', list_all_files) | |
api.router.add_get('/tmdb/mix', list_all_files_tmdb) | |
api.router.add_get('/10/files', list_10_all_files_db) | |
api.router.add_get('/tmdb/tv', list_all_tmdb_tv_from_db) | |
api.router.add_get('/tmdb/movies', list_all_tmdb_movies_from_db) | |
api.router.add_get('/upload', upload_file) | |
api.router.add_get('/dl/{path}', stream_handler) | |