Exemple #1
0
def live_question_handler(message):
    """
        Задать вопрос преподавателю во время лекции.
    """

    if student := Student.objects(user_id=message.chat.id):
        student = student.first()

        if student.status == "standby":
            time_delta = datetime.today() - cfg.FIRST_CLASS_DAY
            if time_delta.seconds <= cfg.CLASS_DURATION and time_delta.days % cfg.CLASS_OFFSET == 0:
                if time.time() - student.last_live_q >= cfg.LIVE_Q_DELAY:
                    student.last_live_q = time.time()
                    student.status = "live_question"

                    student.save()

                    bot.send_message(message.chat.id, "🖋️ Введите ваш вопрос:")
                else:
                    spam_time = int(cfg.LIVE_Q_DELAY -
                                    (time.time() - student.last_live_q))
                    time_msg = f"⏰ Подождите {spam_time} секунд прежде чем еще раз задавать вопрос."
                    bot.send_message(message.chat.id, time_msg)
            else:
                bot.send_message(
                    message.chat.id,
                    "⛔ Вопросы можно задавать только во время лекции.")
        elif student.status == "live_question":
            bot.send_message(message.chat.id, "🖋️ Введите ваш вопрос:")
        else:
            bot.send_message(
                message.chat.id,
                "⛔ Прежде чем задавать вопросы, ответьте на вопросы бота.")
Exemple #2
0
def help_message(message):
    """
        Помощь в использовании бота.
    """

    student = Student.objects(user_id=message.from_user.id).first()

    if student.status == "standby":
        bot.send_message(message.chat.id, cfg.HELP_MSG, parse_mode="markdown")

    elif student.status == "registration":
        bot.send_message(message.chat.id, "️👮🏻‍♀️ Выберите группу.")

    elif student.status == "is_ready":
        answer = "📚 Нажмите кнопку готов, если готовы ответить на вопрос."
        bot.send_message(message.chat.id, answer)

    elif student.status == "question":
        variants = ["🅰️", "🅱️"]
        answer = f"Я ничего не понимаю на человеческом, но вариант {choice(variants)} " \
            "выглядит привлекательно!"
        bot.send_message(message.chat.id, answer)

    elif student.status == "live_question":
        answer = "📚 Задайте свой вопрос:"
        bot.send_message(message.chat.id, answer)

    else:
        bot.send_message(message.chat.id,
                         "Ничем не могу помочь, напишите разработчикам...")
Exemple #3
0
def find_student(user_id, students):
    """
        Поиск студента по user id в рейтинге всех студентов.
    """

    student = Student.objects(user_id=user_id).first()
    student_info = list(filter(lambda x: x[0] == student.login, students))[0]
    return student_info, students.index(student_info) + 1
Exemple #4
0
def query_handler_ready(call):
    """
        Высылание вопроса с inline-кнопками тем,
        кто подтвердил готовность отвечать на вопрос.
    """

    bot.answer_callback_query(call.id)
    student = Student.objects(user_id=call.message.chat.id).first()

    if student.status == "is_ready":
        send_question(student)
Exemple #5
0
def questions_notification():
    """
        Функция рассылки информации о том, что можно задавать вопросы лектору.
    """

    if date.today().isocalendar()[1] % 2:
        for student in Student.objects(status__ne="registration"):
            bot.send_message(student.user_id, "📬")
            bot.send_message(
                student.user_id,
                "Начиная с этого момента вы можете задать вопрос лектору.")
Exemple #6
0
def question_sender(msg):
    """
        Пересылка вопроса преподавателю.
    """

    student = Student.objects(user_id=msg.chat.id).first()

    bot.send_message(cfg.LECTOR_ID, msg.text)
    bot.send_message(msg.chat.id, "📮 Ваш вопрос принят!")

    student.status = "standby"
    student.save()
Exemple #7
0
def send_stat(message):
    """
        Отправляет сообщение со статистикой при запросе пользователя (командой /stat).
    """

    student = Student.objects(user_id=message.chat.id).first()
    if student.status == "standby":
        bot.send_message(message.chat.id,
                         stat.stat_msg(student),
                         parse_mode="markdown")
    else:
        bot.send_message(
            message.chat.id,
            "⛔️ Прежде чем вызвать статистику, ответьте на вопросы бота.")
Exemple #8
0
def send_confirmation():
    """
        Отправка сообщения с вопросом о подтверждении готовности отвечать на вопрос.
    """

    for student in Student.objects():
        if student.status == "standby" and not len(student.queue) and \
                student.queue[0]["days_left"] <= 0:
            student.status = "is_ready"

            # Функция возвращает измененный объект студента (имитация передачи по ссылке).
            # (p.s.: в функции записывается время отправления сообщения с вопросом о готовности).
            student = send_single_confirmation(student, True)
            student.save()
