Esempio n. 1
0
async def cleanup(ctx, target=None, history=100):
    start = analytics.getEventTime()
    if common.isDiscordRegulator(ctx.message.author) != True:
        return

    #make user input something usable first, conform outlandish commands to be sane
    if target is None and history is None:
        await discord.bot.say("Syntax: `!cleanup @mention <1-1000>` where # is last x chat messages to check per channel. Defaults to 100.")
        return
    elif target is None:
        await discord.bot.say("Error: You must target a user by `@mention` or raw ID.")
        return
    elif history > 1000:
        await discord.bot.say("Warning: This command only supports up to the last 1000 channel messages. Limiting your request to 1000.")
        history = 1000
    else:
        pass

    #get the raw mention or just pass the ID depending on what the use supplied. member only needed for protection
    target_id = discord.get_targeted_id(ctx)
    target_member = discord.default_server.get_member(target_id) # Only use the Member lookup for Reg/Admin protection

    #if xiphirx = soy
    if target_id == discord.bot.user.id:
        await discord.bot.say("⚠️{0.message.author.mention} you are not allowed to cleanup after the bot!".format(ctx))
        return

    #dont allow this to be called on regulators/administrators
    if target_member is not None:
        if common.isDiscordRegulator(target_member):
            logger.warn("cleanup() called and is exiting: ID:{0.message.author.id} attempted to call cleanup on ID:{1} but was denied by: IS_REGULATOR_PROTECTED".format(ctx, target_id))
            await discord.bot.say("⚠️{0.message.author.mention} you are not allowed to call that on other admins/regulators!".format(ctx))
            return


    #while this runs lets not flood the mod channel with messages
    deleted.IGNORE_IDS.append(target_id)

    await discord.bot.say("{0.message.author.mention} starting now ID:`{1}` and will @ you when task completed.".format(ctx, target_id))
    logger.info("cleanup() {0.message.author.name} started deletion on ID:{1}. Checking all channels last {2} messages.".format(ctx, target_id, history))
    for channel in ctx.message.server.channels:
        if channel.type == discord.discord.ChannelType.text:
            logger.info("cleanup() {0.message.author.name} started deletion on channel ID: {0.message.channel.id} for user ID:{1}".format(ctx, target_id))
            await delete_messages_from_channel(ctx, channel, target_id, history)

    #no need to keep the id around
    deleted.IGNORE_IDS.remove(target_id)

    #create both a journal entry for the user targeted
    journal.update_journal_event(module=__name__, event="MESSAGE_CLEANUP_MODERATOR", userid=target_id, contents="Invoked by: {0.author.name} in channel {0.channel}".format(ctx.message))
    journal.update_journal_regulator(invoker=ctx.message.author.id, target=target_id, eventdata=history, action="MESSAGE_CLEANUP_MODERATOR", messageid=ctx.message.id)

    secs_taken = int(analytics.getEventTime() - start)
    await discord.bot.say("{0.message.author.mention} cleanup on ID `{1}` completed! Took ~{2} seconds".format(ctx, target_id, secs_taken))
Esempio n. 2
0
async def gamerword_debug(ctx, target):
    if not common.isDiscordRegulator(ctx.message.author):
        return

    target_id = discord.get_targeted_id(ctx)

    # get the forgiveness value and get how far back we should look
    cutoff = int(time.time() -
                 config.cfg['automod']['forgiveness_days'] * 86400)
    database.cursor.execute(
        'SELECT score_final,score_regex,score_prev_infractions,multiply_age_member,multiply_age_account,action from automod_gamerwords WHERE id_targeted=%s AND time>%s',
        (target_id, cutoff))
    dbres = database.cursor.fetchall()
    if len(dbres) == 0:
        await discord.bot.say(
            "{0.message.author.mention} no actions found in the last {1[automod][forgiveness_days]} days."
            .format(ctx, config.cfg))
    else:
        table_result = common.dbtable_to_strtable(dbres)
        if table_result:
            await discord.bot.say(
                "Last {0[automod][forgiveness_days]} days of automoderation against ID:{1} ```{2}```"
                .format(config.cfg, target_id, table_result))
        else:
            await discord.bot.say(
                "{0.message.author.mention} unable to retrieve table, result too big or something broke."
                .format(ctx))
