1
0
mirror of https://github.com/civsocit/olgram.git synced 2026-04-18 16:29:37 +00:00

Пример Instance бота, разные команды

This commit is contained in:
mihalin
2021-06-29 15:29:41 +03:00
parent 4e70ebf32c
commit d738da2fa9
15 changed files with 221 additions and 33 deletions

46
olgram/bot/bot.py Normal file
View File

@@ -0,0 +1,46 @@
from aiogram import types, Bot as AioBot
from aiogram.dispatcher import FSMContext
from aiogram.utils.callback_data import CallbackData
from textwrap import dedent
from olgram.utils.router import Router
from olgram.utils.mix import try_delete_message
from olgram.models.models import Bot, User
router = Router()
# Пользователь выбрал бота
select_bot = CallbackData('bot_select', 'bot_id')
# Пользователь выбрал, что хочет сделать со своим ботом
bot_operation = CallbackData('bot_operation', 'operation')
@router.callback_query_handler(select_bot.filter())
async def select_bot_callback(call: types.CallbackQuery, callback_data: dict, state: FSMContext):
"""
Пользователь выбрал бота для редактирования
"""
bot_id = callback_data["bot_id"]
bot = await Bot.get_or_none(id=bot_id)
if not bot or (await bot.owner).telegram_id != call.from_user.id:
await call.answer("Такого бота нет", show_alert=True)
return
async with state.proxy() as proxy:
proxy["bot"] = bot
await try_delete_message(call.message)
keyboard = types.InlineKeyboardMarkup(row_width=2)
keyboard.insert(types.InlineKeyboardButton(text="Текст", callback_data=bot_operation.new(operation="text")))
keyboard.insert(types.InlineKeyboardButton(text="Чат", callback_data=bot_operation.new(operation="chat")))
keyboard.insert(types.InlineKeyboardButton(text="Удалить бот", callback_data=bot_operation.new(operation="delete")))
keyboard.insert(types.InlineKeyboardButton(text="<<Вернуться к списку ботов",
callback_data=bot_operation.new(operation="back")))
await AioBot.get_current().send_message(call.message.chat.id, dedent(f"""
Управление ботом @{bot.name}.
Если у вас возникли вопросы по настройке бота, то посмотрите нашу справку /help.
"""), reply_markup=keyboard)

View File

@@ -5,40 +5,65 @@ import re
from textwrap import dedent
from ..utils.router import Router
from olgram.models.bot import Bot
from olgram.models.user import User
from .bot import select_bot
from olgram.models.models import Bot, User
from olgram.settings import OlgramSettings
router = Router()
token_pattern = r'[0-9]{8,10}:[a-zA-Z0-9_-]{35}'
@router.message_handler(commands=["my_bots"])
@router.message_handler(commands=["mybots"], state="*")
async def my_bots(message: types.Message, state: FSMContext):
"""
Команда /mybots (список ботов)
"""
user = await User.get_or_none(telegram_id=message.from_user.id)
bots = await Bot.filter(owner=user)
if not bots:
await message.answer(dedent("""
У вас нет добавленных ботов.
Отправьте команду /add_bot, чтобы добавить бот.
Отправьте команду /addbot, чтобы добавить бот.
"""))
return
bots_str = "\n".join(["@" + bot.name for bot in bots])
await message.answer(dedent(f"""
Ваши боты:
{bots_str}
"""))
keyboard = types.InlineKeyboardMarkup(row_width=2)
for bot in bots:
keyboard.insert(types.InlineKeyboardButton(text="@" + bot.name, callback_data=select_bot.new(bot_id=bot.id)))
await message.answer("Ваши боты", reply_markup=keyboard)
@router.message_handler(commands=["add_bot"])
@router.message_handler(commands=["addbot"], state="*")
async def add_bot(message: types.Message, state: FSMContext):
await message.answer("Окей, пришли тогда токен plz")
"""
Команда /addbot (добавить бота)
"""
bot_count = await Bot.filter(user__telegram_id=message.from_user.id).count()
if bot_count > OlgramSettings.max_bots_per_user():
await message.answer("У вас уже слишком много ботов")
return
await message.answer(dedent("""
Чтобы подключить бот, вам нужно выполнить три действия:
1. Перейдите в бот @BotFather, нажмите START и отправьте команду /newbot
2. Введите название бота, а потом username бота.
3. После создания бота перешлите ответное сообщение в этот бот или скопируйте и пришлите token бота.
Важно: не подключайте боты, которые используются в других сервисах (Manybot, Chatfuel, Livegram и других).
Подробную инструкцию по созданию бота читайте здесь /help)
"""))
await state.set_state("add_bot")
@router.message_handler(state="add_bot", content_types="text", regexp="^[^/].+") # Not command
async def bot_added(message: types.Message, state: FSMContext):
"""
Пользователь добавляет бота и мы ждём от него токен
"""
token = re.findall(token_pattern, message.text)
async def on_invalid_token():
@@ -66,6 +91,7 @@ async def bot_added(message: types.Message, state: FSMContext):
try:
test_bot = AioBot(token)
test_bot_info = await test_bot.get_me()
await test_bot.session.close()
except ValueError:
return await on_invalid_token()
except Unauthorized:

