コード例 #1
0
ファイル: botproperties.py プロジェクト: Bfaschat/BotListBot
def set_keywords(bot, update, chat_data, to_edit):
    chat_id = util.uid_from_update(update)
    keywords = Keyword.select().where(Keyword.entity == to_edit)
    chat_data['edit_bot'] = to_edit
    set_keywords_msgid = chat_data.get('set_keywords_msg')

    kw_remove_buttons = [
        InlineKeyboardButton('{} ✖️'.format(x),
                             callback_data=util.callback_for_action(
                                 CallbackActions.REMOVE_KEYWORD, {
                                     'id': to_edit.id,
                                     'kwid': x.id
                                 })) for x in keywords
    ]
    buttons = util.build_menu(
        kw_remove_buttons,
        2,
        header_buttons=[
            InlineKeyboardButton(captions.DONE,
                                 callback_data=util.callback_for_action(
                                     CallbackActions.ABORT_SETTING_KEYWORDS,
                                     {'id': to_edit.id}))
        ])
    reply_markup = InlineKeyboardMarkup(buttons)
    msg = util.send_or_edit_md_message(
        bot,
        chat_id,
        util.action_hint(
            'Send me the keywords for {} one by one...\n\n{}'.format(
                util.escape_markdown(to_edit.username),
                messages.KEYWORD_BEST_PRACTICES)),
        to_edit=set_keywords_msgid,
        reply_markup=reply_markup)
    chat_data['set_keywords_msg'] = msg.message_id
    return BotStates.SENDING_KEYWORDS
コード例 #2
0
def edit_bot_category(bot, update, for_bot, callback_action=None):
    if callback_action is None:
        callback_action = CallbackActions.EDIT_BOT_CAT_SELECTED
    uid = util.uid_from_update(update)
    categories = Category.select().order_by(Category.name.asc()).execute()

    buttons = util.build_menu(
        [
            InlineKeyboardButton(
                "{}{}".format(emoji.emojize(c.emojis, use_aliases=True),
                              c.name),
                callback_data=util.callback_for_action(callback_action, {
                    "cid": c.id,
                    "bid": for_bot.id
                }),
            ) for c in categories
        ],
        2,
    )
    return bot.formatter.send_or_edit(
        uid,
        util.action_hint("Please select a category" +
                         (" for {}".format(for_bot) if for_bot else "")),
        to_edit=util.mid_from_update(update),
        reply_markup=InlineKeyboardMarkup(buttons),
    )
コード例 #3
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)
コード例 #4
0
ファイル: botproperties.py プロジェクト: Bfaschat/BotListBot
def set_country_menu(bot, update, to_edit):
    uid = util.uid_from_update(update)
    countries = Country.select().order_by(Country.name).execute()

    buttons = util.build_menu([
        InlineKeyboardButton('{} {}'.format(c.emojized, c.name),
                             callback_data=util.callback_for_action(
                                 CallbackActions.SET_COUNTRY, {
                                     'cid': c.id,
                                     'bid': to_edit.id
                                 })) for c in countries
    ], 3)
    buttons.insert(0, [
        InlineKeyboardButton(captions.BACK,
                             callback_data=util.callback_for_action(
                                 CallbackActions.EDIT_BOT,
                                 {'id': to_edit.id})),
        InlineKeyboardButton("None",
                             callback_data=util.callback_for_action(
                                 CallbackActions.SET_COUNTRY, {
                                     'cid': 'None',
                                     'bid': to_edit.id
                                 })),
    ])
    return bot.formatter.send_or_edit(
        uid,
        util.action_hint(
            "Please select a country/language for {}".format(to_edit)),
        to_edit=util.mid_from_update(update),
        reply_markup=InlineKeyboardMarkup(buttons))
コード例 #5
0
ファイル: admin.py プロジェクト: n8wachT/BotListBot
def prepare_transmission(bot, update, chat_data):
    chat_id = util.uid_from_update(update)
    text = mdformat.action_hint("Notify subscribers about this update?")
    reply_markup = InlineKeyboardMarkup(
        [[
            InlineKeyboardButton("☑ Notifications",
                                 callback_data=util.callback_for_action(
                                     CallbackActions.SEND_BOTLIST,
                                     {'silent': False})),
            InlineKeyboardButton("Silent",
                                 callback_data=util.callback_for_action(
                                     CallbackActions.SEND_BOTLIST,
                                     {'silent': True}))
        ],
         [
             InlineKeyboardButton("Re-send all Messages",
                                  callback_data=util.callback_for_action(
                                      CallbackActions.SEND_BOTLIST, {
                                          'silent': True,
                                          're': True
                                      }))
         ]])

    # # TODO
    # text = "Temporarily disabled"
    # reply_markup = None

    util.send_md_message(bot, chat_id, text, reply_markup=reply_markup)