Exemple #9
0
def info_message(message):
    """
        Информация о боте.
    """

    student = Student.objects(user_id=message.from_user.id).first()

    if student.status == "standby":
        bot.send_message(message.chat.id, cfg.INFO_MSG, parse_mode="markdown")

    else:
        bot.send_message(
            message.chat.id,
            "⛔️ Прежде чем посмотреть информацию, ответьте на вопросы бота.")
Exemple #10
0
def query_handler_reg(call):
    """
        Обработка нажатия inline-кнопок с выбором группы студентом.
    """

    bot.answer_callback_query(call.id)
    student = Student.objects(user_id=call.message.chat.id).first()

    if student.status == "registration":
        bot.send_message(call.message.chat.id,
                         "✅ Вы успешно зарегистрированы в системе.")

        student.group = call.data
        student.status = "standby"
        student.save()
Exemple #11
0
def authorization(message):
    """
        Выбор учебной группы для авторизации.
    """

    if not Student.objects(user_id=message.chat.id):

        questions_queue = list()
        count_missed_questions = \
            (datetime.today() - cfg.FIRST_QUESTION_DAY).days * cfg.QUESTION_PORTION

        if count_missed_questions > 0:
            questions_queue = [{
                "question_day": i,
                "days_left": 0
            } for i in range(count_missed_questions + cfg.QUESTION_PORTION)]

        login = message.chat.username

        if message.chat.username is None:
            login = f"[{generate_r2d2()}](tg://user?id={str(message.chat.id)})"

        student = Student(user_id=message.chat.id,
                          login=login,
                          status="registration",
                          queue=questions_queue)

        bot.send_message(message.chat.id,
                         "💬 Укажите свою учебную группу: ",
                         reply_markup=create_markup(cfg.GROUPS_BTNS))

        student.save()

    else:
        bot.send_message(message.chat.id,
                         "⚠️ Вы уже зарегистрированы в системе.")
Exemple #12
0
def rules_message(message):
    """
        Правила работы бота.
    """

    student = Student.objects(user_id=message.from_user.id).first()

    if student.status == "standby":
        bot.send_message(message.chat.id, cfg.RULES_MSG, parse_mode="markdown")

    elif student.status == "live_question":
        bot.send_message(
            message.chat.id,
            "⛔️ Прежде чем посмотреть правила, задайте свой вопрос.")

    else:
        bot.send_message(
            message.chat.id,
            "⛔️ Прежде чем посмотреть правила, ответьте на вопросы бота.")
Exemple #13
0
def show_leaderboard(message):
    """
        Вывод лидерборда среди учеников.
    """

    student = Student.objects(user_id=message.from_user.id).first()

    if student.status == "standby" and int(
            time.time()) - student.lb_timeout > cfg.LB_TIMEOUT:
        student.lb_timeout = int(time.time())
        student.save()

        page = create_leaderboard_page(cfg.SCROLL_BTNS[1], message.chat.id)

        if Student.objects.count() > cfg.LB_PAGE_SIZE:
            markup = telebot.types.InlineKeyboardMarkup()
            markup.add(
                telebot.types.InlineKeyboardButton(
                    text=cfg.SCROLL_BTNS[1], callback_data=cfg.SCROLL_BTNS[1]))

            bot.send_message(message.chat.id,
                             page,
                             reply_markup=markup,
                             parse_mode="Markdown")
        else:
            bot.send_message(message.chat.id, page, parse_mode="Markdown")

    elif student.status == "standby":
        bot.send_message(
            message.chat.id,
            "⏰ Вы недавно вызывали лидерборд. Повторите через " +
            f"{cfg.LB_TIMEOUT - (int(time.time()) - student.lb_timeout)} секунд."
        )

    else:
        bot.send_message(
            message.chat.id,
            "⛔️ Прежде чем вызвать лидерборд, ответьте на вопросы бота.")
Exemple #14
0
def update_queue():
    """
        Функция добавления "вопроса дня".
    """

    today_question_day = (datetime.today() - cfg.FIRST_QUESTION_DAY).days

    for student in Student.objects(status__ne="registration"):

        if cfg.DEV_MODE_QUEUE:
            print(
                f"Daily update queue of user: {student.login}\nQueue before: {student.queue}"
            )

        # Кол-во дней ожидания у вопросов, которые уже находятся в очереди, уменьшается на 1
        # (p.s.: Если кол-во дней ожидания <= 0, то вопрос должен быть отправлен сегодня).
        need_miss_msg = False
        for questions in student.queue:
            questions["days_left"] -= 1
            if questions["days_left"] <= -cfg.MISS_DAYS:
                need_miss_msg = True

        if need_miss_msg:
            bot.send_message(student.user_id, cfg.MISS_MESSAGE)

        # Вопрос дня добавляется на самое первое место
        for i in range(today_question_day * cfg.QUESTION_PORTION,
                       (today_question_day + 1) * cfg.QUESTION_PORTION):
            student.queue.insert(0, {"question_day": i, "days_left": 0})

        if cfg.DEV_MODE_QUEUE:
            print(f"Queue after: {student.queue}\n")

        student.save()

    # Предложения ответить будут разосланы тем, кто свободен.
    send_confirmation()