Esempio n. 3
0
def allow_regulation(ctx, target_id):
    #has to be a regulator+
    if common.isDiscordRegulator(ctx.message.author) == True:
        pass
    else:
        logger.info(
            "allow_regulation() attempted to invoke but was rejected for: no permission, Invoker: {}, Target:{}"
            .format(ctx.message.author.id, target_id))
        return False

    #we need an ID to be able to work with, this should already be caught
    if target_id is None:
        return False

    #dont let the user try to play themselves
    if target_id == ctx.message.author.id:
        logger.info(
            "allow_regulation() attempted to invoke but was rejected for: attempted self harm, Invoker: {}, Target:{}"
            .format(ctx.message.author.id, target_id))
        return False

    #if the user is an admin process it bypassing permissions
    if common.isDiscordAdministrator(ctx.message.author) == True:
        return True

    #convert the target_id into a member object, or at least try. This is to cacluate if the user can be touched
    target_member = discord.default_server.get_member(target_id)
    if target_member is None:
        logger.info(
            "allow_regulation() bypassing action restriction since Member object cannot be created. Invoker: {}, Target: {}"
            .format(ctx.message.author.id, target_id))
        return True

    #get the assigned role IDs
    target_roles = []
    for role in target_member.roles:
        target_roles.append(role.id)

    #convert the lists to sets
    target_set = set(target_roles)
    untouchable_set = set(untouchable_roles)

    #if they intersect, they should not be touched
    allowed_set = untouchable_set.intersection(target_set)
    if len(allowed_set) == 0:
        return True
    else:
        logger.info(
            "allow_regulation() attempted to invoke but was rejected for: protected role, Invoker: {}, Target:{}"
            .format(ctx.message.author.id, target_id))
        return False

    #failsafe to no if my bad logic fails
    logger.info(
        "allow_regulation() attempted to invoke but was rejected for: failsafe, Invoker: {}, Target:{}"
        .format(ctx.message.author.id, target_id))
    return False
Esempio n. 4
0
async def kill(ctx):
    if not common.isDiscordRegulator(ctx.message.author):
        return

    # get the current PID to tell the use
    pid = os.getpid()
    await discord.bot.say(
        "{0.message.author.mention} Freezing all motor functions for PID:`{1}`. See you again soon <3"
        .format(ctx, pid))

    # commit sudoku
    sys.exit()
Esempio n. 5
0
async def remind(ctx, duration, *, text):
    if common.isDiscordMainServer(ctx.message.server) is not True:
        return

    #set a cap of max 5 currently waiting jobs, regs+ are exempt
    if not common.isDiscordRegulator(ctx.message.author):
        database.cursor.execute("SELECT * FROM scheduled_tasks WHERE exec_run=0 AND event_type='POST_MESSAGE' AND id_targeted = %s", (ctx.message.author.id,))
        waiting_work_count = database.cursor.fetchall()
        if len(waiting_work_count) >= 5:
            await discord.bot.say("⚠️{0.message.author.mention} you already have 5 waiting reminders. View them via `!todo`".format(ctx))
            return

    #get the user input to seconds
    duration_length = scheduler.user_duration_to_seconds(duration)
    if duration_length is False:
        await discord.bot.say("⚠️{0.message.author.mention} unable to decode message length. Should be `!remind 60s|1m|4d don't forget about the potatoes`".format(ctx))
        return
    elif duration_length is None:
        await discord.bot.say("⚠️{0.message.author.mention} unable to decode message length. allowed: seconds (s), minutes (m), hours (h), days (d), weeks (w), years (y)".format(ctx))
        return

    duration_inrange = scheduler.verify_reminder_duration_length(duration_length)
    if duration_inrange is False:
        await discord.bot.say("⚠️{0.message.author.mention} Reminder is out of expected range. Current Range {1}m to {2}d".format(ctx, config.cfg['scheduler']['time_range_min_mins'], int(config.cfg['scheduler']['time_range_max_mins'] / 1440)))
        return

    #dont allow abusive calls to be made, these should just make API calls to kick the user
    if "@everyone" in text.lower():
        return
    elif "@here" in text.lower():
        return
    else:
        text = text.replace("`","'")

    #limit message to have 3 mentions
    if len(ctx.message.mentions) > 3:
        return

    #calculate the time it should fire
    now = int(time.time())
    time_to_fire = now + duration_length

    #set the reminder
    scheduler.set_future_task(
        invoker=ctx.message.author.id,
        channel=ctx.message.channel.id,
        timestamp=time_to_fire,
        event="POST_MESSAGE",
        msg=text)

    when = time.strftime("%A, %B %d %Y %H:%M %Z", time.localtime(time_to_fire))
    await discord.bot.say("✔️{0.message.author.mention} reminder set for `{1}`! I'll try not to forget about this, I promise.".format(ctx, when))
