def reply_text_or_edit_with_keyboard(
    message: Message,
    query: Optional[CallbackQuery],
    text: str,
    reply_markup: Union[InlineKeyboardMarkup, str],
    quote: bool = False,
    **kwargs,
):
    # Для запросов CallbackQuery нужно менять текущее сообщение
    if query:
        # Fix error: "telegram.error.BadRequest: Message is not modified"
        if text == query.message.text and is_equal_inline_keyboards(
                reply_markup, query.message.reply_markup):
            return

        try:
            message.edit_text(
                text,
                reply_markup=reply_markup,
                **kwargs,
            )
        except telegram.error.BadRequest as e:
            if 'Message is not modified' in str(e):
                return

            raise e

    else:
        message.reply_text(
            text,
            reply_markup=reply_markup,
            quote=quote,
            **kwargs,
        )
Exemple #2
0
    def update_text(self, message: telegram.Message, text: str):
        """
        Update text function.

        Arguments:
            message : Message to update

            text : New text to send
        """
        if message.text != text:
            try:
                message.edit_text(text)
            except Exception as e:
                pass
Exemple #3
0
def edit_mdv2(tg_msg: TelegramMessage,
              msg_text,
              keyboard=None,
              need_cancel=True):
    cancel_button = InlineKeyboardButton(
        text=GlobalTxt.CANCEL_BUTTON_TEXT,
        callback_data=GlobalTxt.CANCEL_BUTTON_CB_DATA)
    if need_cancel:
        if keyboard:
            keyboard.append([cancel_button])
        else:
            keyboard = [[cancel_button]]

    tg_msg.edit_text(
        text=msg_text,
        parse_mode=ParseMode.MARKDOWN_V2,
        reply_markup=InlineKeyboardMarkup(keyboard) if keyboard else None,
        disable_web_page_preview=True)
Exemple #4
0
    def __iteratively_edit_message(self, message: Message, texts: list,
                                   current_item: int,
                                   time_per_message: timedelta):
        if self.iterating_chats[
                message.chat_id] != message.message_id or current_item > 50:
            return

        message = message.edit_text(texts[current_item % len(texts)])
        current_item += 1

        self.updater.dispatcher.job_queue.run_once(
            lambda job: self.__iteratively_edit_message(
                message, texts, current_item, time_per_message),
            time_per_message)
Exemple #5
0
    def __delayed_type_message_part(self, message: Message, text: str,
                                    current_char: int,
                                    time_per_char: timedelta,
                                    callback: callable):
        while text[0:current_char].strip() == message.text:
            current_char += 1
        partial_text = text[0:current_char]
        message = message.edit_text(partial_text)

        if current_char == len(text):
            callback()
            return

        self.updater.dispatcher.job_queue.run_once(
            lambda job: self.__delayed_type_message_part(
                message, text, current_char + 1, time_per_char, callback),
            time_per_char)
    def edit_message(original: Message,
                     message: any,
                     add_dismiss: bool = True):
        """

        :param original:
        :param message:
        :param add_dismiss:
        :return:
        """

        text, callbacks, sizes = MessageManager.__split_message(message)

        # Get Reply Markup
        reply_markup = MessageManager.__make_reply_markup(
            callbacks, sizes, add_dismiss)

        return original.edit_text(text=text,
                                  parse_mode='HTML',
                                  disable_web_page_preview=True,
                                  reply_markup=reply_markup)
Exemple #7
0
def auto_next_frame(message: Message):
    finish = datetime.datetime.now() + datetime.timedelta(days=1)
    time.sleep(5)
    while finish > datetime.datetime.now():
        try:
            for frame in frames[1:5]:
                try:
                    message.edit_text(
                        text=f"<code>{html.escape(frame)}</code>",
                        parse_mode="HTML",
                    )
                except BadRequest:
                    pass
                time.sleep(1)
            time.sleep(3)
            for frame in frames[5:9]:
                try:
                    message.edit_text(
                        text=f"<code>{html.escape(frame)}</code>",
                        parse_mode="HTML",
                    )
                except:
                    pass
                time.sleep(1)
            time.sleep(7)
        except TimedOut:
            time.sleep(2)
            continue
        except RetryAfter as err:
            print("/norooz: retry after", err.retry_after)
            time.sleep(err.retry_after)
    while 1:
        try:
            message.edit_text(
                text=f"<code>{html.escape(frames[9])}</code>",
                parse_mode="HTML",
            )
            break
        except TimedOut:
            time.sleep(2)
        except RetryAfter:
            print("/norooz: retry after", err.retry_after)
            time.sleep(err.retry_after)
    def _create_timelapse(
            self, printing_filename: str, gcode_name: str,
            info_mess: Message) -> Tuple[BytesIO, BytesIO, int, int, str, str]:
        if not printing_filename:
            raise ValueError("Gcode file name is empty")

        while self.light_need_off:
            time.sleep(1)

        lapse_dir = f"{self._base_dir}/{printing_filename}"

        lock_file = Path(f"{lapse_dir}/lapse.lock")
        if not lock_file.is_file():
            lock_file.touch()

        # Todo: check for nonempty photos!
        photos = glob.glob(f"{glob.escape(lapse_dir)}/*.{self._img_extension}")
        photos.sort(key=os.path.getmtime)
        photo_count = len(photos)

        if photo_count == 0:
            raise ValueError(
                f"Empty photos list for {printing_filename} in lapse path {lapse_dir}"
            )

        info_mess.edit_text(text="Creating thumbnail")
        last_photo = photos[-1]
        img = cv2.imread(last_photo)
        height, width, layers = img.shape
        thumb_bio = self._create_thumb(img)

        video_filename = Path(printing_filename).name
        video_filepath = f"{lapse_dir}/{video_filename}.mp4"
        if Path(video_filepath).is_file():
            os.remove(video_filepath)

        lapse_fps = self._calculate_fps(photo_count)

        with self._camera_lock:
            cv2.setNumThreads(
                self._threads)  # TOdo: check self set and remove!
            out = cv2.VideoWriter(
                video_filepath,
                fourcc=cv2.VideoWriter_fourcc(*self._fourcc),
                fps=lapse_fps,
                frameSize=(width, height),
            )

            info_mess.edit_text(text="Images recoding")
            last_update_time = time.time()
            for fnum, filename in enumerate(photos):
                if time.time() >= last_update_time + 3:
                    info_mess.edit_text(
                        text=f"Images recoded {fnum}/{photo_count}")
                    last_update_time = time.time()

                out.write(cv2.imread(filename))

            info_mess.edit_text(
                text=
                f"Repeating last image for {self._last_frame_duration} seconds"
            )
            for _ in range(lapse_fps * self._last_frame_duration):
                out.write(img)

            out.release()
            cv2.destroyAllWindows()
            del out

        del photos, img, layers

        # Todo: some error handling?

        video_bio = BytesIO()
        video_bio.name = f"{video_filename}.mp4"
        target_video_file = f"{self._ready_dir}/{printing_filename}.mp4"
        with open(video_filepath, "rb") as fh:
            video_bio.write(fh.read())
        if self._ready_dir and os.path.isdir(self._ready_dir):
            info_mess.edit_text(text="Copy lapse to target ditectory")
            Path(target_video_file).parent.mkdir(parents=True, exist_ok=True)
            with open(target_video_file, "wb") as cpf:
                cpf.write(video_bio.getvalue())
        video_bio.seek(0)

        os.remove(f"{lapse_dir}/lapse.lock")

        return video_bio, thumb_bio, width, height, video_filepath, gcode_name
Exemple #9
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')}.")