Пример #1
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())))
Пример #2
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)
Пример #3
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()
Пример #4
0
    def cmd_remind_list(self, event, limit=None, mode=None):
        user = event.msg.author
        count = Reminder.count_for_user(user.id)
        avatar = u'https://cdn.discordapp.com/avatars/{}/{}.png'.format(
            user.id,
            user.avatar,
        )

        embed = MessageEmbed()
        embed.title = '{} reminder{}'.format(count, '' if count == 1 else 's')

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

        if count == 0:
            embed.description = 'You have no upcoming reminders.'
        else:
            query = Reminder.select(Reminder).where(
                (Reminder.message_id << Reminder.with_message_join((Message.id, )).where(
                    Message.author_id == event.author.id
                )) & (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)
Пример #5
0
    def queue_reminders(self):
        try:
            next_reminder = Reminder.select().order_by(
                Reminder.remind_at.asc()).limit(1).get()
        except Reminder.DoesNotExist:
            return

        self.reminder_task.set_next_schedule(next_reminder.remind_at)
Пример #6
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()
Пример #7
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()),
        ))
Пример #8
0
    def trigger_reminders(self):
        reminders = Reminder.with_message_join().where(
            (Reminder.remind_at < (datetime.utcnow() + timedelta(seconds=1))))

        for reminder in reminders:
            self.spawn(self.trigger_reminder)

        self.queue_reminders()
Пример #9
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))
Пример #10
0
    def trigger_reminders(self):
        reminders = Reminder.with_message_join().where(
            (Reminder.remind_at < (datetime.utcnow() + timedelta(seconds=1))))

        waitables = []
        for reminder in reminders:
            waitables.append(self.spawn(self.trigger_reminder, reminder))

        for waitable in waitables:
            waitable.join()

        self.queue_reminders()
Пример #11
0
    def cmd_remind_clear(self, event, reminder='all'):
        if reminder == 'all':
            count = Reminder.count_for_user(event.author.id)

            if Reminder.count_for_user(event.author.id) == 0:
                return event.msg.reply('<:{}> cannot clear reminders when you don\'t have any'.format(RED_TICK_EMOJI))
            
            msg = event.msg.reply('Ok, clear {} reminders?'.format(count))
            msg.chain(False).\
                add_reaction(GREEN_TICK_EMOJI).\
                add_reaction(RED_TICK_EMOJI)

            try:
                mra_event = self.wait_for_event(
                    'MessageReactionAdd',
                    message_id=msg.id,
                    conditional=lambda e: (
                        e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and
                        e.user_id == event.author.id
                    )).get(timeout=10)
            except gevent.Timeout:
                return
            finally:
                msg.delete()

            if mra_event.emoji.id != GREEN_TICK_EMOJI_ID:
                return
            
            count = Reminder.delete_all_for_user(event.author.id)
            return event.msg.reply(':ok_hand: I cleared {} reminders for you'.format(count))
        else:
            try:
                # stupid catch because python sucks
                try:
                    reminder = int(reminder)
                except:
                    return event.msg.reply('cannot convert `{}` to `int`'.format(S(reminder)))
                
                r = Reminder.select(Reminder).where(
                    (Reminder.message_id << Reminder.with_message_join((Message.id, )).where(
                        Message.author_id == event.author.id
                    )) & (Reminder.id == reminder)
                ).get()
            except Reminder.DoesNotExist:
                return event.msg.reply('<:{}> cannot find reminder #{}'.format(RED_TICK_EMOJI, reminder))
            
            msg = event.msg.reply('Ok, clear reminder #{}?'.format(reminder))
            msg.chain(False).\
                add_reaction(GREEN_TICK_EMOJI).\
                add_reaction(RED_TICK_EMOJI)

            try:
                mra_event = self.wait_for_event(
                    'MessageReactionAdd',
                    message_id=msg.id,
                    conditional=lambda e: (
                        e.emoji.id in (GREEN_TICK_EMOJI_ID, RED_TICK_EMOJI_ID) and
                        e.user_id == event.author.id
                    )).get(timeout=10)
            except gevent.Timeout:
                return
            finally:
                msg.delete()

            if mra_event.emoji.id != GREEN_TICK_EMOJI_ID:
                return
            
            Reminder.delete_for_user(event.author.id, r.id)
            return event.msg.reply(':ok_hand: I cleared reminder #{} for you'.format(r.id))
Пример #12
0
 def cmd_remind_clear(self, event):
     count = Reminder.delete_for_user(event.author.id)
     return event.msg.reply(
         ':ok_hand: I cleared {} reminders for you'.format(count))
Пример #13
0
 def cmd_remind_clear(self, event):
     count = Reminder.delete_for_user(event.author.id)
     raise CommandSuccess('I cleared {} reminders for you'.format(count))