Skip to content

Commit 3956730

Browse files
committed
bot review (wip)
1 parent ad7889b commit 3956730

File tree

2 files changed

+55
-67
lines changed

2 files changed

+55
-67
lines changed

WWCS/irrigation/telegramBot/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,10 @@ Now edit the Makefile and add the km language to the list of locales, for exampl
132132
LOCALES = km tg
133133

134134
Then you can continue editing the PO file with poedit as described above.
135+
136+
137+
# Local development
138+
139+
To run the bot:
140+
141+
python bot.py

WWCS/irrigation/telegramBot/bot.py

Lines changed: 48 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1+
"""
2+
Telegram bot.
3+
4+
Commands:
5+
/start
6+
"""
7+
8+
19
from datetime import datetime, timedelta
210
import asyncio
311
import gettext
412
import os
513
import pathlib
614

715
# Requirements
16+
from apscheduler.jobstores.base import JobLookupError
817
from apscheduler.schedulers.asyncio import AsyncIOScheduler
18+
from apscheduler.triggers.date import DateTrigger
919
from apscheduler.triggers.interval import IntervalTrigger
1020
from databases import Database
1121
from telebot import types
@@ -36,44 +46,36 @@
3646
_ = translation.gettext
3747

3848

49+
scheduler = AsyncIOScheduler()
50+
3951
class NotificationManager:
40-
def __init__(self):
41-
self.jobs = {}
4252

43-
async def add_job(self, chat_id, job_type, func, *args, **kwargs):
44-
await self.remove_job(chat_id, job_type)
45-
job = scheduler.add_job(func, *args, **kwargs)
46-
self.jobs[f"{job_type}_{chat_id}"] = job
47-
return job
53+
def add_job(self, chat_id, job_type, func, trigger):
54+
job_id = f"{job_type}_{chat_id}"
55+
self.remove_job(chat_id, job_type)
56+
scheduler.add_job(func, trigger, id=job_id, args=[chat_id])
4857

49-
async def remove_job(self, chat_id, job_type):
58+
def remove_job(self, chat_id, job_type):
5059
job_id = f"{job_type}_{chat_id}"
51-
if job_id in self.jobs:
52-
try:
53-
self.jobs[job_id].remove()
54-
except Exception as e:
55-
print (f"Error deleting task {job_id}: {e}")
56-
finally:
57-
self.jobs.pop(job_id, None)
60+
try:
61+
scheduler.remove_job(job_id)
62+
except JobLookupError:
63+
pass
5864

59-
async def remove_all_jobs(self, chat_id):
65+
def remove_all_jobs(self, chat_id):
6066
for job_type in ['water_check', 'polyv_complete']:
61-
await self.remove_job(chat_id, job_type)
67+
self.remove_job(chat_id, job_type)
6268

6369

6470
notification_manager = NotificationManager()
6571

6672

67-
68-
6973
# Инициализация бота
7074
bot = AsyncTeleBot(BOT_TOKEN)
71-
scheduler = AsyncIOScheduler()
7275

7376
# Словари для хранения состояний
7477
user_states = {}
7578
user_irrigation_data = {} # Для хранения данных о поливе
76-
notification_jobs = {} # Для хранения задач уведомлений
7779

7880
# Таблица расхода воды (уровень в см -> расход в м³/мин)
7981
WATER_FLOW_RATES = {
@@ -147,44 +149,29 @@ def create_reply_keyboard():
147149
return markup
148150

149151

150-
async def start_irrigation_notifications(chat_id):
151-
await notification_manager.add_job(
152-
chat_id,
153-
'water_check',
154-
send_water_check_notification,
155-
trigger=IntervalTrigger(minutes=15),
156-
args=[chat_id]
157-
)
152+
def start_irrigation_notifications(chat_id):
153+
notification_manager.add_job(chat_id, 'water_check', send_water_check_notification,
154+
trigger=IntervalTrigger(minutes=15))
158155

159156

160157
async def send_water_check_notification(chat_id):
161158
"""Отправляет уведомление о проверке уровня воды"""
162159
if chat_id in user_irrigation_data:
163-
await bot.send_message(
164-
chat_id,
165-
_("🔄 Please check the current water level in the channel and send its value")
166-
)
160+
message = _("🔄 Please check the current water level in the channel and send its value")
161+
await bot.send_message(chat_id, message)
167162

168163

169-
async def schedule_polyv_completion_notification(chat_id, hours, minutes):
164+
def schedule_polyv_completion_notification(chat_id, hours, minutes):
170165
completion_time = datetime.now() + timedelta(hours=hours, minutes=minutes)
171-
await notification_manager.add_job(
172-
chat_id,
173-
'polyv_complete',
174-
notify_polyv_completion,
175-
trigger='date',
176-
run_date=completion_time,
177-
args=[chat_id]
178-
)
166+
notification_manager.add_job(chat_id, 'polyv_complete', notify_polyv_completion,
167+
trigger=DateTrigger(run_date=completion_time))
179168

180169

181170
async def notify_polyv_completion(chat_id):
182171
if chat_id in user_irrigation_data and user_irrigation_data[chat_id].get('is_active', False):
183-
await bot.send_message(
184-
chat_id,
185-
_("⏰ Watering time is over! Please click the 'Save data' button to save the results.")
186-
)
187-
await notification_manager.remove_job(chat_id, 'water_check')
172+
message = _("⏰ Watering time is over! Please click the 'Save data' button to save the results.")
173+
await bot.send_message(chat_id, message)
174+
notification_manager.remove_job(chat_id, 'water_check')
188175

189176

190177
async def check_irrigation(chat_id):
@@ -216,15 +203,10 @@ async def check_irrigation(chat_id):
216203
)
217204

