feat(admin_bot): show link-senders count and top-5 active users in /stat
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 1m43s
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 1m43s
Adds users.link_count, incremented in bot.py whenever a user submits a recognized link (regardless of eventual download success), and surfaces it in admin_bot's /stat as a count of users who ever sent a link plus a top-5 leaderboard by link count.
This commit is contained in:
parent
772e9fd5b4
commit
d9ff2aec57
2 changed files with 67 additions and 5 deletions
53
admin_bot.py
53
admin_bot.py
|
|
@ -60,6 +60,38 @@ def get_total_users() -> int:
|
|||
return 0
|
||||
|
||||
|
||||
def get_users_sent_link_count() -> int:
|
||||
"""Возвращает количество пользователей, отправивших хотя бы одну ссылку"""
|
||||
try:
|
||||
conn = sqlite3.connect(str(DB_FILE))
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT COUNT(*) FROM users WHERE link_count > 0')
|
||||
result = cursor.fetchone()
|
||||
conn.close()
|
||||
return result[0] if result else 0
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при получении количества активных пользователей: {e}")
|
||||
return 0
|
||||
|
||||
|
||||
def get_top_active_users(limit: int = 5) -> list[tuple[int, str, str, int]]:
|
||||
"""Возвращает топ пользователей по количеству отправленных ссылок"""
|
||||
try:
|
||||
conn = sqlite3.connect(str(DB_FILE))
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
'SELECT chat_id, username, first_name, link_count FROM users '
|
||||
'WHERE link_count > 0 ORDER BY link_count DESC LIMIT ?',
|
||||
(limit,)
|
||||
)
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
return results
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при получении топа активных пользователей: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def get_error_stats() -> dict[str, int]:
|
||||
"""Возвращает статистику ошибок по сервисам"""
|
||||
try:
|
||||
|
|
@ -179,8 +211,10 @@ async def stat_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||
|
||||
total_downloads = get_total_downloads()
|
||||
total_users = get_total_users()
|
||||
users_sent_link = get_users_sent_link_count()
|
||||
top_users = get_top_active_users(5)
|
||||
error_stats = get_error_stats()
|
||||
|
||||
|
||||
# Форматируем статистику ошибок
|
||||
error_stats_text = ""
|
||||
service_names = {
|
||||
|
|
@ -191,19 +225,30 @@ async def stat_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||
'yapfiles': 'Yapfiles',
|
||||
'unknown': 'Unknown'
|
||||
}
|
||||
|
||||
|
||||
for service, count in sorted(error_stats.items()):
|
||||
if count > 0:
|
||||
service_name = service_names.get(service, service)
|
||||
error_stats_text += f" • {service_name}: {count}\n"
|
||||
|
||||
|
||||
if not error_stats_text:
|
||||
error_stats_text = " Нет ошибок"
|
||||
|
||||
|
||||
# Форматируем топ активных пользователей
|
||||
top_users_text = ""
|
||||
for i, (uid, username, first_name, link_count) in enumerate(top_users, start=1):
|
||||
display_name = f"@{username}" if username else (first_name or str(uid))
|
||||
top_users_text += f" {i}. {display_name} — {link_count}\n"
|
||||
|
||||
if not top_users_text:
|
||||
top_users_text = " Пока никто не отправлял ссылки"
|
||||
|
||||
stat_message = (
|
||||
f"📊 Статистика бота:\n\n"
|
||||
f"👥 Всего пользователей: {total_users}\n"
|
||||
f"🔗 Отправляли ссылки: {users_sent_link}\n"
|
||||
f"📹 Всего скачано видео: {total_downloads}\n\n"
|
||||
f"🏆 Топ-5 активных пользователей:\n{top_users_text.strip()}\n\n"
|
||||
f"❌ Ошибки по сервисам:\n{error_stats_text.strip()}"
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue