Example #1
0
 def details(self):
     if self.reason is CensorReason.INVITE:
         if self.ctx['guild']:
             return 'invite `{}` to {}'.format(
                 self.ctx['invite'],
                 S(self.ctx['guild']['name'], escape_codeblocks=True)
             )
         else:
             return 'invite `{}`'.format(self.ctx['invite'])
     elif self.reason is CensorReason.DOMAIN:
         if self.ctx['hit'] == 'whitelist':
             return 'domain `{}` is not in whitelist'.format(S(self.ctx['domain'], escape_codeblocks=True))
         elif self.ctx['hit'] == 'blacklist':
             return 'domain `{}` is in blacklist'.format(S(self.ctx['domain'], escape_codeblocks=True))
         else:
             return 'because links are not allowed here'
     elif self.reason is CensorReason.WORD:
         return 'found blacklisted words `{}`'.format(
             ', '.join([S(i, escape_codeblocks=True) for i in self.ctx['words']]))
     elif self.reason is CensorReason.ZALGO:
         return 'found zalgo at position `{}` in text'.format(
             self.ctx['position']
         )
     else:
         return '...unsure why this message was censored. Please notify my developer.'
Example #2
0
 def command_tags_update(self, event, args):
     updated = Tag.update(value=S(' '.join(args.value))).where(
         (Tag.name == S(args.name.lower()))).execute()
     if not updated:
         event.msg.reply('no tag by that name exists')
     else:
         event.msg.reply('ok updated that tag for you')
Example #3
0
File: tags.py Project: jellz/jetski
    def on_tags_raw(self, event, name):
        tag = self.fetch_tag(name, event.guild.id)

        if not tag:
            raise CommandFail('no tag exists by that name')

        content = tag.content

        source = self.source_re.search(content)
        if source:
            source = source.group(1).lower()
            url = self.remote_url.format(source)
            r = requests.get(url)
            r = self.import_parser.search(r.content)
            r = r.group(1).decode('utf8').strip('`\n') if r else ''
            data = {'here': '@here', 'everyone': '@everyone'}
            r = self.replace_variables(r, data)
            if r and content == r:
                return event.msg.reply((
                    'This tag was imported from `{source}`: <https://github.com/ThaTiemsz'
                    '/RawgoatTags/blob/master/tags/{source}.md>').format(
                        source=source))
            content = self.source_re.sub('', content)
            Tag.update(content=content).where((Tag.name == tag.name) & (
                Tag.guild_id == tag.guild_id)).execute()

        if len(S(content, False, True)) > 1990:
            return event.msg.reply(
                'This tag is too long. See attached file for the source.',
                attachments=[('tag_raw_{}.txt'.format(event.msg.id), content)])

        event.msg.reply(u'```\n{}\n```'.format(S(content, False, True)))
Example #4
0
 def convert_field(self, value, conversion):
     if conversion in ('z', 's'):
         return S(unicode(value), escape_codeblocks=True)
     if conversion == 'e':
         return E(unicode(value))
     if conversion == 'c':
         return S(E(unicode(value)), escape_codeblocks=True)
     return unicode(value)
Example #5
0
    def command_tags_create(self, event, args):
        _, created = Tag.get_or_create(name=S(args.name.lower()),
                                       defaults={
                                           'value': S(' '.join(args.value)),
                                           'author_id': event.author.id,
                                       })
        if not created:
            event.msg.reply('a tag by that name already exists')
            return

        event.msg.reply('ok created that tag for you')
Example #6
0
    def on_tag(self, event, name, value=None):
        # Plugins can easily store data locally using Disco's built in storage
        tags = self.storage.guild.ensure('tags')

        if value:
            tags[name] = value
            event.msg.reply(u':ok_hand: created tag `{}`'.format(S(name)))
        else:
            if name in tags:
                return event.msg.reply(tags[name])
            else:
                return event.msg.reply(u'Unknown tag: `{}`'.format(S(name)))
Example #7
0
    def urban(self, event, term):
        r = requests.get('http://api.urbandictionary.com/v0/define', params={
            'term': term,
        })
        r.raise_for_status()
        data = r.json()

        if not len(data['list']):
            return event.msg.reply(':warning: no matches')

        event.msg.reply(u'{} - {}'.format(
            S(data['list'][0]['word']),
            S(data['list'][0]['definition']),
        ))
