Example #1
0
def lookup_entity(query, exact=True):
    """
    Searches for a Bot or User contained in the query
    """
    if exact:
        try:
            return Bot.by_username(query, include_disabled=True)
        except Bot.DoesNotExist:
            pass

        try:
            return Bot.get(chat_id=int(query))
        except ValueError:
            pass
        except Bot.DoesNotExist:
            pass

        try:
            return User.by_username(query)
        except User.DoesNotExist:
            pass

        try:
            return User.get(chat_id=query)
        except User.DoesNotExist:
            pass
        return None
Example #2
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)
Example #3
0
def add_favorite(bot, update, item: Bot, callback_alert=None):
    user = User.from_update(update)
    uid = util.uid_from_update(update)
    mid = util.mid_from_update(update)
    from botlistbot.components.basic import main_menu_buttons
    main_menu_markup = ReplyKeyboardMarkup(
        main_menu_buttons(uid in settings.MODERATORS))

    fav, created = Favorite.add(user=user, item=item)
    if created:
        Statistic.of(user, 'add-favorite', item.username)
        text = mdformat.love("{} added to your {}favorites.".format(
            fav.bot, '' if callback_alert else '/'))
        if callback_alert:
            update.callback_query.answer(text=text, show_alert=False)
        else:
            msg = util.send_md_message(bot,
                                       uid,
                                       text,
                                       to_edit=mid,
                                       reply_markup=main_menu_markup)
            mid = msg.message_id
            util.wait(bot, update)
            send_favorites_list(bot, update, to_edit=mid)
    else:
        text = mdformat.none_action(
            "{} is already a favorite of yours.{}".format(
                fav.bot, '' if callback_alert else ' /favorites'))
        if callback_alert:
            update.callback_query.answer(text=text, show_alert=False)
        else:
            util.send_md_message(bot, uid, text, reply_markup=main_menu_markup)
    return ConversationHandler.END
Example #4
0
def add_custom(bot, update, username):
    uid = util.uid_from_update(update)
    user = User.from_update(update)
    mid = util.mid_from_update(update)
    from botlistbot.components.basic import main_menu_buttons
    main_menu_markup = ReplyKeyboardMarkup(
        main_menu_buttons(uid in settings.MODERATORS))

    try:
        fav = Favorite.get(custom_bot=username)
        util.send_or_edit_md_message(
            bot,
            uid,
            mdformat.none_action(
                "{} is already a favorite of yours. /favorites".format(
                    fav.custom_bot)),
            to_edit=mid,
            reply_markup=main_menu_markup)
    except Favorite.DoesNotExist:
        fav = Favorite(user=user,
                       custom_bot=username,
                       date_added=datetime.date.today())
        fav.save()
        msg = bot.formatter.send_or_edit(
            uid,
            mdformat.love("{} added to your /favorites.".format(
                fav.custom_bot)),
            to_edit=mid)
        mid = msg.message_id
        util.wait(bot, update)
        send_favorites_list(bot, update, to_edit=mid)
    return ConversationHandler.END
Example #5
0
def edit_bot(bot, update, chat_data, to_edit=None):
    uid = util.uid_from_update(update)
    message_id = util.mid_from_update(update)
    user = User.from_update(update)

    if not to_edit:
        if update.message:
            command = update.message.text

            if "edit" in command:
                b_id = re.match(r"^/edit(\d+)$", command).groups()[0]
            elif "approve" in command:
                b_id = re.match(r"^/approve(\d+)$", command).groups()[0]
            else:
                raise ValueError("No 'edit' or 'approve' in command.")

            try:
                to_edit = Bot.get(id=b_id)
            except Bot.DoesNotExist:
                update.message.reply_text(util.failure("No bot exists with this id."))
                return
        else:
            bot.formatter.send_failure(uid, "An unexpected error occured.")
            return

    # if not to_edit.approved:
    #     return approve_bots(bot, update, override_list=[to_edit])

    pending_suggestions = Suggestion.pending_for_bot(to_edit, user)
    reply_markup = InlineKeyboardMarkup(
        _edit_bot_buttons(to_edit, pending_suggestions, uid in settings.MODERATORS)
    )
    pending_text = (
        "\n\n{} Some changes are pending approval{}.".format(
            captions.SUGGESTION_PENDING_EMOJI,
            "" if user.chat_id in settings.MODERATORS else " by a moderator",
        )
        if pending_suggestions
        else ""
    )
    meta_text = (
        "\n\nDate added: {}\nMember since revision {}\n"
        "Submitted by {}\nApproved by {}".format(
            to_edit.date_added,
            to_edit.revision,
            to_edit.submitted_by,
            to_edit.approved_by,
        )
    )
    bot.formatter.send_or_edit(
        uid,
        "🛃 Edit {}{}{}".format(
            to_edit.detail_text,
            meta_text if user.id in settings.MODERATORS else "",
            pending_text,
        ),
        to_edit=message_id,
        reply_markup=reply_markup,
    )
