Example #1
0
def send_titles_message(chat: Chat, chat_data: 'models.GroupChat',
                        titles_plain: str, titles: str):
    # To avoid excessive notifications for participants who got a title we initially send a message
    # with participant names in plain text and then edit sent message to add inline mentions to names
    do_edit = False
    if chat_data.last_given_titles_count is None:
        titles_text = strings.NO_PARTICIPANTS
    elif chat_data.last_given_titles_count == 0:
        titles_text = strings.NO_TITLES_IN_POOL
    else:
        titles_text = strings.MESSAGE__DAILY_TITLES.format(
            assigned_titles=titles_plain)
        do_edit = True
    send_message_kwargs = dict(parse_mode=ParseMode.MARKDOWN_V2,
                               reply_markup=PARTICIPATION_BUTTONS)
    try:
        sent_message = chat.send_message(titles_text, **send_message_kwargs)
    except telegram.error.ChatMigrated as error:
        new_chat_id = error.new_chat_id
        _logger.info('Trying to migrate chat data for id %d to new id %d',
                     chat.id, new_chat_id)
        session: Session = Session.object_session(chat_data)
        if not try_migrate_chat_data(session, chat_data, chat.id, new_chat_id):
            return
        _logger.info('Trying to resend message to %d', new_chat_id)
        sent_message = chat.bot.send_message(new_chat_id, titles_text,
                                             **send_message_kwargs)
    if do_edit:
        new_text = strings.MESSAGE__DAILY_TITLES.format(assigned_titles=titles)
        sent_message.edit_text(new_text, **send_message_kwargs)
Example #2
0
def send_mdv2_chat(chat: TelegramChat,
                   msg_text,
                   inline_keyboard=None,
                   reply_id=None,
                   need_cancel=False):
    if need_cancel:
        if inline_keyboard:
            inline_keyboard.append([CANCEL_BUTTON])
        else:
            inline_keyboard = [[CANCEL_BUTTON]]

    chat.send_message(text=msg_text,
                      parse_mode=ParseMode.MARKDOWN_V2,
                      reply_markup=InlineKeyboardMarkup(inline_keyboard)
                      if inline_keyboard else None,
                      disable_web_page_preview=True,
                      reply_to_message_id=reply_id)
Example #3
0
def attempt_interaction(command: Command, record: ChatRecord, chat: Chat,
                        is_private: bool, message: Message, *args):
    """
    This function is called when an interaction makes sense to be started. It is responsible for deciding whether it
    will, which is the case if the command is available for the user's role and the chat is not already having an
    interaction. Also, if the command starts a private interaction and is used in a non-private chat, the bot replies to
    the message informing that the interaction will be started privately and sends a private message to do it. However,
    if the interaction will not be started, the bot sends a message explaining why, which is a reply in non-private
    chats.

    Args:
        command (src.bot.managers.Command): namedtuple that represents the received command.
        record (src.bot.auxiliary.ChatRecord): record of the user who is using the command.
        chat (telegram.Chat): chat the the command is being used in.
        is_private (bool): whether that chat is private.
        message (telegram.Message): message that the command is sent in.
        args: arguments that will be passed to the interaction besides the record, if it will be started.
    """
    if record.role >= command.role:

        if record.id not in i.current:  # if the chat is not already having an interaction
            # if the interaction is private but the chat is not
            if command.interaction.IS_PRIVATE and not is_private:
                chat.send_message(t.PRIVATE_INTERACTION[record.language],
                                  reply_to_message_id=message.message_id)
                l.cl.info(
                    l.STARTS_NOT_PRIVATELY.format(
                        record.id, command.interaction.__name__))

            command.interaction(record, *args)

        else:  # if the chat is already having an interaction
            i.current[record.id].respond(command.interaction.COMMAND, message)

    else:  # if the command is an admin one and the user is not an admin
        text = command.interaction.UNAVAILABLE_MESSAGE[record.language]
        chat.send_message(
            text,
            reply_to_message_id=None if is_private else message.message_id)
        l.cl.info(
            l.UNAVAILABLE_COMMAND.format(record.id,
                                         command.interaction.COMMAND,
                                         record.role))
