Exemple #1
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),
    )
Exemple #2
0
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))
Exemple #3
0
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
Exemple #4
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)
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
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
    )
Exemple #8
0
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
Exemple #9
0
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