forked from amirho3inf/aiogram-structured
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
executable file
·190 lines (142 loc) · 4.65 KB
/
bot.py
File metadata and controls
executable file
·190 lines (142 loc) · 4.65 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/usr/bin/env python3
import os
import re
import click
import inspect
import importlib
from aiogram import Bot, Dispatcher, executor
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.contrib.fsm_storage.redis import RedisStorage
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from redis import Redis
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.jobstores.redis import RedisJobStore
MAIN_MODULE_NAME = os.path.basename(__file__)[:-3]
try:
from config import API_TOKEN, SKIP_UPDATES, PARSE_MODE, PROXY, \
PROXY_AUTH, DATABASE_URL, REDIS_URL, HANDLERS_DIR, MODELS_DIR, \
CONTEXT_FILE, ENABLE_APSCHEDULER, SUDOERS, HANDLERS
except ModuleNotFoundError:
click.echo(click.style(
"Config file not found!\n"
"Please create config.py file according to config.py.example",
fg='bright_red'))
exit()
except ImportError as err:
var = re.match(r"cannot import name '(\w+)' from", err.msg).groups()[0]
click.echo(click.style(
f"{var} is not defined in the config file",
fg='bright_red'))
exit()
class _SQLAlchemy(object):
def __init__(self, db_url):
self.engine = create_engine(db_url)
self.Model = declarative_base(self.engine)
self.sessionmaker = sessionmaker(bind=self.engine)
self.session = scoped_session(self.sessionmaker)
self.Model.query = self.session.query_property()
@property
def metadata(self):
return self.Model.metadata
class _Context(object):
def __init__(self, _context_obj):
self._context_obj = _context_obj
def __getattr__(self, name):
r = getattr(self._context_obj, name, None)
if r is None:
return f"< {name} > not defined in context."
frame = inspect.currentframe()
try:
caller_locals = frame.f_back.f_locals
r = r.format_map(caller_locals)
finally:
del frame
return r
class _NotDefinedModule(Exception):
pass
class _NoneModule(object):
def __init__(self, module_name, attr_name):
self.module_name = module_name
self.attr_name = attr_name
def __getattr__(self, attr):
msg = f"You are using {self.module_name} while the {self.attr_name} is not set in config"
raise _NotDefinedModule(msg)
def _get_bot_obj():
bot = Bot(
token=API_TOKEN,
proxy=PROXY,
proxy_auth=PROXY_AUTH,
parse_mode=PARSE_MODE
)
return bot
def _get_redis_obj():
if REDIS_URL is not None:
redis = Redis.from_url(
REDIS_URL,
encoding='utf-8',
decode_responses=True
)
else:
redis = _NoneModule("redis", "REDIS_URL")
return redis
def _get_dp_obj(bot, redis):
if not isinstance(redis, _NoneModule):
cfg = redis.connection_pool.connection_kwargs
storage = RedisStorage(
host=cfg.get("host"),
port=cfg.get("port"),
db=cfg.get("db"),
password=cfg.get("password")
)
else:
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
return dp
def _get_db_obj():
if DATABASE_URL is not None:
db = _SQLAlchemy(DATABASE_URL)
else:
db = _NoneModule("db", "DATABASE_URL")
return db
def _get_text_obj():
if CONTEXT_FILE is not None:
context = importlib.import_module(CONTEXT_FILE)
text = _Context(context)
else:
text = _NoneModule("text", "CONTEXT_FILE")
return text
def _get_scheduler_obj(redis):
job_defaults = {
"misfire_grace_time": 3600
}
if not isinstance(redis, _NoneModule):
cfg = redis.connection_pool.connection_kwargs
jobstores = {
'default': RedisJobStore(host=cfg.get("host"),
port=cfg.get("port"),
db=cfg.get("db"),
password=cfg.get("password"))
}
else:
jobstores = {
"default": MemoryJobStore()
}
scheduler = AsyncIOScheduler(
jobstores=jobstores,
job_defaults=job_defaults
)
return scheduler
__all__ = ["bot", "dp", "db", "redis", "text", "scheduler"]
if __name__ == MAIN_MODULE_NAME:
bot = _get_bot_obj()
redis = _get_redis_obj()
dp = _get_dp_obj(bot, redis)
db = _get_db_obj()
text = _get_text_obj()
scheduler = _get_scheduler_obj(redis)
if __name__ == '__main__':
from cli import cli
cli()