Add files via upload

This commit is contained in:
DerrtSML 2025-06-23 15:48:05 +03:00 committed by GitHub
commit ac0d56d9b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 220 additions and 0 deletions

15
Dockerfile Normal file
View File

@ -0,0 +1,15 @@
# Используем официальный образ Python
FROM python:3.10-slim-buster
# Устанавливаем рабочую директорию
WORKDIR /app
# Копируем файл зависимостей и устанавливаем их
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Копируем остальные файлы приложения
COPY . .
# Команда для запуска приложения
CMD ["python", "bot.py"]

181
bot.py Normal file
View File

@ -0,0 +1,181 @@
import logging
import os
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Application,
CommandHandler,
MessageHandler,
filters,
CallbackQueryHandler,
ContextTypes,
)
from qbittorrent import Client, APIError
# Настройка логирования
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
# --- Конфигурация (будет загружаться из переменных окружения Docker) ---
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
QBT_HOST = os.getenv("QBT_HOST")
QBT_PORT = os.getenv("QBT_PORT", "8080")
QBT_USERNAME = os.getenv("QBT_USERNAME")
QBT_PASSWORD = os.getenv("QBT_PASSWORD")
# Определение доступных директорий (предполагаем, что они известны)
# В реальной системе можно было бы получить список из qBittorrent API
# или настроить их через переменные окружения.
DOWNLOAD_DIRECTORIES = {
"Фильмы": "/share/Data/Felms",
"Сериалы": "/share/Data/Serials",
"Музыка": "/share/Music",
"Другое": "/share/Data/torrents",
}
# --- Инициализация qBittorrent клиента ---
qb = None
def init_qbittorrent_client():
global qb
if not all([QBT_HOST, QBT_USERNAME, QBT_PASSWORD]):
logger.error("QBittorrent credentials are not fully set in environment variables.")
return False
try:
qb = Client(f"http://{QBT_HOST}:{QBT_PORT}/")
qb.login(QBT_USERNAME, QBT_PASSWORD)
logger.info(f"Successfully connected to qBittorrent at {QBT_HOST}:{QBT_PORT}")
return True
except APIError as e:
logger.error(f"Failed to connect or login to qBittorrent: {e}")
qb = None
return False
except Exception as e:
logger.error(f"An unexpected error occurred during qBittorrent connection: {e}")
qb = None
return False
# --- Обработчики команд ---
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if not init_qbittorrent_client():
await update.message.reply_text(
"Не удалось подключиться к qBittorrent. Проверьте переменные окружения и доступность сервера."
)
return
await update.message.reply_text(
"Привет! Я бот для управления qBittorrent.\n"
"Отправь мне magnet-ссылку или URL torrent-файла, "
"чтобы добавить загрузку.\n"
"Используй /status для просмотра текущих загрузок."
)
async def status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if not qb:
if not init_qbittorrent_client():
await update.message.reply_text(
"Не удалось подключиться к qBittorrent. Попробуйте еще раз или проверьте настройки."
)
return
try:
torrents = qb.torrents()
if not torrents:
await update.message.reply_text("Нет активных загрузок.")
return
message = "Текущие загрузки:\n\n"
for t in torrents:
progress = f"{t.progress:.2%}"
size = f"{t.size / (1024*1024*1024):.2f} GB" if t.size else "N/A"
download_speed = f"{t.dlspeed / (1024*1024):.2f} MB/s"
upload_speed = f"{t.upspeed / (1024*1024):.2f} MB/s"
message += (
f"📝 Имя: {t.name}\n"
f"📊 Прогресс: {progress}\n"
f"📦 Размер: {size}\n"
f"⬇️ Скорость загрузки: {download_speed}\n"
f"⬆️ Скорость отдачи: {upload_speed}\n"
f"🚦 Статус: {t.state}\n"
f"--- \n"
)
await update.message.reply_text(message)
except APIError as e:
logger.error(f"Error fetching torrents: {e}")
await update.message.reply_text(f"Ошибка при получении списка загрузок: {e}")
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")
await update.message.reply_text(f"Произошла непредвиденная ошибка: {e}")
async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if not qb:
if not init_qbittorrent_client():
await update.message.reply_text(
"Не удалось подключиться к qBittorrent. Попробуйте еще раз или проверьте настройки."
)
return
url = update.message.text
context.user_data['download_url'] = url
keyboard = []
for name, path in DOWNLOAD_DIRECTORIES.items():
keyboard.append([InlineKeyboardButton(name, callback_data=f"dir_{path}")])
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(
f"Вы хотите загрузить: `{url}`\n"
"Выберите директорию для загрузки:",
reply_markup=reply_markup,
parse_mode='Markdown'
)
async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.callback_query
await query.answer()
if query.data.startswith("dir_"):
selected_directory = query.data.replace("dir_", "")
download_url = context.user_data.get('download_url')
if not download_url:
await query.edit_message_text("Ошибка: URL для загрузки не найден. Пожалуйста, отправьте ссылку снова.")
return
try:
qb.download_from_link(download_url, save_path=selected_directory)
await query.edit_message_text(
f"Загрузка '{download_url}' добавлена в '{selected_directory}'."
)
logger.info(f"Added download '{download_url}' to '{selected_directory}'")
except APIError as e:
logger.error(f"Error adding download: {e}")
await query.edit_message_text(f"Ошибка при добавлении загрузки: {e}")
except Exception as e:
logger.error(f"An unexpected error occurred while adding download: {e}")
await query.edit_message_text(f"Произошла непредвиденная ошибка при добавлении загрузки: {e}")
def main() -> None:
application = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("status", status))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_url))
application.add_handler(CallbackQueryHandler(button_callback))
logger.info("Bot started polling...")
application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
if not TELEGRAM_BOT_TOKEN:
logger.error("TELEGRAM_BOT_TOKEN is not set. Please set the environment variable.")
exit(1)
if not all([QBT_HOST, QBT_USERNAME, QBT_PASSWORD]):
logger.warning("QBittorrent connection details (QBT_HOST, QBT_USERNAME, QBT_PASSWORD) are not fully set. Bot will attempt to connect on first use of qBittorrent related commands.")
main()

22
docker-compose.yml Normal file
View File

@ -0,0 +1,22 @@
version: '3.8'
services:
qbittorrent_telegram_bot:
container_name: qbittorrent_telegram_bot
build: .
restart: unless-stopped
environment:
# Замените на ваш токен бота
- TELEGRAM_BOT_TOKEN=6239443076:AAFnFHT9VWd5iuEriQZqssEAn2DugbLK0v8
# Замените на IP или hostname вашего сервера qBittorrent
- QBT_HOST=https://qbittorrent.derrt.site/
# Порт Web UI qBittorrent (по умолчанию 8080)
- QBT_PORT=443
# Логин для qBittorrent Web UI
- QBT_USERNAME=Derrt
# Пароль для qBittorrent Web UI
- QBT_PASSWORD=Derrty5Derrt5
# Если qBittorrent находится на другом хосте или вы используете Docker bridge network,
# убедитесь, что бот может до него достучаться.
# Если qBittorrent также в Docker и в той же сети, можно использовать имя сервиса.
# network_mode: host # Используйте, если хотите, чтобы бот видел хост напрямую

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
python-telegram-bot
python-qbt