Esempio n. 6
0
async def warn(ctx, target, *, reason):
    if common.isDiscordRegulator(ctx.message.author) != True:
        return

    # convert the target into a usable ID
    target_id = discord.get_targeted_id(ctx)
    target_member = await discord.get_user_info(target_id)
    if target_member is None:
        await discord.bot.say(
            "{} тЪая╕П I was not able to lookup that user ID.".format(
                ctx.message.author.mention))
        return

    # warn reason has to have at least a word in it
    if len(reason) < 4:
        await discord.bot.say(
            "тЪая╕П Warning reason must be longer than 4 characters. `!warn @username reason goes here`"
        )
        return

    # warn reason has to be a reasonable length
    if len(reason) > 200:
        await discord.bot.say(
            "тЪая╕П Reason too long - please limit to 200 characters or less.")
        return

    if allow_regulation(ctx, target_id):
        # return what is happening in the same channel to alert the user
        await discord.bot.say(
            "тЬФя╕П {} is warning {} with the reason of `{}`.".format(
                ctx.message.author.mention, target_member.mention, reason))

        # update the internal bot log
        journal.update_journal_regulator(invoker=ctx.message.author.id,
                                         target=target_id,
                                         eventdata=reason,
                                         action="WARN_MEMBER",
                                         messageid=ctx.message.id)

        # update the internal user log
        journal.update_journal_event(module=__name__,
                                     event="ON_MEMBER_WARN",
                                     userid=target_id,
                                     contents="{0.name}#{0.discriminator} "
                                     "warned by {1.name}#{1.discriminator} "
                                     "with reason '{2}'".format(
                                         target_member, ctx.message.author,
                                         reason))
    else:
        await discord.bot.say(
            "ЁЯЫС {} unable to moderate user. Either you failed to tag the user properly or the member is protected from regulators."
            .format(ctx.message.author.mention))
Esempio n. 7
0
async def stats(ctx, more=None):
    if common.isDiscordRegulator(ctx.message.author) is False:
        return

    if more == None:
        #get the avg without numpy because I dont want to import useless shit but will do it anyway in 3 months <-- haha I did exactly this check git
        emd = discord.embeds.Embed(color=0xE79015)
        emd.add_field(name="Bot Uptime", value=analytics.getRuntime())
        emd.add_field(name="Messages Processed",
                      value="{:,d}".format(analytics.messages_processed))
        emd.add_field(name="Unique Users",
                      value="{:,d}".format(
                          len(analytics.messages_processed_users)))
        emd.add_field(name="Unique Channels",
                      value="{:,d}".format(
                          len(analytics.messages_processed_perchannel)))
        emd.add_field(name="on_message() Statistics",
                      value=analytics.get_onMessageProcessTime())
        emd.add_field(name="on_member() Statistics",
                      value=analytics.get_onMemberProcessTime())
        await discord.bot.say(embed=emd)
    elif more.startswith("c"):
        sorted_channels = sorted(
            analytics.messages_processed_perchannel.items(),
            key=lambda x: x[1],
            reverse=True)
        msg = ""
        for channel in sorted_channels:
            msg = msg + "#{0}: {1:,d}\n".format(
                discord.bot.get_channel(channel[0]), channel[1])
        await discord.bot.say(
            "Most active channels since bot reboot, {}:\n```{}```".format(
                analytics.getRuntime(), msg))
    elif more.startswith("u"):
        sorted_users = sorted(analytics.messages_processed_users.items(),
                              key=lambda x: x[1],
                              reverse=True)
        server = discord.bot.get_server(config.cfg['discord']['server'])
        msg = ""
        for user in sorted_users[:10]:
            msg = msg + "{0}: {1:,d}\n".format(server.get_member(user[0]),
                                               user[1])
        await discord.bot.say(
            "Top 10 talkative users since bot reboot, {}:\n```{}```".format(
                analytics.getRuntime(), msg))
    else:
        await discord.bot.say("Unknown subcommand. Try `channel | user`")
