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)
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)
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))
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')}.")