218205
else:
219-
text = _(
220-
"ERROR!"
221-
)
206+
text = _("ERROR!")
222207

223-
await bot.send_message(
224-
chat_id,
225-
text.format(first_name=row['firstName'], water=round(m3_needed, 2)),
226-
reply_markup=markup
227-
)
208+
message = text.format(first_name=row['firstName'], water=round(m3_needed, 2))
209+
await bot.send_message(chat_id, message, reply_markup=markup)
228210
return True
229211
return False
230212

@@ -253,11 +235,11 @@ async def calculate_irrigation(chat_id, water_level, irrigation_need, area, ie,
253235
'total_needed_m3': total_needed_m3,
254236
'total_used_m3': 0,
255237
'history': [(water_level, datetime.now())],
256-
'is_active': True
238+
'is_active': True,
257239
}
258240

259-
# Запускаем уведомления только для нового полива
260-
await start_irrigation_notifications(chat_id)
241+
# We launch notifications only for new watering
242+
start_irrigation_notifications(chat_id)
261243
else:
262244
data = user_irrigation_data[chat_id]
263245
time_elapsed = (datetime.now() - data['last_update']).total_seconds()
@@ -278,13 +260,13 @@ async def calculate_irrigation(chat_id, water_level, irrigation_need, area, ie,
278260
if remaining_time > 0:
279261
hours = int(remaining_time)
280262
minutes = int((remaining_time - hours) * 60)
281-
await schedule_polyv_completion_notification(chat_id, hours, minutes)
263+
schedule_polyv_completion_notification(chat_id, hours, minutes)
282264

283265
return {
284266
'used_m3': user_irrigation_data[chat_id]['total_used_m3'],
285267
'remaining_m3': remaining_m3,
286268
'remaining_time': remaining_time,
287-
'is_completed': remaining_m3 <= 0
269+
'is_completed': remaining_m3 <= 0,
288270
}
289271

290272

@@ -303,7 +285,7 @@ async def handle_recommendation(message):
303285
if str(chat_id) == str(row['telegramID']):
304286
if row['type'] == "channel":
305287
user_states[chat_id] = "waiting_for_water_level"
306-
await bot.send_message (chat_id, _("Enter the current water level in the channel (in cm):"))
288+
await bot.send_message(chat_id, _("Enter the current water level in the channel (in cm):"))
307289

308290
elif row['type'] == "counter":
309291
user_states[chat_id] = "waiting_for_counter_start"
@@ -348,7 +330,7 @@ async def handle_counter_start(message):
348330
'start_counter': start_counter,
349331
'target_counter': target_counter,
350332
'is_active': True,
351-
'last_update': datetime.now()
333+
'last_update': datetime.now(),
352334
}
353335
user_states[chat_id] = None
354336
return
@@ -381,7 +363,7 @@ async def handle_water_level(message):
381363
float(row['irrigationNeed']),
382364
float(row['area']),
383365
float(row['ie']),
384-
float(row['wa'])
366+
float(row['wa']),
385367
)
386368

387369
if calculation['is_completed']:
@@ -399,7 +381,7 @@ async def handle_water_level(message):
399381
hours=hours,
400382
minutes=minutes,
401383
used_m3=calculation['used_m3'],
402-
total_m3=calculation['used_m3'] + calculation['remaining_m3']
384+
total_m3=calculation['used_m3'] + calculation['remaining_m3'],
403385
)
404386

405387
await bot.send_message(chat_id, msg)
@@ -410,13 +392,12 @@ async def handle_water_level(message):
410392
await bot.send_message(chat_id, _("⚠️ Please enter a valid number (water level in cm)"))
411393

412394

413-
414395
@bot.message_handler(func=lambda message: message.text == BUTTONS["save_data"])
415396
async def handle_send_data(message):
416397
chat_id = message.chat.id
417398

418-
# Останавливаем все уведомления
419-
await notification_manager.remove_all_jobs(chat_id)
399+
# Stop all notifications
400+
notification_manager.remove_all_jobs(chat_id)
420401

421402
rows = await get_irrigation_data()
422403
for row in rows:

0 commit comments

Comments
 (0)