Exemplo n.º 1
0
    def tempmute(self, event, user, duration=None, reason=None):
        if not duration and reason:
            duration = parse_duration(reason.split(' ')[0], safe=True)
            if duration:
                if ' ' in reason:
                    reason = reason.split(' ', 1)[-1]
                else:
                    reason = None
        elif duration:
            duration = parse_duration(duration)

        member = event.guild.get_member(user)
        if member:
            self.can_act_on(event, member.id)
            if not event.config.mute_role:
                raise CommandFail('mute is not setup on this server')

            if event.config.mute_role in member.roles:
                raise CommandFail(u'{} is already muted'.format(member.user))

            # If we have a duration set, this is a tempmute
            if duration:
                # Create the infraction
                Infraction.tempmute(self, event, member, reason, duration)
                self.queue_infractions()

                self.confirm_action(event, maybe_string(
                    reason,
                    u':ok_hand: {u} is now muted for {t} (`{o}`)',
                    u':ok_hand: {u} is now muted for {t}',
                    u=member.user,
                    t=humanize.naturaldelta(duration - datetime.utcnow()),
                ))
            else:
                existed = False
                # If the user is already muted check if we can take this from a temp
                #  to perma mute.
                if event.config.mute_role in member.roles:
                    existed = Infraction.clear_active(event, member.id, [Infraction.Types.TEMPMUTE])

                    # The user is 100% muted and not tempmuted at this point, so lets bail
                    if not existed:
                        raise CommandFail(u'{} is already muted'.format(member.user))

                Infraction.mute(self, event, member, reason)

                existed = u' [was temp-muted]' if existed else ''
                self.confirm_action(event, maybe_string(
                    reason,
                    u':ok_hand: {u} is now muted (`{o}`)' + existed,
                    u':ok_hand: {u} is now muted' + existed,
                    u=member.user,
                ))
        else:
            raise CommandFail('invalid user')
Exemplo n.º 2
0
    def tempmute(self, event, user, duration, reason=None):
        member = event.guild.get_member(user)
        if member:
            self.can_act_on(event, member.id)
            if not event.config.mute_role:
                raise CommandFail('mute is not setup on this server')

            if event.config.mute_role in member.roles:
                raise CommandFail(u'{} is already muted'.format(member.user))

            expire_dt = parse_duration(duration)

            # Reset the infraction task so we make sure it runs after this new infraction
            self.inf_task.set_next_schedule(expire_dt)

            # Create the infraction
            Infraction.tempmute(self, event, member, reason, expire_dt)

            if event.config.confirm_actions:
                event.msg.reply(
                    maybe_string(
                        reason,
                        u':ok_hand: {u} is now muted for {t} (`{o}`)',
                        u':ok_hand: {u} is now muted for {t}',
                        u=member.user,
                        t=humanize.naturaldelta(expire_dt - datetime.utcnow()),
                    ))
        else:
            raise CommandFail('invalid user')
Exemplo n.º 3
0
    def command_recover(self, event, duration, pool=4, mode=None):
        if mode == 'global':
            channels = list(self.state.channels.values())
        else:
            channels = list(event.guild.channels.values())

        start_at = parse_duration(duration, negative=True)

        pool = Pool(pool)

        total = len(channels)
        count = 0
        msg = event.msg.reply('Recovery Status: 0/{}'.format(total))

        def updater():
            last = count

            while True:
                if last != count:
                    last = count
                    msg.edit('Recovery Status: {}/{}'.format(count, total))
                gevent.sleep(5)

        u = self.spawn(updater)

        try:
            for channel in channels:
                pool.wait_available()
                r = Recovery(self.log, channel, start_at)
                pool.spawn(r.run)
                count += 1
        finally:
            u.kill()

        msg.edit('RECOVERY COMPLETED')
Exemplo n.º 4
0
    def temprole(self, event, user, role, duration, reason=None):
        member = event.guild.get_member(user)
        if not member:
            raise CommandFail('invalid user')

        self.can_act_on(event, member.id)
        role_id = role if isinstance(role, (int, long)) else event.config.role_aliases.get(role.lower())
        if not role_id or role_id not in event.guild.roles:
            raise CommandFail('invalid or unknown role')

        if role_id in member.roles:
            raise CommandFail(u'{} is already in that role'.format(member.user))

        expire_dt = parse_duration(duration)
        Infraction.temprole(self, event, member, role_id, reason, expire_dt)
        self.queue_infractions()

        self.confirm_action(event, maybe_string(
            reason,
            u':ok_hand: {u} is now in the {r} role for {t} (`{o}`)',
            u':ok_hand: {u} is now in the {r} role for {t}',
            r=event.guild.roles[role_id].name,
            u=member.user,
            t=humanize.naturaldelta(expire_dt - datetime.utcnow()),
        ))
