Exemple #1
0
def rules(bot, update, quote=True):
    chat_id = update.effective_chat.id
    if chat_id == settings.BOTLISTCHAT_ID or util.is_private_message(update):
        reroute_private_chat(bot, update, quote, const.DeepLinkingActions.RULES, messages.BOTLISTCHAT_RULES)
    else:
        update.message.reply_text("Sorry, but I don't know the rules in this group 👻\n\n" + messages.PROMOTION_MESSAGE,
                                  parse_mode=ParseMode.MARKDOWN)
    return ConversationHandler.END
Exemple #2
0
def explore(bot, update, chat_data):
    cid = update.effective_chat.id
    uid = update.effective_user.id
    mid = util.mid_from_update(update)
    explorable_bots = Bot.explorable_bots()

    chat_data["explored"] = chat_data.get("explored", list())

    # don't explore twice
    for explored in chat_data["explored"]:
        explorable_bots.remove(explored)

    if len(explorable_bots) == 0:
        util.send_md_message(
            bot,
            cid,
            mdformat.none_action(
                "You have explored all the bots. Congratulations, you might be the first 😜"
            ),
        )
        return

    random_bot = random.choice(explorable_bots)

    buttons = [
        [
            InlineKeyboardButton(
                captions.ADD_TO_FAVORITES,
                callback_data=util.callback_for_action(
                    CallbackActions.ADD_TO_FAVORITES, {"id": random_bot.id}
                ),
            ),
            InlineKeyboardButton(
                captions.SHARE, switch_inline_query=random_bot.username
            ),
        ],
        [
            InlineKeyboardButton(
                random_explore_text(),
                callback_data=util.callback_for_action(CallbackActions.EXPLORE_NEXT),
            )
        ],
    ]

    markup = InlineKeyboardMarkup(buttons)

    text = random_bot.detail_text

    if uid in settings.MODERATORS and util.is_private_message(update):
        text += "\n\n🛃 /edit{}".format(random_bot.id)

    msg = bot.formatter.send_or_edit(cid, text, to_edit=mid, reply_markup=markup)
    chat_data["explored"].append(random_bot)
Exemple #3
0
def main_menu(bot, update):
    chat_id = update.effective_chat.id
    is_admin = chat_id in settings.MODERATORS
    reply_markup = (ReplyKeyboardMarkup(main_menu_buttons(is_admin),
                                        resize_keyboard=True,
                                        one_time_keyboard=True) if
                    util.is_private_message(update) else ReplyKeyboardRemove())

    bot.sendMessage(
        chat_id,
        mdformat.action_hint("What would you like to do?"),
        reply_markup=reply_markup,
    )
Exemple #4
0
def start(bot, update, chat_data, args):
    tg_user = update.message.from_user
    chat_id = tg_user.id

    # Get or create the user from/in database
    User.from_telegram_object(tg_user)

    if isinstance(args, list) and len(args) > 0:
        # CATEGORY BY ID
        try:
            cat = Category.get(Category.id == args[0])
            from botlistbot.components.explore import send_category

            return send_category(bot, update, chat_data, cat)
        except (ValueError, Category.DoesNotExist):
            pass

        query = " ".join(args).lower()

        # SPECIFIC DEEP-LINKED QUERIES
        if query == const.DeepLinkingActions.CONTRIBUTING:
            return help.contributing(bot, update, quote=False)
        elif query == const.DeepLinkingActions.EXAMPLES:
            return help.examples(bot, update, quote=False)
        elif query == const.DeepLinkingActions.RULES:
            return help.rules(bot, update, quote=False)
        elif query == const.DeepLinkingActions.SEARCH:
            return search_handler(bot, update, chat_data)

        # SEARCH QUERY
        search_query(bot, update, chat_data, query)

    else:
        bot.sendSticker(
            chat_id,
            open(
                os.path.join(appglobals.ROOT_DIR, "assets", "sticker",
                             "greetings-humanoids.webp"),
                "rb",
            ),
        )
        help.help(bot, update)
        util.wait(bot, update)
        if util.is_private_message(update):
            main_menu(bot, update)
        return ConversationHandler.END
Exemple #5
0
def short_approve_list(bot, update):
    uid = update.effective_chat.id
    bots = Bot.select_unapproved()

    if len(bots) == 0:
        update.message.reply_text("No bots to be approved.")
        return

    txt = "Bots pending approval:\n\n"

    if uid in settings.MODERATORS and util.is_private_message(update):
        # append admin edit buttons
        txt += "\n".join(["{} — /approve{}".format(b, b.id) for b in bots])
    else:
        txt += "\n".join([str(b) for b in bots])

    bot.formatter.send_message(uid, txt)
Exemple #6
0
def pending_update(bot, update):
    uid = update.effective_chat.id
    bots = Bot.select_pending_update()

    if len(bots) == 0:
        update.message.reply_text("No bots pending for update.")
        return

    txt = "Bots pending for next Update:\n\n"

    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])

    bot.formatter.send_message(uid, txt)
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 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
Exemple #9
0
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