312 lines
14 KiB
Python
312 lines
14 KiB
Python
import datetime
|
||
|
||
import pytz
|
||
from telebot.types import Message
|
||
|
||
from daemons.bot import bot
|
||
from daemons.fetch import fetch_schedule_for_user
|
||
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, student_or_teacher_keyboard, campus_keyboard
|
||
from helpers.models import UserSchema, User
|
||
from helpers.mongo import mongo
|
||
from helpers.ruz import ruz
|
||
|
||
|
||
class BaseAnswer:
|
||
def process(self, message: Message):
|
||
user = mongo.users_collection.find_one({"chat_id": message.chat.id})
|
||
if user is None:
|
||
user = User(chat_id=message.chat.id)
|
||
mongo.users_collection.insert_one(UserSchema().dump(user))
|
||
else:
|
||
user = UserSchema().load(user)
|
||
attr = getattr(self, "handle_state_" + user.state, None)
|
||
if attr is None:
|
||
raise NotImplementedError(f"handled state {user.state} but not implemented!")
|
||
attr(message, user)
|
||
|
||
def set_state(self, user: User, state: str):
|
||
user.state = state
|
||
mongo.users_collection.update_one({"chat_id": user.chat_id}, {"$set": {"state": state}})
|
||
|
||
|
||
class Answer(BaseAnswer):
|
||
|
||
def handle_state_new(self, message: Message, user: User):
|
||
bot.send_message(
|
||
message.chat.id,
|
||
"Привет! Я буду помогать тебе выживать в вышке!\nИз какого ты кампуса?",
|
||
reply_markup=campus_keyboard()
|
||
)
|
||
self.set_state(user, "wait_for_campus")
|
||
|
||
def handle_state_wait_for_campus(self, message: Message, user: User):
|
||
if message.text not in ["Москва", "Санкт-Петербург", "Нижний Новгород", "Пермь"]:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Ты прислал мне что-то непонятное, используй кнопки. Из какого ты кампуса?",
|
||
reply_markup=campus_keyboard()
|
||
)
|
||
return
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Принято! Ты преподаватель или студент?",
|
||
reply_markup=student_or_teacher_keyboard()
|
||
)
|
||
mongo.users_collection.update_one(
|
||
{"chat_id": user.chat_id},
|
||
{"$set": {"campus": message.text, "state": "wait_for_student_or_teacher"}}
|
||
)
|
||
|
||
def handle_state_wait_for_student_or_teacher(self, message: Message, user: User):
|
||
if message.text == "Студент":
|
||
bot.send_message(user.chat_id, "Принято! Теперь отправь мне свое ФИО.", reply_markup=again_keyboard())
|
||
mongo.users_collection.update_one(
|
||
{"chat_id": user.chat_id},
|
||
{"$set": {"is_teacher": False, "state": "wait_for_name"}}
|
||
)
|
||
self.set_state(user, "wait_for_name")
|
||
elif message.text == "Преподаватель":
|
||
bot.send_message(user.chat_id, "Принято! Теперь отправь мне свое ФИО.", reply_markup=again_keyboard())
|
||
mongo.users_collection.update_one(
|
||
{"chat_id": user.chat_id},
|
||
{"$set": {"is_teacher": True, "state": "wait_for_name"}}
|
||
)
|
||
self.set_state(user, "wait_for_name")
|
||
elif message.text == "Начать заново":
|
||
bot.send_message(
|
||
message.chat.id,
|
||
"Привет! Я буду помогать тебе выживать в вышке!\nИз какого ты кампуса?",
|
||
reply_markup=campus_keyboard()
|
||
)
|
||
self.set_state(user, "wait_for_campus")
|
||
return
|
||
else:
|
||
bot.send_message(user.chat_id, "Ты отправил мне что-то неправильное, используй кнопки. Ты преподаватель или студент?", reply_markup=student_or_teacher_keyboard())
|
||
|
||
def handle_state_wait_for_name(self, message: Message, user: User):
|
||
if message.text == "Начать заново":
|
||
bot.send_message(
|
||
message.chat.id,
|
||
"Привет! Я буду помогать тебе выживать в вышке!\nИз какого ты кампуса?",
|
||
reply_markup=campus_keyboard()
|
||
)
|
||
self.set_state(user, "wait_for_campus")
|
||
return
|
||
user.name = message.text
|
||
data = ruz.find_person(user)
|
||
if data is None:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"В РУЗе какая-то поломка, попробуй еще раз позже."
|
||
)
|
||
return
|
||
if len(data) == 0:
|
||
bot.send_message(user.chat_id, "К сожалению, в РУЗе не нашлось такого человека, попробуй еще раз.")
|
||
return
|
||
mongo.users_collection.update_one(
|
||
{"chat_id": user.chat_id},
|
||
{"$set": {"name": user.name}})
|
||
if user.is_teacher:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Отлично! Теперь выбери из списка свой департамент.",
|
||
reply_markup=groups_keyboard(data)
|
||
)
|
||
else:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Отлично! Теперь выбери из списка свою группу.",
|
||
reply_markup=groups_keyboard(data)
|
||
)
|
||
self.set_state(user, "wait_for_group")
|
||
|
||
def handle_state_wait_for_group(self, message: Message, user: User):
|
||
if message.text == "Начать заново":
|
||
bot.send_message(
|
||
message.chat.id,
|
||
"Привет! Я буду помогать тебе выживать в вышке!\nИз какого ты кампуса?",
|
||
reply_markup=campus_keyboard()
|
||
)
|
||
self.set_state(user, "wait_for_campus")
|
||
return
|
||
group = message.text
|
||
data = ruz.find_person(user)
|
||
if data is None:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"В РУЗе какая-то поломка, попробуй еще раз позже."
|
||
)
|
||
return
|
||
for element in data:
|
||
if element['description'] == group:
|
||
user.hse_id = int(element['id'])
|
||
user.group = group
|
||
user.name = element['label']
|
||
break
|
||
if user.group is None:
|
||
bot.send_message(user.chat_id, "Ты ввел что-то неправильно, попробуй еще раз сначала. Из какого ты кампуса?", reply_markup=campus_keyboard())
|
||
self.set_state(user, "wait_for_campus")
|
||
return
|
||
mongo.users_collection.update_one({"chat_id": user.chat_id}, {"$set": {
|
||
"hse_id": user.hse_id,
|
||
"group": group,
|
||
"name": user.name
|
||
}})
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Я нашел тебя в базе РУЗ. Я буду подсказывать тебе расписание, а также уведомлять о предстоящих парах.",
|
||
)
|
||
success = fetch_schedule_for_user(user)
|
||
if success:
|
||
lessons = mongo.get_today_lessons(user)
|
||
if len(lessons) == 0:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Сегодня у тебя нет пар, отдыхай",
|
||
reply_markup=main_keyboard()
|
||
)
|
||
else:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Твои пары сегодня:\n" + ruz.schedule_builder(lessons),
|
||
reply_markup=main_keyboard()
|
||
)
|
||
self.set_state(user, "ready")
|
||
|
||
def handle_state_ready(self, message: Message, user: User):
|
||
if message.text == "Пары сегодня":
|
||
lessons = mongo.get_today_lessons(user)
|
||
if len(lessons) == 0:
|
||
text = "Сегодня у тебя нет пар, отдыхай."
|
||
else:
|
||
text = ruz.schedule_builder(lessons)
|
||
elif message.text == "Пары завтра":
|
||
lessons = mongo.get_tomorrow_lessons(user)
|
||
if len(lessons) == 0:
|
||
text = "Завтра у тебя нет пар, отдыхай."
|
||
else:
|
||
text = ruz.schedule_builder(lessons)
|
||
elif message.text == "Уведомления о парах":
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Выбери за сколько минут мне нужно напомнить тебе о предстоящей паре",
|
||
reply_markup=notify_keyboard()
|
||
)
|
||
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")
|
||
return
|
||
else:
|
||
text = "Я не понимаю такой команды, используй кнопки."
|
||
bot.send_message(
|
||
user.chat_id,
|
||
text,
|
||
reply_markup=main_keyboard()
|
||
)
|
||
|
||
def handle_state_wait_for_notify(self, message: Message, user: User):
|
||
text = message.text
|
||
if text == "Не уведомлять":
|
||
user.notify_minutes = None
|
||
elif text == "5 минут":
|
||
user.notify_minutes = 5
|
||
elif text == "10 минут":
|
||
user.notify_minutes = 10
|
||
elif text == "15 минут":
|
||
user.notify_minutes = 15
|
||
elif text == "20 минут":
|
||
user.notify_minutes = 20
|
||
else:
|
||
bot.send_message(
|
||
user.chat_id,
|
||
"Я не понимаю такой команды, используй кнопки.",
|
||
reply_markup=notify_keyboard()
|
||
)
|
||
return
|
||
mongo.users_collection.update_one({"chat_id": user.chat_id}, {"$set": {"notify_minutes": user.notify_minutes}})
|
||
if user.notify_minutes is not None:
|
||
text = f"Принято! Буду уведомлять тебя за {text}."
|
||
else:
|
||
text = f"Принято! Я не уведомлять тебя."
|
||
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 or 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})
|
||
bot.send_message(user.chat_id, "Настройки сброшены, ждем твоего возвращения", reply_markup=again_keyboard())
|
||
elif message.text == "Нет":
|
||
bot.send_message(user.chat_id, "Возращаюсь к прежнему режиму", reply_markup=main_keyboard())
|
||
self.set_state(user, "ready")
|
||
else:
|
||
bot.send_message(user.chat_id,
|
||
"Я не понимаю, используй кнопки",
|
||
reply_markup=yes_no_keyboard())
|
||
|
||
|
||
answer = Answer()
|