Esempio n. 1
0
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)
Esempio n. 2
0
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),
    )
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
 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))
Esempio n. 6
0
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)
Esempio n. 7
0
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
Esempio n. 8
0
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)
Esempio n. 9
0
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
    )
Esempio n. 10
0
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
Esempio n. 11
0
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
    )