/AiogramMailingMenu

Multifunctional modular mailing menu for bots on aiogram v3.x.x

Primary LanguagePython

Без имени-1

Мультифункциональное модульное меню рассылки для ботов на aiogram v3.x.x

Russian

О меню

Мультифункциональное модульное меню рассылки для aiogram v3.x.x с полной поддержкой форматирования, гибкой настройкой и поддержкой различных медиа

Преимущества

  • Полная поддержка форматирования Markdown в Telegram
  • Поддержка 7 типов медиа
    • Фотография
    • Видеозапись
    • Аудиозапись
    • GIF-изображение
    • Голосовое сообщение
    • Видеосообщение
    • Документ
  • Полная автономность – вся информация о рассылке хранится в отдельной базе данных PostgreSQL или SQLite, в зависимости от вашего выбора
  • Дополнительные параметры рассылки автоматически подстраиваются под тип файла, используемого в рассылке
  • Отслеживание информации о запущенной рассылке в режиме реального времени

Установка

1. Клонируйте этот репозиторий в свой проект.

git clone https://github.com/Belyashik2K/AiogramMailingMenu.git .

2. Установите необходимые зависимости для работы меню

pip install sqlalchemy[asyncio] aiogram

— Для работы с SQLite

pip install aiosqlite

— Для работы с PostgreSQL

pip install asyncpg

3. Откройте mailing/config.py и замените данные переменных своими, например:

admin_menu_data = 'back_to_admin' # Callback data для кнопки «↪️ Назад» (возврат в админ-меню)
mailing_button_data = 'mailing' # Callback data для открытия меню рассылки
is_postgres = True # Если вы хотите использовать PostgreSQL + asyncpg — оставьте все как есть, но если вы хотите использовать SQLite + aiosqlite — установите параметр в значение False.
...
DB_INSTANCE = database # Объект класса вашей базы данных, в котором хранятся пользовательские данные (user_ids) (импортирован из другого файла).
BOT_INSTANCE = bot # Объект вашего бота (импортирован из другого файла)

4. Откройте класс для взаимодействия с базой данных и добавьте в него 3 функции. Имя функций должно строго соответствовать названию в примере.

  • get_users_count()
# Example
async def get_users_count(self) -> int:
    """Получение количества пользователей в базе данных
    
    Returns:
        int: Количество пользователей в базе данных"""
    async with self.session() as session:
        stmt = select(User.user_id)
        result = await session.execute(stmt)
        return len(result.fetchall())
  • get_users_list()
# Example
async def get_users_list(self) -> list[int]:
    """Получение всех user_id из базы данных
    
    Returns:
        list[int]: Список всех user_id из базы данных"""
    async with self.session() as session:
        stmt = select(User.user_id)
        result = await session.execute(stmt)
        return [user_id[0] for user_id in result]
  • get_admins()
# Example
async def get_admins(self) -> list[int]:
    """Получение списка всех user_id администраторов бота

    Если информация об администраторах хранится не в базе данных, вы можете использовать следующую реализацию:
        async def get_admins(self) -> list[int]:
            return [123456789, 987654321]
    
    Returns:
        list[int]: Список всех user_id администраторов бота"""
    async with self.session() as session:
        stmt = select(User.user_id).where(User.is_admin == True)
        result = await session.execute(stmt)
        return [user_id[0] for user_id in result]

5. Откройте свой основной файл и импортируйте все функции из модуля рассылки.

from mailing import *

6. Подключите роутер рассылки к диспетчеру

import asyncio

from initialization import dp, bot
from mailing import *

async def main():
    dp.include_router(mailing_router)
    # ...
    # Здесь Ваш код...
    await dp.start_polling(bot)

if __name__ == '__main__':
    asyncio.run(main())

7. Создайте кнопку с данными, которые вы установили в mailing/config.py, и создайте обработчик, который обрабатывает кнопку возврата в админ-меню.

@user_router.message(Command('admin'))
async def admin_menu(message: types.Message):
  markup = InlineKeyboardBuilder()
  markup.button(text="Mailing", callback_data="mailing")
  await message.answer(text="Админ-меню. Но только с одной кнопкой.", reply_markup=markup.as_markup())