コード例 #6
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 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
コード例 #7
0
ファイル: admin.py プロジェクト: n8wachT/BotListBot
def _input_failed(bot, update, chat_data, text):
    chat_id = util.uid_from_update(update)
    bot.formatter.send_failure(chat_id, text)
    Statistic.of(update, 'error',
                 'input failed in admin menu for {}'.format(text),
                 Statistic.ANALYSIS)
    chat_data['add_bot_message'] = None
コード例 #8
0
ファイル: botproperties.py プロジェクト: Bfaschat/BotListBot
def set_text_property(bot, update, chat_data, property_name, to_edit=None):
    uid = util.uid_from_update(update)
    user = User.from_update(update)
    if check_suggestion_limit(bot, update, user):
        return

    if to_edit:
        text = (util.escape_markdown(getattr(to_edit, property_name)) +
                "\n\n" if getattr(to_edit, property_name) else '')
        text += mdformat.action_hint(
            messages.SET_BOTPROPERTY.format(
                property_name, util.escape_markdown(to_edit.username),
                CLEAR_QUERY))
        if property_name == 'description':
            text += ', markdown enabled.'
        update.effective_message.reply_text(
            text,
            reply_markup=ForceReply(selective=True),
            parse_mode=ParseMode.MARKDOWN)
        chat_data['edit_bot'] = to_edit
    elif update.message:
        value = None
        text = update.message.text

        to_edit = chat_data.get('edit_bot', None)

        def too_long(n):
            bot.formatter.send_failure(
                uid, "Your {} text is too long, it must be shorter "
                "than {} characters. Please try again.".format(
                    property_name, n))
            util.wait(bot, update)
            return admin.edit_bot(bot, update, chat_data, to_edit)

        # Validation
        if property_name == 'description' and len(text) > 300:
            return too_long(300)
        if property_name == 'username':
            value = helpers.validate_username(text)
            if value:
                to_edit = chat_data.get('edit_bot', None)
            else:
                bot.formatter.send_failure(
                    uid,
                    "The username you entered is not valid. Please try again..."
                )
                return admin.edit_bot(bot, update, chat_data, to_edit)

        if not value:
            value = text

        if to_edit:
            if _is_clear_query(text):
                Suggestion.add_or_update(user, property_name, to_edit, None)
            else:
                Suggestion.add_or_update(user, property_name, to_edit, value)
            admin.edit_bot(bot, update, chat_data, to_edit)
        else:
            bot.formatter.send_failure(uid, "An unexpected error occured.")
コード例 #9
0
ファイル: botproperties.py プロジェクト: Bfaschat/BotListBot
def delete_bot(bot, update, to_edit):
    chat_id = util.uid_from_update(update)
    username = to_edit.username
    to_edit.delete_instance()
    bot.formatter.send_or_edit(chat_id,
                               "Bot has been deleted.",
                               to_edit=util.mid_from_update(update))
    Statistic.of(update, 'delete', username, Statistic.IMPORTANT)
コード例 #10
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,
    )
コード例 #11
0
ファイル: eastereggs.py プロジェクト: n8wachT/BotListBot
def send_next(bot, update, args=None):
    uid = util.uid_from_update(update)
    rows = None
    if args:
        try:
            rows = int(args[0])
        except:
            rows = None
    reply_markup = ReplyKeyboardMarkup(_crapPy_Tr0ll_kbmarkup(rows), one_time_keyboard=True, per_user=True)
    text = 'ɹoʇɐɹǝuǝb ǝɯɐuɹǝsn ɯɐɹbǝןǝʇ'
    util.send_md_message(bot, uid, text, reply_markup=reply_markup)
