privateone commited on
Commit
63bf853
·
1 Parent(s): 9ece90d

Slight Edit

Browse files
FileStream/Exceptions/__init__.py CHANGED
@@ -1,2 +1 @@
1
-
2
  from .exceptions import FIleNotFound, InvalidHash
 
 
1
  from .exceptions import FIleNotFound, InvalidHash
FileStream/server/API/__init__.py CHANGED
@@ -2,14 +2,14 @@ import aiohttp_cors
2
  from aiohttp import web
3
 
4
  #---------------------- Local Imports --------------------#
5
- from .listings import (
6
- list_all_files_db,
7
- list_all_files,
8
- list_all_files_tmdb,
9
- list_10_all_files_db,
10
- list_all_tmdb_tv_from_db,
11
- list_all_tmdb_movies_from_db,
12
- )
13
  from .downloads import stream_handler
14
  from .uploads import upload_file
15
 
@@ -37,12 +37,12 @@ cors = aiohttp_cors.setup(api, defaults={"*": aiohttp_cors.ResourceOptions(
37
 
38
  cors.add(api.router.add_get('/', handle_v2))
39
 
40
- api.router.add_get('/files', list_all_files_db)
41
- api.router.add_get('/files/mix', list_all_files)
42
- api.router.add_get('/tmdb/mix', list_all_files_tmdb)
43
- api.router.add_get('/10/files', list_10_all_files_db)
44
- api.router.add_get('/tmdb/tv', list_all_tmdb_tv_from_db)
45
- api.router.add_get('/tmdb/movies', list_all_tmdb_movies_from_db)
46
 
47
  api.router.add_get('/upload', upload_file)
48
  api.router.add_get('/dl/{path}', stream_handler)
 
2
  from aiohttp import web
3
 
4
  #---------------------- Local Imports --------------------#
5
+ #from .listings import (
6
+ # list_all_files_db,
7
+ # list_all_files,
8
+ # list_all_files_tmdb,
9
+ # list_10_all_files_db,
10
+ # list_all_tmdb_tv_from_db,
11
+ # list_all_tmdb_movies_from_db,
12
+ #)
13
  from .downloads import stream_handler
14
  from .uploads import upload_file
15
 
 
37
 
38
  cors.add(api.router.add_get('/', handle_v2))
39
 
40
+ #api.router.add_get('/files', list_all_files_db)
41
+ #api.router.add_get('/files/mix', list_all_files)
42
+ #api.router.add_get('/tmdb/mix', list_all_files_tmdb)
43
+ #api.router.add_get('/10/files', list_10_all_files_db)
44
+ #api.router.add_get('/tmdb/tv', list_all_tmdb_tv_from_db)
45
+ #api.router.add_get('/tmdb/movies', list_all_tmdb_movies_from_db)
46
 
47
  api.router.add_get('/upload', upload_file)
48
  api.router.add_get('/dl/{path}', stream_handler)
FileStream/server/Functions/downloader copy.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 (until_bytes > file_size) or (from_bytes < 0) or (until_bytes < from_bytes):
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
+
63
+ # Ensure we don't go past the file size
64
+ until_bytes = min(until_bytes, file_size - 1)
65
+
66
+ # Compute offset and range parts
67
+ offset, first_part_cut, last_part_cut, part_count = compute_offsets(from_bytes, until_bytes, chunk_size)
68
+
69
+ # Request the file chunks
70
+ body = tg_connect.yield_file(
71
+ file_id, client['index'], offset, first_part_cut, last_part_cut, part_count, chunk_size
72
+ )
73
+
74
+ # Determine MIME type and filename
75
+ mime_type = file_id.mime_type or mimetypes.guess_type(file_id.file_name)[0] or "application/octet-stream"
76
+ file_name = utils.get_name(file_id)
77
+ disposition = "attachment"
78
+
79
+ # Return the response with proper headers and status
80
+ req_length = until_bytes - from_bytes + 1
81
+ return web.Response(
82
+ status=206 if range_header else 200,
83
+ body=body,
84
+ headers={
85
+ "Content-Type": mime_type,
86
+ "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}",
87
+ "Content-Length": str(req_length),
88
+ "Content-Disposition": f'{disposition}; filename="{file_name}"',
89
+ "Accept-Ranges": "bytes",
90
+ },
91
+ )
92
+ except Exception as e:
93
+ logging.error(f"Error in media_streamer: {traceback.format_exc()}")
94
+ raise web.HTTPInternalServerError() # Re-raise the exception as a server error
95
+
96
+
97
+ def parse_range(range_header: str, file_size: int):
98
+ """Helper function to parse the range header."""
99
+ try:
100
+ if range_header:
101
+ from_bytes, until_bytes = range_header.replace("bytes=", "").split("-")
102
+ from_bytes = int(from_bytes)
103
+ until_bytes = int(until_bytes) if until_bytes else file_size - 1
104
+ else:
105
+ from_bytes = 0
106
+ until_bytes = file_size - 1
107
+ #request :web.Request ,
108
+ #from_bytes = request.http_range.start or 0
109
+ #until_bytes = (request.http_range.stop or file_size) - 1
110
+ return from_bytes, until_bytes
111
+ except ValueError:
112
+ return None, None
113
+
114
+
115
+ def compute_offsets(from_bytes: int, until_bytes: int, chunk_size: int):
116
+ """Compute the offsets, cuts, and part counts for file chunking."""
117
+ offset = from_bytes - (from_bytes % chunk_size)
118
+ first_part_cut = from_bytes - offset
119
+ last_part_cut = until_bytes % chunk_size + 1
120
+ part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
121
+ return offset, first_part_cut, last_part_cut, part_count
FileStream/server/Functions/downloader.py CHANGED
@@ -22,23 +22,22 @@ from FileStream.utils.FileProcessors.custom_ul import TeleUploader
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")
@@ -68,7 +67,7 @@ async def media_streamer(request: web.Request, db_id: str, speed: str):
68
 
69
  # Request the file chunks
70
  body = tg_connect.yield_file(
71
- file_id, client['index'], offset, first_part_cut, last_part_cut, part_count, chunk_size
72
  )
73
 
74
  # Determine MIME type and filename
@@ -108,6 +107,7 @@ def parse_range(range_header: str, file_size: int):
108
  #from_bytes = request.http_range.start or 0
109
  #until_bytes = (request.http_range.stop or file_size) - 1
110
  return from_bytes, until_bytes
 
111
  except ValueError:
112
  return None, None
113
 
 
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
+
26
+ index = min(WORK_LOADS, key=WORK_LOADS.get)
27
+ faster_client = MULTI_CLIENTS[index]
28
  # Log client info if multi-client mode
 
 
29
 
 
 
30
 
31
+ if Telegram.MULTI_CLIENT:
32
+ logging.info(f"Client {index} is now serving {request.headers.get('X-FORWARDED-FOR', request.remote)}")
 
 
33
 
34
+ if faster_client in ACTIVE_CLIENTS:
35
+ tg_connect = ACTIVE_CLIENTS[faster_client]
36
+ logging.debug(f"Using cached ByteStreamer object for client {index}")
37
  else:
38
+ logging.debug(f"Creating new ByteStreamer object forclient {index}")
39
+ tg_connect = utils.ByteStreamer(faster_client)
40
+ ACTIVE_CLIENTS[faster_client] = tg_connect
41
  try:
42
  # Fetch file properties once and use it throughout
43
  logging.debug("Fetching file properties")
 
67
 
68
  # Request the file chunks
69
  body = tg_connect.yield_file(
70
+ file_id, index, offset, first_part_cut, last_part_cut, part_count, chunk_size
71
  )
72
 
73
  # Determine MIME type and filename
 
107
  #from_bytes = request.http_range.start or 0
108
  #until_bytes = (request.http_range.stop or file_size) - 1
109
  return from_bytes, until_bytes
110
+
111
  except ValueError:
112
  return None, None
113
 
FileStream/server/Middlewares/__init__.py DELETED
@@ -1,7 +0,0 @@
1
- from .app_token_middleware import app_token_middleware
2
- from .jwt_middleware import jwt_middleware,create_jwt
3
- from .logging_middleware import logging_middleware
4
-
5
- #from .rate_limit_middleware import rate_limit_middleware
6
-
7
- from .security_headers_middleware import security_headers_middleware
 
 
 
 
 
 
 
 
FileStream/server/Middlewares/app_token_middleware.py DELETED
@@ -1,12 +0,0 @@
1
- from aiohttp import web
2
-
3
- DEFAULT_APP_TOKEN = "supersecureapptoken"
4
-
5
- @web.middleware
6
- async def app_token_middleware(request, handler):
7
- """Middleware to enforce token authentication for /app."""
8
- if request.path.startswith("/app"):
9
- token = request.headers.get("App-Token")
10
- if token != DEFAULT_APP_TOKEN:
11
- raise web.HTTPUnauthorized(reason="Invalid or missing App-Token")
12
- return await handler(request)
 
 
 
 
 
 
 
 
 
 
 
 
 
FileStream/server/Middlewares/jwt_middleware.py DELETED
@@ -1,26 +0,0 @@
1
- import jwt
2
- from aiohttp import web
3
-
4
- SECRET_KEY = "your_secret_key" # Use a strong, randomly generated secret key
5
-
6
- def create_jwt(user_id: str):
7
- """Create a JWT token."""
8
- payload = {"sub": user_id, "role": "api_user"}
9
- return jwt.encode(payload, SECRET_KEY, algorithm="HS256")
10
-
11
- @web.middleware
12
- async def jwt_middleware(request, handler):
13
- """JWT Middleware for /api endpoints."""
14
- if request.path.startswith("/api"):
15
- token = request.headers.get("Authorization")
16
- if not token or not token.startswith("Bearer "):
17
- raise web.HTTPUnauthorized(reason="Authorization header missing or malformed")
18
- token = token.split("Bearer ")[1]
19
- try:
20
- decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
21
- request["user"] = decoded # Attach user info to the request
22
- except jwt.ExpiredSignatureError:
23
- raise web.HTTPUnauthorized(reason="Token has expired")
24
- except jwt.InvalidTokenError:
25
- raise web.HTTPUnauthorized(reason="Invalid token")
26
- return await handler(request)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
FileStream/server/Middlewares/logging_middleware.py DELETED
@@ -1,8 +0,0 @@
1
- import logging
2
- from aiohttp import web
3
-
4
- @web.middleware
5
- async def logging_middleware(request, handler):
6
- """Log each request."""
7
- logging.info(f"Incoming request: {request.method} {request.path}")
8
- return await handler(request)
 
 
 
 
 
 
 
 
 
FileStream/server/Middlewares/rate_limit_middleware.py DELETED
@@ -1,10 +0,0 @@
1
- """
2
- from aiohttp_rate_limiter import RateLimiter
3
-
4
- rate_limiter = RateLimiter(per_minute=60)
5
-
6
- @rate_limiter.limit("60/minute")
7
- async def rate_limit_middleware(request, handler):
8
- Rate limiter middleware.
9
- return await handler(request)
10
- """
 
 
 
 
 
 
 
 
 
 
 
FileStream/server/Middlewares/security_headers_middleware.py DELETED
@@ -1,14 +0,0 @@
1
- from aiohttp import web
2
-
3
- @web.middleware
4
- async def security_headers_middleware(request, handler):
5
- """Add security headers."""
6
- response = await handler(request)
7
- response.headers.update({
8
- "Content-Security-Policy": "default-src 'self'",
9
- "X-Content-Type-Options": "nosniff",
10
- "X-Frame-Options": "DENY",
11
- "Referrer-Policy": "no-referrer",
12
- "Strict-Transport-Security": "max-age=31536000; includeSubDomains"
13
- })
14
- return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
FileStream/server/__init__.py CHANGED
@@ -9,29 +9,6 @@ from .Authentication import auth
9
  from .routes_main import routes
10
  from FileStream.bot import MULTI_CLIENTS, WORK_LOADS, ACTIVE_CLIENTS
11
 
12
- """
13
- from .Middlewares.jwt_middleware import jwt_middleware
14
- from .Middlewares.app_token_middleware import app_token_middleware
15
- from .Middlewares.logging_middleware import logging_middleware
16
- #from .Middlewares.rate_limit_middleware import rate_limit_middleware
17
- """
18
- # Set time to consider a client inactive (e.g., 10 minutes)
19
- INACTIVITY_TIMEOUT = 180 # 3 minutes
20
-
21
- async def clear_inactive_clients():
22
- """Clear inactive clients from ACTIVE_CLIENTS."""
23
- await asyncio.sleep(INACTIVITY_TIMEOUT) # Check every INACTIVITY_TIMEOUT seconds
24
- now = asyncio.get_event_loop().time() # Get current time
25
- inactive_clients = [
26
- client_id for client_id, tg_connect in ACTIVE_CLIENTS.items()
27
- if now - tg_connect.last_activity > INACTIVITY_TIMEOUT # Compare with last_activity timestamp
28
- ]
29
- for client in inactive_clients:
30
- # Log and clear the inactive client
31
- logging.info(f"** Clearing inactive client: {client.name}")
32
- del ACTIVE_CLIENTS[client] # Remove inactive client from ACTIVE_CLIENTS
33
-
34
-
35
  async def root_route_handler(request):
36
  return web.json_response({"status": "alive", "message": "Server is running","active_clients":[{"client_name": tg_connect.client.name} for client_id, tg_connect in ACTIVE_CLIENTS.items()],"public_ip":request.remote})
37
 
 
9
  from .routes_main import routes
10
  from FileStream.bot import MULTI_CLIENTS, WORK_LOADS, ACTIVE_CLIENTS
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  async def root_route_handler(request):
13
  return web.json_response({"status": "alive", "message": "Server is running","active_clients":[{"client_name": tg_connect.client.name} for client_id, tg_connect in ACTIVE_CLIENTS.items()],"public_ip":request.remote})
14
 
Unused Codes/downloader_old.py CHANGED
@@ -25,22 +25,22 @@ from FileStream.utils.FileProcessors.custom_ul import TeleUploader
25
  async def media_streamer(request: web.Request, db_id: str, speed:str):
26
 
27
  range_header = request.headers.get("Range", 0)
28
- #index = minWORK_LOADS, keyWORK_LOADS.get)
29
- #faster_client = MULTI_CLIENTS[index]
30
 
31
- client = await req_client()
32
 
33
  if Telegram.MULTI_CLIENT:
34
  logging.info(f"Client {client['index']} is now serving {request.headers.get('X-FORWARDED-FOR',request.remote)}")
35
 
36
- if client['client'] in ACTIVE_CLIENTS:
37
- tg_connect = ACTIVE_CLIENTS[client['client']]
38
  logging.debug(f"Using cached ByteStreamer object for client {client['index']}")
39
 
40
  else:
41
  logging.debug(f"Creating new ByteStreamer object for client {client['index']}")
42
- tg_connect = utils.ByteStreamer(client['client'])
43
- ACTIVE_CLIENTS[client['client']] = tg_connect
44
 
45
  logging.debug("before calling get_file_properties")
46
  file_id = await tg_connect.get_file_properties(db_id, MULTI_CLIENTS)
@@ -75,7 +75,7 @@ async def media_streamer(request: web.Request, db_id: str, speed:str):
75
  req_length = until_bytes - from_bytes + 1
76
  part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
77
 
78
- body = tg_connect.yield_file(file_id, client['index'], offset, first_part_cut,last_part_cut, part_count, chunk_size)
79
 
80
  mime_type = file_id.mime_type
81
  file_name = utils.get_name(file_id)
 
25
  async def media_streamer(request: web.Request, db_id: str, speed:str):
26
 
27
  range_header = request.headers.get("Range", 0)
28
+ index = min(WORK_LOADS, key=WORK_LOADS.get)
29
+ faster_client = MULTI_CLIENTS[index]
30
 
31
+ #client = await req_client()
32
 
33
  if Telegram.MULTI_CLIENT:
34
  logging.info(f"Client {client['index']} is now serving {request.headers.get('X-FORWARDED-FOR',request.remote)}")
35
 
36
+ if faster_client in ACTIVE_CLIENTS:
37
+ tg_connect = ACTIVE_CLIENTS[faster_client]
38
  logging.debug(f"Using cached ByteStreamer object for client {client['index']}")
39
 
40
  else:
41
  logging.debug(f"Creating new ByteStreamer object for client {client['index']}")
42
+ tg_connect = utils.ByteStreamer(faster_client)
43
+ ACTIVE_CLIENTS[faster_client] = tg_connect
44
 
45
  logging.debug("before calling get_file_properties")
46
  file_id = await tg_connect.get_file_properties(db_id, MULTI_CLIENTS)
 
75
  req_length = until_bytes - from_bytes + 1
76
  part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
77
 
78
+ body = tg_connect.yield_file(file_id, index, offset, first_part_cut,last_part_cut, part_count, chunk_size)
79
 
80
  mime_type = file_id.mime_type
81
  file_name = utils.get_name(file_id)
{FileStream/server/API → Unused Codes}/listings.py RENAMED
File without changes