| import math, mimetypes | |
| from fastapi.responses import StreamingResponse, Response | |
| from utils.logger import Logger | |
| from utils.streamer.custom_dl import ByteStreamer | |
| from utils.streamer.file_properties import get_name | |
| from utils.clients import ( | |
| get_client, | |
| ) | |
| from urllib.parse import quote | |
| logger = Logger(__name__) | |
| class_cache = {} | |
| async def media_streamer(channel: int, message_id: int, file_name: str, request): | |
| global class_cache | |
| range_header = request.headers.get("Range", 0) | |
| faster_client = get_client() | |
| if faster_client in class_cache: | |
| tg_connect = class_cache[faster_client] | |
| else: | |
| tg_connect = ByteStreamer(faster_client) | |
| class_cache[faster_client] = tg_connect | |
| file_id = await tg_connect.get_file_properties(channel, message_id) | |
| file_size = file_id.file_size | |
| if range_header: | |
| from_bytes, until_bytes = range_header.replace("bytes=", "").split("-") | |
| from_bytes = int(from_bytes) | |
| until_bytes = int(until_bytes) if until_bytes else file_size - 1 | |
| else: | |
| from_bytes = 0 | |
| until_bytes = file_size - 1 | |
| if (until_bytes > file_size) or (from_bytes < 0) or (until_bytes < from_bytes): | |
| return Response( | |
| status_code=416, | |
| content="416: Range not satisfiable", | |
| headers={"Content-Range": f"bytes */{file_size}"}, | |
| ) | |
| chunk_size = 1024 * 1024 | |
| until_bytes = min(until_bytes, file_size - 1) | |
| offset = from_bytes - (from_bytes % chunk_size) | |
| first_part_cut = from_bytes - offset | |
| last_part_cut = until_bytes % chunk_size + 1 | |
| req_length = until_bytes - from_bytes + 1 | |
| part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size) | |
| body = tg_connect.yield_file( | |
| file_id, offset, first_part_cut, last_part_cut, part_count, chunk_size | |
| ) | |
| disposition = "attachment" | |
| mime_type = mimetypes.guess_type(file_name.lower())[0] or "application/octet-stream" | |
| if ( | |
| "video/" in mime_type | |
| or "audio/" in mime_type | |
| or "image/" in mime_type | |
| or "/html" in mime_type | |
| ): | |
| disposition = "inline" | |
| return StreamingResponse( | |
| status_code=206 if range_header else 200, | |
| content=body, | |
| headers={ | |
| "Content-Type": f"{mime_type}", | |
| "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}", | |
| "Content-Length": str(req_length), | |
| "Content-Disposition": f'{disposition}; filename="{quote(file_name)}"', | |
| "Accept-Ranges": "bytes", | |
| }, | |
| media_type=mime_type, | |
| ) | |