コード例 #1
0
ファイル: utils.py プロジェクト: BESTLviv/EJF_Vacancies
def delete_message(bot: TeleBot, call: CallbackQuery):
    chat_id = call.message.chat_id
    message_id = call.message.message_id

    try:
        bot.delete_message(chat_id, message_id)

    except:
        bot.answer_callback_query(call.id,
                                  text="Щоб продовжити натискай на /start")
コード例 #2
0
ファイル: inline_calendar.py プロジェクト: edition89/projects
def calendar_query_handler(
    bot: TeleBot,
    call: CallbackQuery,
    name: str,
    action: str,
    year: int,
    month: int,
    day: int,
) -> None or datetime.datetime:
    """
    The method creates a new calendar if the forward or backward button is pressed
    This method should be called inside CallbackQueryHandler.
    :param bot: The object of the bot CallbackQueryHandler
    :param call: CallbackQueryHandler data
    :param day:
    :param month:
    :param year:
    :param action:
    :param name:
    :return: Returns a tuple
    """

    current = datetime.datetime(int(year), int(month), 1)
    if action == "IGNORE":
        bot.answer_callback_query(callback_query_id=call.id)
        return False, None
    elif action == "DAY":
        bot.delete_message(chat_id=call.message.chat.id,
                           message_id=call.message.message_id)
        return datetime.datetime(int(year), int(month), int(day))
    elif action == "PREVIOUS-MONTH":
        preview_month = current - datetime.timedelta(days=1)
        bot.edit_message_text(
            text=call.message.text,
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            reply_markup=create_calendar(name=name,
                                         year=int(preview_month.year),
                                         month=int(preview_month.month)),
        )
        return None
    elif action == "NEXT-MONTH":
        next_month = current + datetime.timedelta(days=31)
        bot.edit_message_text(
            text=call.message.text,
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            reply_markup=create_calendar(name=name,
                                         year=int(next_month.year),
                                         month=int(next_month.month)),
        )
        return None
    elif action == "MONTHS":
        bot.edit_message_text(
            text=call.message.text,
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            reply_markup=create_months_calendar(name=name, year=current.year),
        )
        return None
    elif action == "MONTH":
        bot.edit_message_text(
            text=call.message.text,
            chat_id=call.message.chat.id,
            message_id=call.message.message_id,
            reply_markup=create_calendar(name=name,
                                         year=int(year),
                                         month=int(month)),
        )
        return None
    elif action == "Выход":
        bot.delete_message(chat_id=call.message.chat.id,
                           message_id=call.message.message_id)
        return "Выход", None
    else:
        #bot.answer_callback_query(callback_query_id=call.id, text="ERROR!")
        bot.delete_message(chat_id=call.message.chat.id,
                           message_id=call.message.message_id)
        return None