コード例 #12
0
def _too_many_favorites_handler(bot, update, user):
    uid = util.uid_from_update(update)
    any_removed = False
    while too_many_favorites(user):
        oldest = Favorite.get_oldest(user)
        oldest.delete_instance()
        any_removed = True
        Statistic.of(update, 'had to lose a favorite because HE HAD TOO F****N MANY 😬')
    if any_removed:
        txt = "You have too many favorites, _they do not fit into a single message_. That's why I removed your " \
              "oldest bot, *{}*, from your list of favorites.".format(oldest.bot if oldest.bot else oldest.custom_bot)
        util.send_md_message(bot, uid, txt)
コード例 #13
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, settings.BOT_ACCEPTED_IDLE_TIME),
            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.")
コード例 #14
0
ファイル: botproperties.py プロジェクト: Bfaschat/BotListBot
def delete_bot_confirm(bot, update, to_edit):
    chat_id = util.uid_from_update(update)
    reply_markup = InlineKeyboardMarkup([[
        InlineKeyboardButton("Yes, delete it!",
                             callback_data=util.callback_for_action(
                                 CallbackActions.DELETE_BOT,
                                 {'id': to_edit.id})),
        InlineKeyboardButton(captions.BACK,
                             callback_data=util.callback_for_action(
                                 CallbackActions.EDIT_BOT, {'id': to_edit.id}))
    ]])
    bot.formatter.send_or_edit(chat_id,
                               "Are you sure?",
                               to_edit=util.mid_from_update(update),
                               reply_markup=reply_markup)
コード例 #15
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)
コード例 #16
0
ファイル: admin.py プロジェクト: n8wachT/BotListBot
def send_offline(bot, update):
    chat_id = util.uid_from_update(update)
    offline = Bot.select(Bot, Ping).join(Ping, JOIN.LEFT_OUTER).where(
        Bot.offline == True).order_by(Ping.last_response.asc())

    def offline_since(b):
        if not b.ping.last_response:
            return 'a long time'
        slanged_time = helpers.slang_datetime(b.ping.last_response)
        return slanged_time.replace(' ago', '')

    if len(offline) > 0:
        text = "Offline Bots:\n\n"
        text += '\n'.join([
            "{}{} — /edit{}".format(str(b),
                                    " (for {})".format(offline_since(b)), b.id)
            for b in offline
        ])
    else:
        text = "No bots are offline."
    bot.formatter.send_message(chat_id, text)
コード例 #17
0
def send_next(bot, update, job_queue: JobQueue, args=None):
    uid = util.uid_from_update(update)
    num_rows = None
    if args:
        try:
            num_rows = int(args[0])
        except:
            num_rows = None

    reply_markup = ReplyKeyboardMarkup(_crapPy_Tr0ll_kbmarkup(num_rows),
                                       one_time_keyboard=False,
                                       per_user=True)
    text = "ɹoʇɐɹǝuǝb ǝɯɐuɹǝsn ɯɐɹbǝןǝʇ"
    util.send_md_message(bot, uid, text, reply_markup=reply_markup)

    if util.is_group_message(update):
        del_msg = bot.formatter.send_message(
            update.effective_chat.id, "Have fun in private ;)\n/easteregg")
        update.effective_message.delete()
        job_queue.run_once(lambda *_: del_msg.delete(safe=True),
                           4,
                           name="delete easteregg hint")
コード例 #18
0
def add_favorite_handler(bot, update, args=None):
    uid = util.uid_from_update(update)
    from components.basic import main_menu_buttons
    main_menu_markup = ReplyKeyboardMarkup(main_menu_buttons(uid in settings.MODERATORS))

    if args:
        query = ' '.join(args) if isinstance(args, list) else args
        try:
            # TODO: add multiple
            username = re.match(settings.REGEX_BOT_IN_TEXT, query).groups()[0]
            try:
                # TODO: get exact database matches for input without `@`
                item = Bot.by_username(username, include_disabled=True)

                return add_favorite(bot, update, item)
            except Bot.DoesNotExist:
                buttons = [
                    InlineKeyboardButton(
                        "Yai!", callback_data=util.callback_for_action(CallbackActions.ADD_ANYWAY, {'u': username})),
                    InlineKeyboardButton("Nay...", callback_data=util.callback_for_action(CallbackActions.ADD_FAVORITE))
                ]
                reply_markup = InlineKeyboardMarkup([buttons])
                util.send_md_message(bot, uid,
                                     "{} is not in the @BotList. Do you want to add it to your {} anyway?".format(
                                         username, captions.FAVORITES),
                                     reply_markup=reply_markup)
        except AttributeError:
            # invalid bot username
            # TODO when does this happen?
            update.message.reply_text(
                util.failure("Sorry, but that is not a valid username. Please try again. /addfav"))
    else:
        buttons = [
            InlineKeyboardButton("Search inline", switch_inline_query_current_chat='')
        ]
        reply_markup = InlineKeyboardMarkup([buttons])

        bot.sendMessage(uid, messages.ADD_FAVORITE, reply_markup=ForceReply(selective=True))
    return ConversationHandler.END
