Compare commits

...

9 commits

Author SHA1 Message Date
9c6a250a33
README.md 2025-06-30 20:11:37 +03:00
b73df23108
README.md 2025-06-30 13:26:57 +03:00
616d7295da
requirements 2025-06-30 13:24:31 +03:00
faab8abc8e
v. 3.0 2025-06-30 13:14:57 +03:00
8f43acaa50
Delete libraries.txt 2025-06-30 13:12:14 +03:00
Egor Deev
de5a86a133
v. 2.2 2023-10-19 13:24:47 +03:00
Egor Deev
ba5aa85800
v. 1.1 2023-10-19 13:23:42 +03:00
Egor Deev
59af13e95b
Delete data/data directory 2023-10-19 13:22:26 +03:00
Egor Deev
178df95ab2
v. 2.2 2023-10-19 12:53:58 +03:00
10 changed files with 773 additions and 438 deletions

156
README.md
View file

@ -1,7 +1,153 @@
<h2>Telegram 🤖 ABOBOT / Телеграм 🤖 АБОБОТ</h2> # 🤖 ABOBOT - Telegram Group Management Bot
Этот бот создан для чатов в Телеграм , он может упомянуть всех участников в чате, выдать статистику ![Python](https://img.shields.io/badge/Python-3.8+-blue.svg)
по группе / участнику группы, также имеет ситуативные функции, как: перевод транслита, разворачинание / переворачивание ![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)
<b>Также вы можете ознакомиться с этим ботом прямо сейчас перейдя по этой <a href="https://t.me/abobusik_bot">ссылке</a></b> Многофункциональный Telegram-бот для управления групповыми чатами с расширенной аналитикой и интерактивными возможностями.
## 🎯 Основные возможности
### 📊 Система аналитики
- **Комплексная статистика** - детальный учёт активности участников
- **Временная сегментация** - анализ данных за месяц и весь период
- **Многомерные метрики** - сообщения, ответы, команды, медиафайлы, голосовые
### 👥 Управление участниками
- **Интеллектуальные упоминания** - автоматическое обнаружение имён в сообщениях
- **Динамическое именование** - морфологическая обработка и нормализация
- **Групповые вызовы** - команда `/all` для оповещения всех участников
### 🔧 Утилиты и инструменты
- **Транслитерация** - автоматический перевод с латиницы на кириллицу
- **Транскрипция** - конвертация голосовых сообщений в текст (gTTS)
- **Текстовые трансформации** - реверс слов и предложений
- **Генерация голоса** - озвучивание текстовых сообщений
### 🎮 Интерактивные функции
- **Игровые механики** - симуляция драк и взаимодействий
- **Рандомизация** - генерация случайных чисел в диапазоне
- **Советник** - интеграция с API для получения рандомных советов
## 🏗️ Архитектура системы
### Технологический стек
```
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
```
### Конфигурация
1. Получите токен бота у [@BotFather](https://t.me/BotFather)
2. Обновите `TOKEN` в `code/base.py`
3. Настройте права администратора для автоудаления системных сообщений
### Запуск
```bash
cd code
python bot.py
```
## 📋 Команды
| Команда | Функционал |
|---------|------------|
| `/start`, `/help` | Интерактивное меню с описанием возможностей |
| `/all` | Упоминание всех участников группы |
| `/stat_group` | Детальная аналитика группы |
| `/stat_user` | Персональная статистика пользователя |
| `/recognize` | Транскрипция голосового сообщения |
| `/edit <имя>` | Установка кастомного имени для упоминаний |
| `/back_edit` | Возврат к динамическому именованию |
| `/start_bot` | Активация текстовых событий |
| `/stop_bot` | Деактивация текстовых событий |
## 🎲 Текстовые события
### Интерактивные команды
- **"Чмокнуть [имя]"** - позитивное взаимодействие
- **"Отмудохать [имя]"** - игровая агрессия
- **"Подраться с [имя]"** - симуляция боя с рандомным исходом
- **"Число от X до Y"** - генерация случайного числа
- **"Переведи (символ) - текст"** - трансформация в "кирпичный" язык
- **"Переверни - текст"** - реверс слов с сохранением пунктуации
- **"Озвучь - текст"** - генерация голосового сообщения
## 🔍 Технические особенности
### Алгоритмы обработки
- **Морфологический анализ** - приведение имён к начальной форме
- **Детекция транслита** - эвристический алгоритм определения раскладки
- **Парсинг голоса** - интеграция 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">
<sub>⭐ Если проект оказался полезным, поставьте звезду на GitHub!</sub>
<p><sub>Создано с ❤️ от вашего дорогого - deev.space ©</sub></p>
</div>

View file

@ -1,8 +1,8 @@
# ДАННЫЕ БОТА # ДАННЫЕ БОТА
TOKEN = "" # @chat_abobot TOKEN = "XXXXXXXXXX" # @chat_abobot
DEBAG = "-*********" # Технический чат DEBAG = "XXXXXXXXXX" # Технический чат
TEX_GROUP = "-*********" TEX_GROUP = "XXXXXXXXXX"
# ОБРАЩЕНИЯ К ПОЛЬЗОВАТЕЛЯМ # ОБРАЩЕНИЯ К ПОЛЬЗОВАТЕЛЯМ
KILL_LIST = ["побить", "отмудохать", "избить", "уебать", "отметелить"] KILL_LIST = ["побить", "отмудохать", "избить", "уебать", "отметелить"]

View file

@ -1,422 +1,20 @@
import logging, random, pymorphy2, requests import asyncio
import asyncio, base, re, os, enchant, sql import logging
from gtts import gTTS from init import bot, dp
from script import checker, translator, notice, lang_form, revers, upd_stat from handlers import router
from aiogram import Bot, Dispatcher, executor, types
from datetime import datetime as dt
# from filters import Admin async def main() -> None:
dp.include_router(router)
# log level await bot.delete_webhook(drop_pending_updates=True)
logging.basicConfig(level=logging.INFO) await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types(), skip_updates=True)
# bot init
bot = Bot(token=base.TOKEN) if __name__ == '__main__':
dp = Dispatcher(bot) logging.basicConfig(level=logging.INFO)
morph = pymorphy2.MorphAnalyzer()
engl_dict = enchant.Dict("en_US") try: asyncio.run(main())
except KeyboardInterrupt:
# инициализируем соединение с БД print("Бот остановлен")
db = sql.Base('../db/base.db') pass
du = sql.User('../db/users.db')
dg = sql.Group('../db/groups.db')
dm = sql.Month('../db/month.db')
# инициализируем фильтры
# dp.filters_factory.bind(Admin)
@dp.message_handler(content_types=["new_chat_members"])
async def notification(message: types.Message):
if not du.group_exists(message.chat.id):
du.add_group(message.chat.id)
group_id = du.get_group_id(message.chat.id)
db.add_group(group_id)
dg.created_group(group_id)
await bot.send_message(message.chat.id, f'<b>Привет группа {message.chat.title}!</b>\n\nВсе функции вы можете '
f'узнать по команде /help! Для того, чтобы '
f'уведомления по имени и команда /all нормально функционировали, '
f'необходимо чтобы каждый участник группы написал хотя бы одно '
f'сообщение в чат! Также для того, чтобы системные сообщения удалялись '
f'автоматически, необходимо боту выдать права администратора!',
types.ParseMode.HTML)
else:
try:
await message.delete()
except Exception:
return
# ОБНОВЛЕНИЕ АЙДИ ГРУППЫ
@dp.message_handler(content_types=['migrate_to_chat_id', 'migrate_from_chat_id'])
async def chat_reload(message: types.Message):
if du.group_exists(message.migrate_from_chat_id):
du.update_group_id(du.get_group_id(message.migrate_from_chat_id), message.migrate_to_chat_id)
# КОМАНДЫ
@dp.message_handler(commands=['start', 'help'])
async def helps(message: types.Message):
if message.chat.id > 0:
user_id = message.from_user.id
if not du.user_exists(user_id):
du.add_user(user_id)
else:
group_id, user_id = message.chat.id, message.from_user.id
if not du.user_exists(user_id):
du.add_user(user_id)
if not du.group_exists(group_id):
du.add_group(group_id)
upd_stat(user_id, group_id, 3, message.from_user.first_name, True)
buttons = [types.InlineKeyboardButton(text="КОМАНДЫ", callback_data="com"),
types.InlineKeyboardButton(text="ИВЕНТЫ", callback_data="even"),
types.InlineKeyboardButton(text="АВТОР", callback_data="auth"),
types.InlineKeyboardButton(text="ФУНКЦИИ", callback_data="fun")]
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.add(*buttons)
try:
await bot.send_voice(chat_id=message.chat.id, voice=open('../data/tts.ogg', 'rb'),
caption='*-* Этот АБОБОТ поможет вам приятно провести время в чате с различными командами, '
'ивентами и удобными функциями, которые облегчают использование чата)\n\n'
'*-* Также прошу если вам понравился бот, оставить отзыв о его использовании на '
'команду /report)', parse_mode=types.ParseMode.MARKDOWN, reply_markup=keyboard)
except Exception:
await bot.send_message(chat_id=message.chat.id,
text='*-* Этот АБОБОТ поможет вам приятно провести время в чате с различными командами, '
'ивентами и удобными функциями, которые облегчают использование чата)\n\n'
'*-* Также прошу если вам понравился бот, оставить отзыв о его использовании на '
'команду /report)', parse_mode=types.ParseMode.MARKDOWN, reply_markup=keyboard)
# ИЛАЙН КЛАВИАТУРА HELP
@dp.callback_query_handler(text="auth")
async def author(call: types.CallbackQuery):
await call.message.answer(text='*| АВТОР |*\n\n*>>* Этот бот, как бы это не печально звучало, но одна из лучших'
' моих работ и если кого-нибудь у меня получится действительно достойный продукт,'
' вы сможете о нём узнать в моём телеграм канале *@itsproger*', parse_mode=types.ParseMode.MARKDOWN)
@dp.callback_query_handler(text="fun")
async def function(call: types.CallbackQuery):
await call.message.answer(text='*| ФУНКЦИИ |*\n\n*1.* Возможность перевода случайно написанного текста на '
'транслите\n*2.* Ведение обширной статистики сообщений\n*3.* Упоминание участника '
'при написании его имени в чате\n*4.* Автоматическое удаление системных сообщений',
parse_mode=types.ParseMode.MARKDOWN)
@dp.callback_query_handler(text="com")
async def commands(call: types.CallbackQuery):
await call.message.answer(text='<b>| КОМАНДЫ |</b>\n\n/all - упомянуть всех в чате\n/help - полный список функций\n'
'/stat_group - полная статистика группы\n/stat_user - полная статистика '
'отправителя\n/edit и /back_edit - первая команда даёт возможность '
'сменить имя для упоминаний на любое слово, а вторая для возврата динамического '
'имени\n/start_bot и /stop_bot - возможность отключения текстовых ивентов',
parse_mode=types.ParseMode.HTML)
@dp.callback_query_handler(text="even")
async def events(call: types.CallbackQuery):
await call.message.answer(text='*| ИВЕНТЫ |*\n\n*"Чмокнуть"* - сделать кому-нибудь приятно\n*"Отмудохать"* - '
'выместить злость на кого-нибудь\n*"Число от ... до ..."* - случайное значение из '
'диапозона\n*"Подраться с ..."* - повод кого-нибудь побить\n*"Переведи (..) - ..."* '
'- перевод слова на керпичный язык\n*"Дай блять совет!"* - даёт рандомный охуенный '
'совет\n*"Переверни - ..."* - переворачивает слова в предложении\n*"Озвучь - ..."* '
'- озвучивает написанный текст',
parse_mode=types.ParseMode.MARKDOWN)
# ОСТАЛЬНЫЕ КОМАНДЫ
@dp.message_handler(commands=['all'], commands_prefix='@/')
async def every(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
try:
await message.reply(notice(du.get_user_id(message.from_user.id), True, du.get_group_id(message.chat.id), message.from_user.id),
types.ParseMode.HTML)
except Exception as e:
# print(repr(e))
await message.reply('В группе состоит менее 3х человек, из-за чего команда не работает!')
else:
await message.reply('Эта команда предназначена для вызова в чате!')
@dp.message_handler(commands=['stat_group'])
async def stat_group(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
group_id = du.get_group_id(message.chat.id)
group = db.stat_group(group_id)
month = db.month_stat_group(group_id)
await message.answer(text=f'*| СТАТИСТИКА ГРУППЫ |*\n\n'
f'*>>* В целом сообщений *[ {message.message_id} ]*\n\n'
f'*- За всё время* / *За месяц -*\n'
f'*>>* Сообщений в базе *[ {group[0]} / {month[0]} ]*\n\n'
f'*>* Ответов *- [ {group[1]} / {month[1]} ]*\n'
f'*>* Команд *- [ {group[2]} / {month[2]} ]*\n'
f'*>* Ссылок *- [ {group[3]} / {month[3]} ]*\n'
f'*>* Стикеров *- [ {group[5]} / {month[5]} ]*\n'
f'*>* Медиа файлов *- [ {group[4]} / {month[4] } ]*\n'
f'*>* Голос/Кружочки *- [ {group[6]} / {month[6]} ]*',
parse_mode=types.ParseMode.MARKDOWN)
@dp.message_handler(commands=['stat_user'])
async def stat_user(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
user_id, group_id = du.get_user_id(message.from_user.id), du.get_group_id(message.chat.id)
group = dg.stat_user(user_id, group_id)
month = dm.stat_user(user_id, group_id)
namer = "".join(re.sub(r'[^\w\s]', '', message.from_user.first_name).split())
name = morph.parse(namer)[0].inflect({"gent"})
if name is None: name = namer
else: name = name.word
await message.answer(text=f'*| СТАТИСТИКА {name.upper()} |*\n\n'
f'*- За всё время* / *За месяц -*\n'
f'*>>* Сообщений в базе *[ {group[0]} / {month[0]} ]*\n\n'
f'*>* Ответов *- [ {group[1]} / {month[1]} ]*\n'
f'*>* Команд *- [ {group[2]} / {month[2]} ]*\n'
f'*>* Ссылок *- [ {group[3]} / {month[3]} ]*\n'
f'*>* Стикеров *- [ {group[5]} / {month[5]} ]*\n'
f'*>* Медиа файлов *- [ {group[4]} / {month[4]} ]*\n'
f'*>* Голос/Кружочки *- [ {group[6]} / {month[6]} ]*',
parse_mode=types.ParseMode.MARKDOWN)
@dp.message_handler(commands=['edit'])
async def update(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
user_id, group_id = du.get_user_id(message.from_user.id), du.get_group_id(message.chat.id)
text_edit = re.sub(r'[^\w\s]', '', message.text.lower()).split()
if len(text_edit) == 2:
name = morph.parse(text_edit[1])[0]
if name is None: name = text_edit[1]
else: name = name.normal_form
if name not in list(map(lambda x: x[0], dg.all_names(group_id))):
if not db.edit_user_exists(user_id):
db.add_edit_user(user_id)
dg.update_name(user_id, group_id, name)
await message.reply(f'{name.title()}, ваше имя было успешно изменено)')
else:
await message.reply(f'{message.from_user.first_name.lower().title()}, такое имя уже присутствует в чате!')
else:
await message.reply('Вы не правильно ввели имя! Имя должно быть '
'из одного слова и идти сразу после команды!')
@dp.message_handler(commands=['back_edit'])
async def update_return(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
user_id, group_id = du.get_user_id(message.from_user.id), du.get_group_id(message.chat.id)
name = re.sub(r'[^\w\s]', '', message.from_user.first_name.lower())
if db.edit_user_exists(user_id):
db.del_edit_user(user_id)
dg.update_name(user_id, group_id, name)
await message.reply(f'{name.title()}, вы успешно вернулись к динамическому изменению имени)')
else:
await message.reply(f'{name.title()}, вы не устанавливали постоянное имя!')
@dp.message_handler(commands=['start_bot'])
async def opening(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
group_id = du.get_group_id(message.chat.id)
if db.check_status(group_id):
await message.answer("У вас уже включены текстовые ивенты!")
else:
db.update_status(group_id)
await message.answer("Текстовые ивенты включены!")
@dp.message_handler(commands=['stop_bot'])
async def closing(message: types.Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
group_id = du.get_group_id(message.chat.id)
if db.check_status(group_id):
db.update_status(group_id)
await message.answer("Текстовые ивенты отключены!")
else:
await message.answer("У вас уже отключены текстовые ивенты!")
# УДАЛЕНИЕ ПОЛЬЗОВАТЕЛЕЙ АВТОМАТИЧЕСКИ
@dp.message_handler(content_types=["left_chat_member"])
async def delete(message: types.Message):
if du.user_exists(message.left_chat_member.id):
user_id, group_id = du.get_user_id(message.left_chat_member.id), du.get_group_id(message.chat.id)
dg.del_user(group_id, user_id)
if db.group_exists_month(group_id):
if dm.user_exists(user_id, group_id): dm.del_user(group_id, user_id)
try: await message.delete()
except Exception: return
# УДАЛЕНИЕ ТЕХ. СООБЩЕНИЙ
@dp.message_handler(content_types=["new_chat_title", "new_chat_photo", "pinned_message", "voice_chat_ended",
"voice_chat_participants_invited"])
async def chat_events(message: types.Message):
try: await message.delete()
except Exception: return
# СТАТИСТИКА
@dp.message_handler(content_types=['location', 'contact', 'video', 'photo', 'audio', 'document'])
async def media(message: types.Message):
if message.chat.id < 0: upd_stat(message.from_user.id, message.chat.id, 5, message.from_user.first_name, True)
@dp.message_handler(content_types=['voice', 'video_note'])
async def voice(message: types.Message):
if message.chat.id < 0: upd_stat(message.from_user.id, message.chat.id, 7, message.from_user.first_name, True)
@dp.message_handler(content_types=['sticker'])
async def stick(message: types.Message):
if message.chat.id < 0: upd_stat(message.from_user.id, message.chat.id, 6, message.from_user.first_name, True)
# ТЕКСТОВЫЕ ИВЕНТЫ
@dp.message_handler(content_types=['text'])
async def send_events(message: types.Message):
group_id, user_id, name = message.chat.id, message.from_user.id, message.from_user.first_name
# ОБНОВЛЕНИЕ КОЛ-ВО
if message.chat.id < 0:
upd_stat(user_id, group_id, 1, name) # СООБЩЕНИЙ
if len(message.text) > 1 and message.text[0] == '/': upd_stat(user_id, group_id, 3, name) # КОМАНД
if 'reply_to_message' in message: upd_stat(user_id, group_id, 2, name) # ОТВЕТОВ НА СООБЩЕНИЯ
# ПЕРЕМЕННЫЕ
low_mes = message.text.lower() # СООБЩЕНИЕ В НИЖНЕМ РЕГИСТРЕ
words = message.text.split() # СПИСОК СЛОВ В СООБЩЕНИИ
unsigned = re.sub(r'[^\w\s]', '', low_mes).split() # СПИСОК СЛОВ БЕЗ ПУНКТУАЦИИ
first_form = [morph.parse(i)[0].normal_form for i in unsigned] # СПИСОК СЛОВ В ПЕРВОЙ ФОРМЕ
if message.chat.id < 0: # СПИСОК ИМЕН В СООБЩЕНИИ (ТОЛЬКО В ГРУППЕ)
names = [_ for _ in first_form if _ in list(map(lambda x: x[0], dg.all_names(du.get_group_id(group_id))))]
if len(words) >= 2:
# ПОЛЕЗНЫЕ ФУНКЦИИ
if len(words) == 5 and "число от" in low_mes:
await message.answer(
text=f"Число <b>[ {random.randint(int(low_mes.split()[2]), int(low_mes.split()[4]))} ]</b>",
parse_mode=types.ParseMode.HTML)
return
if unsigned[0] == 'переведи':
if "переведи - " in low_mes:
await message.answer(lang_form([words[_] for _ in range(len(words)) if _ > 1]))
elif f"переведи ({unsigned[1]}) - " in low_mes:
if len(unsigned[1]) == 1:
await message.answer(lang_form([words[_] for _ in range(len(words)) if _ > 2], unsigned[1]))
return
if unsigned[0] == 'переверни':
if "переверни - " in low_mes:
await message.answer(revers(message.text[12:], True))
elif "переверни полностью - " in low_mes:
await message.answer(revers(message.text[22:], False))
return
if unsigned[0] == 'озвучь' and "озвучь - " in low_mes:
text_to_voice = message.text[9:]
tts = gTTS(text_to_voice, lang='ru')
tts.save('../data/voices/voice.ogg')
await bot.send_voice(chat_id=group_id, voice=open('../data/voices/voice.ogg', 'rb'),
caption=f"<b>{text_to_voice}</b>", parse_mode=types.ParseMode.HTML)
os.remove('../data/voices/voice.ogg')
return
# РАНДОМ ИВЕНТЫ
if "подраться" == words[0].lower() and "с" == words[1].lower():
text = " ".join([words[i] for i in range(len(words)) if i > 1])
if random.randint(0, 1) == 0:
await message.bot.send_photo(chat_id=group_id,
photo=open(f"../data/fight/({random.randint(1, 8)}).jpg", 'rb'),
caption=f"{message.from_user.first_name}, ты был унижен {text.title()}"
f", с помощью {base.VAR_LOSE[random.randint(0, 3)]}")
else:
await message.bot.send_photo(chat_id=group_id,
photo=open(f"../data/fight/({random.randint(1, 8)}).jpg", 'rb'),
caption=f"{message.from_user.first_name}, ты победил в драке "
f"с {text.title()}, {base.VAR_WIN[random.randint(0, 1)]}")
# ИВЕНТ ВЗАИМОДЕЙСТВИЯ
for word in base.TMOK_LIST:
if word in low_mes:
lst = [words[i] for i in range(len(words)) if i != 0]
text = " ".join(lst)
slv = morph.parse(words[0].lower())[0]
await message.bot.send_photo(chat_id=group_id,
photo=open(f"../data/tmok/({random.randint(1, 4)}).jpg", 'rb'),
caption=f"{message.from_user.first_name} "
f"{slv.inflect({'past', 'sing', 'indc'}).word} {text}")
for word in base.KILL_LIST:
if word in low_mes:
lst = [words[i] for i in range(len(words)) if i != 0]
text = " ".join(lst)
slv = morph.parse(words[0].lower())[0]
await message.bot.send_photo(chat_id=group_id,
photo=open(f"../data/kill/({random.randint(1, 6)}).jpg", 'rb'),
caption=f"{message.from_user.first_name} "
f"{slv.inflect({'past', 'sing', 'indc'}).word} {text}")
if unsigned[0] in base.QUAT_LIST[0] and \
unsigned[1] in base.QUAT_LIST[1] and unsigned[2] in base.QUAT_LIST[2]:
word = requests.get('http://fucking-great-advice.ru/api/random').json()
await message.reply(word["text"])
return
if message.chat.id < 0:
# ЛИСТ КОМАНДЫ
if names:
try:
await message.reply(notice(names, False, du.get_group_id(group_id), user_id), types.ParseMode.HTML)
except Exception as e:
return
"""
await bot.send_message(chat_id=base.TEX_GROUP, text=f"<b>[ {str(dt.now())[:-10]} ]</b> "
f"<b><i>=></i></b> <i>{repr(e)}</i> (уведомления по именам)",
parse_mode=types.ParseMode.HTML)
"""
return
# ПЕРЕВОДЧИК СЛОВ
if checker([i for i in low_mes], words, group_id, user_id, name.lower()) == len(low_mes) and \
not any([engl_dict.check(i) for i in unsigned]):
await message.reply(f"[{message.from_user.first_name}](tg://user_id?id={user_id}) *>* {translator(words)}",
types.ParseMode.MARKDOWN)
return
if __name__ == '__main__':
loop = asyncio.get_event_loop()
executor.start_polling(dp, skip_updates=True)

540
code/handlers.py Normal file
View file

@ -0,0 +1,540 @@
from aiogram import F, Router
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton, FSInputFile
from aiogram.filters import Command, CommandStart
from aiogram.enums import ContentType
import logging, random, requests, os, re
import speech_recognition as sr
import soundfile as sf
from gtts import gTTS
from init import *
from script import *
import base
router = Router()
# НОВЫЕ УЧАСТНИКИ ГРУППЫ
@router.message(F.content_type == ContentType.NEW_CHAT_MEMBERS)
async def notification(message: Message):
if not du.group_exists(message.chat.id):
du.add_group(message.chat.id)
group_id = du.get_group_id(message.chat.id)
db.add_group(group_id)
dg.created_group(group_id)
await bot.send_message(
message.chat.id,
f'*Привет группа {message.chat.title}!*\n\n'
f'Все функции вы можете узнать по команде /help! Для того, чтобы '
f'уведомления по имени и команда /all нормально функционировали, '
f'необходимо чтобы каждый участник группы написал хотя бы одно '
f'сообщение в чат! Также для того, чтобы системные сообщения удалялись '
f'автоматически, необходимо боту выдать права администратора!'
)
else:
try:
await message.delete()
except Exception:
return
# ОБНОВЛЕНИЕ АЙДИ ГРУППЫ
@router.message(F.content_type.in_([ContentType.MIGRATE_TO_CHAT_ID, ContentType.MIGRATE_FROM_CHAT_ID]))
async def chat_reload(message: Message):
if du.group_exists(message.migrate_from_chat_id):
du.update_group_id(du.get_group_id(message.migrate_from_chat_id), message.migrate_to_chat_id)
# КОМАНДЫ HELP И START
@router.message(CommandStart())
@router.message(Command('help'))
async def helps(message: Message):
if message.chat.id > 0:
user_id = message.from_user.id
if not du.user_exists(user_id):
du.add_user(user_id)
else:
group_id, user_id = message.chat.id, message.from_user.id
if not du.user_exists(user_id):
du.add_user(user_id)
if not du.group_exists(group_id):
du.add_group(group_id)
upd_stat(user_id, group_id, 3, message.from_user.first_name, True)
buttons = [
[InlineKeyboardButton(text="КОМАНДЫ", callback_data="com"),
InlineKeyboardButton(text="ИВЕНТЫ", callback_data="even")],
[InlineKeyboardButton(text="АВТОР", callback_data="auth"),
InlineKeyboardButton(text="ФУНКЦИИ", callback_data="fun")]
]
keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
try:
await bot.send_voice(
chat_id=message.chat.id,
voice=FSInputFile('../data/tts.ogg'),
caption='*-* Этот АБОБОТ поможет вам приятно провести время в чате с различными командами, '
'ивентами и удобными функциями, которые облегчают использование чата)\n\n'
'*-* Также прошу если вам понравился бот, оставить отзыв о его использовании на '
'команду /report)',
reply_markup=keyboard
)
except Exception:
await bot.send_message(
chat_id=message.chat.id,
text='*-* Этот АБОБОТ поможет вам приятно провести время в чате с различными командами, '
'ивентами и удобными функциями, которые облегчают использование чата)\n\n'
'*-* Также прошу если вам понравился бот, оставить отзыв о его использовании на '
'команду /report)',
reply_markup=keyboard
)
# INLINE КЛАВИАТУРА ОБРАБОТЧИКИ
@router.callback_query(F.data == "auth")
async def author(call: CallbackQuery):
await call.message.answer(
text='*| АВТОР |*\n\n*>>* Этот бот, как бы это не печально звучало, но одна из лучших'
' моих работ и если кого-нибудь у меня получится действительно достойный продукт,'
' вы сможете о нём узнать в моём телеграм канале *@programium*'
)
@router.callback_query(F.data == "fun")
async def function(call: CallbackQuery):
await call.message.answer(
text='*| ФУНКЦИИ |*\n\n*1.* Возможность перевода случайно написанного текста на '
'транслите\n*2.* Ведение обширной статистики сообщений\n*3.* Упоминание участника '
'при написании его имени в чате\n*4.* Автоматическое удаление системных сообщений'
)
@router.callback_query(F.data == "com")
async def commands(call: CallbackQuery):
await call.message.answer(
text='*| КОМАНДЫ |*\n\n*/all* - упомянуть всех в чате\n*/help* - полный список функций\n'
'*/recognize* - транскрипция отмеченного голосового сообщения в текст\n'
'*/stat_group* - полная статистика группы\n*/stat_user* - полная статистика '
'отправителя\n*/edit и /back_edit* - первая команда даёт возможность '
'сменить имя для упоминаний на любое слово, а вторая для возврата динамического '
'имени\n*/start_bot и /stop_bot* - возможность отключения текстовых ивентов'
)
@router.callback_query(F.data == "even")
async def events(call: CallbackQuery):
await call.message.answer(
text='*| ИВЕНТЫ |*\n\n*"Чмокнуть"* - сделать кому-нибудь приятно\n*"Отмудохать"* - '
'выместить злость на кого-нибудь\n*"Число от ... до ..."* - случайное значение из '
'диапозона\n*"Подраться с ..."* - повод кого-нибудь побить\n*"Переведи (..) - ..."* '
'- перевод слова на керпичный язык\n*"Дай блять совет!"* - даёт рандомный охуенный '
'совет\n*"Переверни - ..."* - переворачивает слова в предложении\n*"Озвучь - ..."* '
'- озвучивает написанный текст'
)
# КОМАНДА ALL
@router.message(Command('all'))
async def every(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
try:
await message.reply(
notice(du.get_user_id(message.from_user.id), True,
du.get_group_id(message.chat.id), message.from_user.id)
)
except Exception:
await message.reply('В группе состоит менее 3х человек, из-за чего команда не работает!')
else:
await message.reply('Эта команда предназначена для вызова в чате!')
# КОМАНДА RECOGNIZE
@router.message(Command("recognize"))
async def recognise(message: Message):
user_id = du.get_user_id(message.from_user.id)
if message.reply_to_message and message.reply_to_message.voice:
num = random.randint(1000, 9999)
audio = f"../data/voices/{user_id}_{num}.oga"
file_id = message.reply_to_message.voice.file_id
file = await bot.get_file(file_id)
file_path = file.file_path
await bot.download_file(file_path, audio)
data, samplerate = sf.read(audio)
os.remove(audio)
audio = f"../data/voices/{user_id}_{num}.wav"
sf.write(audio, data, samplerate)
af = sr.AudioFile(audio)
r = sr.Recognizer()
with af as source:
r.pause_threshold = 100
source = r.listen(source)
try:
mes = await bot.send_message(
chat_id=message.chat.id,
text="Распознавание.....",
reply_to_message_id=message.reply_to_message.message_id
)
try:
query = r.recognize_google(source, language='ru-RU')
os.remove(audio)
await mes.edit_text(f'*{message.reply_to_message.from_user.first_name} сказал(a)* "{query}"')
except Exception:
try:
os.remove(audio)
except Exception:
pass
await mes.edit_text("Распознать сообщение не удалось!")
except Exception as e:
print(repr(e))
pass
# СТАТИСТИКА ГРУППЫ
@router.message(Command('stat_group'))
async def stat_group(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
group_id = du.get_group_id(message.chat.id)
group = db.stat_group(group_id)
month = db.month_stat_group(group_id)
await message.answer(
text=f'*| СТАТИСТИКА ГРУППЫ |*\n\n'
f'*>>* В целом сообщений *[ {message.message_id} ]*\n\n'
f'*- За всё время* / *За месяц -*\n'
f'*>>* Сообщений в базе *[ {group[0]} / {month[0]} ]*\n\n'
f'*>* Ответов *- [ {group[1]} / {month[1]} ]*\n'
f'*>* Команд *- [ {group[2]} / {month[2]} ]*\n'
f'*>* Ссылок *- [ {group[3]} / {month[3]} ]*\n'
f'*>* Стикеров *- [ {group[5]} / {month[5]} ]*\n'
f'*>* Медиа файлов *- [ {group[4]} / {month[4]} ]*\n'
f'*>* Голос/Кружочки *- [ {group[6]} / {month[6]} ]*'
)
# СТАТИСТИКА ПОЛЬЗОВАТЕЛЯ
@router.message(Command('stat_user'))
async def stat_user(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
user_id, group_id = du.get_user_id(message.from_user.id), du.get_group_id(message.chat.id)
group = dg.stat_user(user_id, group_id)
month = dm.stat_user(user_id, group_id)
namer = "".join(re.sub(r'[^\w\s]', '', message.from_user.first_name).split())
name = morph.parse(namer)[0].inflect({"gent"})
if name is None:
name = namer
else:
name = name.word
await message.answer(
text=f'*| СТАТИСТИКА {name.upper()} |*\n\n'
f'*- За всё время* / *За месяц -*\n'
f'*>>* Сообщений в базе *[ {group[0]} / {month[0]} ]*\n\n'
f'*>* Ответов *- [ {group[1]} / {month[1]} ]*\n'
f'*>* Команд *- [ {group[2]} / {month[2]} ]*\n'
f'*>* Ссылок *- [ {group[3]} / {month[3]} ]*\n'
f'*>* Стикеров *- [ {group[5]} / {month[5]} ]*\n'
f'*>* Медиа файлов *- [ {group[4]} / {month[4]} ]*\n'
f'*>* Голос/Кружочки *- [ {group[6]} / {month[6]} ]*'
)
# РЕДАКТИРОВАНИЕ ИМЕНИ
@router.message(Command('edit'))
async def update(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
user_id, group_id = du.get_user_id(message.from_user.id), du.get_group_id(message.chat.id)
text_edit = re.sub(r'[^\w\s]', '', message.text.lower()).split()
if len(text_edit) == 2:
name = morph.parse(text_edit[1])[0]
if name is None:
name = text_edit[1]
else:
name = name.normal_form
if name not in list(map(lambda x: x[0], dg.all_names(group_id))):
if not db.edit_user_exists(user_id):
db.add_edit_user(user_id)
dg.update_name(user_id, group_id, name)
await message.reply(f'{name.title()}, ваше имя было успешно изменено)')
else:
await message.reply(f'{message.from_user.first_name.lower().title()}, такое имя уже присутствует в чате!')
else:
await message.reply('Вы не правильно ввели имя! Имя должно быть '
'из одного слова и идти сразу после команды!')
# ВОЗВРАТ К ДИНАМИЧЕСКОМУ ИМЕНИ
@router.message(Command('back_edit'))
async def update_return(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
user_id, group_id = du.get_user_id(message.from_user.id), du.get_group_id(message.chat.id)
name = re.sub(r'[^\w\s]', '', message.from_user.first_name.lower())
if db.edit_user_exists(user_id):
db.del_edit_user(user_id)
dg.update_name(user_id, group_id, name)
await message.reply(f'{name.title()}, вы успешно вернулись к динамическому изменению имени)')
else:
await message.reply(f'{name.title()}, вы не устанавливали постоянное имя!')
# ВКЛЮЧЕНИЕ ТЕКСТОВЫХ ИВЕНТОВ
@router.message(Command('start_bot'))
async def opening(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
group_id = du.get_group_id(message.chat.id)
if db.check_status(group_id):
await message.answer("У вас уже включены текстовые ивенты!")
else:
db.update_status(group_id)
await message.answer("Текстовые ивенты включены!")
# ОТКЛЮЧЕНИЕ ТЕКСТОВЫХ ИВЕНТОВ
@router.message(Command('stop_bot'))
async def closing(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 3, message.from_user.first_name, True)
group_id = du.get_group_id(message.chat.id)
if db.check_status(group_id):
db.update_status(group_id)
await message.answer("Текстовые ивенты отключены!")
else:
await message.answer("У вас уже отключены текстовые ивенты!")
# УДАЛЕНИЕ ПОЛЬЗОВАТЕЛЕЙ АВТОМАТИЧЕСКИ
@router.message(F.content_type == ContentType.LEFT_CHAT_MEMBER)
async def delete(message: Message):
if du.user_exists(message.left_chat_member.id):
user_id, group_id = du.get_user_id(message.left_chat_member.id), du.get_group_id(message.chat.id)
dg.del_user(group_id, user_id)
if db.group_exists_month(group_id):
if dm.user_exists(user_id, group_id):
dm.del_user(group_id, user_id)
try:
await message.delete()
except Exception:
return
# УДАЛЕНИЕ ТЕХНИЧЕСКИХ СООБЩЕНИЙ
@router.message(F.content_type.in_([
ContentType.NEW_CHAT_TITLE,
ContentType.NEW_CHAT_PHOTO,
ContentType.PINNED_MESSAGE,
ContentType.VIDEO_CHAT_ENDED,
ContentType.VIDEO_CHAT_PARTICIPANTS_INVITED
]))
async def chat_events(message: Message):
try:
await message.delete()
except Exception:
return
# МЕДИА ФАЙЛЫ
@router.message(F.content_type.in_([
ContentType.LOCATION,
ContentType.CONTACT,
ContentType.VIDEO,
ContentType.PHOTO,
ContentType.AUDIO,
ContentType.DOCUMENT
]))
async def media(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 5, message.from_user.first_name, True)
# ГОЛОСОВЫЕ СООБЩЕНИЯ И КРУЖОЧКИ
@router.message(F.content_type.in_([ContentType.VOICE, ContentType.VIDEO_NOTE]))
async def voice(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 7, message.from_user.first_name, True)
if message.voice and message.chat.id < 0:
if message.voice.duration <= 60:
user_id = du.get_user_id(message.from_user.id)
num = random.randint(1000, 9999)
audio = f"../data/voices/{user_id}_{num}.oga"
file_id = message.voice.file_id
file = await bot.get_file(file_id)
file_path = file.file_path
await bot.download_file(file_path, audio)
data, samplerate = sf.read(audio)
os.remove(audio)
audio = f"../data/voices/{user_id}_{num}.wav"
sf.write(audio, data, samplerate)
af = sr.AudioFile(audio)
r = sr.Recognizer()
with af as source:
r.pause_threshold = 100
source = r.listen(source)
try:
query = r.recognize_google(source, language='ru-RU')
os.remove(audio)
group_id = message.chat.id
unsigned = re.sub(r'[^\w\s]', '', query.lower()).split()
first_form = [morph.parse(i)[0].normal_form for i in unsigned]
names = [_ for _ in first_form if _ in list(map(lambda x: x[0], dg.all_names(du.get_group_id(group_id))))]
if names:
await message.reply(notice(names, False, du.get_group_id(group_id), message.from_user.id))
return
except Exception:
try:
os.remove(audio)
except Exception:
pass
# СТИКЕРЫ
@router.message(F.content_type == ContentType.STICKER)
async def stick(message: Message):
if message.chat.id < 0:
upd_stat(message.from_user.id, message.chat.id, 6, message.from_user.first_name, True)
# ТЕКСТОВЫЕ ИВЕНТЫ
@router.message(F.content_type == ContentType.TEXT)
async def send_events(message: Message):
group_id, user_id, name = message.chat.id, message.from_user.id, message.from_user.first_name
# ОБНОВЛЕНИЕ СТАТИСТИКИ
if message.chat.id < 0:
upd_stat(user_id, group_id, 1, name) # СООБЩЕНИЙ
if len(message.text) > 1 and message.text[0] == '/':
upd_stat(user_id, group_id, 3, name) # КОМАНД
if message.reply_to_message:
upd_stat(user_id, group_id, 2, name) # ОТВЕТОВ НА СООБЩЕНИЯ
# ПЕРЕМЕННЫЕ
low_mes = message.text.lower()
words = message.text.split()
unsigned = re.sub(r'[^\w\s]', '', low_mes).split()
first_form = [morph.parse(i)[0].normal_form for i in unsigned]
if message.chat.id < 0:
names = [_ for _ in first_form if _ in list(map(lambda x: x[0], dg.all_names(du.get_group_id(group_id))))]
if len(words) >= 2:
# ПОЛЕЗНЫЕ ФУНКЦИИ
if len(words) == 5 and "число от" in low_mes:
try:
num1, num2 = int(low_mes.split()[2]), int(low_mes.split()[4])
await message.answer(
text=f"Число *[ {random.randint(num1, num2)} ]*"
)
except ValueError:
pass
return
if unsigned[0] == 'переведи':
if "переведи - " in low_mes:
await message.answer(lang_form([words[_] for _ in range(len(words)) if _ > 1]))
elif f"переведи ({unsigned[1]}) - " in low_mes:
if len(unsigned[1]) == 1:
await message.answer(lang_form([words[_] for _ in range(len(words)) if _ > 2], unsigned[1]))
return
if unsigned[0] == 'переверни':
if "переверни - " in low_mes:
await message.answer(revers(message.text[12:], True))
elif "переверни полностью - " in low_mes:
await message.answer(revers(message.text[22:], False))
return
if unsigned[0] == 'озвучь' and "озвучь - " in low_mes:
text_to_voice = message.text[9:]
tts = gTTS(text_to_voice, lang='ru')
tts.save('../data/voices/voice.ogg')
await bot.send_voice(
chat_id=group_id,
voice=FSInputFile('../data/voices/voice.ogg'),
caption=f"*{text_to_voice}*"
)
os.remove('../data/voices/voice.ogg')
return
# РАНДОМ ИВЕНТЫ
if "подраться" == words[0].lower() and "с" == words[1].lower():
text = " ".join([words[i] for i in range(len(words)) if i > 1])
if random.randint(0, 1) == 0:
await message.answer_photo(
photo=FSInputFile(f"../data/fight/({random.randint(1, 8)}).jpg"),
caption=f"{message.from_user.first_name}, ты был унижен {text.title()}"
f", с помощью {base.VAR_LOSE[random.randint(0, 3)]}"
)
else:
await message.answer_photo(
photo=FSInputFile(f"../data/fight/({random.randint(1, 8)}).jpg"),
caption=f"{message.from_user.first_name}, ты победил в драке "
f"с {text.title()}, {base.VAR_WIN[random.randint(0, 1)]}"
)
# ИВЕНТ ВЗАИМОДЕЙСТВИЯ
for word in base.TMOK_LIST:
if word in low_mes:
lst = [words[i] for i in range(len(words)) if i != 0]
text = " ".join(lst)
slv = morph.parse(words[0].lower())[0]
await message.answer_photo(
photo=FSInputFile(f"../data/tmok/({random.randint(1, 4)}).jpg"),
caption=f"{message.from_user.first_name} "
f"{slv.inflect({'past', 'sing', 'indc'}).word} {text}"
)
for word in base.KILL_LIST:
if word in low_mes:
lst = [words[i] for i in range(len(words)) if i != 0]
text = " ".join(lst)
slv = morph.parse(words[0].lower())[0]
await message.answer_photo(
photo=FSInputFile(f"../data/kill/({random.randint(1, 6)}).jpg"),
caption=f"{message.from_user.first_name} "
f"{slv.inflect({'past', 'sing', 'indc'}).word} {text}"
)
if (unsigned[0] in base.QUAT_LIST[0] and
unsigned[1] in base.QUAT_LIST[1] and
unsigned[2] in base.QUAT_LIST[2]):
try:
word = requests.get('http://fucking-great-advice.ru/api/random').json()
await message.reply(word["text"])
except:
pass
return
if message.chat.id < 0:
# УПОМИНАНИЯ ПО ИМЕНАМ
if names:
try:
await message.reply(notice(names, False, du.get_group_id(group_id), user_id))
except Exception:
pass
return
# ПЕРЕВОДЧИК СЛОВ
if (checker([i for i in low_mes], words, group_id, user_id, name.lower()) == len(low_mes) and
not any([engl_dict.check(i) for i in unsigned if len(i) > 1])):
await message.reply(
f"[{message.from_user.first_name}](tg://user_id?id={user_id}) *>* {translator(words)}"
)
return

21
code/init.py Normal file
View file

@ -0,0 +1,21 @@
from aiogram import Bot, Dispatcher
from aiogram.enums.parse_mode import ParseMode
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.bot import DefaultBotProperties
import base, enchant, pymorphy3
bot = Bot(token=base.TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.MARKDOWN))
dp = Dispatcher(storage=MemoryStorage())
morph = pymorphy3.MorphAnalyzer()
engl_dict = enchant.Dict("en_US")
import sql
db = sql.Base('../db/base.db')
du = sql.User('../db/users.db')
dg = sql.Group('../db/groups.db')
dm = sql.Month('../db/month.db')

View file

@ -63,8 +63,7 @@ def notice(name, all_users, group_id, author):
if all_users: if all_users:
name = dg.user_name(name, group_id) name = dg.user_name(name, group_id)
usr = ["<a href=\""+'tg://user?id='+str(ids[i])+"\">"+names[i].title()+"</a>" for i in range(len(names)) usr = [f"[{names[i].title()}](tg://user?id={str(ids[i])})" for i in range(len(names)) if names[i] != name.lower()]
if names[i] != name.lower()]
usr.append(f'{usr[-2]} и {usr[-1]}') usr.append(f'{usr[-2]} и {usr[-1]}')
del usr[-2], usr[-2] del usr[-2], usr[-2]
return f'{", ".join(usr)} вас вызывает {name.title()}' return f'{", ".join(usr)} вас вызывает {name.title()}'
@ -75,13 +74,12 @@ def notice(name, all_users, group_id, author):
no_copy.append(i) no_copy.append(i)
if len(no_copy) > 1: # ПЕРЕПИСАТЬ КОД ГАВНА КУСОК if len(no_copy) > 1: # ПЕРЕПИСАТЬ КОД ГАВНА КУСОК
usr = ["<a href=\""+'tg://user?id='+str(ids[names.index(_)])+"\">"+_.title()+"</a>" for _ in no_copy usr = [f"[{_.title()}](tg://user?id={str(ids[names.index(_)])})" for _ in no_copy if int(author) != ids[names.index(_)]]
if int(author) != ids[names.index(_)]]
usr.append(f'{usr[-2]} и {usr[-1]}') usr.append(f'{usr[-2]} и {usr[-1]}')
del usr[-2], usr[-2] del usr[-2], usr[-2]
return f"{', '.join(usr)} вас упомянули)" return f"{', '.join(usr)} вас упомянули)"
else: else:
usr = "<a href=\""+'tg://user?id='+str(ids[names.index(no_copy[0])])+"\">"+no_copy[0].title()+"</a>" usr = f"[{no_copy[0].title()}](tg://user?id={str(ids[names.index(no_copy[0])])})"
return f"{usr}, тебя упомянули)" return f"{usr}, тебя упомянули)"

BIN
data/voices/1_7047.oga Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
- - Здраствуйте! Это АБ+ОБОТ, который поможет вам комфортнее провести время в чате. Бот может упомянуть человека, если его имя было упомянуто в сообщении, вызвать всех участников чата, перевести слово с транслита на русский и с русского на кирпичный, а также имеет +уйму интересных функций описаных ниже! - Приятного использования! - -

View file

@ -1,3 +0,0 @@
libraries:
pip install random2, pymorphy2, requests, emoji, re, aiogram

34
requirements.txt Normal file
View file

@ -0,0 +1,34 @@
# Core Framework Dependencies
aiogram==3.10.0
asyncio-mqtt==0.16.1
# Database Management
sqlite3
# Natural Language Processing
pymorphy3==1.2.1
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