def edit_bot_category(bot, update, for_bot, callback_action=None): if callback_action is None: callback_action = CallbackActions.EDIT_BOT_CAT_SELECTED uid = util.uid_from_update(update) categories = Category.select().order_by(Category.name.asc()).execute() buttons = util.build_menu( [ InlineKeyboardButton( "{}{}".format(emoji.emojize(c.emojis, use_aliases=True), c.name), callback_data=util.callback_for_action( callback_action, {"cid": c.id, "bid": for_bot.id} ), ) for c in categories ], 2, ) return bot.formatter.send_or_edit( uid, util.action_hint( "Please select a category" + (" for {}".format(for_bot) if for_bot else "") ), to_edit=util.mid_from_update(update), reply_markup=InlineKeyboardMarkup(buttons), )
def query_too_short_article(): txt = '[I am a stupid, crazy fool.](https://www.youtube.com/watch?v=DLzxrzFCyOs)' return InlineQueryResultArticle( id=uuid4(), title=util.action_hint( 'Your search term must be at least {} characters long.'.format( SEARCH_QUERY_MIN_LENGTH)), input_message_content=InputTextMessageContent( message_text=txt, parse_mode="Markdown", disable_web_page_preview=True))
def select_category(bot, update, chat_data, callback_action=None): chat_id = update.effective_chat.id reply_markup = InlineKeyboardMarkup(_select_category_buttons(callback_action)) reply_markup, callback = botlistchat.append_restricted_delete_button( update, chat_data, reply_markup ) msg = bot.formatter.send_or_edit( chat_id, util.action_hint(messages.SELECT_CATEGORY), to_edit=util.mid_from_update(update), reply_markup=reply_markup, ) callback(msg) return ConversationHandler.END
def remove_favorite_menu(bot, update): uid = util.uid_from_update(update) user = User.from_update(update) favorites = Favorite.select_all(user) fav_remove_buttons = [ InlineKeyboardButton('✖️ {}'.format(str(f.bot.username)), callback_data=util.callback_for_action( CallbackActions.REMOVE_FAVORITE, {'id': f.id})) for f in favorites ] buttons = util.build_menu(fav_remove_buttons, 2, header_buttons=[ InlineKeyboardButton( captions.DONE, callback_data=util.callback_for_action( CallbackActions.SEND_FAVORITES_LIST)) ]) reply_markup = InlineKeyboardMarkup(buttons) bot.formatter.send_or_edit(uid, util.action_hint("Select favorites to remove"), to_edit=util.mid_from_update(update), reply_markup=reply_markup)
def approve_bots(bot, update, page=0, override_list=None): chat_id = util.uid_from_update(update) if override_list: unapproved = override_list else: unapproved = ( Bot.select() .where(Bot.approved == False, Bot.disabled == False) .order_by(Bot.date_added) ) if page < 0: page = 0 last_page = int((len(unapproved) - 1) / settings.PAGE_SIZE_BOT_APPROVAL) if page * settings.PAGE_SIZE_BOT_APPROVAL >= len(unapproved): # old item deleted, list now too small page = last_page start = page * settings.PAGE_SIZE_BOT_APPROVAL end = start + settings.PAGE_SIZE_BOT_APPROVAL has_prev_page = page > 0 has_next_page = (page + 1) * settings.PAGE_SIZE_BOT_APPROVAL < len(unapproved) unapproved = unapproved[start:end] if len(unapproved) == 0: bot.formatter.send_or_edit( chat_id, "No more unapproved bots available. " "Good job! (Is this the first time? 😂)", to_edit=util.mid_from_update(update), ) return buttons = list() for x in unapproved: first_row = [ InlineKeyboardButton( x.username, url="http://t.me/{}".format(x.username[1:]) ) ] second_row = [ InlineKeyboardButton( "👍", callback_data=util.callback_for_action( CallbackActions.ACCEPT_BOT, {"id": x.id} ), ), InlineKeyboardButton( "👎", callback_data=util.callback_for_action( CallbackActions.REJECT_BOT, {"id": x.id, "page": page, "ntfc": True} ), ), InlineKeyboardButton( "🗑", callback_data=util.callback_for_action( CallbackActions.REJECT_BOT, {"id": x.id, "page": page, "ntfc": False}, ), ), InlineKeyboardButton( emojis.RECOMMEND_MODERATOR, callback_data=util.callback_for_action( CallbackActions.RECOMMEND_MODERATOR, {"id": x.id, "page": page} ), ), ] if len(unapproved) > 1: buttons.append(first_row) buttons.append(second_row) page_arrows = list() if has_prev_page: page_arrows.append( InlineKeyboardButton( "⏮", callback_data=util.callback_for_action( CallbackActions.SWITCH_APPROVALS_PAGE, {"page": -1} ), ) ) page_arrows.append( InlineKeyboardButton( Emoji.LEFTWARDS_BLACK_ARROW, callback_data=util.callback_for_action( CallbackActions.SWITCH_APPROVALS_PAGE, {"page": page - 1} ), ) ) if has_prev_page or has_next_page: page_arrows.append( InlineKeyboardButton( "·{}·".format(page + 1), callback_data=util.callback_for_action( CallbackActions.SWITCH_APPROVALS_PAGE, {"page": page} ), ) ) if has_next_page: page_arrows.append( InlineKeyboardButton( Emoji.BLACK_RIGHTWARDS_ARROW, callback_data=util.callback_for_action( CallbackActions.SWITCH_APPROVALS_PAGE, {"page": page + 1} ), ) ) page_arrows.append( InlineKeyboardButton( "⏭", callback_data=util.callback_for_action( CallbackActions.SWITCH_APPROVALS_PAGE, {"page": last_page} ), ) ) buttons.append(page_arrows) reply_markup = InlineKeyboardMarkup(buttons) text = ( "What to do with {}?".format(util.escape_markdown(unapproved[0].username)) if len(unapproved) == 1 else messages.SELECT_BOT_TO_ACCEPT ) bot.formatter.send_or_edit( chat_id, util.action_hint(text), reply_markup=reply_markup, to_edit=util.mid_from_update(update), ) return CallbackStates.APPROVING_BOTS
def approve_suggestions(bot, update, page=0): uid = util.uid_from_update(update) suggestions = Suggestion.select_all() if page * settings.PAGE_SIZE_SUGGESTIONS_LIST >= len(suggestions): # old item deleted, list now too small page = page - 1 if page > 0 else 0 start = page * settings.PAGE_SIZE_SUGGESTIONS_LIST end = start + settings.PAGE_SIZE_SUGGESTIONS_LIST has_prev_page = page > 0 has_next_page = (page + 1) * settings.PAGE_SIZE_SUGGESTIONS_LIST < len(suggestions) suggestions = suggestions[start:end] if len(suggestions) == 0: bot.formatter.send_or_edit( uid, "No more suggestions available.", to_edit=util.mid_from_update(update) ) return buttons = [] count = 1 text = "Please choose suggestions to accept.\n" for x in suggestions: number = str(count) + "." text += "\n{} {}".format(number, str(x)) row = [] # Should the suggestion be editable and is it too long? if x.action in Suggestion.TEXTUAL_ACTIONS: row.append( InlineKeyboardButton( "{} {}📝".format(number, Emoji.WHITE_HEAVY_CHECK_MARK), callback_data=util.callback_for_action( CallbackActions.CHANGE_SUGGESTION, {"id": x.id, "page": page} ), ) ) else: row.append( InlineKeyboardButton( "{} {}".format(number, Emoji.WHITE_HEAVY_CHECK_MARK), callback_data=util.callback_for_action( CallbackActions.ACCEPT_SUGGESTION, {"id": x.id, "page": page} ), ) ) row.append( InlineKeyboardButton( "{} {}".format(number, Emoji.CROSS_MARK), callback_data=util.callback_for_action( CallbackActions.REJECT_SUGGESTION, {"id": x.id, "page": page} ), ) ) buttons.append(row) count += 1 page_arrows = list() if has_prev_page: page_arrows.append( InlineKeyboardButton( Emoji.LEFTWARDS_BLACK_ARROW, callback_data=util.callback_for_action( CallbackActions.SWITCH_SUGGESTIONS_PAGE, {"page": page - 1} ), ) ) if has_next_page: page_arrows.append( InlineKeyboardButton( Emoji.BLACK_RIGHTWARDS_ARROW, callback_data=util.callback_for_action( CallbackActions.SWITCH_SUGGESTIONS_PAGE, {"page": page + 1} ), ) ) buttons.append(page_arrows) reply_markup = InlineKeyboardMarkup(buttons) bot.formatter.send_or_edit( uid, util.action_hint(text), reply_markup=reply_markup, to_edit=util.mid_from_update(update), disable_web_page_preview=True, ) return CallbackStates.APPROVING_BOTS
def send_category(bot, update, chat_data, category): uid = util.uid_from_update(update) cid = update.effective_chat.id bots = Bot.of_category_without_new(category)[: settings.MAX_BOTS_PER_MESSAGE] bots_with_description = [b for b in bots if b.description is not None] detailed_buttons_enabled = len( bots_with_description ) > 0 and util.is_private_message(update) callback = CallbackActions.SEND_BOT_DETAILS if detailed_buttons_enabled: buttons = [ InlineKeyboardButton( x.username, callback_data=util.callback_for_action(callback, {"id": x.id}), ) for x in bots_with_description ] else: buttons = [] menu = util.build_menu(buttons, 2) menu.insert( 0, [ InlineKeyboardButton( captions.BACK, callback_data=util.callback_for_action(CallbackActions.SELECT_CATEGORY), ), InlineKeyboardButton( "Show in BotList", url="http://t.me/botlist/{}".format(category.current_message_id), ), InlineKeyboardButton("Share", switch_inline_query=category.name), ], ) txt = "There are *{}* bots in the category *{}*:\n\n".format( len(bots), str(category) ) if uid in settings.MODERATORS and util.is_private_message(update): # append admin edit buttons txt += "\n".join(["{} — /edit{} 🛃".format(b, b.id) for b in bots]) else: txt += "\n".join([str(b) for b in bots]) if detailed_buttons_enabled: txt += "\n\n" + util.action_hint( "Press a button below to get a detailed description." ) reply_markup = InlineKeyboardMarkup(menu) reply_markup, callback = botlistchat.append_restricted_delete_button( update, chat_data, reply_markup ) msg = bot.formatter.send_or_edit( cid, txt, to_edit=util.mid_from_update(update), reply_markup=reply_markup ) callback(msg) Statistic.of( update, "menu", "of category {}".format(str(category)), Statistic.ANALYSIS )
def notify_bot_offline(bot, update, args=None): tg_user = update.message.from_user user = User.from_telegram_object(tg_user) reply_to = util.original_reply_id(update) if args: text = " ".join(args) else: text = update.message.text command_no_args = ( len(re.findall(r"^/new\s*$", text)) > 0 or text.lower().strip() == "/offline@botlistbot" ) if command_no_args: update.message.reply_text( util.action_hint( "Please use this command with an argument. For example:\n/offline @mybot" ), reply_to_message_id=reply_to, ) return # `#offline` is already checked by handler try: username = re.match(settings.REGEX_BOT_IN_TEXT, text).groups()[0] if username == "@" + settings.SELF_BOT_NAME: log.info("Ignoring {}".format(text)) return except AttributeError: if args: update.message.reply_text( util.failure("Sorry, but you didn't send me a bot `@username`."), quote=True, parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply_to, ) else: log.info("Ignoring {}".format(text)) # no bot username, ignore update pass return try: offline_bot = Bot.get( fn.lower(Bot.username) ** username.lower(), Bot.approved == True ) try: Suggestion.get(action="offline", subject=offline_bot) except Suggestion.DoesNotExist: suggestion = Suggestion( user=user, action="offline", date=datetime.date.today(), subject=offline_bot, ) suggestion.save() update.message.reply_text( util.success( "Thank you! We will review your suggestion and set the bot offline." ), reply_to_message_id=reply_to, ) except Bot.DoesNotExist: update.message.reply_text( util.action_hint("The bot you sent me is not in the @BotList."), reply_to_message_id=reply_to, ) return ConversationHandler.END
def new_bot_submission(bot, update, chat_data, args=None, bot_checker=None): tg_user = update.message.from_user user = User.from_telegram_object(tg_user) if util.stop_banned(update, user): return reply_to = util.original_reply_id(update) if args: text = " ".join(args) else: text = update.message.text command_no_args = ( len(re.findall(r"^/new\s*$", text)) > 0 or text.lower().strip() == "/new@botlistbot" ) if command_no_args: update.message.reply_text( util.action_hint( "Please use this command with an argument. For example:\n/new @mybot 🔎" ), reply_to_message_id=reply_to, ) return # `#new` is already checked by handler try: username = re.match(settings.REGEX_BOT_IN_TEXT, text).groups()[0] if username.lower() == "@" + settings.SELF_BOT_NAME.lower(): log.info("Ignoring {}".format(text)) return except AttributeError: if args: update.message.reply_text( util.failure("Sorry, but you didn't send me a bot `@username`."), quote=True, parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply_to, ) log.info("Ignoring {}".format(text)) # no bot username, ignore update return try: new_bot = Bot.by_username(username, include_disabled=True) if new_bot.disabled: update.message.reply_text( util.failure( "{} is banned from the @BotList.".format(new_bot.username) ), reply_to_message_id=reply_to, ) elif new_bot.approved: update.message.reply_text( util.action_hint( "Sorry fool, but {} is already in the @BotList 😉".format( new_bot.username ) ), reply_to_message_id=reply_to, ) else: update.message.reply_text( util.action_hint( "{} has already been submitted. Please have patience...".format( new_bot.username ) ), reply_to_message_id=reply_to, ) return except Bot.DoesNotExist: new_bot = Bot( revision=Revision.get_instance().next, approved=False, username=username, submitted_by=user, ) new_bot.inlinequeries = "🔎" in text new_bot.official = "🔹" in text # find language languages = Country.select().execute() for lang in languages: if lang.emoji in text: new_bot.country = lang new_bot.date_added = datetime.date.today() description_reg = re.match(settings.REGEX_BOT_IN_TEXT + " -\s?(.*)", text) description_notify = "" if description_reg: description = description_reg.group(2) new_bot.description = description description_notify = " Your description was included." new_bot.save() if ( util.is_private_message(update) and util.uid_from_update(update) in settings.MODERATORS ): from botlistbot.components.explore import send_bot_details send_bot_details(bot, update, chat_data, new_bot) else: update.message.reply_text( util.success( "You submitted {} for approval.{}".format(new_bot, description_notify) ), parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply_to, ) # Ask the user to fill in the bot details util.send_md_message( bot, update.effective_user.id, "Congratulations, you just submitted a bot to the @BotList. Please help us fill in the details below:", ) edit_bot(bot, update, chat_data, to_edit=new_bot) try: check_submission(bot, bot_checker, new_bot) except Exception as e: log.exception(e) return ConversationHandler.END