def append_restricted_delete_button( update, chat_data, reply_markup ) -> Tuple[Optional[ReplyMarkup], Callable[[Message], None]]: uid = update.effective_user.id command_mid = update.effective_message.message_id if not util.is_group_message(update) or not isinstance( reply_markup, InlineKeyboardMarkup): return reply_markup, lambda _: None def append_callback(message): if message is None: # No message was saved return if isinstance(message, Message): mid = message.message_id else: mid = message deletions_pending = chat_data.get("deletions_pending", dict()) if not deletions_pending.get(mid): deletions_pending[mid] = dict(user_id=uid, command_id=command_mid) chat_data["deletions_pending"] = deletions_pending buttons = reply_markup.inline_keyboard buttons.append([ InlineKeyboardButton( captions.random_done_delete(), callback_data=util.callback_for_action( CallbackActions.DELETE_CONVERSATION), ) ]) reply_markup.inline_keyboard = buttons return reply_markup, append_callback
def manage_subscription(bot, update): chat_id = update.effective_chat.id user_id = update.effective_user.id if util.is_group_message(update): admins = bot.get_chat_administrators(chat_id) if user_id not in admins: bot.formatter.send_failure( chat_id, "Sorry, but only Administrators of this group are allowed " "to manage subscriptions.") return text = "Would you like to be notified when new bots arrive at the @BotList?" buttons = [[ InlineKeyboardButton(util.success("Yes"), callback_data=util.callback_for_action( CallbackActions.SET_NOTIFICATIONS, {'value': True})), InlineKeyboardButton("No", callback_data=util.callback_for_action( CallbackActions.SET_NOTIFICATIONS, {'value': False})) ]] reply_markup = InlineKeyboardMarkup(buttons) msg = util.send_md_message(bot, chat_id, text, reply_markup=reply_markup) return ConversationHandler.END
def search_handler(bot, update, chat_data, args=None): if args: search_query(bot, update, chat_data, " ".join(args)) else: # no search term if util.is_group_message(update): action = const.DeepLinkingActions.SEARCH sent_msg = update.message.reply_text( "Please use the search command with arguments, inlinequeries or continue in private. " "Example: `/search awesome bot`", quote=True, parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup([[ InlineKeyboardButton("🔎 Search inline", switch_inline_query_current_chat=""), InlineKeyboardButton( captions.SWITCH_PRIVATE, url="https://t.me/{}?start={}".format( settings.SELF_BOT_NAME, action), ), ]]), ) try_delete_after(appglobals.job_queue, [sent_msg, update.effective_message], delay=10) else: update.message.reply_text(messages.SEARCH_MESSAGE, reply_markup=ForceReply(selective=True)) return ConversationHandler.END
def append_free_delete_button(update, reply_markup) -> Optional[ReplyMarkup]: if not util.is_group_message(update) or not isinstance( reply_markup, InlineKeyboardMarkup): return reply_markup buttons = reply_markup.inline_keyboard buttons.append([ InlineKeyboardButton( captions.random_done_delete(), callback_data=util.callback_for_action( CallbackActions.DELETE_CONVERSATION), ) ]) reply_markup.inline_keyboard = buttons return reply_markup
def hint_handler(bot, update, job_queue: JobQueue): chat_id = update.message.chat_id if not util.is_group_message(update): return text = update.message.text reply_to = update.message.reply_to_message user = User.from_update(update) msg, reply_markup, hashtag = get_hint_data(text) def _send_hint(hint_text): if hint_text is None: return if reply_to: hint_text = f"{user.markdown_short} hints: {hint_text}" bot.formatter.send_message( chat_id, hint_text, reply_markup=reply_markup, reply_to_message_id=reply_to.message_id if reply_to else None, ) update.effective_message.delete() should_reply: bool = HINTS.get(hashtag)["should_reply"] if should_reply and not reply_to: del_markup = append_free_delete_button(update, InlineKeyboardMarkup([[]])) _send_hint(msg) ntfc_msg = update.effective_message.reply_text( f"Hey {user.markdown_short}, next time reply to someone 🙃", parse_mode=ParseMode.MARKDOWN, reply_markup=del_markup, quote=False, disable_web_page_preview=True, ) job_queue.run_once(lambda *_: ntfc_msg.delete(), 7, name="delete notification") else: _send_hint(msg)
def reroute_private_chat( bot, update, quote, action, message, redirect_message=None, reply_markup=None ): cid = update.effective_chat.id mid = util.mid_from_update(update) if redirect_message is None: redirect_message = messages.REROUTE_PRIVATE_CHAT if util.is_group_message(update): update.message.reply_text( redirect_message, quote=quote, parse_mode=ParseMode.MARKDOWN, reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton( captions.SWITCH_PRIVATE, url="https://t.me/{}?start={}".format( settings.SELF_BOT_NAME, action ), ), InlineKeyboardButton( "🔎 Switch to inline", switch_inline_query=action ), ] ] ), ) else: if mid: bot.formatter.send_or_edit(cid, message, mid, reply_markup=reply_markup) else: update.message.reply_text( message, quote=quote, parse_mode=ParseMode.MARKDOWN, reply_markup=reply_markup, )
def send_next(bot, update, job_queue: JobQueue, args=None): uid = util.uid_from_update(update) num_rows = None if args: try: num_rows = int(args[0]) except: num_rows = None reply_markup = ReplyKeyboardMarkup( _crapPy_Tr0ll_kbmarkup(num_rows), one_time_keyboard=False, per_user=True ) text = "ɹoʇɐɹǝuǝb ǝɯɐuɹǝsn ɯɐɹbǝןǝʇ" util.send_md_message(bot, uid, text, reply_markup=reply_markup) if util.is_group_message(update): del_msg = bot.formatter.send_message( update.effective_chat.id, "Have fun in private ;)\n/easteregg" ) update.effective_message.delete() job_queue.run_once( lambda *_: del_msg.delete(safe=True), 4, name="delete easteregg hint" )
def send_bot_details( bot, update, chat_data, item=None, header_msg: Optional[str] = None ): is_group = util.is_group_message(update) cid = update.effective_chat.id user = User.from_update(update) if item is None: if is_group: return try: text = update.message.text bot_in_text = re.findall(settings.REGEX_BOT_IN_TEXT, text)[0] item = Bot.by_username(bot_in_text, include_disabled=True) except Bot.DoesNotExist: update.message.reply_text( util.failure( "This bot is not in the @BotList. If you think this is a " "mistake, see the /examples for /contributing." ) ) return header_buttons = [] buttons = [] if item.disabled: txt = "{} {} and thus removed from the @BotList.".format( item, Bot.DisabledReason.to_str(item.disabled_reason) ) elif item.approved: # bot is already in the botlist => show information txt = f"{header_msg}\n\n{item.detail_text}" if header_msg else item.detail_text if ( item.description is None and not Keyword.select().where(Keyword.entity == item).exists() ): txt += " is in the @BotList, but has no description or keywords yet." btn = InlineCallbackButton( captions.BACK_TO_CATEGORY, CallbackActions.SELECT_BOT_FROM_CATEGORY, {"id": item.category.id}, ) header_buttons.insert(0, btn) header_buttons.append( InlineKeyboardButton(captions.SHARE, switch_inline_query=item.username) ) # if cid in settings.MODERATORS: header_buttons.append( InlineKeyboardButton( "📝 Edit", callback_data=util.callback_for_action( CallbackActions.EDIT_BOT, {"id": item.id} ), ) ) # Add favorite button favorite_found = Favorite.search_by_bot(user, item) if favorite_found: buttons.append( InlineKeyboardButton( captions.REMOVE_FAVORITE_VERBOSE, callback_data=util.callback_for_action( CallbackActions.REMOVE_FAVORITE, {"id": favorite_found.id, "details": True}, ), ) ) else: buttons.append( InlineKeyboardButton( captions.ADD_TO_FAVORITES, callback_data=util.callback_for_action( CallbackActions.ADD_TO_FAVORITES, {"id": item.id, "details": True}, ), ) ) else: txt = "{} is currently pending to be accepted for the @BotList.".format(item) if cid in settings.MODERATORS: header_buttons.append( InlineKeyboardButton( "🛃 Accept / Reject", callback_data=util.callback_for_action( CallbackActions.APPROVE_REJECT_BOTS, {"id": item.id} ), ) ) if buttons or header_buttons: reply_markup = InlineKeyboardMarkup( util.build_menu(buttons, n_cols=3, header_buttons=header_buttons) ) else: reply_markup = None reply_markup, callback = botlistchat.append_restricted_delete_button( update, chat_data, reply_markup ) # Should we ever decide to show thumbnails *shrug* # if os.path.exists(item.thumbnail_file): # preview = True # photo = '[\xad]({})'.format('{}/thumbnail/{}.jpeg'.format( # settings.API_URL, # item.username[1:] # )) # log.info(photo) # txt = photo + txt # else: # preview = False msg = bot.formatter.send_or_edit( cid, txt, to_edit=util.mid_from_update(update), reply_markup=reply_markup ) callback(msg) Statistic.of(update, "view-details", item.username, Statistic.ANALYSIS) return CallbackStates.SHOWING_BOT_DETAILS
def search_query(bot, update: Update, chat_data, query, send_errors=True): cid: int = update.effective_chat.id user: User = User.from_update(update) is_admin: bool = cid in settings.MODERATORS replied_to_message_id: Optional[int] = util.original_reply_id(update) is_suggestion_by_other: bool = (update.effective_chat and update.effective_chat.id == settings.BOTLISTCHAT_ID) results = search.search_bots(query) reply_markup = (ReplyKeyboardMarkup(basic.main_menu_buttons(is_admin), resize_keyboard=True) if util.is_private_message(update) else None) if results: if len(results) == 1: update.effective_message.delete() if is_suggestion_by_other: header = f"{user.markdown_short} found the following bot for you:" else: header = "I found the following bot for you:" return send_bot_details(bot, update, chat_data, results[0], header_msg=header) too_many_results = len(results) > settings.MAX_SEARCH_RESULTS bots_list = "" if cid in settings.MODERATORS: # private chat with moderator # append edit buttons bots_list += "\n".join([ "{} — /edit{} 🛃".format(b, b.id) for b in list(results)[:100] ]) else: bots_list += "\n".join( [str(b) for b in list(results)[:settings.MAX_SEARCH_RESULTS]]) bots_list += "\n…" if too_many_results else "" bots_list = messages.SEARCH_RESULTS.format( bots=bots_list, num_results=len(results), plural="s" if len(results) > 1 else "", query=query, ) if util.is_group_message( update) and not update.message.reply_to_message: try: bot.formatter.send_message( update.effective_user.id, bots_list, reply_markup=reply_markup, disable_web_page_preview=True, ) reply_markup, callback = botlistchat.append_restricted_delete_button( update, chat_data, InlineKeyboardMarkup([[]])) msg = bot.formatter.send_message( update.effective_chat.id, f"Hey {user.plaintext}, let's not annoy the others. I sent you the search results " f"[in private chat](https://t.me/{settings.SELF_BOT_NAME}).", disable_web_page_preview=True, reply_markup=reply_markup, ) callback(msg) update.effective_message.delete() except TelegramError: hint_msg, hint_reply_markup, _ = get_hint_data("#private") bot.formatter.send_message( update.effective_chat.id, hint_msg, reply_markup=hint_reply_markup, reply_to_message_id=update.effective_message.id, disable_web_page_preview=True, ) return ConversationHandler.END if is_suggestion_by_other and replied_to_message_id: bots_list = f"{user.markdown_short} suggests to search and {bots_list}" bot.formatter.send_message( update.effective_chat.id, bots_list, parse_mode=ParseMode.MARKDOWN, reply_markup=reply_markup, disable_web_page_preview=True, reply_to_message_id=replied_to_message_id, ) update.effective_message.delete() else: if send_errors: callback = None if util.is_group_message(update): reply_markup, callback = botlistchat.append_restricted_delete_button( update, chat_data, InlineKeyboardMarkup([[]])) msg = update.message.reply_text( util.failure("Sorry, I couldn't find anything related " "to *{}* in the @BotList. /search".format( util.escape_markdown(query))), parse_mode=ParseMode.MARKDOWN, reply_markup=reply_markup, ) if callback: callback(msg) return ConversationHandler.END