Example #6
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
Example #7
0
def ban_user(_bot, update, user: User, ban_state: bool):
    if user.banned and ban_state is True:
        update.message.reply_text(
            mdformat.none_action("User {} is already banned.".format(user)),
            parse_mode="markdown",
        )
        raise DispatcherHandlerStop
    if not user.banned and ban_state is False:
        update.message.reply_text(
            mdformat.none_action("User {} is not banned.".format(user)),
            parse_mode="markdown",
        )
        raise DispatcherHandlerStop
    user.banned = ban_state
    if ban_state is True:
        with db.atomic():
            user_submissions = Bot.select().where(
                (Bot.approved == False)
                & (Bot.submitted_by == user)
                # TODO: does this need to include `Bot.deleted == True`?
            )
            for b in user_submissions:
                b.delete_instance()

            users_suggestions = Suggestion.select().where(
                (Suggestion.executed == False) & (Suggestion.user == user)
            )
            for s in users_suggestions:
                s.delete_instance()
        update.message.reply_text(
            mdformat.success(
                "User {} banned, all bot submissions and suggestions removed.".format(
                    user
                )
            ),
            parse_mode="markdown",
        )
        Statistic.of(update, "ban", user.markdown_short)
    else:
        update.message.reply_text(
            mdformat.success("User {} unbanned.".format(user)), parse_mode="markdown"
        )
        Statistic.of(update, "unban", user.markdown_short)
    user.save()
Example #8
0
def apply_all_changes(bot, update, chat_data, to_edit):
    user = User.from_update(update)

    user_suggestions = Suggestion.select_all_of_user(user)
    for suggestion in user_suggestions:
        suggestion.apply()

    refreshed_bot = Bot.get(id=to_edit.id)
    edit_bot(bot, update, chat_data, refreshed_bot)
    Statistic.of(update, "apply", refreshed_bot.username)
Example #9
0
def accept_bot_submission(bot, update, of_bot: Bot, category):
    uid = util.uid_from_update(update)
    message_id = util.mid_from_update(update)
    user = User.from_update(update)

    try:
        of_bot.category = category
        of_bot.date_added = datetime.date.today()
        of_bot.approved = True
        of_bot.approved_by = user
        of_bot.save()

        buttons = [
            [
                InlineKeyboardButton(
                    "Edit {} details".format(of_bot.username),
                    callback_data=util.callback_for_action(
                        CallbackActions.EDIT_BOT, {"id": of_bot.id}
                    ),
                )
            ]
        ]
        reply_markup = InlineKeyboardMarkup(buttons)

        bot.formatter.send_or_edit(
            uid,
            "{} has been accepted to the Botlist. ".format(
                of_bot
            ),
            to_edit=message_id,
            reply_markup=reply_markup,
        )

        log_msg = "{} accepted by {}.".format(of_bot.username, uid)

        # notify submittant
        if of_bot.submitted_by != user:
            try:
                bot.sendMessage(
                    of_bot.submitted_by.chat_id,
                    util.success(
                        messages.ACCEPTANCE_PRIVATE_MESSAGE.format(
                            of_bot.username, of_bot.category
                        )
                    ),
                )
                log_msg += "\nUser {} was notified.".format(str(of_bot.submitted_by))
            except TelegramError:
                log_msg += "\nUser {} could NOT be contacted/notified in private.".format(
                    str(of_bot.submitted_by)
                )

        log.info(log_msg)
    except:
        bot.formatter.send_failure(uid, "An error has occured. Bot not added.")
Example #10
0
def access_token(bot, update):
    user = User.from_telegram_object(update.effective_user)
    rd_token = binascii.hexlify(os.urandom(32)).decode('utf-8')
    try:
        db_token = APIAccess.get(user=user).token
    except:
        db_token = "You have no token."
    text = "Random token: {}\n" \
           "Database token (use this for api calls):\n{}".format(rd_token, db_token)
    update.message.reply_text(text)
    return ConversationHandler.END
