mirror of
https://github.com/MrSedan/neuro-reply-bot-reworked.git
synced 2026-01-14 13:39:42 +03:00
Some refactoring and started second bot
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
TOKEN=
|
||||
|
||||
PROXY_TOKEN=
|
||||
|
||||
API_URL="http://localhost:3000"
|
||||
@@ -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
16
handlers/handler.py
Normal 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
|
||||
@@ -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
69
main.py
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
10
neuroapi/types/_singleton.py
Normal file
10
neuroapi/types/_singleton.py
Normal 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]
|
||||
Reference in New Issue
Block a user