Exemplo n.º 5
0
    def cmd_remind(self, event, duration, content=None):
        if Reminder.count_for_user(event.author.id) > 15:
            raise CommandFail('You can only have 15 reminders going at once!')

        remind_at = parse_duration(duration)
        if remind_at > (datetime.utcnow() +
                        timedelta(seconds=5 * YEAR_IN_SEC)):
            raise CommandFail('That\'s too far in the future... I\'ll forget!')

        if event.msg.message_reference.message_id:
            referenced_msg: MessageReference = event.channel.get_message(
                event.msg.message_reference.message_id)
            content = 'https://discord.com/channels/{}/{}/{}'.format(
                self.state.channels.get(referenced_msg.channel_id).guild_id,
                referenced_msg.channel_id, referenced_msg.id)
        elif not content:
            raise CommandFail(
                'You need to provide content for the reminder, or reply to a message!'
            )

        r = Reminder.create(message_id=event.msg.id,
                            remind_at=remind_at,
                            content=content)
        self.reminder_task.set_next_schedule(r.remind_at)
        raise CommandSuccess(
            'I\'ll remind you at <t:{0}:f> (<t:{0}:R>)'.format(
                int(r.remind_at.replace(tzinfo=pytz.UTC).timestamp())))
Exemplo n.º 6
0
    def infraction_duration(self, event, infraction, duration):
        try:
            inf = Infraction.get(id=infraction)
        except Infraction.DoesNotExist:
            raise CommandFail('invalid infraction (try `!infractions recent`)')

        if inf.actor_id != event.author.id and event.user_level < CommandLevels.ADMIN:
            raise CommandFail('only administrators can modify the duration of infractions created by other moderators')

        if not inf.active:
            raise CommandFail('that infraction is not active and cannot be updated')

        expires_dt = parse_duration(duration, inf.created_at)

        converted = False
        if inf.type_ in [Infraction.Types.MUTE.index, Infraction.Types.BAN.index]:
            inf.type_ = Infraction.Types.TEMPMUTE if inf.type_ == Infraction.Types.MUTE.index else Infraction.Types.TEMPBAN
            converted = True
        elif inf.type_ not in [Infraction.Types.TEMPMUTE.index, Infraction.Types.TEMPBAN.index, Infraction.Types.TEMPROLE.index]:
            raise CommandFail('cannot set the duration for that type of infraction')

        inf.expires_at = expires_dt
        inf.save()
        self.queue_infractions()

        if converted:
            raise CommandSuccess('ok, I\'ve made that infraction temporary, it will now expire on {}'.format(
                inf.expires_at.isoformat()
            ))
        else:
            raise CommandSuccess('ok, I\'ve updated that infractions duration, it will now expire on {}'.format(
                inf.expires_at.isoformat()
            ))
Exemplo n.º 7
0
    def archive_extend(self, event, archive_id, duration):
        try:
            archive = MessageArchive.get(archive_id=archive_id)
        except MessageArchive.DoesNotExist:
            raise CommandFail('invalid message archive id')

        archive.expires_at = parse_duration(duration)

        MessageArchive.update(expires_at=parse_duration(duration)).where(
            (MessageArchive.archive_id == archive_id)).execute()

        raise CommandSuccess(
            'duration of archive {} has been extended (<{}>)'.format(
                archive_id,
                archive.url,
            ))