Esempio n. 8
0
async def kick(ctx, target, *, reason):
    if common.isDiscordRegulator(ctx.message.author) != True:
        return

    #convert the target into a usable ID
    target_id = discord.get_targeted_id(ctx)
    target_member = discord.default_server.get_member(target_id)
    if target_member is None:
        await discord.bot.say(
            "{} тЪая╕П I was not able to lookup that user ID.".format(
                ctx.message.author.mention))
        return

    #kick reason has to have at least a word in it
    if len(reason) < 4:
        await discord.bot.say(
            "тЪая╕П Kick reason must be longer than 4 characters. `!kick @username reason goes here`"
        )
        return

    # kick reason has to be a reasonable length
    if len(reason) > 200:
        await discord.bot.say(
            "тЪая╕П Reason too long - please limit to 200 characters or less.")
        return

    if allow_regulation(ctx, target_id):
        #return what is happening in the same channel to alert the user, wait 5 seconds and fire the kick command
        await discord.bot.say(
            "тЬФя╕П {} is kicking {} with the reason of `{}`.".format(
                ctx.message.author.mention, target_member.mention, reason))
        await asyncio.sleep(5)
        await discord.bot.kick(target_member)

        #update the internal bot log, since we cant send kick reasons via this api version #TODO: in rewrite add that
        journal.update_journal_regulator(invoker=ctx.message.author.id,
                                         target=target_id,
                                         eventdata=reason,
                                         action="KICK_MEMBER",
                                         messageid=ctx.message.id)
    else:
        await discord.bot.say(
            "ЁЯЫС {} unable to moderate user. Either you failed to tag the user properly or the member is protected from regulators."
            .format(ctx.message.author.mention))
Esempio n. 9
0
async def journal(ctx, user: str):
    if common.isDiscordRegulator(ctx.message.author) is False:
        return

    target_id = discord.get_targeted_id(ctx)
    target_member = await discord.get_user_info(target_id)

    if target_id is None:
        database.cursor.execute(
            'SELECT * from journal_events WHERE userid=%s ORDER BY time DESC LIMIT 5',
            (target_id, ))
        emd = discord.embeds.Embed(
            title='Last 5 events for ({0})'.format(user), color=0xE79015)
    else:
        database.cursor.execute(
            'SELECT * from journal_events WHERE userid=%s ORDER BY time DESC LIMIT 5',
            (target_id, ))
        emd = discord.embeds.Embed(
            title='Last 5 events for "{0.name}" ({0.id})'.format(
                target_member),
            color=0xE79015)

    dbres = database.cursor.fetchall()

    if len(dbres) == 0:
        await discord.bot.say("Not found in my journal :(")
        return
    else:
        for row in dbres:
            emd.add_field(
                inline=False,
                name="{}".format(
                    datetime.fromtimestamp(float(row['time'])).isoformat()),
                value="{0[event]} ({0[module]}) Result: {0[contents]}\n".
                format(row))
        await discord.bot.say(embed=emd)
