Снижено дублирование кода, связанного с выводом статистики.

Дополнительная логика формирования списка молчунов перенесена в SQL-запрос.
This commit is contained in:
Kirill Kirilenko 2025-09-02 00:50:05 +03:00
parent ecfc83d5ad
commit d914ee5a00
3 changed files with 58 additions and 64 deletions

View file

@ -87,7 +87,7 @@ class Database:
def get_top_messages_today(self, chat_id: int): def get_top_messages_today(self, chat_id: int):
self.cursor.execute(""" self.cursor.execute("""
SELECT user_id, messages_today FROM users SELECT user_id, messages_today AS value FROM users
WHERE chat_id = ? AND messages_today > 0 WHERE chat_id = ? AND messages_today > 0
ORDER BY messages_today DESC ORDER BY messages_today DESC
""", (chat_id,)) """, (chat_id,))
@ -95,23 +95,29 @@ class Database:
def get_top_messages_month(self, chat_id: int): def get_top_messages_month(self, chat_id: int):
self.cursor.execute(""" self.cursor.execute("""
SELECT user_id, messages_month FROM users SELECT user_id, messages_month AS value FROM users
WHERE chat_id = ? AND messages_month > 0 WHERE chat_id = ? AND messages_month > 0
ORDER BY messages_month DESC ORDER BY messages_month DESC
""", (chat_id,)) """, (chat_id,))
return self.cursor.fetchall() return self.cursor.fetchall()
def get_top_silent(self, chat_id: int, threshold_time: int): def get_top_silent(self, chat_id: int, threshold_days: int):
# noinspection SpellCheckingInspection
self.cursor.execute(""" self.cursor.execute("""
SELECT user_id, last_message FROM users SELECT user_id,
WHERE chat_id = ? AND last_message < ? CASE
ORDER BY last_message ASC WHEN last_message = 0 THEN 'никогда'
""", (chat_id, threshold_time)) ELSE (unixepoch() - last_message) / 86400
END AS value
FROM users
WHERE chat_id = ? AND value >= ?
ORDER BY value DESC
""", (chat_id, threshold_days))
return self.cursor.fetchall() return self.cursor.fetchall()
def get_top_warnings(self, chat_id: int): def get_top_warnings(self, chat_id: int):
self.cursor.execute(""" self.cursor.execute("""
SELECT user_id, warnings FROM users SELECT user_id, warnings AS value FROM users
WHERE chat_id = ? AND warnings > 0 WHERE chat_id = ? AND warnings > 0
ORDER BY warnings DESC ORDER BY warnings DESC
""", (chat_id,)) """, (chat_id,))

View file

