forked from itisnotyourenv/questions-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot.py
120 lines (90 loc) · 3.47 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import asyncio
import logging
import betterlogging as bl
from aiogram import Bot, Dispatcher
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.fsm.storage.redis import RedisStorage, DefaultKeyBuilder
from aiogram.types import BotCommand, BotCommandScopeDefault
from tgbot.config import load_config, Config
from tgbot.handlers import routers_list
from tgbot.middlewares.config import ConfigMiddleware
from tgbot.middlewares.database import DatabaseMiddleware
from infrastructure.database.setup import create_session_pool, create_engine
from tgbot.services import broadcaster
async def on_startup(bot: Bot, admin_ids: list[int]):
await broadcaster.broadcast(bot, admin_ids, "Бот був запущений")
def register_global_middlewares(dp: Dispatcher, config: Config, session_pool=None):
"""
Register global middlewares for the given dispatcher.
Global middlewares here are the ones that are applied to all the handlers (you specify the type of update)
:param dp: The dispatcher instance.
:type dp: Dispatcher
:param config: The configuration object from the loaded configuration.
:param session_pool: Optional session pool object for the database using SQLAlchemy.
:return: None
"""
middleware_types = [
ConfigMiddleware(config),
DatabaseMiddleware(session_pool),
]
for middleware_type in middleware_types:
dp.message.outer_middleware(middleware_type)
dp.callback_query.outer_middleware(middleware_type)
def setup_logging():
"""
Set up logging configuration for the application.
This method initializes the logging configuration for the application.
It sets the log level to INFO and configures a basic colorized log for
output. The log format includes the filename, line number, log level,
timestamp, logger name, and log message.
Returns:
None
Example usage:
setup_logging()
"""
log_level = logging.INFO
bl.basic_colorized_config(level=log_level)
logging.basicConfig(
level=logging.INFO,
format="%(filename)s:%(lineno)d #%(levelname)-8s [%(asctime)s] - %(name)s - %(message)s",
)
logger = logging.getLogger(__name__)
logger.info("Starting bot")
def get_storage(config):
"""
Return storage based on the provided configuration.
Args:
config (Config): The configuration object.
Returns:
Storage: The storage object based on the configuration.
"""
if config.tg_bot.use_redis:
return RedisStorage.from_url(
config.redis.dsn(),
key_builder=DefaultKeyBuilder(with_bot_id=True, with_destiny=True),
)
else:
return MemoryStorage()
async def main():
setup_logging()
config = load_config(".env")
storage = get_storage(config)
bot = Bot(token=config.tg_bot.token, parse_mode="HTML")
dp = Dispatcher(storage=storage)
dp.include_routers(*routers_list)
await bot.set_my_commands(
[
BotCommand(command="/start", description="Ссылка"),
],
scope=BotCommandScopeDefault(),
)
engine = create_engine(config.db, echo=True)
session_pool = create_session_pool(engine)
register_global_middlewares(dp, config, session_pool)
await on_startup(bot, config.tg_bot.admin_ids)
await dp.start_polling(bot)
if __name__ == "__main__":
try:
asyncio.run(main())
except (KeyboardInterrupt, SystemExit):
logging.error("Бот був вимкнений!")