Example #8
0
    def roles(self, event, pattern=None):
        buff = ''
        g = event.guild

        total = {}
        members = g.members.values()
        for member in members:
            for role_id in member.roles:
                total[role_id] = total.get(role_id, 0) + 1

        roles = g.roles.values()
        roles = sorted(roles, key=lambda r: r.position, reverse=True)
        for role in roles:
            if pattern and role.name.lower().find(pattern.lower()) == -1:
                continue
            role_members = total.get(role.id, 0) if role.id != g.id else len(
                g.members)
            role = S(u'{} - {} ({} member{})\n'.format(
                role.id, role.name, role_members,
                's' if role_members != 1 else ''),
                     escape_codeblocks=True)
            if len(role) + len(buff) > 1980:
                event.msg.reply(u'```{}```'.format(buff))
                buff = ''
            buff += role

        if not buff:
            return

        return event.msg.reply(u'```dns\n{}\n```'.format(buff))
Example #9
0
    def search(self, event, query: str):
        queries = []

        if query.isdigit():
            queries.append((User.user_id == query))

        q = USER_MENTION_RE.findall(query)
        if len(q) and q[0].isdigit():
            queries.append((User.user_id == q[0]))
        else:
            queries.append(
                (User.username**'%{}%'.format(query.replace('%', ''))))

        if '#' in query:
            username, discrim = query.rsplit('#', 1)
            if discrim is not None:
                queries.append(((User.username == username) &
                                (User.discriminator == discrim)))

        users = User.select().where(reduce(operator.or_, queries)).limit(10)
        if len(users) == 0:
            raise CommandFail('No users found for query `{}`'.format(
                S(query, escape_codeblocks=True)))

        if len(users) == 1:
            if users[0].user_id in self.state.users:
                return self.info(event, self.state.users.get(users[0].user_id))

        raise CommandSuccess(
            'Found the following users for your query: ```{}```'.format(
                '\n'.join([
                    '{} ({})'.format(str(i), i.user_id) for i in users[:25]
                ])))
Example #10
0
    def trigger_reminders(self):
        reminders = Reminder.with_message_join().where(
            (Reminder.remind_at < (datetime.utcnow() + timedelta(seconds=1))))

        for reminder in reminders:
            message = reminder.message_id
            channel = self.state.channels.get(message.channel_id)
            if not channel:
                self.log.warning(
                    'Not triggering reminder, channel %s was not found!',
                    message.channel_id)
                reminder.delete_instance()
                continue

            channel.send_message(
                u'<@{}> you asked me at {} ({} ago) to remind you about: {}'.
                format(
                    message.author_id, reminder.created_at,
                    humanize.naturaldelta(reminder.created_at -
                                          datetime.utcnow()),
                    S(reminder.content)))

            reminder.delete_instance()

        self.queue_reminders()
Example #11
0
    def on_dm_message(self, event):
        if event.channel.type != 1 or event.author.id == self.client.state.me.id:  # Not in DM or self
            return

        if event.author.id in self.preping:
            return

        if list(
                self.bot.get_commands_for_message(
                    self.bot.config.commands_require_mention,
                    self.bot.config.commands_mention_rules,
                    self.bot.config.commands_prefix, event)):
            return

        try:
            room = MailRoom.find_one(event.channel_id)
        except IndexError:
            self.create_room(event)
        else:
            if room.channel in self.room_greenlets:  # I shouldn't need to do this, but it doesn't hurt...
                self.room_greenlets[room.channel].kill()
            self.room_greenlets[room.channel] = self.spawn_later(
                self.config['expiration'], self.expire_room, room)
            self.client.api.channels_messages_create(
                room.channel,
                S(event.content) or "<No message>")
            if event.attachments:
                self.client.api.channels_messages_create(
                    room.channel, """__**Attachments:**__
                {}""".format("\n".join(
                        [f" - {a.url}" for a in event.attachments.values()])))