コード例 #19
0
def send_offline(bot, update):
    chat_id = util.uid_from_update(update)
    offline = (Bot.select().where(Bot.offline == True,
                                  Bot.disabled == False).order_by(
                                      Bot.last_response.asc()))

    def offline_since(b):
        if not b.last_response:
            return "a long time"
        slanged_time = helpers.slang_datetime(b.last_response)
        return slanged_time.replace(" ago", "")

    if len(offline) > 0:
        text = "Offline Bots:\n\n"
        text += "\n".join([
            "{}{} — /edit{}".format(str(b),
                                    " (for {})".format(offline_since(b)), b.id)
            for b in offline
        ])
    else:
        text = "No bots are offline."
    bot.formatter.send_message(chat_id, text)
コード例 #20
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)
コード例 #21
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 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
コード例 #22
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)
コード例 #23
0
ファイル: admin.py プロジェクト: n8wachT/BotListBot
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)
    log_msg = "{} rejected by {}.".format(to_reject.username, user)
    notification_successful = None
    if notify_submittant or reason:
        try:
            if reason:
                bot.send_message(
                    to_reject.submitted_by.chat_id,
                    util.failure(
                        messages.REJECTION_WITH_REASON.format(
                            to_reject.username, reason=reason)))
            else:
                bot.sendMessage(
                    to_reject.submitted_by.chat_id,
                    util.failure(
                        messages.REJECTION_PRIVATE_MESSAGE.format(
                            to_reject.username)))
            log_msg += "\nUser {} was notified.".format(
                str(to_reject.submitted_by))
            notification_successful = True
        except TelegramError:
            log_msg += "\nUser {} could NOT be contacted/notified in private.".format(
                str(to_reject.submitted_by))
            notification_successful = False
    to_reject.delete_instance()
    log.info(log_msg)

    text = util.success("{} rejected.".format(to_reject.username))
    if notification_successful is True:
        text += " User {} was notified.".format(
            to_reject.submitted_by.plaintext)
    elif notification_successful is False:
        text += ' ' + mdformat.failure("Could not contact {}.".format(
            to_reject.submitted_by.plaintext))
    else:
        text += " No notification sent."

    if verbose:
        bot.sendMessage(uid, text)

    if update.callback_query:
        update.callback_query.answer(text=text)
コード例 #24
0
def restart(bot, update):
    chat_id = util.uid_from_update(update)
    os.kill(os.getpid(), signal.SIGINT)
    bot.formatter.send_success(chat_id, "Bot is restarting...")
    time.sleep(0.3)
    os.execl(sys.executable, sys.executable, *sys.argv)