Esempio n. 10
0
async def rapsheet(ctx):
    if common.isDiscordRegulator(ctx.message.author) is False:
        return

    # Get the member
    target_id = discord.get_targeted_id(ctx)
    target_member = await discord.get_user_info(target_id)

    # Pull all their regulator actions, ignoring un-silence events.
    database.cursor.execute(
        'SELECT * from journal_regulators WHERE id_targeted=%s AND NOT action = \'VOICE_UNSILENCE\' ORDER BY time DESC',
        (target_id, ))
    dbres = database.cursor.fetchall()

    # Get the first event in the logs for the user as a "first seen" date
    database.cursor.execute(
        'SELECT MIN(time) AS \'time\' FROM journal_events WHERE userid = %s',
        (target_id, ))
    first_seen = database.cursor.fetchall()

    # If no events are returned, generate and send a clean rapsheet
    if len(dbres) == 0:
        emd = discord.embeds.Embed(title="__Moderation Statistics__",
                                   colour=discord.discord.Color.green(),
                                   timestamp=datetime.utcnow())

        emd.set_author(name="{0}     (ID: {1})".format(target_member.name,
                                                       target_member.id),
                       icon_url=target_member.avatar_url)
        emd.set_thumbnail(url=target_member.avatar_url)

        if first_seen[0]['time'] is None:
            emd.add_field(
                name="No previous moderation actions found for user.",
                value="First Seen - Unknown")
        else:
            emd.add_field(
                name="No previous moderation actions found for user.",
                value="First Seen - {0}".format(
                    datetime.fromtimestamp(first_seen[0]['time']).strftime(
                        '%Y-%m-%d @ %H:%M:%S')))

        await discord.bot.say(embed=emd)
        return
    # Otherwise, total up all the events, generate, and send a dirty rapsheet
    else:
        emd = discord.embeds.Embed(title="__Moderation Statistics__",
                                   colour=discord.discord.Color.red(),
                                   timestamp=datetime.utcnow())

        emd.set_author(name="{0}     (ID: {1})".format(target_member.name,
                                                       target_member.id),
                       icon_url=target_member.avatar_url)
        emd.set_thumbnail(url=target_member.avatar_url)

        warnCount, muteCount, kickCount, banCount = 0, 0, 0, 0
        warns, mutes, kicks, bans = "", "", "", ""
        for row in dbres:
            invoker = await discord.get_user_info(row['id_invoker'])
            if row['action'] == "WARN_MEMBER":
                warnCount += 1
                warns += "{0} - {1} --- *{2}*\n".format(
                    datetime.fromtimestamp(float(
                        row['time'])).date().isoformat(), invoker.mention,
                    row['id_message'])
            elif row['action'] == "VOICE_SILENCE":
                muteCount += 1
                mutes += "{0} - {1} --- *{2}*\n".format(
                    datetime.fromtimestamp(float(
                        row['time'])).date().isoformat(), invoker.mention,
                    row['id_message'])
            elif row['action'] == "KICK_MEMBER":
                kickCount += 1
                kicks += "{0} - {1} --- *{2}*\n".format(
                    datetime.fromtimestamp(float(
                        row['time'])).date().isoformat(), invoker.mention,
                    row['id_message'])
            elif row['action'] == "BAN_MEMBER":
                banCount += 1
                bans += "{0} - {1} --- *{2}*\n".format(
                    datetime.fromtimestamp(float(
                        row['time'])).date().isoformat(), invoker.mention,
                    row['id_message'])

        if warns == "":
            emd.add_field(name="Warnings: {0}".format(warnCount),
                          value="N/A",
                          inline=False)
        else:
            emd.add_field(name="Warnings: {0}".format(warnCount),
                          value=warns,
                          inline=False)

        if mutes == "":
            emd.add_field(name="Mutes: {0}".format(muteCount),
                          value="N/A",
                          inline=False)
        else:
            emd.add_field(name="Mutes: {0}".format(muteCount),
                          value=mutes,
                          inline=False)

        if kicks == "":
            emd.add_field(name="Kicks: {0}".format(kickCount),
                          value="N/A",
                          inline=False)
        else:
            emd.add_field(name="Kicks: {0}".format(kickCount),
                          value=kicks,
                          inline=False)

        if bans == "":
            emd.add_field(name="Bans: {0}".format(banCount),
                          value="N/A",
                          inline=False)
        else:
            emd.add_field(name="Bans: {0}".format(banCount),
                          value=bans,
                          inline=False)

        emd.add_field(
            name="First Seen",
            value=datetime.fromtimestamp(
                first_seen[0]['time']).strftime('%Y-%m-%d @ %H:%M:%S'),
            inline=True)
        emd.add_field(
            name="Time Since Moderation",
            value=str(datetime.now() -
                      datetime.fromtimestamp(float(dbres[0]['time']))).split(
                          '.')[0],
            inline=True)

        await discord.bot.say(embed=emd)
Esempio n. 11
0
async def isregulator(ctx):
    if common.isDiscordRegulator(ctx.message.author):
        await discord.bot.say("{0.message.author.mention} is a regulator, and is ready to abuse all powers granted by the admins™.".format(ctx))
