1
0
Fork 0
mirror of https://github.com/EDeev/chatping_abobot.git synced 2026-10-07 20:49:45 +03:00

Зависимости, тесты, CI, Docker, лицензия MIT и README на русском и английском

requirements.txt раньше не устанавливался (sqlite3, несуществующий enchant==1.6.6) и тянул
неиспользуемые asyncio-mqtt, pyaudio, pydub. README: распознавание — SpeechRecognition,
а не gTTS; число пользователей — по базе бота.
This commit is contained in:
Деев Егор Викторович 2026-10-06 01:10:52 +00:00
parent f5441bdde6
commit 9123f57968
15 changed files with 390 additions and 159 deletions

5
.dockerignore Normal file
View file

@ -0,0 +1,5 @@
.git
.env
db
tests
__pycache__

2
.env.example Normal file
View file

@ -0,0 +1,2 @@
# Токен бота от @BotFather
BOT_TOKEN=123456:your-token

19
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: sudo apt-get update -qq && sudo apt-get install -y -qq libenchant-2-2 hunspell-en-us
- run: pip install -r requirements-dev.txt
- run: ruff check --select E9,F,B code tests
- run: pytest -q

42
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,42 @@
name: Docker
on:
push:
tags: ["v*"]
workflow_dispatch:
jobs:
image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/login-action@v3
with:
registry: dcr.deev.su
username: ${{ secrets.ZOT_USERNAME }}
password: ${{ secrets.ZOT_PASSWORD }}
- id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/edeev/chatping_abobot
dcr.deev.su/edeev/chatping_abobot
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.env
__pycache__/
*.pyc
.pytest_cache/
db/*.db

23
Dockerfile Normal file
View file

@ -0,0 +1,23 @@
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
# словарь английского для распознавания текста в неправильной раскладке
RUN apt-get update \
&& apt-get install -y --no-install-recommends libenchant-2-2 hunspell-en-us \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY code/ code/
COPY data/ data/
RUN useradd --create-home --uid 1000 app && mkdir -p db && chown -R app:app /app
USER app
VOLUME ["/app/db"]
# пути к базам и картинкам в коде — относительно папки code/ (../db, ../data)
WORKDIR /app/code
CMD ["python", "bot.py"]

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Egor Deev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

103
README.en.md Normal file
View file

@ -0,0 +1,103 @@
# AboBot
[Русский](README.md) · **English**
[![CI](https://github.com/EDeev/chatping_abobot/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/chatping_abobot/actions/workflows/ci.yml)
[![Docker](https://github.com/EDeev/chatping_abobot/actions/workflows/docker.yml/badge.svg)](https://github.com/EDeev/chatping_abobot/actions/workflows/docker.yml)
[![License](https://img.shields.io/github/license/EDeev/chatping_abobot)](LICENSE)
A Telegram bot for group chats. It:
- pings a member when their name comes up in a message or a voice note;
- keeps statistics for the chat and every member;
- fixes text typed in the wrong keyboard layout;
- transcribes and voices messages;
- runs playful events.
The bot speaks Russian.
**Status:** personal project, running since 2021 · bot [@chat_abobot](https://t.me/chat_abobot) · over
20,000 users from 45 chats in the bot's database (October 2026)
**Stack:** Python 3.12 · aiogram 3 · pymorphy3 · pyenchant · SpeechRecognition · gTTS · SQLite · Docker
## Features
- **Name mentions.** Words of a message are reduced to their base form (pymorphy3) and compared with
members' names, so any grammatical case of a name mentions the right person. A custom name can be set with `/edit`. Names are also found
in voice notes up to a minute long.
- **`/all`** mentions every member.
- **All-time and monthly statistics** (`/stat_group`, `/stat_user`): messages, replies, commands, links,
media, stickers, voice and video notes. Monthly numbers reset at the start of each month.
- **Wrong keyboard layout.** A message like `ghbdtn` is repeated as «привет». English words are recognized
with a dictionary (pyenchant) and left alone.
- **Voice.** `/recognize` as a reply to a voice note transcribes it; «Озвучь - текст» turns text into a
voice note.
- **Events:**
- random numbers;
- reversing text;
- a language game;
- mock fights;
- picture reactions.
Turned off with `/stop_bot`.
- Deleting service messages (joins, leaves, title and photo changes) when the bot is an admin.
## Running
```bash
git clone https://github.com/EDeev/chatping_abobot.git && cd chatping_abobot
cp .env.example .env # BOT_TOKEN from @BotFather
docker compose up -d
```
Prebuilt image: `docker pull ghcr.io/edeev/chatping_abobot` or `docker pull dcr.deev.su/edeev/chatping_abobot`.
The SQLite databases are created on first start.
Without Docker you need Python 3.12, the enchant system library and an English dictionary
(`apt install libenchant-2-2 hunspell-en-us`). Then: `pip install -r requirements.txt` and
`cd code && BOT_TOKEN=… python bot.py`.
## How it works
```
code/bot.py entry point and monthly statistics reset
code/handlers.py message, command, voice and event handlers
code/script.py statistics, name lookup, keyboard layout, text reversal
code/sql.py four SQLite databases: groups, users, all-time and monthly statistics
data/ event pictures and the greeting
```
Member statistics live in a separate table per chat — that is how the bot's production databases are
built. Counters are incremented in a single query, so simultaneous messages are not lost. Speech recognition
and synthesis (Google Web Speech and gTTS) run in a separate thread, so the bot never freezes.
## Development
```bash
pip install -r requirements-dev.txt
ruff check --select E9,F,B code tests && pytest
```
What the tests cover:
- statistics counters;
- mentions and `/all`;
- the monthly reset;
- keyboard layout, reversal and escaping;
- loading of the bot's handlers.
The Docker image is built on `v*` tags and published to GitHub Packages and `dcr.deev.su`.
## License
MIT — see [LICENSE](LICENSE).
## Author
**Egor Deev** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
<div align="center">
<sub>⭐ If you find this project useful, give it a star on GitHub!</sub>
<p><sub>Made with ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
</div>

199
README.md
View file

@ -1,153 +1,100 @@
# 🤖 ABOBOT - Telegram Group Management Bot # AboBot
![Python](https://img.shields.io/badge/Python-3.8+-blue.svg) **Русский** · [English](README.en.md)
![Aiogram](https://img.shields.io/badge/Aiogram-3.x-green.svg)
![SQLite](https://img.shields.io/badge/SQLite-3-orange.svg)
![License](https://img.shields.io/badge/License-MIT-yellow.svg)
Многофункциональный Telegram-бот для управления групповыми чатами с расширенной аналитикой и интерактивными возможностями. [![CI](https://github.com/EDeev/chatping_abobot/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/chatping_abobot/actions/workflows/ci.yml)
[![Docker](https://github.com/EDeev/chatping_abobot/actions/workflows/docker.yml/badge.svg)](https://github.com/EDeev/chatping_abobot/actions/workflows/docker.yml)
[![License](https://img.shields.io/github/license/EDeev/chatping_abobot)](LICENSE)
## 🎯 Основные возможности Telegram-бот для групповых чатов. Он:
- зовёт участника, когда его имя звучит в сообщении или в голосовом;
- ведёт статистику чата и каждого участника;
- исправляет текст, набранный в неправильной раскладке;
- распознаёт и озвучивает голосовые;
- устраивает шуточные ивенты.
### 📊 Система аналитики **Статус:** личный проект, работает с 2021 года · бот [@chat_abobot](https://t.me/chat_abobot) · в базе
- **Комплексная статистика** - детальный учёт активности участников бота больше 20 000 пользователей из 45 чатов (октябрь 2026)
- **Временная сегментация** - анализ данных за месяц и весь период
- **Многомерные метрики** - сообщения, ответы, команды, медиафайлы, голосовые
### 👥 Управление участниками **Стек:** Python 3.12 · aiogram 3 · pymorphy3 · pyenchant · SpeechRecognition · gTTS · SQLite · Docker
- **Интеллектуальные упоминания** - автоматическое обнаружение имён в сообщениях
- **Динамическое именование** - морфологическая обработка и нормализация
- **Групповые вызовы** - команда `/all` для оповещения всех участников
### 🔧 Утилиты и инструменты ## Возможности
- **Транслитерация** - автоматический перевод с латиницы на кириллицу
- **Транскрипция** - конвертация голосовых сообщений в текст (gTTS)
- **Текстовые трансформации** - реверс слов и предложений
- **Генерация голоса** - озвучивание текстовых сообщений
### 🎮 Интерактивные функции - **Упоминания по имени.** Слова сообщения приводятся к начальной форме (pymorphy3) и сравниваются с
- **Игровые механики** - симуляция драк и взаимодействий именами участников, поэтому участницу Машу позовут и «Маша», и «позови Машу», и «с Машей». Своё имя
- **Рандомизация** - генерация случайных чисел в диапазоне для упоминаний можно задать командой `/edit`. Имена ищутся и в голосовых до минуты.
- **Советник** - интеграция с API для получения рандомных советов - **`/all`** — упомянуть всех участников.
- **Статистика за всё время и за месяц** (`/stat_group`, `/stat_user`): сообщения, ответы, команды,
ссылки, медиа, стикеры, голосовые и кружочки. Месячная обнуляется в начале месяца.
- **Неправильная раскладка.** Сообщение вида `ghbdtn` бот повторит как «привет». Английские слова он
отличает по словарю (pyenchant) и не трогает.
- **Голос.** `/recognize` ответом на голосовое — расшифровка; «Озвучь - текст» — голосовое из текста.
- **Ивенты:**
- «Число от 1 до 100»;
- «Переверни - …»;
- «Переведи - …» — на кирпичный язык;
- «Подраться с …»;
- «Чмокнуть» и другие действия с картинками.
## 🏗️ Архитектура системы Отключаются командой `/stop_bot`.
- Удаление служебных сообщений (вход, выход, смена названия и фото) — если у бота права администратора.
### Технологический стек ## Запуск
```
Backend Framework: aiogram (Async Telegram Bot API)
Database Engine: SQLite (многотабличная структура)
NLP Processing: pymorphy3 (морфологический анализ)
Speech Recognition: speech_recognition + gTTS
Async Framework: asyncio (асинхронная обработка)
```
### Структура базы данных
```
📁 Databases
├── base.db # Основная статистика групп
├── users.db # Маппинг пользователей
├── groups.db # Индивидуальная статистика участников
└── month.db # Временная сегментация данных
```
### Модульная организация
```
📁 Project Structure
├── bot.py # Точка входа и инициализация
├── handlers.py # Обработчики событий и команд
├── script.py # Бизнес-логика и алгоритмы
├── sql.py # Абстракция базы данных
├── init.py # Конфигурация и зависимости
└── base.py # Константы и настройки
```
## 🚀 Быстрый старт
### Установка зависимостей
```bash ```bash
pip install -r requirements.txt git clone https://github.com/EDeev/chatping_abobot.git && cd chatping_abobot
cp .env.example .env # BOT_TOKEN от @BotFather
docker compose up -d
``` ```
### Конфигурация Готовый образ: `docker pull ghcr.io/edeev/chatping_abobot` или `docker pull dcr.deev.su/edeev/chatping_abobot`.
1. Получите токен бота у [@BotFather](https://t.me/BotFather) Базы SQLite создаются при первом запуске.
2. Обновите `TOKEN` в `code/base.py`
3. Настройте права администратора для автоудаления системных сообщений Без Docker нужны Python 3.12, системная библиотека enchant и английский словарь
(`apt install libenchant-2-2 hunspell-en-us`). Затем: `pip install -r requirements.txt` и
`cd code && BOT_TOKEN=… python bot.py`.
## Как устроено
```
code/bot.py запуск и ежемесячное обнуление статистики
code/handlers.py обработчики сообщений, команд, голосовых и ивентов
code/script.py учёт статистики, поиск имён, раскладка, переворот текста
code/sql.py четыре базы SQLite: группы, пользователи, статистика за всё время и за месяц
data/ картинки ивентов и приветствие
```
Статистика участников хранится в отдельной таблице на каждый чат — так устроены рабочие базы бота.
Счётчики увеличиваются одним запросом, поэтому одновременные сообщения не теряются. Распознавание и синтез
речи (Google Web Speech и gTTS) идут в отдельном потоке, чтобы бот не замирал.
## Разработка
### Запуск
```bash ```bash
cd code pip install -r requirements-dev.txt
python bot.py ruff check --select E9,F,B code tests && pytest
``` ```
## 📋 Команды Что проверяют тесты:
- счётчики статистики;
- упоминания и `/all`;
- обнуление месячной статистики;
- раскладку, переворот и экранирование;
- что обработчики бота загружаются.
| Команда | Функционал | Docker-образ собирается по тегу `v*` и публикуется в GitHub Packages и `dcr.deev.su`.
|---------|------------|
| `/start`, `/help` | Интерактивное меню с описанием возможностей |
| `/all` | Упоминание всех участников группы |
| `/stat_group` | Детальная аналитика группы |
| `/stat_user` | Персональная статистика пользователя |
| `/recognize` | Транскрипция голосового сообщения |
| `/edit <имя>` | Установка кастомного имени для упоминаний |
| `/back_edit` | Возврат к динамическому именованию |
| `/start_bot` | Активация текстовых событий |
| `/stop_bot` | Деактивация текстовых событий |
## 🎲 Текстовые события ## Лицензия
### Интерактивные команды MIT — см. [LICENSE](LICENSE).
- **"Чмокнуть [имя]"** - позитивное взаимодействие
- **"Отмудохать [имя]"** - игровая агрессия
- **"Подраться с [имя]"** - симуляция боя с рандомным исходом
- **"Число от X до Y"** - генерация случайного числа
- **"Переведи (символ) - текст"** - трансформация в "кирпичный" язык
- **"Переверни - текст"** - реверс слов с сохранением пунктуации
- **"Озвучь - текст"** - генерация голосового сообщения
## 🔍 Технические особенности ## Автор
### Алгоритмы обработки **Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
- **Морфологический анализ** - приведение имён к начальной форме
- **Детекция транслита** - эвристический алгоритм определения раскладки
- **Парсинг голоса** - интеграция Google Speech Recognition
- **Обработка пунктуации** - сохранение форматирования при трансформациях
### Оптимизации производительности
- **Асинхронная архитектура** - неблокирующая обработка запросов
- **Кэширование соединений** - переиспользование подключений к БД
- **Ленивая загрузка** - подгрузка данных по требованию
## 📈 Метрики и аналитика
Система ведёт учёт следующих параметров:
- Общее количество сообщений
- Количество ответов на сообщения
- Использование команд бота
- Отправка медиафайлов и стикеров
- Голосовые сообщения и видеокружки
- Размещение ссылок
## 🛠️ Требования к системе
- Python 3.8+
- Операционная система: Linux/Windows/macOS
- RAM: минимум 512MB
- Свободное место: 100MB для логов и медиафайлов
## 📄 Лицензия
Проект распространяется под лицензией MIT.
## 👨‍💻 Автор
**Деев Егор Викторович** - Backend Developer
- GitHub: [@EDeev](https://github.com/EDeev)
- Email: egor@deev.space
- Telegram: [@Egor_Deev](https://t.me/Egor_Deev)
--- ---
<div align="center"> <div align="center">
<sub>⭐ Если проект оказался полезным, поставьте звезду на GitHub!</sub> <sub>⭐ Если проект оказался полезным, поставьте звёздочку на GitHub!</sub>
<p><sub>Создано с ❤️ от вашего дорогого - deev.space ©</sub></p> <p><sub>Сделано с ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
</div> </div>

11
compose.yaml Normal file
View file

@ -0,0 +1,11 @@
services:
bot:
build: .
image: ghcr.io/edeev/chatping_abobot:latest
env_file: .env
volumes:
- db:/app/db
restart: unless-stopped
volumes:
db:

0
db/.gitkeep Normal file
View file

3
requirements-dev.txt Normal file
View file

@ -0,0 +1,3 @@
-r requirements.txt
pytest==8.4.2
ruff==0.14.0

View file

@ -1,34 +1,8 @@
# Core Framework Dependencies aiogram==3.23.0
aiogram==3.10.0 pymorphy3==2.0.6
asyncio-mqtt==0.16.1
# Database Management
sqlite3
# Natural Language Processing
pymorphy3==1.2.1
pymorphy3-dicts-ru==2.4.417150.4580142 pymorphy3-dicts-ru==2.4.417150.4580142
enchant==1.6.6 pyenchant==3.2.2
SpeechRecognition==3.14.4
# Speech Recognition & Synthesis gTTS==2.5.4
SpeechRecognition==3.10.4 soundfile==0.13.1
gTTS==2.5.1 requests==2.32.5
soundfile==0.12.1
# HTTP Client for API Integration
requests==2.31.0
# Audio Processing Dependencies
pyaudio==0.2.14
pydub==0.25.1
# System Dependencies (if needed)
# Note: Some packages may require system-level installation
# Ubuntu/Debian: sudo apt-get install python3-enchant libenchant-2-2
# macOS: brew install enchant portaudio
# Windows: Download pyaudio wheel from unofficial binaries
# Development Dependencies (Optional)
# pytest==8.2.2
# black==24.4.2
# flake8==7.1.0

11
tests/conftest.py Normal file
View file

@ -0,0 +1,11 @@
import os
import sys
# бот открывает базы по путям ../db относительно папки code — запускаем как в проде, но во временной папке
import tempfile
ROOT = tempfile.mkdtemp()
os.makedirs(os.path.join(ROOT, "code"))
os.chdir(os.path.join(ROOT, "code"))
os.environ.setdefault("BOT_TOKEN", "123456:TEST")
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "code"))

65
tests/test_script.py Normal file
View file

@ -0,0 +1,65 @@
import script
from init import du, dg
def test_md_and_plain():
assert script.md("ivan_petrov *x*") == "ivan\\_petrov \\*x\\*"
assert script.plain("[a]_b*") == "ab"
def test_join_names():
assert script.join_names(["а"]) == "а"
assert script.join_names(["а", "б"]) == "а и б"
assert script.join_names(["а", "б", "в"]) == "а, б и в"
def test_translator_fixes_wrong_layout():
assert script.translator(["ghbdtn", "vbh"]) == "привет мир"
def test_revers_and_lang_form():
assert script.revers("Привет, мир!", True) == "Тевирп, рим!"
assert script.lang_form(["кот"]) == "когот"
def test_stats_counters_and_mentions():
chat, author, other, third = -100500, 1, 2, 3
script.upd_stat(author, chat, 1, "Автор")
script.upd_stat(other, chat, 1, "Иван_")
script.upd_stat(other, chat, 1, "Иван_")
script.upd_stat(third, chat, 2, "Пётр")
group_id = du.get_group_id(chat)
ivan = du.get_user_id(other)
assert dg.stat_user(ivan, group_id)[0] == 2 # два сообщения — счётчик атомарный
# упоминание: спецсимволы Markdown из имени внутри ссылки убираются, автор себя не упоминает
text = script.notice(["иван_", "автор"], False, group_id, author)
assert text == "[Иван](tg://user?id=2), тебя упомянули)"
assert script.notice(["автор"], False, group_id, author).startswith("[Автор]")
every = script.notice(du.get_user_id(author), True, group_id, author)
assert "[Иван](tg://user?id=2) и [Пётр](tg://user?id=3) вас вызывает Автор" == every
def test_bot_imports():
import bot # noqa: F401 — обработчики и роутер собираются без ошибок
def test_month_reset():
from datetime import date
import bot
from init import db, dm
chat, user = -200300, 10
script.upd_stat(user, chat, 1, "Маша")
group_id = du.get_group_id(chat)
member = du.get_user_id(user)
assert bot.reset_month_if_needed(date(2026, 10, 6)) is False # первый запуск — только запомнить
assert dm.stat_user(member, group_id)[0] == 1
assert bot.reset_month_if_needed(date(2026, 10, 20)) is False # тот же месяц
assert bot.reset_month_if_needed(date(2026, 11, 1)) is True
assert dm.stat_user(member, group_id)[0] == 0 and db.month_stat_group(group_id)[0] == 0
assert dg.stat_user(member, group_id)[0] == 1 # статистика за всё время не трогается