TelegramIndex-Fork/app/views/download.py

77 lines
2.5 KiB
Python
Raw Normal View History

2020-12-12 15:16:44 +01:00
import logging
from aiohttp import web
from app.util import get_file_name
from app.config import block_downloads
log = logging.getLogger(__name__)
class Download:
async def download_get(self, req):
return await self.handle_request(req)
async def download_head(self, req):
return await self.handle_request(req, head=True)
async def handle_request(self, req, head=False):
if block_downloads:
2020-12-12 17:31:21 +01:00
return web.Response(status=403, text="403: Forbiden" if not head else None)
2020-12-12 15:16:44 +01:00
file_id = int(req.match_info["id"])
2021-05-22 16:00:08 +02:00
alias_id = req.match_info["chat"]
chat = self.chat_ids[alias_id]
chat_id = chat["chat_id"]
2020-12-12 15:16:44 +01:00
try:
message = await self.client.get_messages(entity=chat_id, ids=file_id)
2021-05-22 16:00:08 +02:00
except Exception:
2020-12-12 15:16:44 +01:00
log.debug(f"Error in getting message {file_id} in {chat_id}", exc_info=True)
message = None
if not message or not message.file:
log.debug(f"no result for {file_id} in {chat_id}")
2021-05-22 16:00:08 +02:00
return web.Response(
status=410,
text="410: Gone. Access to the target resource is no longer available!"
if not head
else None,
)
2020-12-12 15:16:44 +01:00
media = message.media
size = message.file.size
file_name = get_file_name(message)
mime_type = message.file.mime_type
try:
offset = req.http_range.start or 0
limit = req.http_range.stop or size
if (limit > size) or (offset < 0) or (limit < offset):
raise ValueError("range not in acceptable format")
except ValueError:
return web.Response(
status=416,
2020-12-12 17:31:21 +01:00
text="416: Range Not Satisfiable" if not head else None,
2021-05-22 16:00:08 +02:00
headers={"Content-Range": f"bytes */{size}"},
2020-12-12 15:16:44 +01:00
)
if not head:
body = self.client.download(media, size, offset, limit)
2021-05-22 16:00:08 +02:00
log.info(
f"Serving file in {message.id} (chat {chat_id}) ; Range: {offset} - {limit}"
)
2020-12-12 15:16:44 +01:00
else:
body = None
headers = {
"Content-Type": mime_type,
"Content-Range": f"bytes {offset}-{limit}/{size}",
"Content-Length": str(limit - offset),
"Accept-Ranges": "bytes",
2021-05-22 16:00:08 +02:00
"Content-Disposition": f'attachment; filename="{file_name}"',
2020-12-12 15:16:44 +01:00
}
2021-05-22 16:00:08 +02:00
return web.Response(status=206 if offset else 200, body=body, headers=headers)