privateone commited on
Commit
d0b286c
·
1 Parent(s): 316caa6

Code Updates & Optimisations :Server Upgraded-Minor Chnages Due to Download problem

Browse files
FileStream/server/Functions/downloader.py CHANGED
@@ -19,96 +19,80 @@ from FileStream.Exceptions import FIleNotFound, InvalidHash
19
  from FileStream.utils.FileProcessors.custom_ul import TeleUploader
20
 
21
 
22
- async def media_streamer(request: web.Request, db_id: str, speed: str):
23
- # Get the Range header from the request, default to 0 if not present
24
- range_header = request.headers.get("Range", 0)
25
- client = await req_client()
26
- # Log client info if multi-client mode
27
- if Telegram.MULTI_CLIENT:
28
- logging.info(f"Client {client['index']} is now serving {request.headers.get('X-FORWARDED-FOR', request.remote)}")
29
-
30
- # Use an existing ByteStreamer or create a new one
31
- tg_connect = ACTIVE_CLIENTS.get(client['client'], None)
32
-
33
- if tg_connect is None:
34
- logging.debug(f"Creating new ByteStreamer object for client {client['index']}")
35
- tg_connect = utils.ByteStreamer(client['client'])
36
- ACTIVE_CLIENTS[client['client']] = tg_connect
37
-
38
- else:
39
- tg_connect.update_last_activity()
40
- logging.debug(f"Using cached ByteStreamer object for client {client['index']}")
41
-
42
- try:
43
- # Fetch file properties once and use it throughout
44
- logging.debug("Fetching file properties")
45
- file_id = await tg_connect.get_file_properties(db_id, MULTI_CLIENTS)
46
- file_size = file_id.file_size
47
-
48
- # Parse range header efficiently
49
- from_bytes, until_bytes = parse_range(range_header, file_size)
50
-
51
- # If range is invalid, return a 416 error
52
- if from_bytes is None or until_bytes is None:
53
- return web.Response(
54
- status=416,
55
- body="416: Range not satisfiable",
56
- headers={"Content-Range": f"bytes */{file_size}"},
57
- )
58
-
59
- # Set chunk size based on speed
60
- chunk_size = 1024 * 1024 if speed == "FAST" else 512 * 1024
61
-
62
- # Ensure we don't go past the file size
63
- until_bytes = min(until_bytes, file_size - 1)
64
-
65
- # Compute offset and range parts
66
- offset, first_part_cut, last_part_cut, part_count = compute_offsets(from_bytes, until_bytes, chunk_size)
67
-
68
- # Request the file chunks
69
- body = tg_connect.yield_file(
70
- file_id, client['index'], offset, first_part_cut, last_part_cut, part_count, chunk_size
71
- )
72
-
73
- # Determine MIME type and filename
74
- mime_type = file_id.mime_type or mimetypes.guess_type(file_id.file_name)[0] or "application/octet-stream"
75
- file_name = utils.get_name(file_id)
76
- disposition = "attachment"
77
-
78
- # Return the response with proper headers and status
79
- req_length = until_bytes - from_bytes + 1
80
- return web.Response(
81
- status=206 if range_header else 200,
82
- body=body,
83
- headers={
84
- "Content-Type": mime_type,
85
- "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}",
86
- "Content-Length": str(req_length),
87
- "Content-Disposition": f'{disposition}; filename="{file_name}"',
88
- "Accept-Ranges": "bytes",
89
- },
90
- )
91
- except Exception as e:
92
- logging.error(f"Error in media_streamer: {traceback.format_exc()}")
93
- raise web.HTTPInternalServerError() # Re-raise the exception as a server error
94
-
95
-
96
- def parse_range(range_header: str, file_size: int):
97
- """Helper function to parse the range header."""
98
- try:
99
- range_str = range_header.replace("bytes=", "")
100
- from_bytes, until_bytes = range_str.split("-")
101
- from_bytes = int(from_bytes)
102
- until_bytes = int(until_bytes) if until_bytes else file_size - 1
103
- return from_bytes, until_bytes
104
- except ValueError:
105
- return None, None
106
-
107
-
108
- def compute_offsets(from_bytes: int, until_bytes: int, chunk_size: int):
109
- """Compute the offsets, cuts, and part counts for file chunking."""
110
- offset = from_bytes - (from_bytes % chunk_size)
111
- first_part_cut = from_bytes - offset
112
- last_part_cut = until_bytes % chunk_size + 1
113
- part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
114
- return offset, first_part_cut, last_part_cut, part_count
 