@ -1,13 +1,32 @@
from vkbottle import bold, italic from typing import List, Any
from vkbottle import bold, italic, API
from vkbottle.bot import Message from vkbottle.bot import Message
import database import database
from messages import * from messages import *
import utils
from labeler import labeler from labeler import labeler
# top_users - массив sqlite3.Row с двумя столбцами: user_id и value
async def format_rating(top_users: List[Any], api: API) -> str:
top_user_ids = [user['user_id'] for user in top_users]
users_info = await api.users.get(user_ids=top_user_ids)
result = ''
i = 1
for user in top_users:
for info in users_info:
if info.id == user['user_id']:
result += '{}. {} {} - {}\n'.format(i, info.first_name, info.last_name, user['value'])
i = i + 1
break
return result
# noinspection SpellCheckingInspection
@labeler.chat_message(text="!помощь") @labeler.chat_message(text="!помощь")
async def rules_handler(message: Message): async def rules_handler(message: Message):
chat_id = message.peer_id chat_id = message.peer_id
@ -50,18 +69,8 @@ async def stats_today_handler(message: Message):
await message.answer('Сегодня еще никто не писал.') await message.answer('Сегодня еще никто не писал.')
return return
top_user_ids = [user['user_id'] for user in top_users]
users_info = await message.ctx_api.users.get(user_ids=top_user_ids)
response = bold('Статистика за сегодня') + '\n' response = bold('Статистика за сегодня') + '\n'
i = 1 response += await format_rating(top_users, message.ctx_api)
for user in top_users:
for info in users_info:
if info.id == user['user_id']:
response += '{}. {} {} - {}\n'.format(i, info.first_name, info.last_name, user['messages_today'])
i = i + 1
break
await message.answer(response) await message.answer(response)
@ -78,18 +87,8 @@ async def stats_month_handler(message: Message):
await message.answer('В этом месяце еще никто не писал.') await message.answer('В этом месяце еще никто не писал.')
return return
top_user_ids = [user['user_id'] for user in top_users]
users_info = await message.ctx_api.users.get(user_ids=top_user_ids)
response = bold('Статистика за месяц') + '\n' response = bold('Статистика за месяц') + '\n'
i = 1 response += await format_rating(top_users, message.ctx_api)
for user in top_users:
for info in users_info:
if info.id == user['user_id']:
response += '{}. {} {} - {}\n'.format(i, info.first_name, info.last_name, user['messages_month'])
i = i + 1
break
await message.answer(response) await message.answer(response)
@ -101,29 +100,13 @@ async def silent_handler(message: Message):
await message.answer(MESSAGE_CHAT_NOT_ACTIVE) await message.answer(MESSAGE_CHAT_NOT_ACTIVE)
return return
now = utils.posix_time() top_users = database.DB.get_top_silent(chat_id, 14)
threshold = now - 14 * 24 * 3600
top_users = database.DB.get_top_silent(message.peer_id, threshold)
if len(top_users) == 0: if len(top_users) == 0:
await message.answer('Молчунов нет. Все молодцы!') await message.answer('Молчунов нет. Все молодцы!')
return return
top_user_ids = [user['user_id'] for user in top_users]
users_info = await message.ctx_api.users.get(user_ids=top_user_ids)
response = bold('Молчуны чата') + ' (не писали больше 2 недель)\n' response = bold('Молчуны чата') + ' (не писали больше 2 недель)\n'
i = 1 response += await format_rating(top_users, message.ctx_api)
for user in top_users:
for info in users_info:
if info.id == user['user_id']:
if user['last_message'] == 0:
response += '{}. {} {} - никогда\n'.format(i, info.first_name, info.last_name)
else:
days_silent = round((now - user['last_message']) / 3600 / 24)
response += '{}. {} {} - {} дней\n'.format(i, info.first_name, info.last_name, days_silent)
i = i + 1
break
await message.answer(response) await message.answer(response)
@ -140,18 +123,8 @@ async def warnings_handler(message: Message):
await message.answer('Пока все спокойно. Продолжайте в том же духе.') await message.answer('Пока все спокойно. Продолжайте в том же духе.')
return return
top_user_ids = [user['user_id'] for user in top_users]
users_info = await message.ctx_api.users.get(user_ids=top_user_ids)
response = bold('Участники с предупреждениями') + '\n' response = bold('Участники с предупреждениями') + '\n'
i = 1 response += await format_rating(top_users, message.ctx_api)
for user in top_users:
for info in users_info:
if info.id == user['user_id']:
response += '{}. {} {} - {}\n'.format(i, info.first_name, info.last_name, user['warnings'])
i = i + 1
break
await message.answer(response) await message.answer(response)

View file

@ -2,17 +2,32 @@ import datetime
import traceback import traceback
from asyncio import sleep from asyncio import sleep
from vkbottle import API from vkbottle import API, bold
import database import database
from handlers.user import format_rating
from messages import * from messages import *
def reset_counters(reset_month: bool): async def reset_counters(reset_month: bool, api: API):
database.DB.reset_messages_today() database.DB.reset_messages_today()
print('Дневные счетчики сброшены.') print('Дневные счетчики сброшены.')
if reset_month: if reset_month:
for chat in database.DB.get_chats():
if chat['active'] == 0:
continue
top_users = database.DB.get_top_messages_month(chat['id'])
if len(top_users) == 0:
continue
message = bold('Итоговая статистика за прошедший месяц') + '\n'
message += await format_rating(top_users, api)
# noinspection PyArgumentList
await api.messages.send(random_id=0, peer_id=chat['id'],
message=str(message), format_data=message.as_raw_data())
database.DB.reset_messages_month() database.DB.reset_messages_month()
print('Месячные счетчики сброшены.') print('Месячные счетчики сброшены.')
@ -76,7 +91,7 @@ async def daily_maintenance_task(api: API):
await wait_until(target_datetime) await wait_until(target_datetime)
try: try:
reset_counters(target_datetime.day == 1) await reset_counters(target_datetime.day == 1, api)
await check_birthdays(api) await check_birthdays(api)
except Exception: except Exception:
print(traceback.format_exc()) print(traceback.format_exc())