Exemplo n.º 8
0
    def tempban(self, event, duration, user, reason=None):
        member = event.guild.get_member(user)
        if member:
            self.can_act_on(event, member.id)
            expires_dt = parse_duration(duration)
            if event.config.limit_temp.duration_limit_level:
                if event.user_level <= event.config.limit_temp.duration_limit_level:
                    if expires_dt > parse_duration(
                            event.config.limit_temp.maximum_limited_duration):
                        raise CommandFail(
                            'You cannot temp ban users for longer than ' +
                            event.config.limit_temp.maximum_limited_duration)
            if event.config.notify_action_on:
                if event.config.notify_action_on.bans:
                    try:
                        event.guild.get_member(user.id).user.open_dm(
                        ).send_message(
                            'You have been **Temporarily Banned** in the guild **{}** for **{}** for `{}`'
                            .format(
                                event.guild.name,
                                humanize.naturaldelta(expires_dt -
                                                      datetime.utcnow()),
                                reason or 'no reason specified.'))
                    except:
                        pass
                else:
                    pass
            else:
                pass

            Infraction.tempban(self, event, member, reason, expires_dt)
            self.queue_infractions()
            self.confirm_action(
                event,
                maybe_string(
                    reason,
                    u':ok_hand: temp-banned {u} for {t} (`{o}`)',
                    u':ok_hand: temp-banned {u} for {t}',
                    u=member.user,
                    t=humanize.naturaldelta(expires_dt - datetime.utcnow()),
                ))
        else:
            raise CommandFail('invalid user')
Exemplo n.º 9
0
 def tempban(self, event, duration, user, reason=None):
     member = event.guild.get_member(user)
     if member:
         self.can_act_on(event, member.id)
         expires_dt = parse_duration(duration)
         Infraction.tempban(self, event, member, reason, expires_dt)
         self.queue_infractions()
         self.confirm_action(event, maybe_string(
             reason,
             u':ok_hand: temp-banned {u} for {t} (`{o}`)',
             u':ok_hand: temp-banned {u} for {t}',
             u=member.user,
             t=humanize.naturaldelta(expires_dt - datetime.utcnow()),
         ))
     else:
         raise CommandFail('invalid user')
Exemplo n.º 10
0
    def command_recover(self, event, duration, pool=4, mode=None):
        channels = []
        if mode == 'global':
            chlist = self.bot.client.state.channels
        else:
            chlist = event.guild.channels
        for gch in chlist:
            if self.bot.client.state.channels[
                    gch].type == 0 or self.bot.client.state.channels[
                        gch].type == 5:
                if self.bot.client.state.channels[gch].get_permissions(
                        self.bot.client.state.me).can(
                            Permissions.VIEW_CHANNEL):
                    channels.append(self.bot.client.state.channels[gch])

        start_at = parse_duration(duration, negative=True)
        pool = Pool(pool)

        total = len(channels)
        msg = event.msg.reply('Recovery Status: 0/{}'.format(total))
        recoveries = []

        def updater():
            last = len(recoveries)

            while True:
                if last != len(recoveries):
                    last = len(recoveries)
                    msg.edit('Recovery Status: {}/{}'.format(
                        len(recoveries), total))
                gevent.sleep(5)

        u = self.spawn(updater)

        try:
            for channel in channels:
                pool.wait_available()
                r = Recovery(self.log, channel, start_at)
                pool.spawn(r.run)
                recoveries.append(r)
        finally:
            pool.join()
            u.kill()

        msg.edit('RECOVERY COMPLETED ({} total messages)'.format(
            sum([i._recovered for i in recoveries])))
Exemplo n.º 11
0
    def cmd_remind(self, event, duration, content):
        if Reminder.count_for_user(event.author.id) > 15:
            raise CommandFail('You can only have 15 reminders going at once!')

        remind_at = parse_duration(duration)
        if remind_at > (datetime.utcnow() +
                        timedelta(seconds=5 * YEAR_IN_SEC)):
            raise CommandSuccess('Thats too far in the future, I\'ll forget!')

        r = Reminder.create(message_id=event.msg.id,
                            remind_at=remind_at,
                            content=content)
        self.reminder_task.set_next_schedule(r.remind_at)
        raise CommandSuccess('I\'ll remind you at {} ({})'.format(
            r.remind_at.isoformat(),
            humanize.naturaldelta(r.remind_at - datetime.utcnow()),
        ))