Example #12
0
    def command_locate(self, event, user):
        if isinstance(user, (int, long)):
            uid = user
            user = self.state.users.get(uid)
            if not user:
                return event.msg.reply('User {} not found.'.format(uid))

        buff = ''
        count = 0
        guilds = self.state.guilds.values()
        guilds = sorted(guilds, key=lambda g: g.name)
        for guild in guilds:
            member = guild.members.get(user.id)
            if not member:
                continue
            guild = S(u'{} - {} (level: {})\n'.format(
                guild.id, guild.name, self.get_level(guild, user.id)),
                      escape_codeblocks=True)
            if len(guild) + len(buff) > 1920:
                event.msg.reply(u'```{}```'.format(buff))
                buff = ''
            buff += guild
            count += 1

        user = u'{} ({} - {})'.format(user, user.mention, user.id)

        if not count:
            return event.msg.reply(u'User {} not found.'.format(user))

        event.msg.reply(u'```{}```*User {} found in {} server{}.*'.format(
            buff, user, count, 's' if count > 1 else ''))
Example #13
0
 def command_tags_delete(self, event, args):
     deleted = Tag.delete().where(
         (Tag.name == S(args.name.lower()))).execute()
     if deleted:
         event.msg.reply('ok deleted that tag for you')
     else:
         event.msg.reply('no tag exists by that name')
Example #14
0
    def help_command(self, event, name: str = None):  # TODO: Fix issue with commands with same name different group
        """
        ***The Help Command***

        This command will provide information on a certain command, or list all commands if no command is specified.

        ***Optional Values***
        > __name__ **The name of the target command**
        """
        if name is None:
            collections = [plugin.command_list for plugin in self.bot.plugins.values()]
            complete = []
            for collection in collections:
                complete.extend(collection)

            embed = MessageEmbed()
            embed.title = 'List of Commands'
            embed.color = 0x6832E3
            embed.description = ', '.join(complete)
        else:
            for plugin in self.bot.plugins.values():
                desc = plugin.get_help(name.lower())
                if desc:
                    break
            else:
                return event.msg.reply("Could not find command '{}'".format(S(name)))
            embed = MessageEmbed()
            embed.title = '**{}**'.format(name)
            embed.color = 0x6832E3
            embed.description = desc

        event.msg.reply(" ", embed=embed)
Example #15
0
File: tags.py Project: jellz/jetski
 def fetch_tag(self, name, guild_id):
     try:
         tag = Tag.select(Tag).where((Tag.name == S(name))
                                     & (Tag.guild_id == guild_id)).get()
     except Tag.DoesNotExist:
         return
     return tag
Example #16
0
    def search(self, event, query):
        queries = []

        if query.isdigit():
            queries.append((User.user_id == query))

        q = USER_MENTION_RE.findall(query)
        if len(q) and q[0].isdigit():
            queries.append((User.user_id == q[0]))
        else:
            queries.append((User.username ** u'%{}%'.format(query.replace('%', ''))))

        if '#' in query:
            username, discrim = query.rsplit('#', 1)
            if discrim.isdigit():
                queries.append((
                    (User.username == username) &
                    (User.discriminator == int(discrim))))

        users = User.select().where(reduce(operator.or_, queries))
        if len(users) == 0:
            return event.msg.reply(u'No users found for query `{}`'.format(S(query, escape_codeblocks=True)))

        if len(users) == 1:
            if users[0].user_id in self.state.users:
                return self.info(event, self.state.users.get(users[0].user_id))

        return event.msg.reply(u'Found the following users for your query: ```{}```'.format(
            u'\n'.join(map(lambda i: u'{} ({})'.format(unicode(i), i.user_id), users[:25]))
        ))
Example #17
0
        def generate_simple(chan_config):
            info = self.action_simple.get(action)

            if config._custom:
                if action in config._custom:
                    info = config._custom[action]

            contents = self.fmt.format(six.text_type(info['format']),
                                       e=event,
                                       **details)

            msg = u':{}: {}'.format(
                info['emoji'],
                S(contents),
            )

            if chan_config.timestamps:
                ts = pytz.utc.localize(datetime.utcnow()).astimezone(
                    chan_config.tz)
                msg = '`[{}]` '.format(ts.strftime('%H:%M:%S')) + msg

            if len(msg) > 2000:
                msg = msg[0:1997] + '...'

            return msg