View File

@@ -1,4 +1,4 @@
from aiogram import Bot, Dispatcher, executor, types
from aiogram import types
from aiogram.dispatcher import FSMContext
from textwrap import dedent
from ..utils.router import Router
@@ -9,7 +9,7 @@ router = Router()
@router.message_handler(commands=["start"], state="*")
async def start(message: types.Message, state: FSMContext):
"""
Start command handler
Команда /start
"""
await state.reset_state()
@@ -20,8 +20,8 @@ async def start(message: types.Message, state: FSMContext):
Используйте эти команды, чтобы управлять этим ботом:
/add_bot - добавить бот
/my_bots - управление ботами
/addbot - добавить бот
/mybots - управление ботами
/help - помощь
@@ -32,7 +32,7 @@ async def start(message: types.Message, state: FSMContext):
@router.message_handler(commands=["help"], state="*")
async def help(message: types.Message, state: FSMContext):
"""
Help command handler
Команда /help
"""
await message.answer(dedent("""
<todo: help here>

View File

@@ -10,3 +10,11 @@ class Bot(Model):
class Meta:
table = 'bot'
class User(Model):
id = fields.IntField(pk=True)
telegram_id = fields.IntField(index=True, unique=True)
class Meta:
table = 'user'

View File

@@ -1,9 +0,0 @@
from tortoise import Model, fields
class User(Model):
id = fields.IntField(pk=True)
telegram_id = fields.IntField(index=True, unique=True)
class Meta:
table = 'user'

45
olgram/settings.py Normal file
View File

@@ -0,0 +1,45 @@
from abc import ABC
from dotenv import load_dotenv
import os
load_dotenv()
class _Settings(ABC):
@classmethod
def _get_env(cls, parameter: str) -> str:
parameter = os.getenv(parameter, None)
if not parameter:
raise ValueError(f"{parameter} not defined in ENV")
return parameter
class OlgramSettings(_Settings):
@classmethod
def max_bots_per_user(cls) -> int:
"""
Максимальное количество ботов у одного пользователя
:return: int
"""
return 5
class BotSettings(_Settings):
@classmethod
def token(cls) -> str:
return cls._get_env("BOT_TOKEN")
class DatabaseSettings(_Settings):
@classmethod
def user(cls) -> str:
return cls._get_env("POSTGRES_USER")
@classmethod
def password(cls) -> str:
return cls._get_env("POSTGRES_PASSWORD")
@classmethod
def database_name(cls) -> str:
return cls._get_env("POSTGRES_DB")

View File

@@ -8,8 +8,8 @@ async def init_database():
# which contain models from "app.models"
await Tortoise.init(
db_url=f'postgres://{DatabaseSettings.user()}:{DatabaseSettings.password()}'
f'@localhost:5431/{DatabaseSettings.database_name()}',
modules={'models': ['olgram.models.bot', 'olgram.models.user']}
f'@localhost:5430/{DatabaseSettings.database_name()}',
modules={'models': ['olgram.models.models']}
)
# Generate the schema
await Tortoise.generate_schemas()

9
olgram/utils/mix.py Normal file
View File

@@ -0,0 +1,9 @@
from aiogram.types import Message
from aiogram.utils.exceptions import TelegramAPIError
async def try_delete_message(message: Message):
try:
await message.delete()
except TelegramAPIError:
pass