Initial commit: UMB Telegram Bot
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from aiogram import Router
|
||||
from aiogram.filters import Command
|
||||
from aiogram.types import Message, FSInputFile
|
||||
|
||||
from bot.utils.database import get_file_id, save_file_id
|
||||
from bot.utils.yadisk_download import download_yandex_file
|
||||
from bot.utils.s3_client import upload_file
|
||||
|
||||
router = Router()
|
||||
logger = logging.getLogger("yadisk")
|
||||
|
||||
MAX_TELEGRAM_FILE_SIZE = 50 * 1024 * 1024
|
||||
|
||||
|
||||
def is_valid_yandex_public_link(value: str) -> bool:
|
||||
value = value.strip().lower()
|
||||
return (
|
||||
value.startswith("https://disk.yandex.")
|
||||
or value.startswith("http://disk.yandex.")
|
||||
or value.startswith("https://yadi.sk/")
|
||||
or value.startswith("http://yadi.sk/")
|
||||
)
|
||||
|
||||
|
||||
@router.message(Command("ydf"))
|
||||
async def yandex_download_handler(message: Message):
|
||||
text = (message.text or "").strip()
|
||||
parts = text.split(maxsplit=1)
|
||||
|
||||
if len(parts) < 2 or not parts[1].strip():
|
||||
await message.answer("Укажите ссылку: /ydf https://yadi.sk/...")
|
||||
return
|
||||
|
||||
url = parts[1].strip()
|
||||
|
||||
if url.startswith("(new)"):
|
||||
url = url.replace("(new)", "", 1).strip()
|
||||
if not url:
|
||||
await message.answer("После (new) укажите ссылку.")
|
||||
return
|
||||
await save_file_id(url, None)
|
||||
|
||||
if not is_valid_yandex_public_link(url):
|
||||
await message.answer("Это не похоже на публичную ссылку Яндекс.Диска.")
|
||||
return
|
||||
|
||||
cached_id = await get_file_id(url)
|
||||
if cached_id:
|
||||
await message.answer_document(
|
||||
cached_id,
|
||||
caption="Файл из кеша Telegram. /ydf (new) [ссылка] для обновления.",
|
||||
)
|
||||
return
|
||||
|
||||
status_msg = await message.answer("Начинаю загрузку с Яндекс.Диска...")
|
||||
last_text = "Начинаю загрузку с Яндекс.Диска..."
|
||||
|
||||
async def progress(downloaded: int, total: int):
|
||||
nonlocal last_text
|
||||
if total <= 0:
|
||||
return
|
||||
pct = int(downloaded / total * 100)
|
||||
new_text = f"Загрузка: {pct}%"
|
||||
if new_text != last_text and pct % 5 == 0:
|
||||
try:
|
||||
await status_msg.edit_text(new_text)
|
||||
last_text = new_text
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
file_path = await download_yandex_file(url, progress_callback=progress)
|
||||
except Exception as exc:
|
||||
logger.exception("Ошибка скачивания с Яндекс.Диска")
|
||||
await status_msg.edit_text("Не удалось скачать файл. Проверьте ссылку.")
|
||||
return
|
||||
|
||||
try:
|
||||
file_size = os.path.getsize(file_path)
|
||||
|
||||
if file_size < MAX_TELEGRAM_FILE_SIZE:
|
||||
doc = FSInputFile(file_path)
|
||||
sent = await message.answer_document(doc)
|
||||
if sent.document and sent.document.file_id:
|
||||
await save_file_id(url, sent.document.file_id)
|
||||
await status_msg.delete()
|
||||
else:
|
||||
await status_msg.edit_text("Файл больше 50MB, загружаю в облако...")
|
||||
s3_url = await asyncio.to_thread(upload_file, file_path)
|
||||
if s3_url:
|
||||
await message.answer(f"Файл доступен для скачивания: {s3_url}")
|
||||
await status_msg.delete()
|
||||
else:
|
||||
await status_msg.edit_text("Не удалось загрузить файл в облако.")
|
||||
finally:
|
||||
try:
|
||||
os.remove(file_path)
|
||||
except OSError:
|
||||
pass
|
||||
Reference in New Issue
Block a user