Example #18
0
    def emoji(self, event, emoji):
        if not EMOJI_RE.match(emoji):
            return event.msg.reply(u'Unknown emoji: `{}`'.format(emoji))

        fields = []

        name, eid = EMOJI_RE.findall(emoji)[0]
        fields.append('**ID:** {}'.format(eid))
        fields.append('**Name:** {}'.format(S(name)))

        guild = self.state.guilds.find_one(lambda v: eid in v.emojis)
        if guild:
            fields.append('**Guild:** {} ({})'.format(S(guild.name), guild.id))

        url = 'https://discordapp.com/api/emojis/{}.png'.format(eid)
        r = requests.get(url)
        r.raise_for_status()
        return event.msg.reply('\n'.join(fields), attachments=[('emoji.png', r.content)])
Example #19
0
 def roles(self, event):
     buff = ''
     for role in event.guild.roles.values():
         role = S(u'{} - {}\n'.format(role.id, role.name), escape_codeblocks=True)
         if len(role) + len(buff) > 1990:
             event.msg.reply(u'```{}```'.format(buff))
             buff = ''
         buff += role
     return event.msg.reply(u'```{}```'.format(buff))
Example #20
0
 def details(self):
     if self.reason is CensorReason.INVITE:
         if self.ctx['guild']:
             return u'invite `{}` to {}'.format(self.ctx['invite'], S(self.ctx['guild']['name'], escape_codeblocks=True))
         else:
             return u'invite `{}`'.format(self.ctx['invite'])
     elif self.reason is CensorReason.DOMAIN:
         if self.ctx['hit'] == 'whitelist':
             return u'domain `{}` is not in whitelist'.format(S(self.ctx['domain'], escape_codeblocks=True))
         else:
             return u'domain `{}` is in blacklist'.format(S(self.ctx['domain'], escape_codeblocks=True))
     elif self.reason is CensorReason.WORD:
         return u'found blacklisted words `{}`'.format(
             u', '.join([S(i, escape_codeblocks=True) for i in self.ctx['words']]))
     elif self.reason is CensorReason.ZALGO:
         return u'found zalgo at position `{}` in text'.format(
             self.ctx['position']
         )
Example #21
0
    def on_tags_create(self, event, name, content):
        name = S(name)
        content = S(content)

        if len(content) > event.config.max_tag_length:
            raise CommandFail('tag content is too long (max {} characters)'.format(event.config.max_tag_length))

        _, created = Tag.get_or_create(
            guild_id=event.guild.id,
            author_id=event.author.id,
            name=name,
            content=content
        )

        if not created:
            raise CommandFail('a tag by that name already exists')

        raise CommandSuccess('ok, your tag named `{}` has been created'.format(name))
Example #22
0
File: tags.py Project: jellz/jetski
 def S(self, text, restore=False):
     if not text:
         return ''
     chars = [('{', '['), ('}', ']'), ('|', '&')]
     for t in chars:
         a, b = t[0], t[1]
         if not restore:
             text = text.replace(a, '%{}%'.format(b))
             continue
         text = text.replace('%{}%'.format(b), a)
         text = text.replace('%{}%'.format(a), b)
     return S(text, False, not restore)
