Spaces:
Running
Running
Foydalanuvchi commited on
Commit Β·
54844e5
1
Parent(s): 5425774
Phase 15: Admin Panel added with stats, broadcast and db export
Browse files- database.py +30 -0
- main.py +87 -6
database.py
CHANGED
|
@@ -88,5 +88,35 @@ class Database:
|
|
| 88 |
result = cursor.fetchone()
|
| 89 |
return result[0] if result else 'retro'
|
| 90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
# Global DB instance
|
| 92 |
db = Database()
|
|
|
|
| 88 |
result = cursor.fetchone()
|
| 89 |
return result[0] if result else 'retro'
|
| 90 |
|
| 91 |
+
def get_stats(self):
|
| 92 |
+
"""Bot statistikasini qaytaradi (jami userlar va amallar)."""
|
| 93 |
+
with self.get_connection() as conn:
|
| 94 |
+
cursor = conn.cursor()
|
| 95 |
+
cursor.execute('SELECT COUNT(*) FROM users')
|
| 96 |
+
total_users = cursor.fetchone()[0]
|
| 97 |
+
|
| 98 |
+
cursor.execute('SELECT COUNT(*) FROM history')
|
| 99 |
+
total_processed = cursor.fetchone()[0]
|
| 100 |
+
|
| 101 |
+
# Oxirgi 24 soatdagi faollik
|
| 102 |
+
cursor.execute('''
|
| 103 |
+
SELECT COUNT(*) FROM history
|
| 104 |
+
WHERE processed_at > datetime("now", "-1 day")
|
| 105 |
+
''')
|
| 106 |
+
daily_active = cursor.fetchone()[0]
|
| 107 |
+
|
| 108 |
+
return {
|
| 109 |
+
"total_users": total_users,
|
| 110 |
+
"total_processed": total_processed,
|
| 111 |
+
"daily_active": daily_active
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
def get_all_users(self):
|
| 115 |
+
"""Xabar tarqatish uchun barcha user ID-larini qaytaradi."""
|
| 116 |
+
with self.get_connection() as conn:
|
| 117 |
+
cursor = conn.cursor()
|
| 118 |
+
cursor.execute('SELECT user_id FROM users')
|
| 119 |
+
return [row[0] for row in cursor.fetchall()]
|
| 120 |
+
|
| 121 |
# Global DB instance
|
| 122 |
db = Database()
|
main.py
CHANGED
|
@@ -55,11 +55,13 @@ from filters import (
|
|
| 55 |
process_video_trim, process_video_face_fix, process_video_auto_enhance,
|
| 56 |
process_video_fps_boost, apply_nudenet_filter, process_video_nnsfw,
|
| 57 |
process_video_subtitle,
|
| 58 |
-
apply_glitch_filter, apply_mirror_filter, apply_watermark, apply_bg_remove,
|
| 59 |
-
apply_style_transfer, apply_quality_boost,
|
| 60 |
-
process_video_glitch, process_video_mirror, process_video_watermark,
|
| 61 |
process_video_subtitle_translate
|
| 62 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
from database import db
|
| 64 |
from concurrent.futures import ThreadPoolExecutor
|
| 65 |
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
@@ -266,6 +268,34 @@ async def handle_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
| 266 |
logger.error(f"Error in handle_photo: {e}")
|
| 267 |
await update.message.reply_text("β Xatolik yuz berdi.")
|
| 268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
async def handle_video(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
| 270 |
"""Videolarni qabul qilish."""
|
| 271 |
try:
|
|
@@ -376,11 +406,60 @@ async def navigation_handler(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
|
| 376 |
keyboard = [[InlineKeyboardButton("π Orqaga", callback_data="nav|main")]]
|
| 377 |
await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode=constants.ParseMode.MARKDOWN)
|
| 378 |
|
| 379 |
-
async def
|
| 380 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
query = update.callback_query
|
| 382 |
await query.answer()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 383 |
|
|
|
|
| 384 |
try:
|
| 385 |
data = query.data.split("|")
|
| 386 |
action, m_type, short_id = data[0], data[1], data[2]
|
|
@@ -604,11 +683,13 @@ if __name__ == '__main__':
|
|
| 604 |
app = ApplicationBuilder().token(TOKEN).request(request).post_init(post_init).build()
|
| 605 |
|
| 606 |
app.add_handler(CommandHandler("start", start))
|
|
|
|
| 607 |
app.add_handler(CallbackQueryHandler(navigation_handler, pattern=r"^nav\|"))
|
| 608 |
app.add_handler(CallbackQueryHandler(settings_callback_handler, pattern=r"^set\|"))
|
| 609 |
-
app.add_handler(CallbackQueryHandler(
|
| 610 |
app.add_handler(MessageHandler(filters.PHOTO, handle_photo))
|
| 611 |
app.add_handler(MessageHandler(filters.VIDEO | filters.ANIMATION | filters.Document.ALL, handle_video))
|
|
|
|
| 612 |
|
| 613 |
logger.info("Bot polling rejimi ishga tushmoqda...")
|
| 614 |
app.run_polling()
|
|
|
|
| 55 |
process_video_trim, process_video_face_fix, process_video_auto_enhance,
|
| 56 |
process_video_fps_boost, apply_nudenet_filter, process_video_nnsfw,
|
| 57 |
process_video_subtitle,
|
|
|
|
|
|
|
|
|
|
| 58 |
process_video_subtitle_translate
|
| 59 |
)
|
| 60 |
+
|
| 61 |
+
# Admin sozlamalari
|
| 62 |
+
ADMIN_ID = int(os.environ.get("ADMIN_ID", 6309900880))
|
| 63 |
+
BROADCAST_MODE = {} # {admin_id: True}
|
| 64 |
+
|
| 65 |
from database import db
|
| 66 |
from concurrent.futures import ThreadPoolExecutor
|
| 67 |
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
|
|
| 268 |
logger.error(f"Error in handle_photo: {e}")
|
| 269 |
await update.message.reply_text("β Xatolik yuz berdi.")
|
| 270 |
|
| 271 |
+
async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
| 272 |
+
"""Matn xabarlarini qabul qilish."""
|
| 273 |
+
# Agar admin xabar tarqatish rejimida bo'lsa
|
| 274 |
+
if update.effective_user.id == ADMIN_ID and BROADCAST_MODE.get(ADMIN_ID):
|
| 275 |
+
BROADCAST_MODE[ADMIN_ID] = False
|
| 276 |
+
text_to_send = update.message.text
|
| 277 |
+
users = db.get_all_users()
|
| 278 |
+
count = 0
|
| 279 |
+
status_msg = await update.message.reply_text(f"π Xabar tarqatish boshlandi (0/{len(users)})...")
|
| 280 |
+
|
| 281 |
+
for u_id in users:
|
| 282 |
+
try:
|
| 283 |
+
await context.bot.send_message(u_id, text_to_send)
|
| 284 |
+
count += 1
|
| 285 |
+
if count % 10 == 0:
|
| 286 |
+
await status_msg.edit_text(f"π Xabar tarqatish davom etmoqda ({count}/{len(users)})...")
|
| 287 |
+
except:
|
| 288 |
+
pass
|
| 289 |
+
|
| 290 |
+
await status_msg.edit_text(f"β
Xabar tarqatish yakunlandi. {count} ta foydalanuvchiga yuborildi.")
|
| 291 |
+
return
|
| 292 |
+
|
| 293 |
+
# Check for text (if they send prompt for style transfer or other features)
|
| 294 |
+
text = update.message.text
|
| 295 |
+
# Add any other text handling logic here if needed
|
| 296 |
+
await update.message.reply_text("Kechirasiz, men faqat rasm va videolarni qayta ishlay olaman. Iltimos, rasm yoki video yuboring.")
|
| 297 |
+
|
| 298 |
+
|
| 299 |
async def handle_video(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
| 300 |
"""Videolarni qabul qilish."""
|
| 301 |
try:
|
|
|
|
| 406 |
keyboard = [[InlineKeyboardButton("π Orqaga", callback_data="nav|main")]]
|
| 407 |
await query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyboard), parse_mode=constants.ParseMode.MARKDOWN)
|
| 408 |
|
| 409 |
+
async def admin_panel(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
| 410 |
+
"""Faqat admin ko'ra oladigan boshqaruv paneli."""
|
| 411 |
+
if update.effective_user.id != ADMIN_ID:
|
| 412 |
+
return
|
| 413 |
+
|
| 414 |
+
keyboard = [
|
| 415 |
+
[
|
| 416 |
+
InlineKeyboardButton("π Statistika", callback_data="admin_stats"),
|
| 417 |
+
InlineKeyboardButton("π Bazani yuklab olish", callback_data="admin_db")
|
| 418 |
+
],
|
| 419 |
+
[
|
| 420 |
+
InlineKeyboardButton("π’ Xabar tarqatish", callback_data="admin_broadcast")
|
| 421 |
+
]
|
| 422 |
+
]
|
| 423 |
+
reply_markup = InlineKeyboardMarkup(keyboard)
|
| 424 |
+
await update.message.reply_text("π **Admin Panel**\n\nBotni boshqarish uchun kerakli bo'limni tanlang:",
|
| 425 |
+
reply_markup=reply_markup, parse_mode=constants.ParseMode.MARKDOWN)
|
| 426 |
+
|
| 427 |
+
async def handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
| 428 |
query = update.callback_query
|
| 429 |
await query.answer()
|
| 430 |
+
|
| 431 |
+
if query.data.startswith("admin_"):
|
| 432 |
+
if update.effective_user.id != ADMIN_ID:
|
| 433 |
+
return
|
| 434 |
+
|
| 435 |
+
if query.data == "admin_stats":
|
| 436 |
+
stats = db.get_stats()
|
| 437 |
+
text = (f"π **Bot Statistikasi**\n\n"
|
| 438 |
+
f"π₯ Jami foydalanuvchilar: {stats['total_users']}\n"
|
| 439 |
+
f"π Jami tahrirlangan media: {stats['total_processed']}\n"
|
| 440 |
+
f"π Oxirgi 24 soatdagi faollik: {stats['daily_active']}")
|
| 441 |
+
await query.edit_message_text(text, parse_mode=constants.ParseMode.MARKDOWN,
|
| 442 |
+
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("β¬
οΈ Orqaga", callback_data="admin_back")]]))
|
| 443 |
+
|
| 444 |
+
elif query.data == "admin_db":
|
| 445 |
+
await query.message.reply_document(document=open(db.db_path, 'rb'), caption="π Bot ma'lumotlar bazasi zaxira nusxasi.")
|
| 446 |
+
|
| 447 |
+
elif query.data == "admin_broadcast":
|
| 448 |
+
BROADCAST_MODE[ADMIN_ID] = True
|
| 449 |
+
await query.edit_message_text("π **Xabar tarqatish rejimi**\n\nBarcha foydalanuvchilarga yubormoqchi bo'lgan matningizni kiriting:",
|
| 450 |
+
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("β Bekor qilish", callback_data="admin_back")]]))
|
| 451 |
+
|
| 452 |
+
elif query.data == "admin_back":
|
| 453 |
+
BROADCAST_MODE[ADMIN_ID] = False
|
| 454 |
+
keyboard = [
|
| 455 |
+
[InlineKeyboardButton("π Statistika", callback_data="admin_stats"),
|
| 456 |
+
InlineKeyboardButton("π Bazani yuklab olish", callback_data="admin_db")],
|
| 457 |
+
[InlineKeyboardButton("π’ Xabar tarqatish", callback_data="admin_broadcast")]
|
| 458 |
+
]
|
| 459 |
+
await query.edit_message_text("π **Admin Panel**", reply_markup=InlineKeyboardMarkup(keyboard), parse_mode=constants.ParseMode.MARKDOWN)
|
| 460 |
+
return
|
| 461 |
|
| 462 |
+
# [Avvalgi button_handler mantiqi davom etadi...]
|
| 463 |
try:
|
| 464 |
data = query.data.split("|")
|
| 465 |
action, m_type, short_id = data[0], data[1], data[2]
|
|
|
|
| 683 |
app = ApplicationBuilder().token(TOKEN).request(request).post_init(post_init).build()
|
| 684 |
|
| 685 |
app.add_handler(CommandHandler("start", start))
|
| 686 |
+
app.add_handler(CommandHandler("admin", admin_panel))
|
| 687 |
app.add_handler(CallbackQueryHandler(navigation_handler, pattern=r"^nav\|"))
|
| 688 |
app.add_handler(CallbackQueryHandler(settings_callback_handler, pattern=r"^set\|"))
|
| 689 |
+
app.add_handler(CallbackQueryHandler(handle_callback)) # This now handles all callbacks, including admin and regular buttons
|
| 690 |
app.add_handler(MessageHandler(filters.PHOTO, handle_photo))
|
| 691 |
app.add_handler(MessageHandler(filters.VIDEO | filters.ANIMATION | filters.Document.ALL, handle_video))
|
| 692 |
+
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_text)) # Handle general text messages
|
| 693 |
|
| 694 |
logger.info("Bot polling rejimi ishga tushmoqda...")
|
| 695 |
app.run_polling()
|