コード例 #3
0
class BOT:
    index = 0
    count_films = utils.STEP
    config_file_name = 'config.json'

    def __init__(self):
        self.cfg = self.JSON()
        self.construct()

    def construct(self):
        self.bot = TeleBot(self.cfg['token'])
        self.commands = {
            "List films": utils.call(self.manage),
            "Unsubscribe": utils.call(self.del_user),
        }
        self.film_view_markup = {
            "back": utils.call(self.revert),
            "open": utils.call(lambda *x, **b:...),
        }
        self.markup = {
            "1": utils.call(self.film, 0),
            "2": utils.call(self.film, 1),
            "3": utils.call(self.film, 2),
            "4": utils.call(self.film, 3),
            "5": utils.call(self.film, 4),
            "6": utils.call(self.film, 5),
            "7": utils.call(self.film, 6),
            "8": utils.call(self.film, 7),
            "9": utils.call(self.film, 8),
            "10": utils.call(self.film, 9),
            "prev": utils.call(self.prev),
            "next": utils.call(self.next),
        }

        @self.bot.message_handler(
            commands=['subscribe', 'unsubscribe', 'categories', 'find'])
        def subscribe_detector(message):
            try:
                if "/subscribe" in message.text:
                    category = message.text.split("/subscribe")[-1].strip()
                    if category in list(self.cfg['categories'].keys()):
                        uinfo = (message.chat.id, category)
                        db = utils.DATABASE(self.cfg["db_name"])
                        db.insert(table_name="subscribe_categories",
                                  args=uinfo)
                        self.bot.reply_to(
                            message, self.cfg["subscribe_category"].replace(
                                "{}", category))
                    else:
                        self.bot.send_message(message.chat.id,
                                              self.cfg["category_not_found"])

                elif "/unsubscribe" in message.text:
                    category = message.text.split("/unsubscribe")[-1].strip()
                    if category in self.cfg['categories']:
                        db = utils.DATABASE(self.cfg["db_name"])
                        db.delete(table_name="subscribe_categories",
                                  where=" chat_id =  " + str(message.chat.id))
                        self.bot.reply_to(
                            message, self.cfg["unsibscribe_category"].replace(
                                "{}", category))
                    else:
                        self.bot.send_message(message.chat.id,
                                              self.cfg["category_not_found"])

                elif "/find" in message.text:
                    film_name = message.text.split("/find")[-1].strip()
                    finded = utils.load_films(
                        db_name=self.cfg['db_name'],
                        find_perc=[film_name, self.cfg['film_perc']])
                    finded.extend(
                        utils.load_films(db_name=self.cfg['db_name'],
                                         find=film_name))

                    message_ = ""
                    for i, film in enumerate(finded):
                        message_ += "{}. {}\n{}\n\n".format(
                            i + 1, film[1], film[3])

                    messages_ = []

                    if len(message_) > 2800:
                        count = int(len(message_) / 2800)
                        s = 0
                        for i in range(count):
                            ns = s + 2800
                            if len(message_) < ns:
                                ns = -1
                            msg = message_[s:ns]
                            messages_.append(msg)
                            s = ns
                            if not ns:
                                break
                    else:
                        messages_.append(message_)

                    for msg in messages_:
                        if len(msg) > 2:
                            self.bot.send_message(message.chat.id, msg)
                        else:
                            self.bot.send_message(message.chat.id,
                                                  self.cgf['no_film_error'])

                elif "/categories" in message.text:
                    msg = ""
                    for i, key in enumerate(list(self.cfg["categories"])):
                        msg += "{} : {}\n".format(i, key)

                    self.bot.send_message(
                        message.chat.id,
                        self.cfg['categories_text'].replace("{}", msg))

            except Exception as e:
                # utils.log(e)
                raise

        @self.bot.callback_query_handler(func=lambda call: True)
        def callback_query(call):
            try:
                if call.data in self.markup.keys():
                    self.markup[call.data](call)
                elif call.data in self.film_view_markup.keys():
                    self.film_view_markup[call.data](call)
            except Exception as e:
                utils.log(e)

        @self.bot.message_handler(func=lambda x: True)
        def main(message):
            try:
                utils.add_user(message=message, db_name=self.cfg['db_name'])
                if message.text in self.commands:
                    self.commands[message.text](message)
                else:
                    self.bot.send_message(message.chat.id,
                                          text=self.cfg['base_message'],
                                          reply_markup=utils.repl_markup(
                                              list(self.commands.keys())))
            except Exception as e:
                utils.log(e)

    def JSON(self):
        return utils.loads(open(self.config_file_name).read())

    def del_user(self, message):
        self.bot.send_message(message.chat.id, self.cfg["global_unsubscribe"])
        utils.delete_subscriber(message.chat.id, db_name=self.cfg['db_name'])

    def manage(self, message, text=None):
        self.bot.send_message(
            message.chat.id,
            text=utils.new_message(
                msg=text if text else self.cfg['default_message'],
                db_name=self.cfg["db_name"],
                repl=self.cfg['message_repl']),
            reply_markup=utils.inline_markup(self.markup))

    def revert(self, call):
        id = call.message.chat.id
        messages = utils.new_message(index=self.index,
                                     msg=self.cfg['default_message'],
                                     repl=self.cfg['message_repl'],
                                     db_name=self.cfg["db_name"])
        self.bot.delete_message(id, call.message.message_id)
        self.bot.send_message(id,
                              text=messages,
                              reply_markup=utils.inline_markup(self.markup))
        self.bot.answer_callback_query(call.id, "Success")

    def send_all(self, msg):
        mkp = utils.repl_markup(utils.START_MARKUP)
        for id in utils.get_all_subscribers_id(db_name=self.cfg["db_name"]):
            try:
                self.bot.send_message(id, msg, reply_markup=mkp)
            except Exception as e:
                utils.delete_subscriber(id, db_name=self.cfg["db_name"])

    def film(self, call, id=0):
        id_ = call.message.chat.id

        db = utils.DATABASE(self.cfg['db_name'])
        film_info = db.read(table_name="films",
                            where=" id = '{}'".format(
                                utils.class_db.film_list[id][1]))[0]
        db.close()

        def download():
            utils.image_download(film_info[2])

        t = Thread(target=download)
        t.start()
        t.join()

        self.bot.delete_message(id_, call.message.message_id)

        self.bot.send_photo(
            chat_id=id_,
            photo=open(".image.jpg", "rb"),
            reply_markup=utils.inline_markup(self.film_view_markup),
            caption=utils.render_film_info(film_info[0],
                                           db_name=self.cfg["db_name"]))

    def next(self, call):
        utils.class_db.index += utils.STEP

        messages = utils.new_message(msg=self.cfg['default_message'],
                                     repl=self.cfg['message_repl'],
                                     index=utils.class_db.index,
                                     db_name=self.cfg["db_name"])
        self.bot.edit_message_text(text=messages,
                                   chat_id=call.message.chat.id,
                                   message_id=call.message.message_id,
                                   reply_markup=utils.inline_markup(
                                       self.markup),
                                   inline_message_id=call.inline_message_id)

    def prev(self, call):
        utils.class_db.index -= utils.STEP
        if utils.class_db.index < 0:
            utils.class_db.index = 0
            self.bot.answer_callback_query(call.id, self.cfg['no_films_error'])
            return True

        message = utils.new_message(msg=self.cfg['default_message'],
                                    repl=self.cfg['message_repl'],
                                    index=utils.class_db.index,
                                    db_name=self.cfg["db_name"])
        self.bot.edit_message_text(text=message,
                                   chat_id=call.message.chat.id,
                                   message_id=call.message.message_id,
                                   reply_markup=utils.inline_markup(
                                       self.markup),
                                   inline_message_id=call.inline_message_id)

    def start(self, msg=True):
        if msg:
            self.send_all(self.cfg["start_message"])
        utils.new_message(msg=self.cfg['default_message'],
                          repl=self.cfg['message_repl'],
                          db_name=self.cfg["db_name"])
        self.bot.polling()

    def stop(self):
        self.bot.stop_polling()