Example #11
0
def t3chnostats(bot, update):
    days = 30
    txt = 'Bots approved by other people *in the last {} days*:\n\n'.format(
        days)
    bots = Bot.select().where(
        (Bot.approved_by != User.get(User.chat_id == 918962))
        & (Bot.date_added.between(
            datetime.date.today() -
            datetime.timedelta(days=days), datetime.date.today())))
    txt += '\n'.join(
        ['{} by @{}'.format(str(b), b.approved_by.username) for b in bots])
    update.message.reply_text(txt, parse_mode=ParseMode.MARKDOWN)
Example #12
0
def send_favorites_list(bot, update, to_edit=None):
    uid = util.uid_from_update(update)
    user = User.from_update(update)

    t = threading.Thread(target=_too_many_favorites_handler,
                         args=(bot, update, user))
    t.start()

    favorites = Favorite.select_all(user)

    buttons = [[
        InlineKeyboardButton(captions.ADD_FAVORITE,
                             callback_data=util.callback_for_action(
                                 CallbackActions.ADD_FAVORITE)),
        InlineKeyboardButton(captions.REMOVE_FAVORITE,
                             callback_data=util.callback_for_action(
                                 CallbackActions.REMOVE_FAVORITE_MENU))
    ],
               [
                   InlineKeyboardButton(
                       'Layout: ' + Layouts.get_caption(user.favorites_layout),
                       callback_data=util.callback_for_action(
                           CallbackActions.TOGGLE_FAVORITES_LAYOUT,
                           {'v': Layouts.get_next(user.favorites_layout)})),
               ],
               [
                   InlineKeyboardButton(
                       captions.SHARE,
                       switch_inline_query=DeepLinkingActions.FAVORITES),
               ]]
    reply_markup = InlineKeyboardMarkup(buttons)

    if to_edit is None:
        to_edit = util.mid_from_update(update)

    if len(favorites) == 0:
        text = "You have no favorites yet."
    else:
        text = _favorites_categories_md(favorites, user.favorites_layout)

    bot.formatter.send_or_edit(uid,
                               text,
                               to_edit=to_edit,
                               reply_markup=reply_markup)
Example #13
0
    def of(cls, issuer, action: str, entity: str = None, level=logging.INFO):
        # if action not in Statistic.ACTIONS.keys():
        #     raise ValueError('"{}" is not a valid action. Refer to Statistic.ACTIONS for available keys.')

        if isinstance(issuer, User):
            user = issuer
        elif isinstance(issuer, Update):
            user = User.from_update(issuer)
        else:
            raise AttributeError(
                "The issuer argument needs to be an object of type User or Update."
            )
        obj = cls(user=user,
                  date=datetime.datetime.now(),
                  action=action,
                  entity=entity,
                  level=level)
        obj.save()
        return obj
Example #14
0
def broadcast(bot, update, user_data):
    cid = update.effective_chat.id
    uid = update.effective_user.id
    mid = util.mid_from_update(update)
    user = User.from_update(update)
    text = ''

    if cid == settings.BOTLISTCHAT_ID:
        replied_to = update.message.reply_to_message
        if replied_to:
            user_data['broadcast'] = dict(
                user_data.get('broadcast', dict()),
                reply_to_message_id=replied_to.message_id)
            if replied_to.from_user.username.lower() == settings.SELF_BOT_NAME:
                # editing
                text += '*You are editing one of my messages*\n\n'
                user_data['broadcast']['mode'] = 'editing'
            else:
                # replying
                text += '*You are replying to a message of {}.*\n\n'.format(
                    update.message.reply_to_message.from_user.first_name)
                user_data['broadcast']['mode'] = 'replying'
        # answer and clean
        msg = bot.send_message(cid, "k")
        _delete_multiple_delayed(bot,
                                 cid,
                                 delayed=[msg.message_id],
                                 immediately=[update.message.message_id])

    to_text = "  _to_  "
    text += "Send me the text to broadcast to @BotListChat.\n"
    text += "_You can use the following words and they will replaced:_\n\n"

    text += '\n'.join([
        '"{}"{}{}'.format(k, to_text, v)
        for k, v in BROADCAST_REPLACEMENTS.items()
    ])

    # TODO Build text mentioning replacements
    # text += '\n@' + str(update.effective_user.username) + to_text + user.markdown_short

    bot.formatter.send_or_edit(uid, mdformat.action_hint(text), mid)
    return BotStates.BROADCASTING
