diff --git a/main.py b/main.py index 0575457..c06b3ba 100644 --- a/main.py +++ b/main.py @@ -3,6 +3,7 @@ from tortoise import Tortoise from olgram.router import dp from olgram.settings import TORTOISE_ORM +from server.custom import init_redis import olgram.commands.bots # noqa: F401 import olgram.commands.start # noqa: F401 @@ -25,6 +26,7 @@ def main(): """ loop = asyncio.get_event_loop() loop.run_until_complete(init_database()) + loop.run_until_complete(init_redis()) loop.create_task(dp.start_polling()) loop.create_task(server_main().start()) diff --git a/olgram/settings.py b/olgram/settings.py index 4325a5c..a78a6e0 100644 --- a/olgram/settings.py +++ b/olgram/settings.py @@ -46,6 +46,14 @@ class ServerSettings(AbstractSettings): def app_port(cls) -> int: return 80 + @classmethod + def redis_path(cls) -> str: + """ + Путь до БД redis + :return: + """ + return cls._get_env("REDIS_PATH") + class BotSettings(AbstractSettings): @classmethod diff --git a/server/custom.py b/server/custom.py index be5ca70..fca37a8 100644 --- a/server/custom.py +++ b/server/custom.py @@ -1,19 +1,62 @@ from aiogram import Bot as AioBot, Dispatcher from aiogram.dispatcher.webhook import WebhookRequestHandler from aiogram.dispatcher.webhook import SendMessage +from aiogram import exceptions from aiogram import types from contextvars import ContextVar from aiohttp.web_exceptions import HTTPNotFound +import aioredis +import typing as ty +from olgram.settings import ServerSettings + + from olgram.models.models import Bot db_bot_instance: ContextVar[Bot] = ContextVar('db_bot_instance') +_redis: ty.Optional[aioredis.Redis] = None + + +async def init_redis(): + global _redis + _redis = await aioredis.create_redis_pool(ServerSettings.redis_path()) + + +def _message_unique_id(bot_id: int, message_id: int) -> str: + return f"{bot_id}_{message_id}" + async def message_handler(message, *args, **kwargs): + bot = db_bot_instance.get() + if message.text and message.text.startswith("/start"): # На команду start нужно ответить, не пересылая сообщение никуда return SendMessage(chat_id=message.chat.id, - text=db_bot_instance.get().start_text) + text=bot.start_text) + + super_chat_id = await bot.super_chat_id() + + if message.chat.id != super_chat_id: + # Это обычный чат: сообщение нужно переслать в супер-чат + new_message = await message.forward(super_chat_id) + await _redis.set(_message_unique_id(bot.pk, new_message.message_id), message.chat.id) + else: + # Это супер-чат + if message.reply_to_message: + # Ответ из супер-чата переслать тому пользователю, + chat_id = await _redis.get(_message_unique_id(bot.pk, message.reply_to_message.message_id)) + if not chat_id: + chat_id = message.reply_to_message.forward_from_chat + if not chat_id: + return SendMessage(chat_id=message.chat.id, text="Невозможно переслать сообщение: автор не найден") + chat_id = int(chat_id) + try: + await message.copy_to(chat_id) + except exceptions.MessageError: + await message.reply("Невозможно переслать сообщение: возможно, автор заблокировал бота") + return + else: + await message.forward(super_chat_id) class CustomRequestHandler(WebhookRequestHandler):