1
0
Fork 0
mirror of https://github.com/EDeev/chatping_abobot.git synced 2026-10-07 20:49:45 +03:00
chatping_abobot/code/handlers/common.py
Egor Deev a2a0adcf8e AboBot 4.0: PostgreSQL, обработчики по роутерам, HTML-разметка, новые команды
База — PostgreSQL (asyncpg) вместо четырёх файлов SQLite с таблицей на каждый чат:
chats, users, members, chat_stats и member_stats с полем «период» — месяцы хранятся, а не
обнуляются; счётчики растут одним запросом без блокировки бота. scripts/migrate_sqlite.py
переносит старые базы со сверкой сумм (проверено на копии рабочих баз: 20 694 пользователя,
45 чатов, 3 142 038 сообщений — совпадает).

Учёт бота в чатах: статус и права бота (событие my_chat_member и сверка с Telegram при
запуске и раз в 6 часов), история изменений в bot_status_history; из чатов, где бота
исключили, данные не удаляются — меняется только статус.

Большие чаты (больше 100 участников): /all — только для админов, раз в 5 минут и только
писавшие за 30 дней; упоминание одного человека по имени — не чаще раза в минуту. В любом
чате /all делится на сообщения до 4096 символов (раньше в чате на 14 тысяч падал).

Новое: /settings (упоминания, имена в голосовых, ивенты, удаление служебных сообщений —
меняют админы), /top, /month (итоги месяца по команде). /stop_bot раньше ничего не
выключал — флаг не проверялся; теперь работает. Участник, вышедший из чата, больше не
упоминается, но его статистика сохраняется. Ошибки — в технический чат DEBUG_CHAT_ID.

Код: handlers.py разбит на роутеры, Markdown заменён на HTML (экранирование через html.escape),
тесты на PostgreSQL (18), CI на Python 3.10 и 3.12.
2026-10-06 11:16:00 +00:00

44 lines
1.4 KiB
Python

"""Общее для обработчиков: учёт статистики, права, размер чата"""
import time
from aiogram import Bot
from aiogram.types import Message
import config
import db
from nlp import clean_name
_size_cache = {}
def in_group(message: Message):
return message.chat.id < 0
async def count(message: Message, *var_ids):
"""Учёт события в группе от автора сообщения"""
if in_group(message) and message.from_user and not message.from_user.is_bot:
await db.count(message.chat.id, message.from_user.id, var_ids, clean_name(message.from_user.first_name),
message.chat.title)
async def is_admin(bot: Bot, chat_id, user_id):
member = await bot.get_chat_member(chat_id, user_id)
return member.status in ("creator", "administrator")
async def chat_size(bot: Bot, chat_id):
"""Число участников чата по Telegram (кэш на 10 минут)"""
cached = _size_cache.get(chat_id)
if cached and time.monotonic() - cached[1] < 600:
return cached[0]
try:
size = await bot.get_chat_member_count(chat_id)
except Exception:
size = await db.member_count(chat_id)
_size_cache[chat_id] = (size, time.monotonic())
return size
async def is_big(bot: Bot, chat_id):
return await chat_size(bot, chat_id) > config.BIG_CHAT