19
  from FileStream.utils.FileProcessors.custom_ul import TeleUploader
20
 
21
 
22
+ async def media_streamer(request: web.Request, db_id: str, speed:str):
23
+
24
+ range_header = request.headers.get("Range", 0)
25
+ #index = minWORK_LOADS, keyWORK_LOADS.get)
26
+ #faster_client = MULTI_CLIENTS[index]
27
+
28
+ client = await req_client()
29
+
30
+ if Telegram.MULTI_CLIENT:
31
+ logging.info(f"Client {client['index']} is now serving {request.headers.get('X-FORWARDED-FOR',request.remote)}")
32
+
33
+ if client['client'] in ACTIVE_CLIENTS:
34
+ tg_connect = ACTIVE_CLIENTS[client['client']]
35
+ logging.debug(f"Using cached ByteStreamer object for client {client['index']}")
36
+
37
+ else:
38
+ logging.debug(f"Creating new ByteStreamer object for client {client['index']}")
39
+ tg_connect = utils.ByteStreamer(client['client'])
40
+ ACTIVE_CLIENTS[client['client']] = tg_connect
41
+
42
+ logging.debug("before calling get_file_properties")
43
+ file_id = await tg_connect.get_file_properties(db_id, MULTI_CLIENTS)
44
+ logging.debug("after calling get_file_properties")
45
+
46
+ file_size = file_id.file_size
47
+
48
+ if range_header:
49
+ from_bytes, until_bytes = range_header.replace("bytes=", "").split("-")
50
+ from_bytes = int(from_bytes)
51
+ until_bytes = int(until_bytes) if until_bytes else file_size - 1
52
+ else:
53
+ from_bytes = request.http_range.start or 0
54
+ until_bytes = (request.http_range.stop or file_size) - 1
55
+
56
+ if (until_bytes > file_size) or (from_bytes < 0) or (until_bytes < from_bytes):
57
+
58
+ return web.Response(
59
+ status=416,
60
+ body="416: Range not satisfiable",
61
+ headers={"Content-Range": f"bytes */{file_size}"},
62
+ )
63
+
64
+ chunk_size = 4 * 1024 * 1024 if speed == "FAST" else 512 * 1024
65
+
66
+ until_bytes = min(until_bytes, file_size - 1)
67
+
68
+ offset = from_bytes - (from_bytes % chunk_size)
69
+ first_part_cut = from_bytes - offset
70
+ last_part_cut = until_bytes % chunk_size + 1
71
+
72
+ req_length = until_bytes - from_bytes + 1
73
+ part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
74
+
75
+ body = tg_connect.yield_file(file_id, client['index'], offset, first_part_cut,last_part_cut, part_count, chunk_size)
76
+
77
+ mime_type = file_id.mime_type
78
+ file_name = utils.get_name(file_id)
79
+ disposition = "attachment"
80
+
81
+ if not mime_type:
82
+ mime_type = mimetypes.guess_type(file_name)[0] or "application/octet-stream"
83
+
84
+ # if "video/" in mime_type or "audio/" in mime_type:
85
+ # disposition = "inline"
86
+
87
+ return web.Response(
88
+ status=206 if range_header else 200,
89
+ body=body,
90
+ headers={
91
+ "Content-Type": f"{mime_type}",
92
+ "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}",
93
+ "Content-Length": str(req_length),
94
+ "Content-Disposition": f'{disposition}; filename="{file_name}"',
95
+ "Accept-Ranges": "bytes",
96
+ },
97
+ )
98
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Unused Codes/downloader.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import math
4
+ import logging
5
+ import asyncio
6
+ import traceback
7
+ from aiohttp import web
8
+ from pyrogram import raw
9
+ from aiohttp.http_exceptions import BadStatusLine
10
+
11
+ #---------------------Local Upload---------------------#
12
+
13
+ from FileStream.config import Telegram
14
+ from FileStream.bot import req_client, FileStream
15
+ from FileStream import utils, StartTime, __version__
16
+ from FileStream.Tools import mime_identifier, Time_ISTKolNow
17
+ from FileStream.bot import MULTI_CLIENTS, WORK_LOADS, ACTIVE_CLIENTS
18
+ from FileStream.Exceptions import FIleNotFound, InvalidHash
19
+ from FileStream.utils.FileProcessors.custom_ul import TeleUploader
20
+
21
+
22
+ async def media_streamer(request: web.Request, db_id: str, speed: str):
23
+ # Get the Range header from the request, default to 0 if not present
24
+ range_header = request.headers.get("Range", 0)
25
+ client = await req_client()
26
+ # Log client info if multi-client mode
27
+ if Telegram.MULTI_CLIENT:
28
+ logging.info(f"Client {client['index']} is now serving {request.headers.get('X-FORWARDED-FOR', request.remote)}")
29
+
30
+ # Use an existing ByteStreamer or create a new one
31
+ tg_connect = ACTIVE_CLIENTS.get(client['client'], None)
32
+
33
+ if tg_connect is None:
34
+ logging.debug(f"Creating new ByteStreamer object for client {client['index']}")
35
+ tg_connect = utils.ByteStreamer(client['client'])
36
+ ACTIVE_CLIENTS[client['client']] = tg_connect
37
+
38
+ else:
39
+ tg_connect.update_last_activity()
40
+ logging.debug(f"Using cached ByteStreamer object for client {client['index']}")
41
+
42
+ try:
43
+ # Fetch file properties once and use it throughout
44
+ logging.debug("Fetching file properties")
45
+ file_id = await tg_connect.get_file_properties(db_id, MULTI_CLIENTS)
46
+ file_size = file_id.file_size
47
+
48
+ # Parse range header efficiently
49
+ from_bytes, until_bytes = parse_range(range_header, file_size)
50
+
51
+ # If range is invalid, return a 416 error
52
+ if from_bytes is None or until_bytes is None:
53
+ return web.Response(
54
+ status=416,
55
+ body="416: Range not satisfiable",
56
+ headers={"Content-Range": f"bytes */{file_size}"},
57
+ )
58
+
59
+ # Set chunk size based on speed
60
+ chunk_size = 1024 * 1024 if speed == "FAST" else 512 * 1024
61
+
62
+ # Ensure we don't go past the file size
63
+ until_bytes = min(until_bytes, file_size - 1)
64
+
65
+ # Compute offset and range parts
66
+ offset, first_part_cut, last_part_cut, part_count = compute_offsets(from_bytes, until_bytes, chunk_size)
67
+
68
+ # Request the file chunks
69
+ body = tg_connect.yield_file(
70
+ file_id, client['index'], offset, first_part_cut, last_part_cut, part_count, chunk_size
71
+ )
72
+
73
+ # Determine MIME type and filename
74
+ mime_type = file_id.mime_type or mimetypes.guess_type(file_id.file_name)[0] or "application/octet-stream"
75
+ file_name = utils.get_name(file_id)
76
+ disposition = "attachment"
77
+
78
+ # Return the response with proper headers and status
79
+ req_length = until_bytes - from_bytes + 1
80
+ return web.Response(
81
+ status=206 if range_header else 200,
82
+ body=body,
83
+ headers={
84
+ "Content-Type": mime_type,
85
+ "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}",
86
+ "Content-Length": str(req_length),
87
+ "Content-Disposition": f'{disposition}; filename="{file_name}"',
88
+ "Accept-Ranges": "bytes",
89
+ },
90
+ )
91
+ except Exception as e:
92
+ logging.error(f"Error in media_streamer: {traceback.format_exc()}")
93
+ raise web.HTTPInternalServerError() # Re-raise the exception as a server error
94
+
95
+
96
+ def parse_range(range_header: str, file_size: int):
97
+ """Helper function to parse the range header."""
98
+ try:
99
+ range_str = range_header.replace("bytes=", "")
100
+ from_bytes, until_bytes = range_str.split("-")
101
+ from_bytes = int(from_bytes)
102
+ until_bytes = int(until_bytes) if until_bytes else file_size - 1
103
+ return from_bytes, until_bytes
104
+ except ValueError:
105
+ return None, None
106
+
107
+
108
+ def compute_offsets(from_bytes: int, until_bytes: int, chunk_size: int):
109
+ """Compute the offsets, cuts, and part counts for file chunking."""
110
+ offset = from_bytes - (from_bytes % chunk_size)
111
+ first_part_cut = from_bytes - offset
112
+ last_part_cut = until_bytes % chunk_size + 1
113
+ part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
114
+ return offset, first_part_cut, last_part_cut, part_count