コード例 #4
0
 def process_callback(self, callback: CallbackQuery, user, bot: TeleBot):
     bot.answer_callback_query(callback.id)
     return RET.OK, None, None, None
コード例 #5
0
class ColorCodeBot:
    def __init__(self,
                 api_key: str,
                 lang: Mapping[str, str],
                 theme_image_ids: tuple[str],
                 keyboards: Mapping[str, InlineKeyboardMarkup],
                 guesslang_syntaxes: Mapping[str, str],
                 *args: Any,
                 admin_chat_id: Optional[str] = None,
                 db_path: str = str(
                     local.path(__file__).up() / 'user_themes.sqlite'),
                 **kwargs: Any):
        self.lang = lang
        self.theme_image_ids = theme_image_ids
        self.kb = keyboards
        self.guesslang_syntaxes = guesslang_syntaxes
        self.admin_chat_id = admin_chat_id
        self.db_path = db_path
        self.user_themes = KeyValue(key_field=IntegerField(primary_key=True),
                                    value_field=CharField(),
                                    database=APSWDatabase(db_path))
        self.log = mk_logger()
        self.bot = TeleBot(api_key, *args, **kwargs)
        self.register_handlers()
        self.guesser = Guess()

    def register_handlers(self):
        self.welcome = self.bot.message_handler(commands=['start', 'help'])(
            self.welcome)
        self.browse_themes = self.bot.message_handler(
            commands=['theme', 'themes'])(self.browse_themes)
        self.mk_theme_previews = self.bot.message_handler(
            commands=['previews'])(self.mk_theme_previews)
        self.intake_snippet = self.bot.message_handler(
            func=lambda m: m.content_type == 'text')(self.intake_snippet)
        self.recv_photo = self.bot.message_handler(content_types=['photo'])(
            self.recv_photo)
        self.restore_kb = self.bot.callback_query_handler(
            lambda q: yload(q.data)['action'] == 'restore')(self.restore_kb)
        self.set_snippet_filetype = self.bot.callback_query_handler(
            lambda q: yload(q.data)['action'] == 'set ext')(
                self.set_snippet_filetype)
        self.set_theme = self.bot.callback_query_handler(
            lambda q: yload(q.data)['action'] == 'set theme')(self.set_theme)
        self.send_photo_elsewhere = self.bot.inline_handler(
            lambda q: q.query.startswith("img "))(self.send_photo_elsewhere)
        self.switch_from_inline = self.bot.inline_handler(lambda q: True)(
            self.switch_from_inline)

    @retry
    def switch_from_inline(self, inline_query: InlineQuery):
        self.log.msg("receiving inline query",
                     user_id=inline_query.from_user.id,
                     user_first_name=inline_query.from_user.first_name,
                     query=inline_query.query)
        self.bot.answer_inline_query(
            inline_query.id, [],
            switch_pm_text=self.lang['switch to direct'],
            switch_pm_parameter='x')

    @retry
    def welcome(self, message: Message):
        self.log.msg("introducing myself",
                     user_id=message.from_user.id,
                     user_first_name=message.from_user.first_name,
                     chat_id=message.chat.id)
        self.bot.reply_to(
            message,
            self.lang['welcome'],
            reply_markup=ForceReply(
                input_field_placeholder=self.lang['input field placeholder']))

    @retry
    def mk_theme_previews(self, message: Message):
        if not self.admin_chat_id or str(
                message.chat.id) != self.admin_chat_id:
            self.log.msg("naughty preview attempt",
                         user_id=message.from_user.id,
                         user_first_name=message.from_user.first_name,
                         chat_id=message.chat.id,
                         admin_chat_id=self.admin_chat_id)
            return
        sample_code = dedent("""
            # palinDay :: Int -> [ISO Date]
            def palinDay(y):
                '''A possibly empty list containing the palindromic
                   date for the given year, if such a date exists.
                '''
                s = str(y)
                r = s[::-1]
                iso = '-'.join([s, r[0:2], r[2:]])
                try:
                    datetime.strptime(iso, '%Y-%m-%d')
                    return [iso]
                except ValueError:
                    return []
        """)
        for button in chain.from_iterable(self.kb['theme'].keyboard):
            theme = button.text
            html = mk_html(f"# {theme}{sample_code}", 'py', theme)
            with local.tempdir() as folder:
                png_path = mk_png(html, folder=folder)
                send_image(bot=self.bot,
                           chat_id=message.chat.id,
                           png_path=png_path,
                           reply_msg_id=message.message_id)

    @retry
    def browse_themes(self, message: Message):
        self.log.msg("browsing themes",
                     user_id=message.from_user.id,
                     user_first_name=message.from_user.first_name,
                     chat_id=message.chat.id)
        albums = [
            self.theme_image_ids[i:i + 10]
            for i in range(0, len(self.theme_image_ids), 10)
        ]
        for album in albums:
            self.bot.send_media_group(message.chat.id,
                                      map(InputMediaPhoto, album),
                                      reply_to_message_id=message.message_id)
        self.bot.reply_to(message,
                          self.lang['select theme'],
                          reply_markup=self.kb['theme'])

    @retry
    def set_theme(self, cb_query: CallbackQuery):
        data = yload(cb_query.data)
        user = cb_query.message.reply_to_message.from_user
        self.log.msg("setting theme",
                     user_id=user.id,
                     user_first_name=user.first_name,
                     theme=data['theme'],
                     chat_id=cb_query.message.chat.id)
        self.bot.edit_message_reply_markup(cb_query.message.chat.id,
                                           cb_query.message.message_id,
                                           reply_markup=minikb('theme'))
        self.user_themes[user.id] = data['theme']
        self.bot.answer_callback_query(
            cb_query.id,
            text=self.lang['acknowledge theme'].format(data['theme']))
        if self.admin_chat_id:
            with open(self.db_path, 'rb') as doc:
                self.bot.send_document(self.admin_chat_id, doc)

    def guess_ext(self,
                  code: str,
                  probability_min: float = .12) -> Optional[str]:
        syntax, probability = self.guesser.probabilities(code)[0]
        ext = self.guesslang_syntaxes.get(syntax)
        self.log.msg("guessed syntax",
                     probability_min=probability_min,
                     probability=probability,
                     syntax=syntax,
                     ext=ext)
        if probability >= probability_min:
            return ext
        for start, ext in {
                '{': 'json',
                '---\n': 'yaml',
                '[[': 'toml',
                '[': 'ini',
                '<?php': 'php',
                '<': 'xml',
                '-- ': 'lua'
        }.items():
            if code.startswith(start):
                return ext

    @retry
    def intake_snippet(self, message: Message):
        self.log.msg("receiving code",
                     user_id=message.from_user.id,
                     user_first_name=message.from_user.first_name,
                     chat_id=message.chat.id)
        ext = self.guess_ext(message.text)
        if ext:
            kb_msg = self.bot.reply_to(
                message,
                f"{self.lang['query ext']}\n\n{self.lang['guessed syntax'].format(ext)}",
                reply_markup=minikb('syntax', self.lang['syntax picker']),
                parse_mode='Markdown',
                disable_web_page_preview=True)
            self.set_snippet_filetype(cb_query=None,
                                      query_message=kb_msg,
                                      ext=ext)
        else:
            self.bot.reply_to(message,
                              self.lang['query ext'],
                              reply_markup=self.kb['syntax'],
                              parse_mode='Markdown',
                              disable_web_page_preview=True)

    @retry
    def send_photo_elsewhere(self, inline_query: InlineQuery):
        file_id = inline_query.query.split('img ', 1)[-1]
        self.log.msg("creating inline query result",
                     file_id=file_id,
                     file_info=self.bot.get_file(file_id))
        self.bot.answer_inline_query(inline_query.id, [
            InlineQueryResultCachedPhoto(
                id=str(uuid4()), photo_file_id=file_id, title="Send Image")
        ],
                                     is_personal=True)

    @retry
    def restore_kb(self, cb_query: CallbackQuery):
        data = yload(cb_query.data)
        self.bot.edit_message_reply_markup(
            cb_query.message.chat.id,
            cb_query.message.message_id,
            reply_markup=self.kb[data['kb_name']])
        self.bot.answer_callback_query(cb_query.id)

    @retry
    def set_snippet_filetype(self,
                             cb_query: Optional[CallbackQuery] = None,
                             query_message: Optional[Message] = None,
                             ext: Optional[str] = None):
        if cb_query:
            query_message = cb_query.message
            ext = yload(cb_query.data)['ext']
        elif not (query_message and ext):
            raise Exception(
                "Either cb_query or both query_message and ext are required")
        self.log.msg("colorizing code",
                     user_id=query_message.reply_to_message.from_user.id,
                     user_first_name=query_message.reply_to_message.from_user.
                     first_name,
                     syntax=ext,
                     chat_id=query_message.chat.id)
        if cb_query:
            self.bot.edit_message_reply_markup(query_message.chat.id,
                                               query_message.message_id,
                                               reply_markup=minikb(
                                                   'syntax',
                                                   self.lang['syntax picker']))
        snippet = query_message.reply_to_message
        theme = self.user_themes.get(snippet.from_user.id,
                                     'base16/gruvbox-dark-hard')

        html = mk_html(snippet.text, ext, theme)
        send_html(bot=self.bot,
                  chat_id=snippet.chat.id,
                  html=html,
                  reply_msg_id=snippet.message_id)

        with local.tempdir() as folder:
            png_path = mk_png(html, folder=folder)
            did_send = False
            if len(snippet.text.splitlines()) <= 30:
                try:
                    photo_msg = send_image(bot=self.bot,
                                           chat_id=snippet.chat.id,
                                           png_path=png_path,
                                           reply_msg_id=snippet.message_id)
                except ApiException as e:
                    self.log.error("failed to send compressed image",
                                   exc_info=e,
                                   chat_id=snippet.chat.id)
                else:
                    did_send = True
                    kb_to_chat = InlineKeyboardMarkup()
                    kb_to_chat.add(
                        InlineKeyboardButton(
                            self.lang['send to chat'],
                            switch_inline_query=
                            f"img {photo_msg.photo[-1].file_id}"))
                    self.bot.edit_message_reply_markup(photo_msg.chat.id,
                                                       photo_msg.message_id,
                                                       reply_markup=kb_to_chat)
            if not did_send:
                send_image(bot=self.bot,
                           chat_id=snippet.chat.id,
                           png_path=png_path,
                           reply_msg_id=snippet.message_id,
                           compress=False)

        if cb_query:
            self.bot.answer_callback_query(cb_query.id)

    def recv_photo(self, message: Message):
        self.log.msg('received photo',
                     file_id=message.photo[0].file_id,
                     user_id=message.from_user.id,
                     user_first_name=message.from_user.first_name,
                     chat_id=message.chat.id)