Esempio n. 12
0
async def unban(ctx, target):
    target_id = discord.get_targeted_id(ctx)
    target_member = discord.default_server.get_member(target_id)

    if common.isDiscordAdministrator(ctx.message.author):
        #if the user is an admin, let them blindly call IDs, unban blindly from discord
        unban_status_discord = await common.unban_id(target_id)

        #also check the retroactive table, this can be useful if the user was retro banned but never rejoied
        database.cursor.execute('SELECT * FROM bans_retroactive WHERE id=%s',
                                (target_id, ))
        unban_status_retroactive = database.cursor.fetchone()
        if unban_status_retroactive is None:
            unban_status_retroactive = False
        else:
            database.cursor.execute('DELETE FROM bans_retroactive WHERE id=%s',
                                    (target_id, ))
            database.connection.commit()

        #unban message logic
        if unban_status_discord is False and unban_status_retroactive is False:
            await discord.bot.say(
                "тЪая╕П Unable to find ID in either Discord or Retroactive table. Try again?"
            )
        elif unban_status_discord is True and unban_status_retroactive is False:
            await discord.bot.say(
                "тЬФя╕П User was found banned on Discord. Removed ban.")
        elif unban_status_discord is False and unban_status_retroactive is True:
            await discord.bot.say(
                "тЬФя╕П User was found banned in Retroactive table. Removed from database."
            )
        else:
            await discord.bot.say(
                "тЬФя╕П User was found banned on Discord and Retroactive ban table. Removed ban and database entry."
            )
    elif common.isDiscordRegulator(ctx.message.author):
        #regulators have a slightly different logic to follow to allow. Use internal audit log to make decisions
        database.cursor.execute(
            'SELECT * FROM journal_regulators WHERE id_targeted=%s AND id_invoker=%s AND action="BAN_MEMBER" ORDER BY time ASC',
            (target_id, ctx.message.author.id))
        regulator_target_history = database.cursor.fetchone()

        #if there is nothing in the database there is no reason to even try with the logic
        if regulator_target_history is None:
            logger.warn(
                "{0} attempted unban of {1} ID but failed due to reason: DB_RETURNED_NONE"
                .format(ctx.message.author.id, target_id))
            await discord.bot.say(
                "тЪая╕П {0.message.author.mention} Unable to find any record of you banning ID `{1}` (ever). You can only unban people you yourself banned."
                .format(ctx, target_id))
            return

        #get how many mins ago the ban was to see if they are able to be unbanned
        banned_mins_ago = int(
            (time.time() - regulator_target_history['time']) / 60)

        #handle if we should process the unban_id()
        if banned_mins_ago > config.cfg['regulators']['unban_grace_mins']:
            over_grace_mins = int(banned_mins_ago -
                                  config.cfg['regulators']['unban_grace_mins'])
            logger.warn(
                "{0} attempted unban of {1} ID but failed due to reason: OVER_GRACE_PERIOD by {2} minutes"
                .format(ctx.message.author.id, target_id, over_grace_mins))
            await discord.bot.say(
                "тЪая╕П {0.message.author.mention} The user ID `{1}` is over the grace period for regulator unbans by `{2}` minutes. Contact an Administrator."
                .format(ctx, target_id, over_grace_mins))
        else:
            unban_status_discord = await common.unban_id(target_id)
            if unban_status_discord is False:
                logger.warn(
                    "{0} attempted unban of {1} ID but failed due to reason: DISCORD_RETURNED_NOT_BANNED"
                    .format(ctx.message.author.id, target_id))
                await discord.bot.say(
                    "тЪая╕П {0.message.author.mention}  Discord returned no ban found for ID `{1}` (ever). The user was already unbanned or something is wrong :/"
                    .format(ctx, target_id))
            else:
                logger.info(
                    "{0} unbanned {1}. Time elapsed since ban {2}".format(
                        ctx.message.author.id, target_id, banned_mins_ago))
                await discord.bot.say(
                    "тЬФя╕П {0.message.author.mention} ID `{1}` has been unbanned!"
                    .format(ctx, target))
                journal.update_journal_regulator(invoker=ctx.message.author.id,
                                                 target=target_id,
                                                 eventdata=banned_mins_ago,
                                                 action="UNBAN_MEMBER_GRACE",
                                                 messageid=ctx.message.id)
