def recommend_moderator(bot, update, bot_in_question, page): uid = update.effective_user.id mid = util.mid_from_update(update) moderators = User.select().where( (User.chat_id << settings.MODERATORS) & (User.chat_id != uid) ) buttons = [ InlineKeyboardButton( u.first_name, callback_data=util.callback_for_action( CallbackActions.SELECT_MODERATOR, {"bot_id": bot_in_question.id, "uid": u.id, "page": page}, ), ) for u in moderators ] buttons.insert( 0, InlineKeyboardButton( captions.BACK, callback_data=util.callback_for_action( CallbackActions.SWITCH_APPROVALS_PAGE, {"page": page} ), ), ) reply_markup = InlineKeyboardMarkup(util.build_menu(buttons, 1)) text = mdformat.action_hint( "Select a moderator you think is better suited to evaluate the submission of {}.".format( str(bot_in_question) ) ) bot.formatter.send_or_edit(uid, text, to_edit=mid, reply_markup=reply_markup)
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 _select_category_buttons(callback_action=None): if callback_action is None: # set default callback_action = CallbackActions.SELECT_BOT_FROM_CATEGORY 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, {"id": c.id}), ) for c in categories ], 2, ) buttons.insert( 0, [ InlineKeyboardButton( "🆕 New Bots", callback_data=util.callback_for_action( CallbackActions.NEW_BOTS_SELECTED ), ) ], ) return buttons
def broadcast_preview(bot, update, user_data): uid = update.effective_user.id formatted_text = update.message.text_markdown for k, v in BROADCAST_REPLACEMENTS.items(): # replace all occurences but mind escaping with \ pattern = re.compile(r"(?<!\\){}".format(k), re.IGNORECASE) formatted_text = pattern.sub(v, formatted_text) formatted_text = re.sub(r"\\({})".format(k), r"\1", formatted_text, re.IGNORECASE) user_data['broadcast'] = dict( user_data.get('broadcast', dict()), **dict(text=formatted_text, target_chat_id=settings.BOTLISTCHAT_ID)) mode = user_data['broadcast'].get('mode', 'just_send') buttons = [ InlineKeyboardButton( "Type again", callback_data=util.callback_for_action('broadcast')), InlineKeyboardButton("� Edit my message" if mode == 'editing' else "▶� Send to @BotListChat", callback_data=util.callback_for_action( 'send_broadcast', {'P4l': settings.BOTLISTCHAT_ID})), ] reply_markup = InlineKeyboardMarkup(util.build_menu(buttons, 1)) util.send_md_message(bot, uid, formatted_text, reply_markup=reply_markup) return ConversationHandler.END
def portal_markup(self): buttons = [ InlineKeyboardButton("🔺 1️⃣ Categories 📚 🔺", url=BotList.create_hyperlink( self.channel.category_list_mid)), InlineKeyboardButton("▫️ 2️⃣ BotList Bot 🤖 ▫️", url='https://t.me/botlistbot?start'), InlineKeyboardButton("▫️ 3️⃣ BotList Chat 👥💬 ▫️", url='https://t.me/botlistchat'), # InlineKeyboardButton("Add to Group 🤖", # url='https://t.me/botlistbot?startgroup=start'), ] return InlineKeyboardMarkup(util.build_menu(buttons, 1))
def send_broadcast(bot, update, user_data): uid = update.effective_user.id try: bc = user_data['broadcast'] text = bc['text'] recipient = bc['target_chat_id'] mode = bc.get('mode', 'just_send') except AttributeError: bot.formatter.send_failure( uid, "Missing attributes for broadcast. Aborting...") return ConversationHandler.END mid = bc.get('reply_to_message_id') if mode == 'replying': msg = util.send_md_message(bot, recipient, text, reply_to_message_id=mid) elif mode == 'editing': msg = bot.formatter.send_or_edit(recipient, text, to_edit=mid) else: msg = util.send_md_message(bot, recipient, text) # Post actions buttons = [ InlineKeyboardButton(captions.PIN, callback_data=util.callback_for_action( 'pin_message', {'mid': msg.message_id})), InlineKeyboardButton('Add "Thank You" counter', callback_data=util.callback_for_action( 'add_thank_you', { 'cid': recipient, 'mid': msg.message_id })), ] reply_markup = InlineKeyboardMarkup(util.build_menu(buttons, 1)) mid = util.mid_from_update(update) action_taken = "edited" if mode == 'editing' else "broadcasted" bot.formatter.send_or_edit(uid, mdformat.success( "Message {}.".format(action_taken)), mid, reply_markup=reply_markup)
def get_hint_data(text): for k, v in HINTS.items(): if k not in text: continue text = text.replace(k, "") query = text.strip() reply_markup = None if v.get("buttons"): # Replace 'query' placeholder and expand kwargs buttons = [ InlineKeyboardButton( **{k: v.format(query=query) for k, v in b.items()}) for b in v.get("buttons") ] reply_markup = InlineKeyboardMarkup(util.build_menu(buttons, 1)) msg = v["message"].format( query=query if query else v["default"] if v.get("default") else "") return msg, reply_markup, k return None, None, None
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 _edit_bot_buttons(to_edit: Bot, pending_suggestions: Dict, is_moderator): bid = {"id": to_edit.id} def is_pending(action): if isinstance(action, str): return action in pending_suggestions else: return any(a in pending_suggestions for a in action) def pending_or_caption(action, caption): return ( format_pending(str(pending_suggestions[action])) if is_pending(action) else str(caption) ) buttons = [ InlineKeyboardButton( pending_or_caption("name", to_edit.name or "Set Name"), callback_data=util.callback_for_action(CallbackActions.EDIT_BOT_NAME, bid), ), InlineKeyboardButton( pending_or_caption("username", to_edit.username), callback_data=util.callback_for_action( CallbackActions.EDIT_BOT_USERNAME, bid ), ), InlineKeyboardButton( # remove bulletin from category pending_or_caption( "category", str(pending_suggestions.get("category") or to_edit.category)[1:] if to_edit.category else "Choose a category", ), callback_data=util.callback_for_action( CallbackActions.EDIT_BOT_SELECT_CAT, bid ), ), InlineKeyboardButton( pending_or_caption( "description", "Change description" if to_edit.description else "Write a description", ), callback_data=util.callback_for_action( CallbackActions.EDIT_BOT_DESCRIPTION, bid ), ), InlineKeyboardButton( pending_or_caption( "country", to_edit.country.emojized if to_edit.country else "Set country/language", ), callback_data=util.callback_for_action( CallbackActions.EDIT_BOT_COUNTRY, bid ), ), InlineKeyboardButton( pending_or_caption( "extra", "Change extra text" if to_edit.extra else "Add an extra text" ), callback_data=util.callback_for_action(CallbackActions.EDIT_BOT_EXTRA, bid), ), InlineKeyboardButton( format_pending("Set keywords") if is_pending(["add_keyword", "remove_keyword"]) else "Set keywords", callback_data=util.callback_for_action( CallbackActions.EDIT_BOT_KEYWORDS, bid ), ), ] toggleable_properties = [ ("inlinequeries", "🔎", CallbackActions.EDIT_BOT_INLINEQUERIES), ("official", "🔹", CallbackActions.EDIT_BOT_OFFICIAL), # ('offline', '💤', CallbackActions.EDIT_BOT_OFFLINE), ("spam", "🚮", CallbackActions.EDIT_BOT_SPAM), ] def toggle_button(property_name, emoji, callback_action): is_pending = property_name in pending_suggestions.keys() pending_emoji = captions.SUGGESTION_PENDING_EMOJI + " " if is_pending else "" active = ( bool(pending_suggestions[property_name]) if is_pending else bool(getattr(to_edit, property_name)) ) active_emoji = "✔️" if active else Emoji.HEAVY_MULTIPLICATION_X caption = "{}{} {}".format(pending_emoji, emoji, active_emoji) return InlineKeyboardButton( caption, callback_data=util.callback_for_action( callback_action, {"id": to_edit.id, "value": not active} ), ) for toggle in toggleable_properties: buttons.append(toggle_button(*toggle)) if is_moderator: buttons.append( InlineKeyboardButton( "Delete", callback_data=util.callback_for_action( CallbackActions.CONFIRM_DELETE_BOT, bid ), ) ) header = [] if to_edit.category: header.append( InlineKeyboardButton( captions.BACK_TO_CATEGORY, callback_data=util.callback_for_action( CallbackActions.SELECT_BOT_FROM_CATEGORY, {"id": to_edit.category.id}, ), ) ) header.append( InlineKeyboardButton( captions.REFRESH, callback_data=util.callback_for_action( CallbackActions.EDIT_BOT, {"id": to_edit.id} ), ) ) footer = list() if is_moderator and len(pending_suggestions) > 0: footer.append( InlineKeyboardButton( "🛃 Apply all changes", callback_data=util.callback_for_action( CallbackActions.APPLY_ALL_CHANGES, {"id": to_edit.id} ), ) ) return util.build_menu( buttons, n_cols=2, header_buttons=header, footer_buttons=footer )
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 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 )