コード例 #6
0
keyboard.add(url_button)
url_button = types.InlineKeyboardButton(text="Гид по Python на русском",
                                        url="https://pythonworld.ru/")
keyboard.add(url_button)
bot.send_message(message.chat.id, "Нажимай", reply_markup=keyboard)


@bot.callback_query_handler(func=lambda call: True)
def do_callback(call):
    if call.data == "dead":
        mess = choice(["Ты умер", "Ты молодец", "Ты сдох"])


bot.send_message(call.message.chat.id, mess)
bot.answer_callback_query(callback_query_id=call.id,
                          show_alert=False,
                          text="Пыщь!")


@bot.message_handler(func=lambda message: True)
def say_hello(message):
    if message.text.lower() == 'Привет':
        bot.send_message(message.chat.id, "Добрый День!")
    if message.text.lower() == 'СаламуАлейкум':
        bot.send_message(message.chat.id, 'ВаалейкумАссалам')
    if message.text.lower() == 'Как дела?':
        bot.send_message(message.chat.id, "Все хорошо")
    if message.text.lower() == 'Как тебя зовут?':
        bot.send_message(message.chat.id, "Меня зовут Махмудин :)")
    if message.text.lower() == 'Чем занимаешься?':
        bot.send_message(message.chat.id, "Нахожусь в разработке")