Example #23
0
    def cmd_remind_list(self, event, limit=None, mode='server'):
        user = event.msg.author
        count = Reminder.count_for_user(user.id, event.guild.id)
        total_count = Reminder.count_for_user(user.id)

        embed = MessageEmbed()
        embed.title = '{} reminder{} ({} total)'.format(
            count if mode == 'server' else total_count, 's' if
            (count != 1 and mode == 'server') or
            (total_count != 1 and mode == 'global') else '', total_count)

        embed.set_author(name=u'{}#{}'.format(
            user.username,
            user.discriminator,
        ),
                         icon_url=user.avatar_url)
        embed.color = get_dominant_colors_user(user,
                                               user.get_avatar_url('png'))
        embed.set_footer(text='You can cancel reminders with !r clear [ID]')

        if (count == 0 and mode == 'server') or total_count == 0:
            embed.description = 'You have no upcoming reminders{}.'.format(
                ' in this server. Use `!r list global` to list all your upcoming reminders'
                if total_count > 0 else '')
        else:
            query = Reminder.select(Reminder).where(
                (Reminder.message_id << Reminder.with_message_join(
                    (Message.id, )).where(
                        (Message.author_id == event.author.id) &
                        (Message.guild_id == event.guild.id if mode ==
                         'server' else True)))
                & (Reminder.remind_at >
                   (datetime.utcnow() + timedelta(seconds=1)))).order_by(
                       Reminder.remind_at).limit(limit)

            for reminder in query:
                time = humanize_duration(reminder.remind_at -
                                         datetime.utcnow())
                channel = Message.select().where(
                    Message.id == reminder.message_id).get().channel_id
                channel = self.state.channels.get(channel)

                embed.add_field(
                    name=u'#{} in {}'.format(reminder.id, time),
                    value=u'[`#{}`](https://discordapp.com/channels/{}/{}/{}) {}'
                    .format(
                        channel.name if channel.type != ChannelType.DM else
                        'Jetski', channel.guild_id
                        if channel.type != ChannelType.DM else '@me',
                        channel.id, reminder.message_id, S(reminder.content)))

        return event.msg.reply(embed=embed)
Example #24
0
File: client.py Project: zw5/disco
    def channels_messages_create(self,
                                 channel,
                                 content=None,
                                 nonce=None,
                                 tts=False,
                                 attachment=None,
                                 attachments=[],
                                 embed=None,
                                 sanitize=False):

        payload = {
            'nonce': nonce,
            'tts': tts,
        }

        if attachment:
            attachments = [attachment]
            warnings.warn(
                'attachment kwarg has been deprecated, switch to using attachments with a list',
                DeprecationWarning)

        if content:
            if sanitize:
                content = S(content)
            payload['content'] = content

        if embed:
            payload['embed'] = embed.to_dict()

        if attachments:
            if len(attachments) > 1:
                files = {
                    'file{}'.format(idx): tuple(i)
                    for idx, i in enumerate(attachments)
                }
            else:
                files = {
                    'file': tuple(attachments[0]),
                }

            r = self.http(
                Routes.CHANNELS_MESSAGES_CREATE,
                dict(channel=channel),
                data={'payload_json': json.dumps(payload)},
                files=files,
            )
        else:
            r = self.http(Routes.CHANNELS_MESSAGES_CREATE,
                          dict(channel=channel),
                          json=payload)

        return Message.create(self.client, r.json())
Example #25
0
    def emoji(self, event, emoji):
        if not EMOJI_RE.match(emoji):
            return event.msg.reply(u'Unknown emoji: `{}`'.format(S(emoji)))

        fields = []

        name, eid = EMOJI_RE.findall(emoji)[0]
        fields.append('**ID:** {}'.format(eid))
        fields.append('**Name:** {}'.format(S(name)))

        guild = self.state.guilds.find_one(lambda v: eid in v.emojis)
        if guild:
            fields.append('**Guild:** {} ({})'.format(S(guild.name), guild.id))

        anim = emoji.startswith('<a:')
        fields.append('**Animated:** {}'.format('Yes' if anim else 'No'))

        ext = 'gif' if anim else 'png'
        url = 'https://discordapp.com/api/emojis/{}.{}'.format(eid, ext)
        r = requests.get(url)
        r.raise_for_status()
        return event.msg.reply('\n'.join(fields), attachments=[('emoji.'+ext, r.content)])
Example #26
0
    def parse(self, rawargs, ctx=None):
        """
        Parse a string of raw arguments into this argument specification.
        """
        parsed = {}

        flags = {i.name: i for i in self.args if i.flag}
        if flags:
            new_rawargs = []

            for offset, raw in enumerate(rawargs):
                if raw.startswith('-'):
                    raw = raw.lstrip('-')
                    if raw in flags:
                        parsed[raw] = True
                        continue
                new_rawargs.append(raw)

            rawargs = new_rawargs

        for index, arg in enumerate(
            (arg for arg in self.args if not arg.flag)):
            if not arg.required and index + arg.true_count > len(rawargs):
                continue

            if arg.count == 0:
                raw = rawargs[index:]
            else:
                raw = rawargs[index:index + arg.true_count]

            if arg.types:
                for idx, r in enumerate(raw):
                    try:
                        raw[idx] = self.convert(ctx, arg.types, r)
                    except Exception:
                        raise ArgumentError(
                            u'cannot convert `{}` to `{}`'.format(
                                S(r),
                                ', '.join(arg.types),
                            ))

            if arg.count == 1:
                raw = raw[0]

            if (not arg.types or arg.types == ['str']) and isinstance(
                    raw, list):
                raw = ' '.join(raw)

            parsed[arg.name] = raw

        return parsed
