Some refactoring and started second bot

This commit is contained in:
2023-11-27 22:04:50 +03:00
parent b14eeb8342
commit a848733422
8 changed files with 108 additions and 63 deletions

View File

@@ -1,3 +1,5 @@
TOKEN=
PROXY_TOKEN=
API_URL="http://localhost:3000"

View File

@@ -1,6 +1,6 @@
from typing import Any, List
from typing import List
from aiogram import Bot, F, Router, types
from aiogram import Bot, F, types
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.utils.media_group import MediaGroupBuilder
@@ -9,6 +9,7 @@ import neuroapi.types as neuroTypes
from handlers.filters.new_post import (ChangePosts, NewPostFilter,
NewSoloPostFilter)
from handlers.filters.reply_to_user import ReplyToUser
from handlers.handler import Handler
from handlers.middlewares.user import AdminMiddleware
from handlers.states.change_post import ChangePost
from neuroapi import neuroapi
@@ -23,13 +24,9 @@ def get_post_info(post: neuroTypes.Post, post_id: int) -> str:
return s
class Admin_commands:
bot: Bot
router: Router
class AdminCommands(Handler):
def __init__(self, bot: Bot) -> None:
self.bot = bot
self.router = Router()
super().__init__(bot)
self.router.message.middleware(AdminMiddleware())
@self.router.message(NewPostFilter())
@@ -210,9 +207,4 @@ class Admin_commands:
except Exception as e:
print(e)
def __call__(self, *args: Any, **kwds: Any) -> Router:
return self.router
def setup(bot: Bot) -> Router:
return Admin_commands(bot)()

16
handlers/handler.py Normal file
View File

@@ -0,0 +1,16 @@
from typing import Any
from aiogram import Bot, Router
class Handler:
bot: Bot
router: Router
def __init__(self, bot: Bot) -> None:
assert isinstance(bot, Bot)
self.bot = bot
self.router = Router()
def __call__(self) -> Router:
return self.router

View File

@@ -1,19 +1,16 @@
from typing import Any, List
from typing import List
from aiogram import Bot, F, Router, types
from aiogram import Bot, F, types
from handlers.handler import Handler
from neuroapi import neuroapi
from neuroapi.types import Admin as AdminType
class User_commands:
bot: Bot
router: Router
class UserCommands(Handler):
def __init__(self, bot: Bot) -> None:
self.bot = bot
self.router = Router()
super().__init__(bot)
@self.router.message(F.chat.type == 'private')
async def forward_post(message: types.Message):
@@ -27,9 +24,3 @@ class User_commands:
canReply = False
await message.reply('Ваше сообщение было отправлено администраторам'+('' if canReply else '\nНо они не смогут вам ответить из-за ваших настроек конфиденциальности.'))
def __call__(self, *args: Any, **kwds: Any) -> Router:
return self.router
def setup(bot: Bot) -> Router:
return User_commands(bot)()

69
main.py
View File

@@ -1,37 +1,68 @@
import asyncio
import logging
import os
import signal
import sys
from os.path import dirname, join
# import aioschedule as schedule
import dotenv
from aiogram import Bot, Dispatcher, types
from aiogram.filters import CommandStart
from aiogram import Bot, Dispatcher
dotenv.load_dotenv()
from handlers.admin_commands import AdminCommands
from handlers.handler import Handler
from handlers.user_commands import UserCommands
from neuroapi.config import Config
token = os.getenv('TOKEN')
bot = Bot(token)
dp = Dispatcher()
class NeuroApiBot:
bot: Bot
dp: Dispatcher
@dp.message(CommandStart())
async def start_message(message: types.Message):
await message.answer('Добро пожаловать в бота ')
_instances = {}
handlers_dir = join(dirname(__file__), 'handlers')
def __init__(self, token: str) -> None:
self.bot = Bot(token)
self.dp = Dispatcher()
self._instances
for filename in os.listdir(handlers_dir):
if filename.endswith('.py'):
module_name = filename[:-3]
setup = __import__(f"handlers.{module_name}", locals(), globals(), ['setup']).setup
dp.include_router(setup(bot))
def __new__(cls, token: str) -> 'NeuroApiBot':
assert isinstance(token, str)
if token not in cls._instances:
cls._instances[token] = super(NeuroApiBot, cls).__new__(cls)
return cls._instances[token]
def include_router(self, *routerClasses: Handler) -> None:
for routerClass in routerClasses:
assert issubclass(routerClass, Handler)
self.dp.include_routers(routerClass(self.bot)())
async def start(self, skip_updates=True):
await self.dp.start_polling(self.bot, skip_updates=skip_updates)
async def delay_bot()->None:
if Config().token is None:
print('Delay bot needs token in environment')
return
bot = NeuroApiBot(Config().token)
bot.include_router(AdminCommands, UserCommands)
await bot.start()
async def proxy_bot()->None:
if Config().proxy_token is None:
print('Proxy bot needs token in environment')
return
bot = NeuroApiBot(Config().proxy_token)
bot.include_router()
await bot.start()
async def main() -> None:
await dp.start_polling(bot, skip_updates=True)
tasks = [asyncio.create_task(delay_bot()), asyncio.create_task(proxy_bot())]
await asyncio.gather(*tasks)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
loop.add_signal_handler(getattr(signal, signame), loop.stop)
try:
asyncio.run(main())
except KeyboardInterrupt:
pass

View File

@@ -1,21 +1,15 @@
import os
import tomllib
from typing import List, Self, TypeVar
from typing import List, Optional
from attr import dataclass
from dotenv import load_dotenv
from neuroapi.types import Singleton
from .types._helpers import *
class _Singleton:
_instances = {}
def __new__(cls) -> Self:
if cls not in cls._instances:
cls._instances[cls] = super(_Singleton, cls).__new__(cls)
return cls._instances[cls]
@dataclass
class Settings:
time: List[str]
@@ -31,9 +25,11 @@ class Settings:
result['time'] = from_list(from_str, self.time)
return result
class Config(_Singleton):
class Config(Singleton):
api_url: str
settings: Settings
token: Optional[str]
proxy_token: Optional[str]
def __init__(self):
load_dotenv(os.path.join(os.path.dirname(__file__), '..', '.env'))
if not os.path.exists(os.path.join(os.path.dirname(__file__), '..', 'settings.toml')): raise Exception('Settings.toml must be in root folder')
@@ -41,3 +37,9 @@ class Config(_Singleton):
settings = tomllib.load(f)
self.settings = Settings.from_dict(settings)
self.api_url = os.environ.get('API_URL')
self.token = os.environ.get('TOKEN')
if self.token == '':
self.token = None
self.proxy_token = os.environ.get('PROXY_TOKEN')
if self.proxy_token == '':
self.proxy_token = None

View File

@@ -1,4 +1,5 @@
from ._post import Post
from ._image import Image
from ._admin import Admin
from ._image import Image
from ._post import Post
from ._singleton import Singleton
from ._user import User

View File

@@ -0,0 +1,10 @@
from typing import Self
class Singleton:
_instances = {}
def __new__(cls, *args, **kwargs) -> Self:
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__new__(cls)
return cls._instances[cls]