@user_router.callback_query(F.data=="back_to_admin")
async def back_to_admin_menu(call: types.CallbackQuery):
  markup = InlineKeyboardBuilder()
  markup.button(text="Mailing", callback_data="mailing")
  await call.message.edit_text(text="Админ-меню. Но только с одной кнопкой.", reply_markup=markup.as_markup())
  1. Если все шаги выполнены правильно, значит меню рассылки успешно установлено.

English

About menu

Modular mailing menu for Aiogram v3.x.x with formatting support, flexible configuration and support for various media

Advantages

  • Full support for Markdown Telegram formatting
  • Support for 7 types of media
    • Photo
    • Video
    • Audio
    • GIF
    • Voice
    • Video note
    • Document
  • Full autonomy - all information about the mailing is stored in a separate PostgreSQL or SQLite database
  • Additional mailing options are automatically adjusted to the type of file used in the mailing
  • Tracking information about a launched mailing in real-time

Installatiion

1. Clone this repo to your own project

git clone https://github.com/Belyashik2K/AiogramMailingMenu.git .

2. Install the necessary dependencies for the menu to work

pip install sqlalchemy[asyncio] aiogram

— For SQLite database

pip install aiosqlite

— For PostgreSQL database

pip install asyncpg

3. Open mailing/config.py and replace vars data with your own, example

admin_menu_data = 'back_to_admin' # Callback data for "↪️ Назад" button (back to admin menu)
mailing_button_data = 'mailing' # Callback data for mailing menu button
is_postgres = True # If you wanna use PostgreSQL + asyncpg - leave this as is, but if you wanna use SQLite + aiosqlite - set parameter to False
...
DB_INSTANCE = database # The object of your database class that stores user data (user_ids) (imported from another file)
BOT_INSTANCE = bot # The object of your bot (imported from another file)

4. Open your class for interact with database and add 3 functions into it. The name of the functions must strictly correspond to the name in the example.

  • get_users_count()
# Example
async def get_users_count(self) -> int:
    """Get users count in database
    
    Returns:
        int: Users count"""
    async with self.session() as session:
        stmt = select(User.user_id)
        result = await session.execute(stmt)
        return len(result.fetchall())
  • get_users_list()
# Example
async def get_users_list(self) -> list[int]:
    """Get all users' ids
    
    Returns:
        list[int]: List of users' ids"""
    async with self.session() as session:
        stmt = select(User.user_id)
        result = await session.execute(stmt)
        return [user_id[0] for user_id in result]
  • get_admins()
# Example
async def get_admins(self) -> list[int]:
    """Get all ID of admins

    If info about admins is not in database, you may use this method:
        async def get_admins(self) -> list[int]:
            return [123456789, 987654321]
    
    Returns:
        list[int]: List of admins' ids"""
    async with self.session() as session:
        stmt = select(User.user_id).where(User.is_admin == True)
        result = await session.execute(stmt)
        return [user_id[0] for user_id in result]

5. Open your main file and import all functions from mailing

from mailing import *

6. Include mailing router in dispatcher

import asyncio

from initialization import dp, bot
from mailing import *

async def main():
    dp.include_router(mailing_router)
    # ...
    # Here is your own code
    await dp.start_polling(bot)

if __name__ == '__main__':
    asyncio.run(main())

7. Create inline button with data, which you set in_ mailing/config.py_ and create handler which handle callback of exit button

@user_router.message(Command('admin'))
async def admin_menu(message: types.Message):
  markup = InlineKeyboardBuilder()
  markup.button(text="Mailing", callback_data="mailing")
  await message.answer("Admin-menu. But with only one button.", reply_markup=markup.as_markup())

@user_router.callback_query(F.data=="back_to_admin")
async def back_to_admin_menu(call: types.CallbackQuery):
  markup = InlineKeyboardBuilder()
  markup.button(text="Mailing", callback_data="mailing")
  await call.message.edit_text(text="Admin-menu. But with only one button.", reply_markup=markup.as_markup())

8. If all the steps have been completed, then the mailing menu has been successfully installed.