Spaces:
Configuration error
Configuration 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 | |
) | |