Init
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.DS_Store
|
||||
.idea
|
||||
*.log
|
||||
tmp/
|
||||
venv/
|
||||
__pycache__/
|
||||
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# Use an official Python base image
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Set environment variables
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Set working directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy requirements and install Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy bot source code
|
||||
COPY . .
|
||||
|
||||
# Run the bot
|
||||
CMD ["python", "main.py"]
|
||||
23
api/kuma.py
Normal file
23
api/kuma.py
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from uptime_kuma_api import UptimeKumaApi
|
||||
import json
|
||||
|
||||
class KumaAPI:
|
||||
def __init__(self, ip, password):
|
||||
self.api = UptimeKumaApi(ip)
|
||||
self.api.login('admin', password)
|
||||
|
||||
def get_status(self):
|
||||
monitors = self.api.get_monitors()
|
||||
|
||||
res = {}
|
||||
for monitor in monitors:
|
||||
id = monitor['id']
|
||||
status = self.api.get_monitor_status(id)
|
||||
res[id] = {
|
||||
"status": status,
|
||||
"name": monitor["name"],
|
||||
}
|
||||
|
||||
return res
|
||||
20
api/qbittorrent.py
Normal file
20
api/qbittorrent.py
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from qbittorrent import Client
|
||||
|
||||
# Replace with your qBittorrent Web UI credentials
|
||||
qb = Client('http://192.168.1.17:8112')
|
||||
qb.login('admin', 'tMHNjrJr7nhjyhJrYsahi4anq2h6LJ')
|
||||
|
||||
# Retrieve all active torrents
|
||||
torrents = qb.torrents(filter='downloading')
|
||||
|
||||
# Print details of each active torrent
|
||||
for torrent in torrents:
|
||||
print(f"Name: {torrent['name']}")
|
||||
print(f"State: {torrent['state']}")
|
||||
print(f"Progress: {torrent['progress'] * 100:.2f}%")
|
||||
print(f"Download Speed: {torrent['dlspeed'] / 1024:.2f} KB/s")
|
||||
print(f"Upload Speed: {torrent['upspeed'] / 1024:.2f} KB/s")
|
||||
print(f"Size: {torrent['size'] / (1024 * 1024):.2f} MB")
|
||||
print('-' * 40)
|
||||
27
api/torrent.py
Normal file
27
api/torrent.py
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from qbittorrent import Client
|
||||
|
||||
class TorrentApi:
|
||||
def __init__(self, ip, password, username='admin'):
|
||||
# Initialize the qBittorrent client
|
||||
self.qb = Client(ip)
|
||||
self.qb.login(username, password)
|
||||
|
||||
def get_torrents(self):
|
||||
return self.get_filtered_torrents('all')
|
||||
|
||||
def get_filtered_torrents(self, state):
|
||||
# Retrieve torrents filtered by the given state
|
||||
torrents = self.qb.torrents(filter=state)
|
||||
# Extract relevant information
|
||||
torrent_list = []
|
||||
for torrent in torrents:
|
||||
torrent_info = {
|
||||
'name': torrent['name'],
|
||||
'state': torrent['state'],
|
||||
'progress': torrent['progress'] * 100, # Convert to percentage
|
||||
'eta': torrent['eta']
|
||||
}
|
||||
torrent_list.append(torrent_info)
|
||||
return torrent_list
|
||||
131
main.py
Normal file
131
main.py
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
|
||||
|
||||
from uptime_kuma_api import MonitorStatus
|
||||
import api.kuma as kuma
|
||||
|
||||
import api.torrent as torrent
|
||||
|
||||
TOKEN = "7396669954:AAH8_I0Y-qg3j_LfbUdRTOLPDKh80NdijMo"
|
||||
|
||||
# --- Menu Definitions ---
|
||||
def main_menu_keyboard():
|
||||
return InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("Torrents", callback_data='status_downloading')],
|
||||
[InlineKeyboardButton("Status", callback_data='menu_status')]
|
||||
])
|
||||
|
||||
def torrents_menu_keyboard():
|
||||
return InlineKeyboardMarkup([
|
||||
# First row: Display the status counts for downloading, paused, seeding
|
||||
[InlineKeyboardButton(f"Downloading", callback_data='status_downloading')],
|
||||
[InlineKeyboardButton(f"Active", callback_data='status_active')],
|
||||
[InlineKeyboardButton(f"All", callback_data='status_all')],
|
||||
# Second row: Back button
|
||||
[InlineKeyboardButton("🔙 Back", callback_data='menu_main')]
|
||||
])
|
||||
|
||||
def status_menu_keyboard():
|
||||
return InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("🔙 Back", callback_data='menu_main')]
|
||||
])
|
||||
|
||||
# --- Command Handlers ---
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
await update.message.reply_text("Choose an option:", reply_markup=main_menu_keyboard())
|
||||
|
||||
|
||||
def format_torrents(torrents):
|
||||
if len(torrents) == 0:
|
||||
return "No torrents."
|
||||
|
||||
text = ""
|
||||
|
||||
i = 0
|
||||
for torrent in torrents:
|
||||
if i > 10:
|
||||
text += "...\n"
|
||||
return text
|
||||
|
||||
text += f"- {torrent['name']} - {torrent['progress']} ({torrent['eta']})\n"
|
||||
i += 1
|
||||
|
||||
return text
|
||||
|
||||
# --- Callback Query Handler ---
|
||||
async def handle_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
query = update.callback_query
|
||||
await query.answer()
|
||||
|
||||
match query.data:
|
||||
case 'menu_main':
|
||||
await query.edit_message_text("Choose an option:", reply_markup=main_menu_keyboard())
|
||||
|
||||
case 'status_downloading':
|
||||
torrent_api = context.bot_data.get("torrent_api", {})
|
||||
torrents = torrent_api.get_filtered_torrents("downloading")
|
||||
|
||||
text = format_torrents(torrents)
|
||||
|
||||
await query.edit_message_text(text, reply_markup=torrents_menu_keyboard())
|
||||
|
||||
case 'status_active':
|
||||
torrent_api = context.bot_data.get("torrent_api", {})
|
||||
torrents = torrent_api.get_filtered_torrents("active")
|
||||
|
||||
text = format_torrents(torrents)
|
||||
|
||||
await query.edit_message_text(text, reply_markup=torrents_menu_keyboard())
|
||||
|
||||
|
||||
case 'status_all':
|
||||
torrent_api = context.bot_data.get("torrent_api", {})
|
||||
torrents = torrent_api.get_filtered_torrents("all")
|
||||
|
||||
text = format_torrents(torrents)
|
||||
|
||||
await query.edit_message_text(text, reply_markup=torrents_menu_keyboard())
|
||||
|
||||
case 'menu_status':
|
||||
kuma_api = context.bot_data.get("kuma_api", {})
|
||||
monitors = kuma_api.get_status()
|
||||
|
||||
up_text, down_text, paused_text = "", "", ""
|
||||
for _, monitor in monitors.items():
|
||||
status = monitor['status']
|
||||
|
||||
if status == MonitorStatus.UP:
|
||||
up_text += f" - {monitor['name']}\n"
|
||||
elif status == MonitorStatus.DOWN:
|
||||
down_text += f" - {monitor['name']}\n"
|
||||
else:
|
||||
paused_text += f" - {monitor['name']}\n"
|
||||
|
||||
|
||||
status_text = f"📡 *Status:*\n\n 🟢 Up:\n{up_text}\n🔴 Down\n{down_text}\n⏸️ Paused\n{paused_text}"
|
||||
|
||||
await query.edit_message_text(status_text, reply_markup=status_menu_keyboard())
|
||||
|
||||
case _:
|
||||
await query.edit_message_text("Unknown option selected.", reply_markup=main_menu_keyboard())
|
||||
|
||||
# --- Main Function ---
|
||||
def main():
|
||||
# Initiate api
|
||||
kuma_api = kuma.KumaAPI("http://192.168.1.2:36667", "k!PTfyvoIJho9o*gX6F1")
|
||||
torrent_api = torrent.TorrentApi("http://192.168.1.17:8112", "tMHNjrJr7nhjyhJrYsahi4anq2h6LJ")
|
||||
|
||||
app = Application.builder().token(TOKEN).build()
|
||||
app.bot_data["kuma_api"] = kuma_api
|
||||
app.bot_data["torrent_api"] = torrent_api
|
||||
|
||||
app.add_handler(CommandHandler("start", start))
|
||||
app.add_handler(CallbackQueryHandler(handle_menu))
|
||||
|
||||
print("Bot is running... Press Ctrl+C to stop.")
|
||||
app.run_polling()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
python-qbittorrent
|
||||
uptime-kuma-api
|
||||
python-telegram-bot
|
||||
Reference in New Issue
Block a user