コード例 #25
0
ファイル: admin.py プロジェクト: n8wachT/BotListBot
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).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('👥🔀',
                                 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 "Please select a bot you want to accept for the BotList"
    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
コード例 #26
0
ファイル: admin.py プロジェクト: n8wachT/BotListBot
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
コード例 #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)
コード例 #28
0
ファイル: admin.py プロジェクト: Bfaschat/BotListBot
def reject_bot_submission(bot,
                          update,
                          to_reject=None,
                          verbose=True,
                          notify_submittant=True):
    uid = util.uid_from_update(update)
    user = User.from_update(update)

    if to_reject is None:
        if not update.message.reply_to_message:
            update.message.reply_text(
                util.failure("You must reply to a message of mine."))
            return
        text = update.message.reply_to_message.text

        try:
            username = re.match(settings.REGEX_BOT_IN_TEXT, text).groups()[0]
        except AttributeError:
            log.info("No username in the message that was replied to.")
            # no bot username, ignore update
            return

        try:
            to_reject = Bot.by_username(username)
        except Bot.DoesNotExist:
            log.info("Rejection failed: could not find {}".format(username))
            return

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

    Statistic.of(update, 'reject', to_reject.username)
    log_msg = "{} rejected by {}.".format(to_reject.username, user)
    notification_successful = None
    if notify_submittant:
        try:
            bot.sendMessage(
                to_reject.submitted_by.chat_id,
                util.failure(
                    messages.REJECTION_PRIVATE_MESSAGE.format(
                        to_reject.username)))
            log_msg += "\nUser {} was notified.".format(
                str(to_reject.submitted_by))
            notification_successful = True
        except TelegramError:
            log_msg += "\nUser {} could NOT be contacted/notified in private.".format(
                str(to_reject.submitted_by))
            notification_successful = False
    to_reject.delete_instance()
    log.info(log_msg)

    text = util.success("{} rejected.".format(to_reject.username))
    if notification_successful is True:
        text += " User {} was notified.".format(
            to_reject.submitted_by.plaintext)
    elif notification_successful is False:
        text += ' ' + mdformat.failure("Could not contact {}.".format(
            to_reject.submitted_by.plaintext))
    else:
        text += " No notification sent."

    if verbose:
        bot.sendMessage(uid, text)

    if update.callback_query:
        update.callback_query.answer(text=text)
コード例 #29
0
def new_bot_submission(bot, update, chat_data, args=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)
        if 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 components.explore import send_bot_details
        send_bot_details(bot, update, chat_data, new_bot)
    else:
        msg = 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)
    return ConversationHandler.END
コード例 #30
0
def set_keywords(bot, update, chat_data, to_edit):
    chat_id = util.uid_from_update(update)
    keywords = Keyword.select().where(Keyword.entity == to_edit)
    chat_data['edit_bot'] = to_edit
    set_keywords_msgid = chat_data.get('set_keywords_msg')

    pending = Suggestion.select().where(
        Suggestion.executed == False, Suggestion.subject == to_edit,
        Suggestion.action << ['add_keyword', 'remove_keyword'])
    pending_removal = [y for y in pending if y.action == 'remove_keyword']

    # Filter keywords by name to not include removal suggestions
    # We don't need to do this for add_keyword suggestions, because duplicates are not allowed.
    keywords = [
        k for k in keywords
        if k.name not in [s.value for s in pending_removal]
    ]

    kw_remove_buttons = [
        InlineCallbackButton('{} ✖️'.format(x),
                             callback_action=CallbackActions.REMOVE_KEYWORD,
                             params={
                                 'id': to_edit.id,
                                 'kwid': x.id
                             }) for x in keywords
    ]
    kw_remove_buttons.extend([
        InlineKeyboardButton('#{} 👓✖️'.format(x.value),
                             callback_data=util.callback_for_action(
                                 CallbackActions.DELETE_KEYWORD_SUGGESTION, {
                                     'id': to_edit.id,
                                     'suggid': x.id
                                 }))
        for x in [y for y in pending if y.action == 'add_keyword']
    ])
    kw_remove_buttons.extend([
        InlineKeyboardButton('#{} 👓❌'.format(x.value),
                             callback_data=util.callback_for_action(
                                 CallbackActions.DELETE_KEYWORD_SUGGESTION, {
                                     'id': to_edit.id,
                                     'suggid': x.id
                                 })) for x in pending_removal
    ])
    buttons = util.build_menu(
        kw_remove_buttons,
        2,
        header_buttons=[
            InlineKeyboardButton(captions.DONE,
                                 callback_data=util.callback_for_action(
                                     CallbackActions.ABORT_SETTING_KEYWORDS,
                                     {'id': to_edit.id}))
        ])
    reply_markup = InlineKeyboardMarkup(buttons)
    msg = util.send_or_edit_md_message(
        bot,
        chat_id,
        util.action_hint(
            'Send me the keywords for {} one by one...\n\n{}'.format(
                util.escape_markdown(to_edit.username),
                messages.KEYWORD_BEST_PRACTICES)),
        to_edit=set_keywords_msgid,
        reply_markup=reply_markup)

    if msg:
        # message might not have been edited if the user adds an already-existing keyword
        # TODO: should the user be notified about this?
        chat_data['set_keywords_msg'] = msg.message_id

    return BotStates.SENDING_KEYWORDS