Files

84 lines
2.9 KiB
Python
Raw Permalink Normal View History

2023-11-05 22:02:58 +05:30
from quart import Blueprint, Response, request, render_template, redirect
2024-11-20 15:29:44 +05:30
from math import ceil
from re import match as re_match
2023-11-13 11:55:37 +05:30
from .error import abort
2023-11-09 14:02:06 +05:30
from bot import TelegramBot
2023-11-05 22:02:58 +05:30
from bot.config import Telegram, Server
from bot.modules.telegram import get_message, get_file_properties
bp = Blueprint('main', __name__)
@bp.route('/')
async def home():
return redirect(f'https://t.me/{Telegram.BOT_USERNAME}')
@bp.route('/dl/<int:file_id>')
async def transmit_file(file_id):
2024-11-20 15:29:44 +05:30
file = await get_message(file_id) or abort(404)
2023-11-05 22:02:58 +05:30
code = request.args.get('code') or abort(401)
2024-11-20 15:29:44 +05:30
range_header = request.headers.get('Range')
2023-11-05 22:02:58 +05:30
2024-11-20 15:29:44 +05:30
if code != file.caption.split('/')[0]:
2023-11-05 22:02:58 +05:30
abort(403)
2023-11-09 14:02:06 +05:30
2023-11-13 11:55:37 +05:30
file_name, file_size, mime_type = get_file_properties(file)
2023-11-09 14:02:06 +05:30
2024-11-20 15:29:44 +05:30
start = 0
end = file_size - 1
chunk_size = 1 * 1024 * 1024 # 1 MB
2023-11-09 14:02:06 +05:30
2024-11-20 15:29:44 +05:30
if range_header:
range_match = re_match(r'bytes=(\d+)-(\d*)', range_header)
if range_match:
start = int(range_match.group(1))
end = int(range_match.group(2)) if range_match.group(2) else file_size - 1
if start > end or start >= file_size:
abort(416, 'Requested range not satisfiable')
else:
abort(400, 'Invalid Range header')
offset_chunks = start // chunk_size
total_bytes_to_stream = end - start + 1
chunks_to_stream = ceil(total_bytes_to_stream / chunk_size)
content_length = total_bytes_to_stream
2023-11-13 11:55:37 +05:30
headers = {
2024-11-20 15:29:44 +05:30
'Content-Type': mime_type,
'Content-Disposition': f'attachment; filename={file_name}',
'Content-Range': f'bytes {start}-{end}/{file_size}',
'Accept-Ranges': 'bytes',
'Content-Length': str(content_length),
}
status_code = 206 if range_header else 200
async def file_stream():
bytes_streamed = 0
chunk_index = 0
async for chunk in TelegramBot.stream_media(
file,
offset=offset_chunks,
limit=chunks_to_stream,
):
if chunk_index == 0: # Trim the first chunk if necessary
trim_start = start % chunk_size
if trim_start > 0:
chunk = chunk[trim_start:]
remaining_bytes = content_length - bytes_streamed
if remaining_bytes <= 0:
2023-11-09 14:02:06 +05:30
break
2023-11-13 11:55:37 +05:30
2024-11-20 15:29:44 +05:30
if len(chunk) > remaining_bytes: # Trim the last chunk if necessary
chunk = chunk[:remaining_bytes]
2023-11-09 14:02:06 +05:30
2024-11-20 15:29:44 +05:30
yield chunk
bytes_streamed += len(chunk)
chunk_index += 1
2023-11-05 22:02:58 +05:30
2024-11-20 15:29:44 +05:30
return Response(file_stream(), headers=headers, status=status_code)
2023-11-05 22:02:58 +05:30
@bp.route('/stream/<int:file_id>')
async def stream_file(file_id):
code = request.args.get('code') or abort(401)
return await render_template('player.html', mediaLink=f'{Server.BASE_URL}/dl/{file_id}?code={code}')