Example #15
0
def share_with_moderator(bot, update, bot_in_question, moderator):
    user = User.from_update(update)

    buttons = [
        [
            InlineKeyboardButton(
                "Yea, let me take this one!",
                callback_data=util.callback_for_action(
                    CallbackActions.APPROVE_REJECT_BOTS, {"id": bot_in_question.id}
                ),
            )
        ]
    ]
    reply_markup = InlineKeyboardMarkup(buttons)
    text = "{} thinks that you have the means to inspect this bot submission:\n▶️ {}".format(
        user.markdown_short, bot_in_question
    )
    try:
        util.send_md_message(
            bot,
            moderator.chat_id,
            text,
            reply_markup=reply_markup,
            disable_web_page_preview=True,
        )
        answer_text = mdformat.success(
            "I will ask {} to have a look at this submission.".format(
                moderator.plaintext
            )
        )
    except Exception as e:
        answer_text = mdformat.failure(f"Could not contact {moderator.plaintext}: {e}")

    if update.callback_query:
        update.callback_query.answer(text=answer_text)

    Statistic.of(
        update,
        "share",
        "submission {} with {}".format(bot_in_question.username, moderator.plaintext),
    )
Example #16
0
def hint_handler(bot, update, job_queue: JobQueue):
    chat_id = update.message.chat_id
    if not util.is_group_message(update):
        return
    text = update.message.text
    reply_to = update.message.reply_to_message
    user = User.from_update(update)
    msg, reply_markup, hashtag = get_hint_data(text)

    def _send_hint(hint_text):
        if hint_text is None:
            return
        if reply_to:
            hint_text = f"{user.markdown_short} hints: {hint_text}"

        bot.formatter.send_message(
            chat_id,
            hint_text,
            reply_markup=reply_markup,
            reply_to_message_id=reply_to.message_id if reply_to else None,
        )
        update.effective_message.delete()

    should_reply: bool = HINTS.get(hashtag)["should_reply"]
    if should_reply and not reply_to:
        del_markup = append_free_delete_button(update,
                                               InlineKeyboardMarkup([[]]))
        _send_hint(msg)
        ntfc_msg = update.effective_message.reply_text(
            f"Hey {user.markdown_short}, next time reply to someone 🙃",
            parse_mode=ParseMode.MARKDOWN,
            reply_markup=del_markup,
            quote=False,
            disable_web_page_preview=True,
        )
        job_queue.run_once(lambda *_: ntfc_msg.delete(),
                           7,
                           name="delete notification")
    else:
        _send_hint(msg)
Example #17
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)
Example #18
0
def credits(bot, update):
    users_contrib = User.select().join(Bot)
    pass
    Bot.select(Bot.submitted_by)
    return ConversationHandler.END
Example #19
0
def reject_bot_submission(
    bot,
    update,
    args=None,
    to_reject=None,
    verbose=True,
    notify_submittant=True,
    reason=None,
):
    uid = util.uid_from_update(update)
    user = User.from_update(update)

    if to_reject is None:
        if not update.message.reply_to_message:
            bot.send_message(
                update.effective_user.id,
                util.failure("You must reply to a message of mine."),
            )
            return

        text = update.message.reply_to_message.text
        reason = reason if reason else (" ".join(args) if args else None)

        try:
            update.message.delete()
        except:
            pass

        username = helpers.find_bots_in_text(text, first=True)
        if not username:
            bot.send_message(
                update.effective_user.id,
                util.failure("No username in the message that you replied to."),
            )
            return

        try:
            to_reject = Bot.by_username(username)
        except Bot.DoesNotExist:
            bot.send_message(
                update.effective_user.id,
                util.failure(
                    "Rejection failed: {} is not present in the "
                    "database.".format(username)
                ),
            )
            return

        if to_reject.approved is True:
            msg = "{} has already been accepted, so it cannot be rejected anymore.".format(
                username
            )
            bot.sendMessage(uid, util.failure(msg))
            return

    Statistic.of(update, "reject", to_reject.username)
    text = notify_submittant_rejected(bot, user, notify_submittant, reason, to_reject)
    to_reject.delete_instance()

    if verbose:
        bot.sendMessage(uid, text)

    if update.callback_query:
        update.callback_query.answer(text=text)
