diff --git a/daemons/notify.py b/daemons/notify.py index cf53013..82538c9 100644 --- a/daemons/notify.py +++ b/daemons/notify.py @@ -4,8 +4,10 @@ from time import sleep from telebot.apihelper import ApiTelegramException from daemons.bot import bot -from helpers import now +from helpers import now, get_next_daily_notify_time +from helpers.models import UserSchema from helpers.mongo import mongo +from helpers.ruz import ruz def process(): @@ -28,6 +30,27 @@ def process(): except ApiTelegramException: pass mongo.lessons_collection.update_one({"_id": lesson['_id']}, {"$set": {"notified": True}}) + time_now = now() + for user in mongo.users_collection.find({"next_daily_notify_time": {"$lte": time_now}}): + user_model = UserSchema().load(user) + if time_now.weekday() == 6: + mongo.users_collection.update_one( + {"chat_id": user["chat_id"]}, + {"$set": {"next_daily_notify_time": get_next_daily_notify_time(user_model, time_now)}} + ) + else: + lessons = mongo.get_today_lessons(user_model) + if len(lessons) == 0: + text = "Сегодня у тебя нет пар." + else: + text = ruz.schedule_builder(lessons) + try: + bot.send_message( + user["chat_id"], + "Уведомляю о занятиях!\n" + text + ) + except: + pass def notify(): diff --git a/helpers/__init__.py b/helpers/__init__.py index ad31bac..2533c26 100644 --- a/helpers/__init__.py +++ b/helpers/__init__.py @@ -1,8 +1,26 @@ import datetime import zoneinfo +from helpers.models import User + def now(): zone = zoneinfo.ZoneInfo("Europe/Moscow") today = datetime.datetime.now(zone) + datetime.timedelta(hours=3) return today + + +def get_next_daily_notify_time(user: User, time_now: datetime.datetime | None = None) -> datetime.datetime: + if time_now is None: + time_now = now() + hours, minutes = map(int, user.daily_notify_time.split(":")) + next_time = datetime.datetime( + year=time_now.year, + month=time_now.month, + day=time_now.day, + hour=hours, + minute=minutes + ) + if time_now.hour * 60 * time_now.minute < hours * 60 + minutes: + next_time = next_time + datetime.timedelta(days=1) + return next_time diff --git a/helpers/answer.py b/helpers/answer.py index 8764843..5037f66 100644 --- a/helpers/answer.py +++ b/helpers/answer.py @@ -5,8 +5,9 @@ from telebot.types import Message from daemons.bot import bot from daemons.fetch import fetch_schedule_for_user -from helpers import now -from helpers.keyboards import main_keyboard, notify_keyboard, yes_no_keyboard, again_keyboard, groups_keyboard +from helpers import now, get_next_daily_notify_time +from helpers.keyboards import main_keyboard, notify_keyboard, yes_no_keyboard, again_keyboard, groups_keyboard, \ + no_daily_notify from helpers.models import UserSchema, User from helpers.mongo import mongo from helpers.ruz import ruz @@ -19,6 +20,9 @@ class BaseAnswer: user = User(chat_id=message.chat.id) mongo.users_collection.insert_one(UserSchema().dump(user)) else: + # что-то со временем в маршмеллоу происходит, не знаю как решить + if 'next_daily_notify_time' in user: + user['next_daily_notify_time'] = str(user['next_daily_notify_time']) user = UserSchema().load(user) attr = getattr(self, "handle_state_" + user.state, None) if attr is None: @@ -121,6 +125,14 @@ class Answer(BaseAnswer): ) self.set_state(user, "wait_for_notify") return + elif message.text == "Ежедневные уведомления": + bot.send_message( + user.chat_id, + "Каждый день (кроме воскресенья) я буду присылать тебе расписание на день. Пришли мне в формате чч:мм время, в которое ты хочешь получать расписание. Например, 09:30", + reply_markup=no_daily_notify() + ) + self.set_state(user, "wait_for_daily_notify") + return elif message.text == "Сброс настроек": bot.send_message(user.chat_id, "Ты уверен что хочешь сбросить все настройки и больше не получать уведомления?", reply_markup=yes_no_keyboard()) self.set_state(user, "reset") @@ -160,6 +172,58 @@ class Answer(BaseAnswer): bot.send_message(user.chat_id, text, reply_markup=main_keyboard()) self.set_state(user, "ready") + def _validate_time(self, line: str) -> bool: + if len(line) != 5: + return False + if line.count(":") != 1: + return False + hours, minutes = line.split(":") + try: + hours = int(hours) + minutes = int(minutes) + except ValueError: + return False + if hours < 0 or hours > 23 or minutes < 0 and minutes > 59: + return False + return True + + def handle_state_wait_for_daily_notify(self, message: Message, user: User): + text = message.text + if text == "Не уведомлять": + mongo.users_collection.update_one( + {"chat_id": user.chat_id}, + {"$set": {"daily_notify_time": None, "next_daily_notify_time": None}} + ) + bot.send_message( + user.chat_id, + "Принято! Я не буду присылать тебе ежедневные уведомления.", + reply_markup=main_keyboard() + ) + self.set_state(user, "ready") + return + if not self._validate_time(text): + bot.send_message( + user.chat_id, + "Ты прислал мне что-то неправильное. Пришли мне в формате чч:мм время, в которое ты хочешь получать расписание. Например, 09:30", + reply_markup=no_daily_notify() + ) + return + user.daily_notify_time = text + next_time = get_next_daily_notify_time(user) + bot.send_message( + user.chat_id, + f"Принято! Буду уведомлять тебя каждый день в {text}.", + reply_markup=main_keyboard() + ) + mongo.users_collection.update_one( + {"chat_id": user.chat_id}, + {"$set": { + "daily_notify_time": text, + "next_daily_notify_time": next_time, + "state": "ready" + }} + ) + def handle_state_reset(self, message: Message, user: User): if message.text == "Да": mongo.users_collection.delete_one({"chat_id": user.chat_id}) diff --git a/helpers/keyboards.py b/helpers/keyboards.py index b6574cb..b945eb2 100644 --- a/helpers/keyboards.py +++ b/helpers/keyboards.py @@ -5,6 +5,7 @@ def main_keyboard(): kb = telebot.types.ReplyKeyboardMarkup(True, False) kb.row("Пары сегодня") kb.row("Уведомления о парах") + kb.row("Ежедневные уведомления") kb.row("Сброс настроек") return kb diff --git a/helpers/models.py b/helpers/models.py index c758a29..f0ecc94 100644 --- a/helpers/models.py +++ b/helpers/models.py @@ -14,6 +14,8 @@ class User: hse_id: Optional[int] = None state: str = "new" notify_minutes: Optional[int] = 10 + daily_notify_time: Optional[str] = None + next_daily_notify_time: Optional[datetime.datetime] = None class Meta: unknown = EXCLUDE diff --git a/helpers/mongo.py b/helpers/mongo.py index bf25ace..819bba7 100644 --- a/helpers/mongo.py +++ b/helpers/mongo.py @@ -20,6 +20,9 @@ class Mongo: self.users_collection.create_index([ ("notify_minutes", 1) ]) + self.users_collection.create_index([ + ("next_daily_notify_time", 1) + ]) self.lessons_collection.create_index([ ("discipline", 1), ("auditorium", 1), @@ -60,6 +63,7 @@ class Mongo: "begin": {"$gte": today, "$lte": tomorrow}} ): lessons.append(lesson) + lessons.sort(key=lambda les: les["begin"]) return lessons