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/settings.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

70 lines
3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Настройки бота в чате: кнопки-переключатели, менять могут администраторы"""
from aiogram import Bot, F, Router
from aiogram.filters import Command
from aiogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message
import db
from .common import count, in_group, is_admin
router = Router()
LABELS = {
"mentions_enabled": "Упоминания по имени",
"voice_names": "Имена в голосовых (через Google)",
"events_enabled": "Текстовые ивенты",
"delete_service": "Удаление служебных сообщений",
}
async def keyboard(chat_id):
current = await db.settings(chat_id)
return InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text=f"{'✅' if current[key] else '❌'} {label}", callback_data=f"set:{key}")]
for key, label in LABELS.items()
])
@router.message(Command('settings'))
async def show_settings(message: Message):
if not in_group(message):
await message.reply('Настройки есть только у групп — вызовите команду в чате!')
return
await count(message, 3, 1)
await message.answer('<b>| НАСТРОЙКИ ЧАТА |</b>\n\nНажмите, чтобы включить или выключить. Менять настройки '
'могут администраторы.', reply_markup=await keyboard(message.chat.id))
@router.callback_query(F.data.startswith("set:"))
async def toggle(call: CallbackQuery, bot: Bot):
key = call.data[4:]
if key not in LABELS:
return
if not await is_admin(bot, call.message.chat.id, call.from_user.id):
await call.answer("Настройки могут менять только администраторы", show_alert=True)
return
value = await db.toggle_setting(call.message.chat.id, key)
await call.message.edit_reply_markup(reply_markup=await keyboard(call.message.chat.id))
await call.answer(f"{LABELS[key]}: {'включено' if value else 'выключено'}")
async def set_events(message: Message, enable):
if not in_group(message):
return
await count(message, 3, 1)
if await db.get_setting(message.chat.id, "events_enabled") == enable:
await message.answer("У вас уже включены текстовые ивенты!" if enable
else "У вас уже отключены текстовые ивенты!")
return
await db.toggle_setting(message.chat.id, "events_enabled")
await message.answer("Текстовые ивенты включены!" if enable else "Текстовые ивенты отключены!")
@router.message(Command('start_bot'))
async def opening(message: Message):
await set_events(message, True)
@router.message(Command('stop_bot'))
async def closing(message: Message):
await set_events(message, False)