Example #20
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
Example #21
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
Example #22
0
def check_submission(bot, bot_checker: "BotChecker", to_check: Bot):
    # TODO: make this method async
    if bot_checker is None:
        return

    botlistbot_user = User.botlist_user_instance()

    log.debug("Checking bot {}...".format(to_check.username))

    def reject(reason):
        to_check.delete_instance()
        msg = notify_submittant_rejected(
            bot,
            botlistbot_user,
            notify_submittant=True,
            reason=reason,
            to_reject=to_check,
        )
        bot.formatter.send_message(settings.BOTLIST_NOTIFICATIONS_ID, msg)

    try:
        peer = bot_checker.resolve_bot(to_check)
    except UsernameNotOccupied:
        to_check.delete_instance()
        reject(
            "The entity you submitted either does not exist or is not a Telegram bot."
        )
        return

    bot_checker.update_bot_details(to_check, peer)

    if to_check.userbot:
        reject(
            "You submitted the name of a Telegram user, not one of a bot. If you're trying to "
            "submit a userbot, please contact the BLSF directly ("
            "@BotListChat)."
        )
        return

    # Check online state
    response = loop.run_until_complete(
        bot_checker.get_ping_response(
            to_check, timeout=18, try_inline=to_check.inlinequeries
        )
    )

    is_offline = not bool(response)

    if is_offline:
        reject(
            "The bot you sent seems to be offline, unfortunately. Feel free to submit it again "
            "when it's back up 😙"
        )
        return

    now = datetime.datetime.now()
    to_check.last_ping = now
    to_check.last_response = now

    loop.run_until_complete(add_keywords(bot, response, to_check))

    # Download profile picture
    if settings.DOWNLOAD_PROFILE_PICTURES:
        # TODO: does this work asynchronously?
        loop.run_until_complete(download_profile_picture(bot, bot_checker, to_check))

    to_check.save()
    log.info(f"{to_check} was evaluated and looks good for approval.")
Example #23
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
Example #24
0
def inlinequery_handler(bot, update, chat_data):
    query = update.inline_query.query.lower()

    # TODO: remove or enhance eventually, this is potentially very spammy
    # Statistic.of(update, 'inlinequery', '"{}"'.format(query), Statistic.DETAILED)

    user = User.from_update(update)
    results_list = list()

    input_given = len(query.strip()) > 0
    query_too_short = 0 < len(query.strip()) < SEARCH_QUERY_MIN_LENGTH

    too_many_results = False
    cat_results = []
    bot_results = []

    if input_given:
        # query category results
        cat_results = search.search_categories(query)

        if not query_too_short:
            # query bot results
            bot_results = list(search.search_bots(query))
            if len(bot_results) > MAX_BOTS:
                bot_results = bot_results[:MAX_BOTS]
                too_many_results = True

    # query for new bots
    if query == messages.NEW_BOTS_INLINEQUERY.lower() or query == 'new':
        results_list.append(new_bots_article())
        bot.answer_inline_query(update.inline_query.id, results=results_list)
        return

    if query in CONTRIBUTING_QUERIES:
        results_list.append(
            InlineQueryResultArticle(
                id=uuid4(),
                title='Contributing',
                input_message_content=InputTextMessageContent(
                    message_text=messages.CONTRIBUTING, parse_mode="Markdown"),
            ))
        bot.answer_inline_query(update.inline_query.id,
                                results=results_list,
                                cache_time=600)
        return

    if query in EXAMPLES_QUERIES:
        results_list.append(
            InlineQueryResultArticle(
                id=uuid4(),
                title='Examples',
                input_message_content=InputTextMessageContent(
                    message_text=messages.EXAMPLES, parse_mode="Markdown"),
            ))
        bot.answer_inline_query(update.inline_query.id,
                                results=results_list,
                                cache_time=600)
        return

    if query in (const.DeepLinkingActions.RULES, '#rules'):
        results_list.append(
            InlineQueryResultArticle(
                id=uuid4(),
                title='@BotListChat Rules',
                input_message_content=InputTextMessageContent(
                    message_text=messages.BOTLISTCHAT_RULES,
                    parse_mode="Markdown",
                    disable_web_page_preview=True),
            ))
        bot.answer_inline_query(update.inline_query.id,
                                results=results_list,
                                cache_time=600)
        return

    if query == const.DeepLinkingActions.FAVORITES and user.has_favorites:
        results_list.append(favorites_article(user))
        bot.answer_inline_query(update.inline_query.id,
                                results=results_list,
                                cache_time=0,
                                is_personal=True)
        return

    msg, reply_markup, key = botlistchat.get_hint_data(query)
    if msg is not None:
        results_list.append(hint_article(msg, reply_markup, key))
        bot.answer_inline_query(update.inline_query.id,
                                results=results_list,
                                cache_time=600)
        return

    invalid_search_term = query_too_short and not cat_results
    if invalid_search_term:
        results_list.append(query_too_short_article())

    results_available = cat_results or bot_results
    if results_available:
        if len(bot_results) > 1:
            results_list.append(
                all_bot_results_article(bot_results, too_many_results))
        for c in cat_results:
            results_list.append(category_article(c))
        for b in bot_results:
            results_list.append(bot_article(b))

        if len(bot_results) > 0:
            bot.answer_inline_query(
                update.inline_query.id,
                results=results_list,
                switch_pm_text="See all results"
                if too_many_results else "Search in private chat",
                switch_pm_parameter=util.encode_base64(query),
                cache_time=0,
                is_personal=True)
        else:
            bot.answer_inline_query(update.inline_query.id,
                                    results=results_list,
                                    cache_time=0,
                                    is_personal=True)
    else:
        if user.has_favorites:
            results_list.append(favorites_article(user))
        results_list.append(new_bots_article())
        categories = Category.select_all()
        for c in categories:
            results_list.append(category_article(c))

        if invalid_search_term or not input_given:
            bot.answer_inline_query(update.inline_query.id,
                                    results=results_list,
                                    cache_time=0,
                                    is_personal=True)
        else:
            bot.answer_inline_query(
                update.inline_query.id,
                results=results_list,
                switch_pm_text="No results. Contribute a bot?",
                switch_pm_parameter='contributing',
                cache_time=0,
                is_personal=True)