Esempio n. 13
0
async def inviteban(ctx, target, *, reason):
    if common.isDiscordRegulator(ctx.message.author) != True:
        return

    # ban reason has to be a reasonable length
    if len(reason) > 200:
        await discord.bot.say(
            "тЪая╕П Invite ban reason must be longer than 4 characters. `!inviteban inviteCode reason goes here`"
        )
        return

    # ban reason has to be a reasonable length
    if len(reason) > 200:
        await discord.bot.say(
            "тЪая╕П Reason too long - please limit to 200 characters or less.")
        return

    #get anyone who joined via the invite
    database.cursor.execute(
        "SELECT * FROM journal_events WHERE event='ON_MEMBER_JOINED_WITH_INVITE' AND contents=%s",
        (target, ))
    invitees = database.cursor.fetchall()

    #if there is not anyone, dont even do anything
    if len(invitees) == 0 or target.lower() == "none":
        await discord.bot.say(
            "тЪая╕П {} Invalid invite code! 0 members joined via internal journal. Retype invite or bother Cake."
            .format(ctx.message.author.mention))
        return

    #get the invite data, make sure it is valid and then get who made it. They purge first.
    try:
        invite = await discord.bot.get_invite(target)
    except Exception as e:
        invite = None
        await discord.bot.say(
            "тЪая╕П {} unable to look up invite code: {} for ownership! Moving on to blind mode!"
            .format(ctx.message.author.mention, e))

    #ban the inviter if we know who they are
    if invite is not None:
        banned_inviter = await common.ban_verbose(
            invite.inviter,
            "{} from invite {} - '{}'".format(ctx.message.author.name, target,
                                              reason))
        if banned_inviter == False:
            pass
            await discord.bot.say(
                "тЭУ Something's f****d! Unable to issue ban to Discord API for root invite creator. Bother cake. (protected user?)"
            )
        else:
            journal.update_journal_regulator(
                invoker=ctx.message.author.id,
                target=invite.inviter.id,
                eventdata=target,
                action="BAN_MEMBER_VIA_INVITE_MAKER",
                messageid=ctx.message.id)
            await discord.bot.say(
                "тЬФя╕П {} is dropping the hammer on {} and anyone who joined via their invite `{}`. Let the bombs drop! "
                .format(ctx.message.author.mention, invite.inviter.mention,
                        target))

    for invited in invitees:

        #attempt to turn the ID into a valid member object
        server = discord.bot.get_server(config.cfg['discord']['server'])
        invited_member = server.get_member(str(invited['userid']))

        #if that cant happen, the user probably left or was banned already. Add to retroactive table (TODO)
        if invited_member == None:
            database.cursor.execute(
                'INSERT IGNORE INTO bans_retroactive(id, name, reason) VALUES(%s,%s,%s)',
                (invited['userid'], "UNKNOWN_INVITEBAN_CALLED", reason))
            database.connection.commit()
            await discord.bot.say(
                "тЪая╕П `{}` is getting banned for joining on invite `{}` (retroactive fallback. User either left or already banned) "
                .format(invited['userid'], target))
        else:
            banned_inviter = await common.ban_verbose(
                invited_member,
                "{} inviteban via {} - '{}'".format(ctx.message.author.name,
                                                    target, reason))
            if banned_inviter == False:
                await discord.bot.say(
                    "тЭУ Something's f****d! Unable to issue ban to Discord API for {}. Bother cake."
                    .format(invited_member.mention))
            else:
                await discord.bot.say(
                    "тЬФя╕П {} is getting banned for joining on invite `{}` ".
                    format(invited_member.mention, target))

        #take a break between to prevent r8 limited
        await asyncio.sleep(2)

    await discord.bot.say(
        "Invite ban completed. {} members removed. Thanks for playing!".format(
            len(invitees)))
Esempio n. 14
0
async def timedban(ctx, target, duration, *, reason):
    if common.isDiscordRegulator(ctx.message.author) != True:
        return

    #convert the target into a usable ID
    target_id = discord.get_targeted_id(ctx)
    target_member = discord.default_server.get_member(target_id)

    #ban reason has to have at least a word in it
    if len(reason) < 4:
        await discord.bot.say(
            "тЪая╕П {0.message.author.mention} ban reason must be longer than 4 characters. `!ban @username 1d reason goes here`"
            .format(ctx))
        return

    #if the user cannot be banned
    if allow_regulation(ctx, target_id) is False:
        await discord.bot.say(
            "ЁЯЫС {0.message.author.mention} unable to moderate user. (no permissions)"
            .format(ctx))
        return

    #verify the ban duration, and get the durations in seconds
    duration_length = scheduler.user_duration_to_seconds(duration)
    if duration_length is False:
        await discord.bot.say(
            "тЪая╕П{0.message.author.mention} unable to decode message length. Should be `!ban @username 60s|1m|7d could not stop using gamer words`"
            .format(ctx))
        return
    elif duration_length is None:
        await discord.bot.say(
            "тЪая╕П{0.message.author.mention} unable to decode message length. allowed: seconds (s), minutes (m), hours (h), days (d), weeks (w), years (y)"
            .format(ctx))
        return

    duration_inrange = scheduler.verify_reminder_duration_length(
        duration_length)
    if duration_inrange is False:
        await discord.bot.say(
            "тЪая╕П{0.message.author.mention} Ban duration is out of range. Have some mercy! Current range {1}m to {2}d"
            .format(ctx, config.cfg['scheduler']['time_range_min_mins'],
                    int(config.cfg['scheduler']['time_range_max_mins'] / 1440))
        )
        return

    #if we have a Member object, it is not retroactive and can be run live against discord
    if target_member is not None:
        #get the time to unban, make a db entry for unban
        now = int(time.time())
        time_to_fire = now + duration_length
        when_nice = time.strftime("%A, %B %d %Y %H:%M %Z",
                                  time.localtime(time_to_fire))

        scheduler.set_future_task(invoker=ctx.message.author.id,
                                  target=target_member.id,
                                  channel=ctx.message.channel.id,
                                  timestamp=time_to_fire,
                                  event="UNBAN_MEMBER",
                                  msg=reason)

        await discord.bot.say(
            "тЬФя╕П {0.message.author.mention} is **BANNING** {1} with the reason of `{2}`. (Duration: {3}, Unban at:`{4}`)"
            .format(ctx, target_member.mention, reason, duration, when_nice))
        await asyncio.sleep(5)

        #ship the ban off to discord
        res = await common.ban_verbose(
            target_member,
            "{0.message.author.name} - '{1}'".format(ctx, reason))
        if res is False:
            await discord.bot.say(
                "тЭУ Something's f****d! Unable to issue ban to Discord API. Bother <@{}>"
                .format(config.cfg['bernard']['owner']))
        else:
            journal.update_journal_regulator(invoker=ctx.message.author.id,
                                             target=target_id,
                                             eventdata=reason,
                                             action="BAN_MEMBER",
                                             messageid=ctx.message.id)
        #if a raw mention exists but not the Member object, handle it as retroactive
    elif target_id is not None and target_member is None:
        await discord.bot.say(
            "тЪая╕П {0.message.author.mention} You cannot issue retroactive timed bans. Please use normal !ban."
            .format(ctx))
    else:
        await discord.bot.say(
            "ЁЯЫС {0.message.author.mention} unable to moderate user. Target did not resolve to a valid Discord Member."
            .format(ctx))