Exemplo n.º 12
0
    def command_recover(self, event, duration, pool=4, mode=None):
        channels = []
        if mode == 'global':
            chlist = list(self.state.channels.values())
        else:
            chlist = list(event.guild.channels.values())
        for gch in chlist:
            if self.state.channels[gch.id].type is ChannelType.GUILD_TEXT:
                if self.state.channels[gch.id].get_permissions(
                        self.state.me.id).can(
                            Permissions.VIEW_CHANNEL,
                            Permissions.READ_MESSAGE_HISTORY):
                    channels.append(self.state.channels[gch.id])

        start_at = parse_duration(duration, negative=True)
        pool = Pool(pool)

        total = len(channels)
        msg = event.msg.reply('Recovery Status: 0/{}'.format(total))
        recoveries = []

        def updater():
            last = len(recoveries)

            while True:
                if last != len(recoveries):
                    last = len(recoveries)
                    msg.edit('Recovery Status: {}/{}'.format(
                        len(recoveries), total))
                gevent.sleep(2)

        u = self.spawn(updater)

        try:
            for channel in channels:
                pool.wait_available()
                r = Recovery(self.log, channel, start_at)
                pool.spawn(r.run)
                recoveries.append(r)
        finally:
            pool.join()
            u.kill()

        msg.edit(':ok_hand: Recovery Completed ({} total messages)'.format(
            sum([i._recovered for i in recoveries])))
Exemplo n.º 13
0
 def tempban(self, event, duration, user, reason=None):
     member = event.guild.get_member(user)
     if member:
         expires_dt = parse_duration(duration)
         self.inf_task.set_next_schedule(expires_dt)
         Infraction.tempban(self, event, member, reason, expires_dt)
         if event.config.confirm_actions:
             event.msg.reply(
                 maybe_string(
                     reason,
                     u':ok_hand: temp-banned {u} for {t} (`{o}`)',
                     u':ok_hand: temp-banned {u} for {t}',
                     u=member.user,
                     t=humanize.naturaldelta(expires_dt -
                                             datetime.utcnow()),
                 ))
     else:
         raise CommandFail('invalid user')
Exemplo n.º 14
0
    def cmd_remind(self, event, duration, content):
        if Reminder.count_for_user(event.author.id) > 30:
            return event.msg.reply(
                ':warning: you can only have 15 reminders going at once!')

        remind_at = parse_duration(duration)
        if remind_at > (datetime.utcnow() +
                        timedelta(seconds=5 * YEAR_IN_SEC)):
            return event.msg.reply(
                ':warning: thats too far in the future, I\'ll forget!')

        r = Reminder.create(message_id=event.msg.id,
                            remind_at=remind_at,
                            content=content)
        self.reminder_task.set_next_schedule(r.remind_at)
        event.msg.reply(':ok_hand: I\'ll remind you at {} ({}) #{}'.format(
            r.remind_at.isoformat(),
            humanize_duration(r.remind_at - datetime.utcnow()), r.id))
Exemplo n.º 15
0
    def command_recover(self, event, duration, pool=4, mode=None):
        if mode == 'global':
            channels = list(self.state.channels.values())
        else:
            channels = list(event.guild.channels.values())

        start_at = parse_duration(duration, negative=True)

        pool = Pool(pool)

        total = len(channels)
        msg = event.msg.reply('Recovery Status: 0/{}'.format(total))
        recoveries = []

        def updater():
            last = len(recoveries)

            while True:
                if last != len(recoveries):
                    last = len(recoveries)
                    msg.edit('Recovery Status: {}/{}'.format(
                        len(recoveries), total))
                gevent.sleep(5)

        u = self.spawn(updater)

        try:
            for channel in channels:
                pool.wait_available()
                r = Recovery(self.log, channel, start_at)
                pool.spawn(r.run)
                recoveries.append(r)
        finally:
            pool.join()
            u.kill()

        msg.edit('RECOVERY COMPLETED ({} total messages)'.format(
            sum([i._recovered for i in recoveries])))
Exemplo n.º 16
0
 def test_basic_durations(self):
     dt = parse_duration('1w2d3h4m5s')
     self.assertTrue(dt < (datetime.utcnow() + timedelta(days=10)))
     self.assertTrue(dt > (datetime.utcnow() + timedelta(days=7)))
Exemplo n.º 17
0
 def test_invalid_duration(self):
     self.assertEquals(parse_duration('mmmmm', safe=True), None)
Exemplo n.º 18
0
 def test_source_durations(self):
     origin = datetime.utcnow() + timedelta(days=17)
     dt = parse_duration('1w2d3h4m5s', source=origin)
     compare = (origin - datetime.utcnow()) + datetime.utcnow()
     self.assertTrue(dt < (compare + timedelta(days=10)))
     self.assertTrue(dt > (compare + timedelta(days=7)))