Spaces:
Runtime error
Runtime error
| import math, asyncio, subprocess | |
| from telethon import TelegramClient | |
| from aiohttp import web | |
| import logging | |
| logging.getLogger(__name__) | |
| logging.basicConfig(level=logging.INFO) | |
| class Download: | |
| client: TelegramClient | |
| route: str | |
| offset: int | |
| handler: None | |
| file: None | |
| limit: int | |
| file_size: float | |
| def __init__(self, handler): | |
| self.handler = handler | |
| self.file = handler.message.media | |
| self.file_size = handler.message.file.size | |
| self.limit = handler.sanity.limit | |
| self.offset = handler.sanity.offset | |
| self.client = handler.client | |
| self.mime_type = handler.message.file.mime_type | |
| async def download(self): | |
| part_size = int(512 * 1024) * 2 | |
| first_part_cut = self.offset % part_size | |
| first_part = math.floor(self.offset / part_size) | |
| last_part_cut = part_size - (self.limit % part_size) | |
| last_part = math.ceil(self.limit / part_size) | |
| part_count = math.ceil(self.file_size / part_size) | |
| part = first_part | |
| try: | |
| async for chunk in self.client.iter_download( | |
| self.file, offset=first_part * part_size, request_size=part_size | |
| ): | |
| if part == first_part: | |
| yield chunk[first_part_cut:] | |
| elif part == last_part: | |
| yield chunk[:last_part_cut] | |
| else: | |
| yield chunk | |
| logging.debug(f"Part {part}/{last_part} (total {part_count}) served!") | |
| part += 1 | |
| logging.debug("serving finished") | |
| except (GeneratorExit, StopAsyncIteration, asyncio.CancelledError): | |
| logging.debug("file serve interrupted") | |
| raise | |
| except Exception as e: | |
| print(e) | |
| logging.debug("file serve errored", exc_info=True) | |
| async def handle_request(self): | |
| headers = { | |
| "content-type": self.mime_type, | |
| "content-range": f"bytes {self.offset}-{self.limit-1}/{self.file_size}", | |
| "content-length": str(self.limit - self.offset), | |
| "accept-ranges": "bytes", | |
| "content-transfer-encoding": "Binary", | |
| "content-disposition": f'{self.handler.route}; filename="{self.handler.message.file.name}"', | |
| } | |
| logging.info( | |
| f"Serving file in {self.handler.message.file.name}) ; Range: {self.offset} - {self.limit}" | |
| ) | |
| if self.handler.head: | |
| body = None | |
| else: | |
| body = self.download() | |
| # if body: | |
| # ffmpeg = "ffmpeg" | |
| # cmd = [ | |
| # ffmpeg, | |
| # "ffmpeg", | |
| # "-i", | |
| # "pipe:0", | |
| # "-c", | |
| # "copy", | |
| # "-re", | |
| # "pipe:1", | |
| # ] | |
| # ffmpeg_cmd = subprocess.Popen( | |
| # cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False | |
| # ) | |
| # body = await body.__anext__() | |
| # ffmpeg_cmd.stdin.write(body.tobytes()) | |
| # ffmpeg_cmd.stdin.close() | |
| # body = b"" | |
| # while True: | |
| # print(body) | |
| # output = ffmpeg_cmd.stdout.read() | |
| # if len(output) > 0: | |
| # body += output | |
| # ffmpeg_cmd.stdout.close() | |
| # else: | |
| # error_msg = ffmpeg_cmd.poll() | |
| # if error_msg is not None: | |
| # break | |
| return web.Response( | |
| body=body, headers=headers, status=206 if self.offset else 200 | |
| ) | |