# import re # import math # import logging # import secrets # import mimetypes # from aiohttp import web # from aiohttp.http_exceptions import BadStatusLine # from lazybot import multi_clients, work_loads, StreamBot # from server.exceptions import FIleNotFound, InvalidHash # from zzint import StartTime, __version__ # from ..util.custom_dl import ByteStreamer # from util.render_template import render_page # from info import * # routes = web.RouteTableDef() # @routes.get("/", allow_head=True) # async def root_route_handler(request): # return web.json_response("in & as LazyDeveloper...") # @routes.get(r"/watch/{path:\S+}", allow_head=True) # async def stream_handler(request: web.Request): # try: # path = request.match_info["path"] # match = re.search(r"^([a-zA-Z0-9_-]{6})(\d+)$", path) # if match: # secure_hash = match.group(1) # id = int(match.group(2)) # else: # id = int(re.search(r"(\d+)(?:\/\S+)?", path).group(1)) # secure_hash = request.rel_url.query.get("hash") # return web.Response(text=await render_page(id, secure_hash), content_type='text/html') # 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 # except Exception as e: # logging.critical(e.with_traceback(None)) # raise web.HTTPInternalServerError(text=str(e)) # @routes.get(r"/{path:\S+}", allow_head=True) # async def stream_handler(request: web.Request): # try: # path = request.match_info["path"] # match = re.search(r"^([a-zA-Z0-9_-]{6})(\d+)$", path) # if match: # secure_hash = match.group(1) # id = int(match.group(2)) # else: # id = int(re.search(r"(\d+)(?:\/\S+)?", path).group(1)) # secure_hash = request.rel_url.query.get("hash") # return await media_streamer(request, id, secure_hash) # 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 # except Exception as e: # logging.critical(e.with_traceback(None)) # raise web.HTTPInternalServerError(text=str(e)) # class_cache = {} # async def media_streamer(request: web.Request, id: int, secure_hash: str): # range_header = request.headers.get("Range", 0) # index = min(work_loads, key=work_loads.get) # faster_client = multi_clients[index] # if MULTI_CLIENT: # logging.info(f"Client {index} is now serving {request.remote}") # if faster_client in class_cache: # tg_connect = class_cache[faster_client] # logging.debug(f"Using cached ByteStreamer object for client {index}") # else: # logging.debug(f"Creating new ByteStreamer object for client {index}") # tg_connect = ByteStreamer(faster_client) # class_cache[faster_client] = tg_connect # logging.debug("before calling get_file_properties") # file_id = await tg_connect.get_file_properties(id) # logging.debug("after calling get_file_properties") # if file_id.unique_id[:6] != secure_hash: # logging.debug(f"Invalid hash for message with ID {id}") # raise InvalidHash # 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 = request.http_range.start or 0 # until_bytes = (request.http_range.stop or file_size) - 1 # if (until_bytes > file_size) or (from_bytes < 0) or (until_bytes < from_bytes): # return web.Response( # status=416, # body="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, index, offset, first_part_cut, last_part_cut, part_count, chunk_size # ) # mime_type = file_id.mime_type # file_name = file_id.file_name # disposition = "attachment" # if mime_type: # if not file_name: # try: # file_name = f"{secrets.token_hex(2)}.{mime_type.split('/')[1]}" # except (IndexError, AttributeError): # file_name = f"{secrets.token_hex(2)}.unknown" # else: # if file_name: # mime_type = mimetypes.guess_type(file_id.file_name) # else: # mime_type = "application/octet-stream" # file_name = f"{secrets.token_hex(2)}.unknown" # return web.Response( # status=206 if range_header else 200, # body=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="{file_name}"', # "Accept-Ranges": "bytes", # }, # )