Example #4
0
def send_plan(userid: str, chat: Chat, new_plan=True, message: Message = None, date=None, custom_name=None):
    if not date:
        date = datetime.today()
    logging.debug("/send_plan")
    if date.weekday() == 5:
        date += timedelta(days=2)
    elif date.weekday() == 6:
        date += timedelta(days=1)

    def date_to_name(_date):
        return ("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag")[date.weekday()]

    def construct_message(day, _substitution, _date, _infos):

        week = "B"
        if _date.isocalendar()[1] % 2 == 0:  # even = A
            week = "A"

        msg = "```"
        msg += f' {week}  {date_to_name(_date).ljust(7)}  {_date.strftime("%d-%m-%y")}'

        # plan
        for row in range(len(day)):  # for every lesson
            if day[row] != "---":  # if day not empty
                msg += f'\n{row + 1}  '
                msg += f"{day[row].split(' ')[1].rjust(7)} "
                msg += f"{day[row].split(' ')[2].ljust(4)} "
                if len(day[row].split(' ')) > 3:
                    msg += f"{day[row].split(' ')[3]} "

                # add substitution plan infos
                # possible types: Vertr. | Verlegung | Raum | Vtr. | enfälllt | EVA | Betreuung | Unterricht geändert | Trotz Absenz
                for entry in _substitution:
                    if entry["subject"] == day[row].split(" ")[1]:  # if substitution matches a subject
                        subst_msg = "-> "
                        if entry["type"] == "entfälllt":
                            subst_msg += f"Entfall"
                        else:
                            something_changed = False  # append type of entry to message (to prevent empty arrows ->   )
                            if entry["teacher"] != day[row].split(" ")[2]:
                                subst_msg += f"{entry['teacher']} "
                                something_changed = True
                            if entry["room"] != day[row].split(" ")[3]:
                                subst_msg += f"{entry['room']} "
                                something_changed = True
                            if not something_changed:
                                subst_msg += f"{entry['type']} "
                        if len(subst_msg) > 10:
                            subst_msg = "\n   " + subst_msg
                        msg += subst_msg
                        break
            else:
                msg += f'\n{row + 1}'

        # info
        msg += "\n"
        for info in _infos:
            if info[0] not in ["Abwesende Lehrer", "Blockierte Räume", "Betroffene Klassen"]:
                msg += "\n" + " - ".join(info)

        msg += "```"
        return msg

    if custom_name:
        name = custom_name
    else:
        userdata = load_userdata()
        if userid not in userdata or userdata[userid][0] == "":
            userdata[userid] = ["", chat.id]
            save_userdata(userdata)
            chat.send_message("Bitte gib mir die Login-Daten für deinen Stundenplan (Nachname).",
                              reply_markup=ForceReply())
            return

        name = userdata[userid][0]

    splan = Stundenplan(name)
    vplan_obj = Vertretungsplan()
    vplan = vplan_obj.get_filtered(splan)
    if date.strftime("%d-%m-%y") in vplan:  # get only substitution info for that date
        substitution = vplan[date.strftime("%d-%m-%y")]
    else:  # empty list if none
        substitution = []

    if date.strftime("%d-%m-%y") in vplan_obj.infos:  # get only substitution info for that date
        infos = vplan_obj.infos[date.strftime("%d-%m-%y")]
    else:  # empty list if none
        infos = []

    new_message = construct_message(splan.get_day(date), substitution, date, infos)

    # inline keyboard date already contains date for previous and next plans
    next_date = (date + timedelta(days=1))
    prev_date = (date - timedelta(days=1))
    if next_date.weekday() == 5:
        next_date += timedelta(days=2)
    if prev_date.weekday() == 6:
        prev_date -= timedelta(days=2)

    reply_markup = InlineKeyboardMarkup([[
        InlineKeyboardButton(ARROW_LEFT, callback_data=f'plan {prev_date.strftime("%d-%m-%y")}'),
        InlineKeyboardButton(ARROW_RIGHT, callback_data=f'plan {next_date.strftime("%d-%m-%y")}')
    ]])
    if new_plan:
        chat.send_message(new_message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN_V2)
        add_admin_log(f"Sent plan to {userid}, date={date.strftime('%d-%m-%y')}.")
    else:
        message.edit_text(new_message, reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN_V2)
        add_admin_log(f"Sent plan to {userid}, date={date.strftime('%d-%m-%y')}.")