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")
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
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()
def process_callback(self, callback: CallbackQuery, user, bot: TeleBot): bot.answer_callback_query(callback.id) return RET.OK, None, None, None
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)
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, "Нахожусь в разработке")
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