File size: 3,432 Bytes
e566133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import os
import time
import math
import logging
import asyncio
import traceback
from aiohttp import web
from pyrogram import raw

from aiohttp.http_exceptions import BadStatusLine

#---------------------Local Upload---------------------#

from FileStream.config import Telegram
from FileStream import utils, StartTime, __version__
from FileStream.Tools import mime_identifier, Time_ISTKolNow
from FileStream.bot import multi_clients, work_loads, req_client, FileStream
from FileStream.server.exceptions import FIleNotFound, InvalidHash
from FileStream.server.render_template import render_page, render_upload
from FileStream.utils.FileProcessors.custom_ul import  TeleUploader

class_cache={}


async def media_streamer(request: web.Request, db_id: str):
  range_header = request.headers.get("Range", 0)

  #index = min(work_loads, key=work_loads.get)
  #faster_client = multi_clients[index]
  client = await req_client()

  if Telegram.MULTI_CLIENT:
    logging.info(f"Client {client['index']} is now serving {request.headers.get('X-FORWARDED-FOR',request.remote)}")

  if client['client'] in class_cache:
    tg_connect = class_cache[client['client']]
    logging.debug(f"Using cached ByteStreamer object for client {client['index']}")
  else:
    logging.debug(f"Creating new ByteStreamer object for client {client['index']}")
    tg_connect = utils.ByteStreamer(client['client'])
    class_cache[client['client']] = tg_connect
  logging.debug("before calling get_file_properties")
  file_id = await tg_connect.get_file_properties(db_id, multi_clients)
  logging.debug("after calling get_file_properties")

  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 = 512 * 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, client['index'], offset, first_part_cut,
                               last_part_cut, part_count, chunk_size)

  mime_type = file_id.mime_type
  file_name = utils.get_name(file_id)
  disposition = "attachment"

  if not mime_type:
    mime_type = mimetypes.guess_type(
        file_name)[0] or "application/octet-stream"

  # if "video/" in mime_type or "audio/" in mime_type:
  #     disposition = "inline"

  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",
      },
  )