Example #25
0
def callback_router(bot, update, chat_data, user_data, job_queue):
    obj = json.loads(str(update.callback_query.data))
    user = User.from_update(update)

    try:
        if "a" in obj:
            action = obj["a"]

            # BOTLISTCHAT
            if action == CallbackActions.DELETE_CONVERSATION:
                botlistchat.delete_conversation(bot, update, chat_data)
            # HELP
            elif action == CallbackActions.HELP:
                help.help(bot, update)
            elif action == CallbackActions.CONTRIBUTING:
                help.contributing(bot, update)
            elif action == CallbackActions.EXAMPLES:
                help.examples(bot, update)
            # BASIC QUERYING
            elif action == CallbackActions.SELECT_CATEGORY:
                select_category(bot, update, chat_data)
            elif action == CallbackActions.SELECT_BOT_FROM_CATEGORY:
                category = Category.get(id=obj["id"])
                send_category(bot, update, chat_data, category)
            elif action == CallbackActions.SEND_BOT_DETAILS:
                item = Bot.get(id=obj["id"])
                send_bot_details(bot, update, chat_data, item)
            # FAVORITES
            elif action == CallbackActions.TOGGLE_FAVORITES_LAYOUT:
                value = obj["v"]
                favorites.toggle_favorites_layout(bot, update, value)
            elif action == CallbackActions.ADD_FAVORITE:
                favorites.add_favorite_handler(bot, update)
            elif action == CallbackActions.REMOVE_FAVORITE_MENU:
                favorites.remove_favorite_menu(bot, update)
            elif action == CallbackActions.REMOVE_FAVORITE:
                to_remove = Favorite.get(id=obj["id"])
                bot_details = to_remove.bot
                to_remove.delete_instance()
                if obj.get("details"):
                    send_bot_details(bot, update, chat_data, bot_details)
                else:
                    favorites.remove_favorite_menu(bot, update)
            elif action == CallbackActions.SEND_FAVORITES_LIST:
                favorites.send_favorites_list(bot, update)
            elif action == CallbackActions.ADD_ANYWAY:
                favorites.add_custom(bot, update, obj["u"])
            elif action == CallbackActions.ADD_TO_FAVORITES:
                details = obj.get("details")
                discreet = obj.get("discreet", False) or details
                item = Bot.get(id=obj["id"])
                favorites.add_favorite(bot,
                                       update,
                                       item,
                                       callback_alert=discreet)
                if details:
                    send_bot_details(bot, update, chat_data, item)
            # ACCEPT/REJECT BOT SUBMISSIONS
            elif action == CallbackActions.APPROVE_REJECT_BOTS:
                custom_approve_list = [Bot.get(id=obj["id"])]
                admin.approve_bots(bot,
                                   update,
                                   override_list=custom_approve_list)
            elif action == CallbackActions.ACCEPT_BOT:
                to_accept = Bot.get(id=obj["id"])
                admin.edit_bot_category(bot, update, to_accept,
                                        CallbackActions.BOT_ACCEPTED)
                # Run in x minutes, giving the moderator enough time to edit bot details
                job_queue.run_once(
                    lambda b, job: botlistchat.
                    notify_group_submission_accepted(b, job, to_accept),
                    settings.BOT_ACCEPTED_IDLE_TIME * 60,
                )
            elif action == CallbackActions.RECOMMEND_MODERATOR:
                bot_in_question = Bot.get(id=obj["id"])
                admin.recommend_moderator(bot, update, bot_in_question,
                                          obj["page"])
            elif action == CallbackActions.SELECT_MODERATOR:
                bot_in_question = Bot.get(id=obj["bot_id"])
                moderator = User.get(id=obj["uid"])
                admin.share_with_moderator(bot, update, bot_in_question,
                                           moderator)
                admin.approve_bots(bot, update, obj["page"])
            elif action == CallbackActions.REJECT_BOT:
                to_reject = Bot.get(id=obj["id"])
                notification = obj.get("ntfc", True)
                admin.reject_bot_submission(
                    bot,
                    update,
                    None,
                    to_reject,
                    verbose=False,
                    notify_submittant=notification,
                )
                admin.approve_bots(bot, update, obj["page"])
            elif action == CallbackActions.BOT_ACCEPTED:
                to_accept = Bot.get(id=obj["bid"])
                category = Category.get(id=obj["cid"])
                admin.accept_bot_submission(bot, update, to_accept, category)
            elif action == CallbackActions.COUNT_THANK_YOU:
                new_count = obj.get("count", 1)
                basic.count_thank_you(bot, update, new_count)
            # ADD BOT
            # elif action == CallbackActions.ADD_BOT_SELECT_CAT:
            #     category = Category.get(id=obj['id'])
            #     admin.add_bot(bot, update, chat_data, category)
            # EDIT BOT
            elif action == CallbackActions.EDIT_BOT:
                to_edit = Bot.get(id=obj["id"])
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_SELECT_CAT:
                to_edit = Bot.get(id=obj["id"])
                admin.edit_bot_category(bot, update, to_edit)
            elif action == CallbackActions.EDIT_BOT_CAT_SELECTED:
                to_edit = Bot.get(id=obj["bid"])
                cat = Category.get(id=obj["cid"])
                botproperties.change_category(bot, update, to_edit, cat)
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_COUNTRY:
                to_edit = Bot.get(id=obj["id"])
                botproperties.set_country_menu(bot, update, to_edit)
            elif action == CallbackActions.SET_COUNTRY:
                to_edit = Bot.get(id=obj["bid"])
                if obj["cid"] == "None":
                    country = None
                else:
                    country = Country.get(id=obj["cid"])
                botproperties.set_country(bot, update, to_edit, country)
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_DESCRIPTION:
                to_edit = Bot.get(id=obj["id"])
                botproperties.set_text_property(bot, update, chat_data,
                                                "description", to_edit)
            elif action == CallbackActions.EDIT_BOT_EXTRA:
                to_edit = Bot.get(id=obj["id"])
                # SAME IS DONE HERE, but manually
                botproperties.set_text_property(bot, update, chat_data,
                                                "extra", to_edit)
            elif action == CallbackActions.EDIT_BOT_NAME:
                to_edit = Bot.get(id=obj["id"])
                botproperties.set_text_property(bot, update, chat_data, "name",
                                                to_edit)
            elif action == CallbackActions.EDIT_BOT_USERNAME:
                to_edit = Bot.get(id=obj["id"])
                botproperties.set_text_property(bot, update, chat_data,
                                                "username", to_edit)
            # elif action == CallbackActions.EDIT_BOT_KEYWORDS:
            #     to_edit = Bot.get(id=obj['id'])
            #     botproperties.set_keywords_init(bot, update, chat_data, to_edit)
            elif action == CallbackActions.APPLY_ALL_CHANGES:
                to_edit = Bot.get(id=obj["id"])
                admin.apply_all_changes(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_INLINEQUERIES:
                to_edit = Bot.get(id=obj["id"])
                value = bool(obj["value"])
                botproperties.toggle_value(bot, update, "inlinequeries",
                                           to_edit, value)
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_OFFICIAL:
                to_edit = Bot.get(id=obj["id"])
                value = bool(obj["value"])
                botproperties.toggle_value(bot, update, "official", to_edit,
                                           value)
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_OFFLINE:
                to_edit = Bot.get(id=obj["id"])
                value = bool(obj["value"])
                botproperties.toggle_value(bot, update, "offline", to_edit,
                                           value)
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.EDIT_BOT_SPAM:
                to_edit = Bot.get(id=obj["id"])
                value = bool(obj["value"])
                botproperties.toggle_value(bot, update, "spam", to_edit, value)
                admin.edit_bot(bot, update, chat_data, to_edit)
            elif action == CallbackActions.CONFIRM_DELETE_BOT:
                to_delete = Bot.get(id=obj["id"])
                botproperties.delete_bot_confirm(bot, update, to_delete)
            elif action == CallbackActions.DELETE_BOT:
                to_edit = Bot.get(id=obj["id"])
                botproperties.delete_bot(bot, update, to_edit)
                # send_category(bot, update, chat_data, to_edit.category)
            elif action == CallbackActions.ACCEPT_SUGGESTION:
                suggestion = Suggestion.get(id=obj["id"])
                components.botproperties.accept_suggestion(
                    bot, update, suggestion)
                admin.approve_suggestions(bot, update, page=obj["page"])
            elif action == CallbackActions.REJECT_SUGGESTION:
                suggestion = Suggestion.get(id=obj["id"])
                suggestion.delete_instance()
                admin.approve_suggestions(bot, update, page=obj["page"])
            elif action == CallbackActions.CHANGE_SUGGESTION:
                suggestion = Suggestion.get(id=obj["id"])
                botproperties.change_suggestion(bot,
                                                update,
                                                suggestion,
                                                page_handover=obj["page"])
            elif action == CallbackActions.SWITCH_SUGGESTIONS_PAGE:
                page = obj["page"]
                admin.approve_suggestions(bot, update, page)
            elif action == CallbackActions.SWITCH_APPROVALS_PAGE:
                admin.approve_bots(bot, update, page=obj["page"])
            elif action == CallbackActions.SET_NOTIFICATIONS:
                set_notifications(bot, update, obj["value"])
            elif action == CallbackActions.NEW_BOTS_SELECTED:
                show_new_bots(bot, update, chat_data, back_button=True)
            elif action == CallbackActions.ABORT_SETTING_KEYWORDS:
                to_edit = Bot.get(id=obj["id"])
                admin.edit_bot(bot, update, chat_data, to_edit)
            # SENDING BOTLIST
            elif action == CallbackActions.SEND_BOTLIST:
                silent = obj.get("silent", False)
                re_send = obj.get("re", False)
                botlist.send_botlist(bot,
                                     update,
                                     resend=re_send,
                                     silent=silent)
            elif action == CallbackActions.RESEND_BOTLIST:
                botlist.send_botlist(bot, update, resend=True, silent=True)
            # BROADCASTING
            elif action == "send_broadcast":
                broadcasts.send_broadcast(bot, update, user_data)
            elif action == "pin_message":
                broadcasts.pin_message(bot, update, obj["mid"])
            elif action == "add_thank_you":
                basic.add_thank_you_button(bot, update, obj["cid"], obj["mid"])
            # EXPLORING
            elif action == CallbackActions.EXPLORE_NEXT:
                explore.explore(bot, update, chat_data)
    except Exception as e:
        traceback.print_exc()

        # get the callback action in plaintext
        actions = dict(CallbackActions.__dict__)
        a = next(k for k, v in actions.items() if v == obj.get("a"))
        util.send_md_message(
            bot,
            settings.DEVELOPER_ID,
            "Exception in callback query for {}:\n{}\n\nWith CallbackAction {}\n\nWith data:\n{}"
            .format(
                user.markdown_short,
                util.escape_markdown(e),
                util.escape_markdown(a),
                util.escape_markdown(str(obj)),
            ),
        )
    finally:
        bot.answerCallbackQuery(update.callback_query.id)
        return ConversationHandler.END
Example #26
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
Example #27
0
def toggle_favorites_layout(bot, update, value):
    uid = util.uid_from_update(update)
    user = User.from_update(update)
    user.favorites_layout = value
    user.save()
    send_favorites_list(bot, update)
Example #28
0
from botlistbot.models import Bot
from botlistbot.models import User

if __name__ == '__main__':
    all_bots = Bot.select()
    for bot in all_bots:
        if bot.spam is None:
            bot.spam = False
        if bot.official is None:
            bot.official = False
        if bot.inlinequeries is None:
            bot.inlinequeries = False
        if bot.offline is None:
            bot.offline = False
        bot.save()

    all_users = User.select()
    for user in all_users:
        if user.favorites_layout is None:
            user.favorites_layout = 'categories'
        user.save()