1
- import asyncio
2
- import i18n
3
1
import logging
4
2
import settings
5
3
6
4
from aiogram import Bot
7
5
from aiogram import Dispatcher
8
6
from aiogram .contrib .fsm_storage .memory import MemoryStorage
9
- from aiogram .dispatcher .filters .state import State
10
- from aiogram .dispatcher .filters .state import StatesGroup
11
7
from aiogram .utils import executor
12
8
from aiogram .types .message import ParseMode
13
9
14
- from scraper import fetch_delivery_price
15
- from utils import Message
16
- from utils import is_float
17
10
18
- logging . basicConfig ( level = logging . INFO )
11
+ class TelegramBot :
19
12
20
- # Initialize bot and dispatcher
21
- bot = Bot (settings .TOKEN , parse_mode = ParseMode .MARKDOWN_V2 )
22
- storage = MemoryStorage ()
23
- dp = Dispatcher (bot , storage = storage )
24
-
25
-
26
- # States for "start" command
27
- class Form (StatesGroup ):
28
- address = State ()
29
- max_price = State ()
30
-
31
-
32
- async def _poll_price (message , data ):
33
- address = data ['address' ]
34
- max_price = data ['max_price' ]
35
- state = None
36
- # Poll two hours at max
37
- for _ in range (20 ):
38
- result = await asyncio .gather (fetch_delivery_price (address ))
39
- state = dp .current_state ()
40
- data = await state .get_data ()
41
- if not data ['poll_price' ]:
42
- break
43
- price = result [0 ]
44
- if not price :
45
- await Message .answer (
46
- message , i18n ['poll_failure' ].format (
47
- address = address
48
- ),
49
- escape_text = False , bot = bot
50
- )
51
- break
52
- price_str = format (price , '.2f' )
53
- if price < max_price :
54
- await Message .answer (
55
- message , i18n ['poll_success' ].format (
56
- price_str = price_str
57
- ),
58
- bot = bot
59
- )
60
- break
61
- await state .update_data (latest_price = price_str )
62
- await asyncio .sleep (60 * 10 )
63
- await state .reset_state ()
64
-
65
-
66
- @dp .message_handler (commands = ['start' ])
67
- async def cmd_start (message ):
68
- await Form .address .set ()
69
- return await Message .reply (message , i18n ['start' ])
70
-
71
-
72
- @dp .message_handler (state = Form .address )
73
- async def process_address (message , state ):
74
- await state .update_data (address = message .text )
75
- await Form .next ()
76
- return await Message .reply (message , i18n ['process_address' ])
77
-
78
-
79
- @dp .message_handler (lambda message : not is_float (message .text ), state = Form .max_price )
80
- async def process_max_price_invalid (message ):
81
- return await Message .reply (message , i18n ['process_max_price_invalid' ])
82
-
83
-
84
- @dp .message_handler (lambda message : is_float (message .text ), state = Form .max_price )
85
- async def process_max_price (message , state ):
86
- await state .update_data (
87
- max_price = float (message .text .replace (',' , '.' )),
88
- poll_interval = 60 * 10 , # seconds
89
- poll_price = True ,
90
- latest_price = None
91
- )
92
- await Form .next ()
93
- async with state .proxy () as data :
94
- asyncio .create_task (_poll_price (message , data ))
95
- price_str = str (data ['max_price' ]).replace ('.' , '\\ .' )
96
- return await Message .answer (
97
- message , i18n ['process_max_price' ].format (
98
- price_str = price_str ,
99
- address = data ['address' ]
100
- ),
101
- escape_text = False
102
- )
103
-
104
-
105
- @dp .message_handler (commands = ['showlatestprice' ])
106
- async def cmd_latest_price (message ):
107
- data = await dp .current_state ().get_data ()
108
- price = data .get ('latest_price' )
109
- if not price :
110
- return await Message .answer (message , i18n ['latest_price_invalid' ])
111
- else :
112
- return await Message .answer (message , i18n ['latest_price' ].format (price = price ))
113
-
114
-
115
- @dp .message_handler (commands = ['stop' ])
116
- async def cmd_stop (message ):
117
- await dp .current_state ().update_data (poll_price = False )
118
- return await Message .answer (message , i18n ['stop' ])
119
-
120
-
121
- @dp .message_handler (commands = ['help' ])
122
- async def cmd_help (message ):
123
- return await Message .answer (message , i18n ['help' ])
124
-
125
-
126
- @dp .message_handler ()
127
- async def echo (message ):
128
- print (message )
13
+ # Initialize bot and dispatcher
14
+ bot = Bot (settings .TOKEN , parse_mode = ParseMode .MARKDOWN_V2 )
15
+ storage = MemoryStorage ()
16
+ dp = Dispatcher (bot , storage = storage )
129
17
130
18
131
19
async def on_startup (dp ):
20
+ from cmds import setup_handlers
132
21
if settings .ENV == 'production' :
133
- await bot .set_webhook (settings .WEBHOOK_URL )
22
+ await TelegramBot .bot .set_webhook (settings .WEBHOOK_URL )
23
+ setup_handlers (dp )
134
24
135
25
136
26
async def on_shutdown (dp ):
137
27
# Remove webhook (not acceptable in some cases)
138
- await bot .delete_webhook ()
28
+ await TelegramBot . bot .delete_webhook ()
139
29
140
30
141
31
def main ():
32
+ logging .basicConfig (level = logging .INFO )
142
33
if settings .MODE == 'webhook' :
143
34
executor .start_webhook (
144
- dispatcher = dp ,
35
+ dispatcher = TelegramBot . dp ,
145
36
webhook_path = settings .WEBHOOK_PATH ,
146
37
on_startup = on_startup ,
147
38
on_shutdown = on_shutdown ,
@@ -150,7 +41,4 @@ def main():
150
41
port = settings .WEBAPP_PORT
151
42
)
152
43
if settings .MODE == 'polling' :
153
- executor .start_polling (dp , skip_updates = True )
154
-
155
-
156
- main ()
44
+ executor .start_polling (TelegramBot .dp , on_startup = on_startup , skip_updates = True )
0 commit comments