mirror of
https://github.com/flibusta-apps/telegram_files_server.git
synced 2025-12-06 12:35:39 +01:00
Add downloading
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from app.services.file_uploader import FileUploader
|
from app.services.storages import StoragesContainer
|
||||||
|
|
||||||
|
|
||||||
async def on_start():
|
async def on_start():
|
||||||
await FileUploader.prepare()
|
await StoragesContainer.prepare()
|
||||||
|
|||||||
61
fastapi_file_server/app/services/file_downloader.py
Normal file
61
fastapi_file_server/app/services/file_downloader.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from io import BytesIO
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from telegram_files_storage import AiogramFilesStorage, TelethonFilesStorage
|
||||||
|
|
||||||
|
from app.services.storages import StoragesContainer
|
||||||
|
|
||||||
|
|
||||||
|
class FileDownloader:
|
||||||
|
_aiogram_storage_index = 0
|
||||||
|
_telethon_storage_index = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@property
|
||||||
|
def AIOGRAM_STORAGES(cls) -> list[AiogramFilesStorage]:
|
||||||
|
return StoragesContainer.AIOGRAM_STORAGES
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@property
|
||||||
|
def TELETHON_STORAGES(cls) -> list[TelethonFilesStorage]:
|
||||||
|
return StoragesContainer.TELETHON_STORAGES
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_aiogram_storage(cls) -> AiogramFilesStorage:
|
||||||
|
if not cls.AIOGRAM_STORAGES:
|
||||||
|
raise ValueError("Aiogram storage not exist!")
|
||||||
|
|
||||||
|
cls._aiogram_storage_index = (cls._aiogram_storage_index + 1) % len(
|
||||||
|
cls.AIOGRAM_STORAGES
|
||||||
|
)
|
||||||
|
|
||||||
|
return cls.AIOGRAM_STORAGES[cls._aiogram_storage_index]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_telethon_storage(cls) -> TelethonFilesStorage:
|
||||||
|
if not cls.TELETHON_STORAGES:
|
||||||
|
raise ValueError("Telethon storage not exists!")
|
||||||
|
|
||||||
|
cls._telethon_storage_index = (cls._telethon_storage_index + 1) % len(
|
||||||
|
cls.TELETHON_STORAGES
|
||||||
|
)
|
||||||
|
|
||||||
|
return cls.TELETHON_STORAGES[cls._telethon_storage_index]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def download_by_file_id(cls, file_id: str) -> Optional[BytesIO]:
|
||||||
|
if not cls.AIOGRAM_STORAGES:
|
||||||
|
return None
|
||||||
|
|
||||||
|
storage = cls.get_aiogram_storage()
|
||||||
|
|
||||||
|
return await storage.download(file_id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def download_by_message_id(cls, message_id: int) -> Optional[BytesIO]:
|
||||||
|
if not cls.TELETHON_STORAGES:
|
||||||
|
return None
|
||||||
|
|
||||||
|
storage = cls.get_telethon_storage()
|
||||||
|
|
||||||
|
return await storage.download(message_id)
|
||||||
@@ -6,16 +6,23 @@ from fastapi import UploadFile
|
|||||||
from telegram_files_storage import AiogramFilesStorage, TelethonFilesStorage
|
from telegram_files_storage import AiogramFilesStorage, TelethonFilesStorage
|
||||||
|
|
||||||
from app.models import UploadedFile, UploadBackends
|
from app.models import UploadedFile, UploadBackends
|
||||||
from core.config import env_config
|
from app.services.storages import StoragesContainer
|
||||||
|
|
||||||
|
|
||||||
class FileUploader:
|
class FileUploader:
|
||||||
AIOGRAM_STORAGES: list[AiogramFilesStorage] = []
|
|
||||||
TELETHON_STORAGES: list[TelethonFilesStorage] = []
|
|
||||||
|
|
||||||
_aiogram_storage_index = 0
|
_aiogram_storage_index = 0
|
||||||
_telethon_storage_index = 0
|
_telethon_storage_index = 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@property
|
||||||
|
def AIOGRAM_STORAGES(cls) -> list[AiogramFilesStorage]:
|
||||||
|
return StoragesContainer.AIOGRAM_STORAGES
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@property
|
||||||
|
def TELETHON_STORAGES(cls) -> list[TelethonFilesStorage]:
|
||||||
|
return StoragesContainer.TELETHON_STORAGES
|
||||||
|
|
||||||
def __init__(self, file: UploadFile, caption: Optional[str] = None) -> None:
|
def __init__(self, file: UploadFile, caption: Optional[str] = None) -> None:
|
||||||
self.file = file
|
self.file = file
|
||||||
self.caption = caption
|
self.caption = caption
|
||||||
@@ -81,28 +88,6 @@ class FileUploader:
|
|||||||
data=self.upload_data,
|
data=self.upload_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def prepare(cls):
|
|
||||||
if env_config.BOT_TOKENS:
|
|
||||||
cls.AIOGRAM_STORAGES: list[AiogramFilesStorage] = [
|
|
||||||
AiogramFilesStorage(env_config.TELEGRAM_CHAT_ID, token)
|
|
||||||
for token in env_config.BOT_TOKENS
|
|
||||||
]
|
|
||||||
|
|
||||||
if env_config.TELETHON_APP_CONFIG and env_config.TELETHON_SESSIONS:
|
|
||||||
cls.TELETHON_STORAGES: list[TelethonFilesStorage] = [
|
|
||||||
TelethonFilesStorage(
|
|
||||||
env_config.TELEGRAM_CHAT_ID,
|
|
||||||
env_config.TELETHON_APP_CONFIG.APP_ID,
|
|
||||||
env_config.TELETHON_APP_CONFIG.API_HASH,
|
|
||||||
session,
|
|
||||||
)
|
|
||||||
for session in env_config.TELETHON_SESSIONS
|
|
||||||
]
|
|
||||||
|
|
||||||
for storage in [*cls.AIOGRAM_STORAGES, *cls.TELETHON_STORAGES]:
|
|
||||||
await storage.prepare()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_aiogram_storage(cls) -> AiogramFilesStorage:
|
def get_aiogram_storage(cls) -> AiogramFilesStorage:
|
||||||
if not cls.AIOGRAM_STORAGES:
|
if not cls.AIOGRAM_STORAGES:
|
||||||
|
|||||||
30
fastapi_file_server/app/services/storages.py
Normal file
30
fastapi_file_server/app/services/storages.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
from telegram_files_storage import AiogramFilesStorage, TelethonFilesStorage
|
||||||
|
|
||||||
|
from core.config import env_config
|
||||||
|
|
||||||
|
|
||||||
|
class StoragesContainer:
|
||||||
|
AIOGRAM_STORAGES: list[AiogramFilesStorage] = []
|
||||||
|
TELETHON_STORAGES: list[TelethonFilesStorage] = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def prepare(cls):
|
||||||
|
if env_config.BOT_TOKENS:
|
||||||
|
cls.AIOGRAM_STORAGES: list[AiogramFilesStorage] = [
|
||||||
|
AiogramFilesStorage(env_config.TELEGRAM_CHAT_ID, token)
|
||||||
|
for token in env_config.BOT_TOKENS
|
||||||
|
]
|
||||||
|
|
||||||
|
if env_config.TELETHON_APP_CONFIG and env_config.TELETHON_SESSIONS:
|
||||||
|
cls.TELETHON_STORAGES: list[TelethonFilesStorage] = [
|
||||||
|
TelethonFilesStorage(
|
||||||
|
env_config.TELEGRAM_CHAT_ID,
|
||||||
|
env_config.TELETHON_APP_CONFIG.APP_ID,
|
||||||
|
env_config.TELETHON_APP_CONFIG.API_HASH,
|
||||||
|
session,
|
||||||
|
)
|
||||||
|
for session in env_config.TELETHON_SESSIONS
|
||||||
|
]
|
||||||
|
|
||||||
|
for storage in [*cls.AIOGRAM_STORAGES, *cls.TELETHON_STORAGES]:
|
||||||
|
await storage.prepare()
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from fastapi import File, UploadFile, Depends, Form, APIRouter, HTTPException
|
from fastapi import (
|
||||||
|
File,
|
||||||
from starlette import status
|
UploadFile,
|
||||||
|
Depends,
|
||||||
|
Form,
|
||||||
|
APIRouter,
|
||||||
|
HTTPException,
|
||||||
|
Response,
|
||||||
|
status,
|
||||||
|
)
|
||||||
|
|
||||||
from app.depends import check_token
|
from app.depends import check_token
|
||||||
from app.models import UploadedFile as UploadedFileDB
|
from app.models import UploadedFile as UploadedFileDB
|
||||||
from app.serializers import UploadedFile, CreateUploadedFile
|
from app.serializers import UploadedFile, CreateUploadedFile
|
||||||
|
from app.services.file_downloader import FileDownloader
|
||||||
from app.services.file_uploader import FileUploader
|
from app.services.file_uploader import FileUploader
|
||||||
|
|
||||||
|
|
||||||
@@ -46,6 +54,26 @@ async def upload_file(file: UploadFile = File({}), caption: Optional[str] = Form
|
|||||||
return await FileUploader.upload(file, caption=caption)
|
return await FileUploader.upload(file, caption=caption)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/download_by_file_id/{file_id}")
|
||||||
|
async def download_by_file_id(file_id: str):
|
||||||
|
data = await FileDownloader.download_by_file_id(file_id)
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
return Response(data.read())
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/download_by_message/{chat_id}/{message_id}")
|
||||||
|
async def download_by_message(chat_id: str, message_id: int):
|
||||||
|
data = await FileDownloader.download_by_message_id(message_id)
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
return Response(data.read())
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{file_id}", response_model=UploadedFile, responses={400: {}})
|
@router.delete("/{file_id}", response_model=UploadedFile, responses={400: {}})
|
||||||
async def delete_file(file_id: int):
|
async def delete_file(file_id: int):
|
||||||
uploaded_file = await UploadedFileDB.objects.get_or_none(id=file_id)
|
uploaded_file = await UploadedFileDB.objects.get_or_none(id=file_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user