Example #27
0
    def trigger_reminder(self, reminder: Reminder):
        message = Message.get(reminder.message_id)
        channel = self.state.channels.get(message.channel_id)
        if not channel:
            self.log.warning(
                'Not triggering reminder, channel %s was not found!',
                message.channel_id)
            reminder.delete_instance()
            return

        msg = channel.send_message(
            '<@{}> you asked me on <t:{reminder_time}:f> (<t:{reminder_time}:R>) to remind you about: {}'
            .format(
                message.author_id,
                S(reminder.content),
                reminder_time=int(
                    reminder.created_at.replace(tzinfo=pytz.UTC).timestamp()),
            ),
            allowed_mentions={'users': [str(message.author_id)]})

        # Add the emoji options
        msg.add_reaction(SNOOZE_EMOJI)
        msg.add_reaction(GREEN_TICK_EMOJI)

        try:
            mra_event = self.wait_for_event(
                'MessageReactionAdd',
                message_id=msg.id,
                conditional=lambda e:
                ((e.emoji.name == SNOOZE_EMOJI or e.emoji.id ==
                  GREEN_TICK_EMOJI_ID) and e.user_id == message.author_id
                 )).get(timeout=30)
        except gevent.Timeout:
            reminder.delete_instance()
            return
        finally:
            # Cleanup
            try:
                msg.delete_all_reactions()
            except APIException:  # We don't have permission to remove reactions, but, we don't want to fail the reminder.
                pass

        if mra_event.emoji.name == SNOOZE_EMOJI:
            reminder.remind_at = datetime.utcnow() + timedelta(minutes=20)
            reminder.save()
            msg.edit(
                'Ok, I\'ve snoozed that reminder. You\'ll get another notification in 20 minutes.'
            )
            return

        reminder.delete_instance()
Example #28
0
    def command_tags_search(self, event, args):
        query = Tag.select()

        if args.name:
            query = query.where(Tag.name**'%{}%'.format(S(args.name.lower())))

        if args.value:
            query = query.where(Tag.value**'%{}%'.format(S(
                args.value.lower())))

        if args.author:
            if args.author.isdigit():
                query = query.where(Tag.author_id == int(args.author))
            else:
                matches = USER_MENTION_RE.findall(args.author)
                if not matches:
                    return event.msg.reply('invalid author argument')

                query = query.where(Tag.author_id == int(matches[0]))

        query = query.limit(50)

        event.msg.reply('Results: {}'.format(', '.join(i.name for i in query)))
Example #29
0
    def try_levelup(self, event, level):
        if event.config.actions.message:
            event.channel.send_message(
                ':ok_hand: You are now level {} in {}!'.format(
                    level, event.guild.name))

        if event.config.actions.chat:
            event.channel.send_message(
                S(':ok_hand: {} is now level {}!'.format(event.author, level)))

        if event.config.rewards:
            if event.config.rewards[level]:
                event.member.add_role(event.config.rewards[level],
                                      reason="Leveled Up!")
Example #30
0
    def on_tags(self, event, name):
        try:
            tag = Tag.select(Tag, User).join(
                User, on=(User.user_id == Tag.author_id
                          )).where((Tag.guild_id == event.guild.id)
                                   & (Tag.name == S(name))).get()
        except Tag.DoesNotExist:
            raise CommandFail('no tag by that name exists')

        # Track the usage of the tag
        Tag.update(times_used=Tag.times_used +
                   1).where((Tag.guild_id == tag.guild_id)
                            & (Tag.name == tag.name)).execute()

        event.msg.reply(':information_source: {}'.format(tag.content))