コード例 #7
0
class TelegramBot:
    def __init__(self):
        social_app = SocialApp.objects.last()
        TELEGRAM_TOKEN = social_app.secret
        TELEGRAM_WEBHOOK_HOST = social_app.sites.last().domain
        TELEGRAM_WEBHOOK_PATH = reverse("telegrambot:webhook")
        self.bot = TeleBot(TELEGRAM_TOKEN)
        self.WEBHOOK_URL = f"https://{TELEGRAM_WEBHOOK_HOST}{TELEGRAM_WEBHOOK_PATH}"
        logger.debug("%s: __init__()", self.__class__)

    def send_message(self, chat_id: int, text: str, reply_markup=None):
        try:
            self.bot.send_message(chat_id, text, reply_markup=reply_markup)
        except apihelper.ApiTelegramException as msg:
            logger.exception(msg)
        logger.debug(f"{self.__class__}: send_message({chat_id}, {text})")

    def send_photo(self,
                   chat_id: str,
                   photo_path: str,
                   caption=None,
                   reply_markup=None):
        with open(photo_path, "rb") as photo_file:
            photo = photo_file.read()
        try:
            self.bot.send_photo(chat_id,
                                photo=photo,
                                caption=caption,
                                reply_markup=reply_markup)
        except apihelper.ApiTelegramException as msg:
            logger.exception(msg)
            logger.info(
                f"{self.__class__}: User {chat_id} baned your TelegramBot")
        else:
            logger.debug(
                f"{self.__class__}: send_photo({chat_id}, {photo_path})")

    def answer_callback_query(self,
                              callback_id,
                              text=None,
                              show_alert=None,
                              url=None,
                              cache_time=None):
        self.bot.answer_callback_query(
            callback_id,
            text=text,
            show_alert=show_alert,
            url=url,
            cache_time=cache_time,
        )

    def set_webhook(self):
        logger.debug("%s: set_hook() %s" % (self.__class__, self.WEBHOOK_URL))
        return self.bot.set_webhook(url=self.WEBHOOK_URL)

    def remove_webhook(self):
        logger.debug("%s: remove_webhook()", self.__class__)
        return self.bot.remove_webhook()

    def get_kb_phone(self):
        keyboard = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
        button_phone = types.KeyboardButton(text="Отправить номер телефона",
                                            request_contact=True)
        button_geo = types.KeyboardButton(text="Отправить местоположение",
                                          request_location=True)
        keyboard.add(button_phone, button_geo)
        return keyboard

    def get_kb_catalog(self):
        keyboard = types.ReplyKeyboardMarkup(row_width=1,
                                             resize_keyboard=True,
                                             one_time_keyboard=True)
        buttons = [
            types.KeyboardButton(text=item.name)
            for item in models.Catalog.objects.all()
        ]
        keyboard.add(*buttons)
        return keyboard

    def get_kb_inline_buy(self, product):
        keyboard = types.InlineKeyboardMarkup()
        buy = _("Buy")
        text = f"{buy}: {product.name}"
        buy_btn = types.InlineKeyboardButton(text,
                                             callback_data=str(product.id))
        keyboard.add(buy_btn)
        return keyboard