Exemple #15
0
def get_rating():
    """
        Возвращает отсортированный массив кортежей-пар (nickname, summary).
    """

    rating = dict()
    questions = Question.objects()

    for student in Student.objects():
        summary = 0
        datastore = json.loads(student.data)

        for question in questions:
            if len(datastore) > question.day:
                number_of_answers = 2 if len(datastore[question.day]["right"]) > 2 \
                    else len(datastore[question.day]["right"])
                for i in range(number_of_answers):
                    summary += answer_summary(student, question, i)
            else:
                break

        if student.login not in rating:
            rating[student.login] = (summary if summary != 0 else 0,
                                     student.group)
        else:
            i = 1
            while student.login + f" ({i})" in rating:
                i += 1

            rating[student.login +
                   f" ({i})"] = (summary if summary != 0 else 0, student.group)
    if cfg.DEV_MODE_RATING:
        print("rating:\n", rating, end="\n\n")

    items = [(elem[0], elem[1][0], elem[1][1]) for elem in rating.items()]

    return sorted(items, key=lambda x: x[1], reverse=True)
Exemple #16
0
                                    (time.time() - student.last_live_q))
                    time_msg = f"⏰ Подождите {spam_time} секунд прежде чем еще раз задавать вопрос."
                    bot.send_message(message.chat.id, time_msg)
            else:
                bot.send_message(
                    message.chat.id,
                    "⛔ Вопросы можно задавать только во время лекции.")
        elif student.status == "live_question":
            bot.send_message(message.chat.id, "🖋️ Введите ваш вопрос:")
        else:
            bot.send_message(
                message.chat.id,
                "⛔ Прежде чем задавать вопросы, ответьте на вопросы бота.")


@bot.message_handler(func=lambda msg: Student.objects(user_id=msg.chat.id).
                     first().status == "live_question")
def question_sender(msg):
    """
        Пересылка вопроса преподавателю.
    """

    student = Student.objects(user_id=msg.chat.id).first()

    bot.send_message(cfg.LECTOR_ID, msg.text)
    bot.send_message(msg.chat.id, "📮 Ваш вопрос принят!")

    student.status = "standby"
    student.save()


@bot.callback_query_handler(lambda call: call.data in cfg.GROUPS_BTNS)
Exemple #17
0
def query_handler_questions(call):
    """
        Обработка нажатия inline-кнопок с выбором ответа студентом.
        Обновление статистики после ответа на вопрос.
    """

    bot.answer_callback_query(call.id)
    student = Student.objects(user_id=call.message.chat.id).first()

    if student.status == "question":
        day = student.queue[0]["question_day"]
        question = Question.objects(day=day).first()

        if cfg.DEV_MODE_QUEUE:
            print(
                f"Queue of {student.login} after answering the question (before)"
                + f": {student.queue}",
                f"Got day {day}",
                sep='\n',
                end='\n\n')

        datastore = json.loads(student.data)

        # 4 - emoji + вариант ответа (перед самим ответом)
        student_answer = call.message.text.split("\n")[
            cfg.ANSWERS_BTNS[call.data] + 1][4:]
        correct_answer = question.answers[
            cfg.ANSWERS_BTNS[question.correct_answer] - 1]

        # Очередь очищается от текущего вопроса (и обзаводится новым в некоторых случаях)
        # внутри handler'ов.
        if student_answer == correct_answer:
            datastore[
                day], question, student.queue = stat.right_answer_handler(
                    datastore[day], question,
                    (time.time(), student.qtime_start, student.waiting_time),
                    student.queue)

            bot.send_message(call.message.chat.id,
                             "✅ Верно! Ваш ответ засчитан.")
        else:
            datastore[
                day], question, student.queue = stat.wrong_answer_handler(
                    datastore[day], question, student.queue)

            bot.send_message(
                call.message.chat.id,
                "❌ К сожалению, ответ неправильный, и он не будет засчитан.")

        question.save()

        # Обновить статистику.
        student.data = json.dumps(datastore)
        student.qtime_start = time.time()
        student.waiting_time = 0

        if cfg.DEV_MODE_QUEUE:
            print(
                f"Queue of {student.login} after answering the question (after) "
                + f": {student.queue}",
                end='\n\n')
            print(f"Check update of the stat: {datastore[day]}\n")

        # Если есть вопросы, запланированные на сегодня, то еще раз спросить о готовности
        # и задать вопрос.
        if len(student.queue) != 0 and student.queue[0]["days_left"] <= 0:
            if cfg.DEV_MODE_QUEUE:
                print("Asking one more question\n")
            send_question(student)
        else:
            if cfg.DEV_MODE_QUEUE:
                print("No more questions for today")
            student.status = "standby"
            bot.send_message(
                call.message.chat.id,
                "🏁 На сегодня у меня нет больше к тебе вопросов, до завтра!")

        student.save()