Esempio n. 15
0
async def ban(ctx, target, *, reason):
    if common.isDiscordRegulator(ctx.message.author) != True:
        return

    #convert the target into a usable ID
    target_id = discord.get_targeted_id(ctx)
    target_member = discord.default_server.get_member(target_id)

    #ban reason has to have at least a word in it
    if len(reason) < 4:
        await discord.bot.say(
            "тЪая╕П ban reason must be longer than 4 characters. `!ban @username reason goes here`"
        )
        return

    # ban reason has to be a reasonable length
    if len(reason) > 200:
        await discord.bot.say(
            "тЪая╕П Reason too long - please limit to 200 characters or less.")
        return

    #if the user cannot be banned
    if allow_regulation(ctx, target_id) is False:
        await discord.bot.say(
            "ЁЯЫС {} unable to moderate user. (no permissions)".format(
                ctx.message.author.mention))
        return

    #if we have a Member object, it is not retroactive and can be run live against discord
    if target_member is not None:
        await discord.bot.say(
            "тЬФя╕П {} is **BANNING** {} with the reason of `{}`.".format(
                ctx.message.author.mention, target_member.mention, reason))
        await asyncio.sleep(5)
        res = await common.ban_verbose(
            target_member, "{} - '{}'".format(ctx.message.author.name, reason))
        if res is False:
            await discord.bot.say(
                "тЭУ Something's f****d! Unable to issue ban to Discord API. Bother <@{}>"
                .format(config.cfg['bernard']['owner']))
        else:
            journal.update_journal_regulator(invoker=ctx.message.author.id,
                                             target=target_id,
                                             eventdata=reason,
                                             action="BAN_MEMBER",
                                             messageid=ctx.message.id)
        #if a raw mention exists but not the Member object, handle it as retroactive and log who did it.
    elif target_id is not None and target_member is None:
        await discord.bot.say(
            "тЬФя╕П {} is (retroactive) **BANNING** userid `{}` with the reason of `{}`."
            .format(ctx.message.author.mention, target_id, reason))

        journal.update_journal_regulator(invoker=ctx.message.author.id,
                                         target=target_id,
                                         eventdata=reason,
                                         action="BAN_MEMBER_RETROACTIVE",
                                         messageid=ctx.message.id)

        retroactive_reason = "VIA_RETROACTIVE: {} - '{}'".format(
            ctx.message.author.name, reason)
        database.cursor.execute(
            'INSERT INTO bans_retroactive (id, name, reason) VALUES (%s,%s,%s)',
            (target_id, "N/A", retroactive_reason))
        database.connection.commit()
    else:
        await discord.bot.say(
            "ЁЯЫС {} unable to moderate user. Target did not resolve to a valid Discord Member."
            .format(ctx.message.author.mention))
Esempio n. 16
0
async def getid(ctx, target):
    if common.isDiscordRegulator(ctx.message.author):
        id = discord.get_targeted_id(ctx)
        await discord.bot.say(id)