diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..93d6b00
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+.git
+.env
+db
+tests
+__pycache__
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..7fcca50
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,2 @@
+# Токен бота от @BotFather
+BOT_TOKEN=123456:your-token
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..7b77a23
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -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
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
new file mode 100644
index 0000000..17433a2
--- /dev/null
+++ b/.github/workflows/docker.yml
@@ -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 }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..780d67e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.env
+__pycache__/
+*.pyc
+.pytest_cache/
+db/*.db
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..4723f55
--- /dev/null
+++ b/Dockerfile
@@ -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"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d424a8d
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000..19ac620
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,103 @@
+# AboBot
+
+[Русский](README.md) · **English**
+
+[](https://github.com/EDeev/chatping_abobot/actions/workflows/ci.yml)
+[](https://github.com/EDeev/chatping_abobot/actions/workflows/docker.yml)
+[](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)
+
+---
+
+
+
⭐ If you find this project useful, give it a star on GitHub!
+
Made with ❤️ — deev.space
+
diff --git a/README.md b/README.md
index 63f87f0..819b65b 100644
--- a/README.md
+++ b/README.md
@@ -1,153 +1,100 @@
-# 🤖 ABOBOT - Telegram Group Management Bot
+# AboBot
-
-
-
-
+**Русский** · [English](README.en.md)
-Многофункциональный Telegram-бот для управления групповыми чатами с расширенной аналитикой и интерактивными возможностями.
+[](https://github.com/EDeev/chatping_abobot/actions/workflows/ci.yml)
+[](https://github.com/EDeev/chatping_abobot/actions/workflows/docker.yml)
+[](LICENSE)
-## 🎯 Основные возможности
+Telegram-бот для групповых чатов. Он:
+- зовёт участника, когда его имя звучит в сообщении или в голосовом;
+- ведёт статистику чата и каждого участника;
+- исправляет текст, набранный в неправильной раскладке;
+- распознаёт и озвучивает голосовые;
+- устраивает шуточные ивенты.
-### 📊 Система аналитики
-- **Комплексная статистика** - детальный учёт активности участников
-- **Временная сегментация** - анализ данных за месяц и весь период
-- **Многомерные метрики** - сообщения, ответы, команды, медиафайлы, голосовые
+**Статус:** личный проект, работает с 2021 года · бот [@chat_abobot](https://t.me/chat_abobot) · в базе
+бота больше 20 000 пользователей из 45 чатов (октябрь 2026)
-### 👥 Управление участниками
-- **Интеллектуальные упоминания** - автоматическое обнаружение имён в сообщениях
-- **Динамическое именование** - морфологическая обработка и нормализация
-- **Групповые вызовы** - команда `/all` для оповещения всех участников
+**Стек:** Python 3.12 · aiogram 3 · pymorphy3 · pyenchant · SpeechRecognition · gTTS · SQLite · Docker
-### 🔧 Утилиты и инструменты
-- **Транслитерация** - автоматический перевод с латиницы на кириллицу
-- **Транскрипция** - конвертация голосовых сообщений в текст (gTTS)
-- **Текстовые трансформации** - реверс слов и предложений
-- **Генерация голоса** - озвучивание текстовых сообщений
+## Возможности
-### 🎮 Интерактивные функции
-- **Игровые механики** - симуляция драк и взаимодействий
-- **Рандомизация** - генерация случайных чисел в диапазоне
-- **Советник** - интеграция с API для получения рандомных советов
+- **Упоминания по имени.** Слова сообщения приводятся к начальной форме (pymorphy3) и сравниваются с
+ именами участников, поэтому участницу Машу позовут и «Маша», и «позови Машу», и «с Машей». Своё имя
+ для упоминаний можно задать командой `/edit`. Имена ищутся и в голосовых до минуты.
+- **`/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
-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
```
-### Конфигурация
-1. Получите токен бота у [@BotFather](https://t.me/BotFather)
-2. Обновите `TOKEN` в `code/base.py`
-3. Настройте права администратора для автоудаления системных сообщений
+Готовый образ: `docker pull ghcr.io/edeev/chatping_abobot` или `docker pull dcr.deev.su/edeev/chatping_abobot`.
+Базы SQLite создаются при первом запуске.
+
+Без 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
-cd code
-python bot.py
+pip install -r requirements-dev.txt
+ruff check --select E9,F,B code tests && pytest
```
-## 📋 Команды
+Что проверяют тесты:
+- счётчики статистики;
+- упоминания и `/all`;
+- обнуление месячной статистики;
+- раскладку, переворот и экранирование;
+- что обработчики бота загружаются.
-| Команда | Функционал |
-|---------|------------|
-| `/start`, `/help` | Интерактивное меню с описанием возможностей |
-| `/all` | Упоминание всех участников группы |
-| `/stat_group` | Детальная аналитика группы |
-| `/stat_user` | Персональная статистика пользователя |
-| `/recognize` | Транскрипция голосового сообщения |
-| `/edit <имя>` | Установка кастомного имени для упоминаний |
-| `/back_edit` | Возврат к динамическому именованию |
-| `/start_bot` | Активация текстовых событий |
-| `/stop_bot` | Деактивация текстовых событий |
+Docker-образ собирается по тегу `v*` и публикуется в GitHub Packages и `dcr.deev.su`.
-## 🎲 Текстовые события
+## Лицензия
-### Интерактивные команды
-- **"Чмокнуть [имя]"** - позитивное взаимодействие
-- **"Отмудохать [имя]"** - игровая агрессия
-- **"Подраться с [имя]"** - симуляция боя с рандомным исходом
-- **"Число от X до Y"** - генерация случайного числа
-- **"Переведи (символ) - текст"** - трансформация в "кирпичный" язык
-- **"Переверни - текст"** - реверс слов с сохранением пунктуации
-- **"Озвучь - текст"** - генерация голосового сообщения
+MIT — см. [LICENSE](LICENSE).
-## 🔍 Технические особенности
+## Автор
-### Алгоритмы обработки
-- **Морфологический анализ** - приведение имён к начальной форме
-- **Детекция транслита** - эвристический алгоритм определения раскладки
-- **Парсинг голоса** - интеграция 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)
+**Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
---
-
⭐ Если проект оказался полезным, поставьте звезду на GitHub!
-
Создано с ❤️ от вашего дорогого - deev.space ©
+
⭐ Если проект оказался полезным, поставьте звёздочку на GitHub!
+
Сделано с ❤️ — deev.space
diff --git a/compose.yaml b/compose.yaml
new file mode 100644
index 0000000..b5a1717
--- /dev/null
+++ b/compose.yaml
@@ -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:
diff --git a/db/.gitkeep b/db/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 0000000..b065da0
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1,3 @@
+-r requirements.txt
+pytest==8.4.2
+ruff==0.14.0
diff --git a/requirements.txt b/requirements.txt
index 07c71ba..2ef520a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,34 +1,8 @@
-# Core Framework Dependencies
-aiogram==3.10.0
-asyncio-mqtt==0.16.1
-
-# Database Management
-sqlite3
-
-# Natural Language Processing
-pymorphy3==1.2.1
+aiogram==3.23.0
+pymorphy3==2.0.6
pymorphy3-dicts-ru==2.4.417150.4580142
-enchant==1.6.6
-
-# Speech Recognition & Synthesis
-SpeechRecognition==3.10.4
-gTTS==2.5.1
-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
+pyenchant==3.2.2
+SpeechRecognition==3.14.4
+gTTS==2.5.4
+soundfile==0.13.1
+requests==2.32.5
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..982ccfd
--- /dev/null
+++ b/tests/conftest.py
@@ -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"))
diff --git a/tests/test_script.py b/tests/test_script.py
new file mode 100644
index 0000000..a0895cd
--- /dev/null
+++ b/tests/test_script.py
@@ -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 # статистика за всё время не трогается