コード例 #1
0
 def _parse_timedelta(timedelta_string, repeating):
     """Parse a timedelta, taking into account if it is a repeating timedelta (day minimum) or not."""
     result = None
     testing_text = ""
     for chunk in timedelta_string.split():
         if chunk == "and":
             continue
         if chunk.isdigit():
             testing_text += chunk
             continue
         testing_text += chunk.rstrip(",")
         if repeating:
             try:
                 parsed = parse_timedelta(
                     testing_text,
                     minimum=timedelta(days=1),
                     allowed_units=["weeks", "days"],
                 )
             except commands.BadArgument as ba:
                 orig_message = str(ba)[0].lower() + str(ba)[1:]
                 raise BadArgument(
                     f"For the repeating portion of this reminder, {orig_message}. "
                     "You must only use `days` or `weeks` when dealing with repeating reminders."
                 )
         else:
             parsed = parse_timedelta(testing_text,
                                      minimum=timedelta(minutes=1))
         if parsed != result:
             result = parsed
         else:
             return None
     return result
コード例 #2
0
    async def removerole(
        self, ctx: commands.Context, role: discord.Role, time: str, *requiredroles: discord.Role
    ):
        """
        Add a role to be removed after specified time on server

        Useful with an autorole cog
        """
        guild = ctx.guild
        try:
            parsed_time = parse_timedelta(time, allowed_units=["weeks", "days", "hours"])
        except commands.BadArgument:
            await ctx.maybe_send_embed("Error: Invalid time string.")
            return

        days = parsed_time.days
        hours = parsed_time.seconds // 60 // 60

        to_set = {"days": days, "hours": hours, "remove": True}
        if requiredroles:
            to_set["required"] = [r.id for r in requiredroles]

        await self.config.guild(guild).roles.set_raw(role.id, value=to_set)
        await ctx.maybe_send_embed(
            f"Time Role for {role.name} set to {days} days  and {hours} hours until removed"
        )
コード例 #3
0
ファイル: reminder.py プロジェクト: sifton/PCXCogs
    async def time(self, ctx: commands.Context, reminder_id: int, *,
                   time: str):
        """Modify the time of an existing reminder."""
        users_reminders = await self.get_user_reminders(ctx.message.author.id)
        old_reminder = self._get_reminder(users_reminders, reminder_id)
        if not old_reminder:
            await self._send_non_existant_msg(ctx, reminder_id)
            return
        try:
            time_delta = parse_timedelta(time, minimum=timedelta(minutes=1))
            if not time_delta:
                await ctx.send_help()
                return
        except commands.BadArgument as ba:
            await self._send_message(ctx, str(ba))
            return
        seconds = time_delta.total_seconds()
        future = int(current_time.time() + seconds)
        future_text = humanize_timedelta(timedelta=time_delta)

        new_reminder = old_reminder.copy()
        new_reminder.update(FUTURE=future, FUTURE_TEXT=future_text)
        async with self.config.reminders() as current_reminders:
            current_reminders.remove(old_reminder)
            current_reminders.append(new_reminder)
        await self._send_message(
            ctx,
            f"Reminder with ID# **{reminder_id}** has been edited successfully, "
            f"and will now remind you {future_text} from now.",
        )
コード例 #4
0
    async def time(self, ctx: commands.Context, reminder_id: int, *,
                   time: str):
        """Modify the time of an existing reminder."""
        users_reminders = await self.get_user_reminders(ctx.message.author.id)
        old_reminder = self._get_reminder(users_reminders, reminder_id)
        if not old_reminder:
            await self._send_non_existent_msg(ctx, reminder_id)
            return
        try:
            time_delta = parse_timedelta(time, minimum=timedelta(minutes=1))
            if not time_delta:
                await ctx.send_help()
                return
        except commands.BadArgument as ba:
            await reply(ctx, str(ba))
            return
        future = int(current_time.time() + time_delta.total_seconds())
        future_text = humanize_timedelta(timedelta=time_delta)

        new_reminder = old_reminder.copy()
        new_reminder.update(FUTURE=future, FUTURE_TEXT=future_text)
        async with self.config.reminders() as current_reminders:
            current_reminders.remove(old_reminder)
            current_reminders.append(new_reminder)
        message = f"Reminder with ID# **{reminder_id}** will remind you in {future_text} from now (<t:{future}:f>)"
        if "REPEAT" in new_reminder and new_reminder["REPEAT"]:
            message += f", repeating every {humanize_timedelta(seconds=new_reminder['REPEAT'])} thereafter."
        else:
            message += "."
        await reply(ctx, message)
コード例 #5
0
ファイル: converters.py プロジェクト: Vexed01/Vex-Cogs
        async def convert(self, ctx: Context,
                          argument: str) -> datetime.timedelta:
            if argument.lower() == "all":
                return datetime.timedelta(days=9000)
            delta = parse_timedelta(argument,
                                    minimum=datetime.timedelta(hours=1))
            if delta is None:
                raise BadArgument("That's not a valid time.")

            return delta
コード例 #6
0
 async def repeat(self, ctx: commands.Context, reminder_id: int, *,
                  time: str):
     """Modify the repeating time of an existing reminder. Pass "0" to <time> in order to disable repeating."""
     users_reminders = await self.get_user_reminders(ctx.message.author.id)
     old_reminder = self._get_reminder(users_reminders, reminder_id)
     if not old_reminder:
         await self._send_non_existent_msg(ctx, reminder_id)
         return
     if time.lower() in ["0", "stop", "none", "false", "no", "cancel", "n"]:
         new_reminder = old_reminder.copy()
         new_reminder.update(REPEAT=None)
         async with self.config.reminders() as current_reminders:
             current_reminders.remove(old_reminder)
             current_reminders.append(new_reminder)
         await reply(
             ctx,
             f"Reminder with ID# **{reminder_id}** will not repeat anymore. "
             f"The final reminder will be sent <t:{new_reminder['FUTURE']}:f>.",
         )
     else:
         try:
             time_delta = parse_timedelta(time,
                                          minimum=timedelta(days=1),
                                          allowed_units=["weeks", "days"])
             if not time_delta:
                 await ctx.send_help()
                 return
         except commands.BadArgument as ba:
             await reply(ctx, str(ba))
             return
         new_reminder = old_reminder.copy()
         new_reminder.update(REPEAT=int(time_delta.total_seconds()))
         async with self.config.reminders() as current_reminders:
             current_reminders.remove(old_reminder)
             current_reminders.append(new_reminder)
         await reply(
             ctx,
             f"Reminder with ID# **{reminder_id}** will now remind you "
             f"every {humanize_timedelta(timedelta=time_delta)}, with the first reminder being sent "
             f"<t:{new_reminder['FUTURE']}:f>.",
         )
コード例 #7
0
ファイル: reminder.py プロジェクト: sifton/PCXCogs
    async def _create_reminder(self, ctx: commands.Context,
                               time_and_optional_text: str):
        """Logic to create a reminder."""
        author = ctx.message.author
        maximum = await self.config.max_user_reminders()
        users_reminders = await self.get_user_reminders(author.id)
        if len(users_reminders) > maximum - 1:
            plural = "reminder" if maximum == 1 else "reminders"
            await self._send_message(
                ctx,
                "You have too many reminders! "
                f"I can only keep track of {maximum} {plural} for you at a time.",
            )
            return

        # Supported:
        # [p]remindme in {time} to {text}
        # [p]remindme in {time}    {text}
        # [p]remindme in {time}
        # [p]remindme    {time} to {text}
        # [p]remindme    {time}    {text}
        # [p]remindme    {time}
        # [p]remindme to {text} in {time}
        # [p]remindme to {text}    {time}
        # [p]remindme    {text} in {time}
        # [p]remindme    {text}    {time}

        # find the time delta(s) in the text
        time = ""
        index = -1
        time_index_start = -1
        time_index_end = -1
        prev_num = ""
        full_split = self.split_all.split(time_and_optional_text.strip())
        for chunk in full_split:
            index += 1
            if chunk.isspace():
                continue
            chunk = self.alpha_num.sub("", chunk)
            if chunk == "and" and not prev_num:
                # "and" can appear between time deltas
                continue
            if chunk.isdigit():
                prev_num = chunk
                if time_index_start == -1:
                    time_index_start = index
                continue
            if chunk.isalpha() and prev_num:
                chunk = f"{prev_num} {chunk}"
            try:
                if parse_timedelta(chunk):
                    time = f"{time} {chunk}" if time else chunk
                    if time_index_start == -1:
                        time_index_start = index
                    time_index_end = index
                elif time:
                    break
                else:
                    time_index_start = -1
            except commands.BadArgument:
                pass
            prev_num = ""
        if not time:
            await ctx.send_help()
            return
        # At this point we have a time string able to be parsed for a time delta,
        # as well as the starting and ending index of where it appeared in the text

        # detect preceding "in" so it can be removed from text as well
        if (time_index_start > 1 and self.alpha_num.sub(
                "", full_split[time_index_start - 2]) == "in"):
            time_index_start -= 2
        # the time portion of the text must now either be at the beginning or the end
        if time_index_start != 0 and time_index_end != len(full_split) - 1:
            await ctx.send_help()
            return
        # delete time (and optional "in", and surrounding space) from the text
        del full_split[max(time_index_start -
                           1, 0):min(time_index_end + 2, len(full_split))]
        # if the text begins with an optional "to", delete that as well
        if len(full_split) > 1 and self.alpha_num.sub("",
                                                      full_split[0]) == "to":
            del full_split[0:2]

        # parse resulting time delta
        try:
            time_delta = parse_timedelta(time, minimum=timedelta(minutes=1))
        except commands.BadArgument as ba:
            await self._send_message(ctx, str(ba))
            return
        # recreate cleaned up text
        text = "".join(full_split).strip()
        if len(text) > 1000:
            await self._send_message(ctx, "Your reminder text is too long.")
            return

        seconds = time_delta.total_seconds()
        future = int(current_time.time() + seconds)
        future_text = humanize_timedelta(timedelta=time_delta)
        next_reminder_id = self.get_next_user_reminder_id(users_reminders)

        reminder = {
            "USER_REMINDER_ID": next_reminder_id,
            "USER_ID": author.id,
            "REMINDER": text,
            "FUTURE": future,
            "FUTURE_TEXT": future_text,
            "JUMP_LINK": ctx.message.jump_url,
        }
        async with self.config.reminders() as current_reminders:
            current_reminders.append(reminder)
        await self._send_message(
            ctx,
            f"I will remind you of {'that' if text else 'this'} in {future_text}."
        )

        if (ctx.guild and await self.config.guild(ctx.guild).me_too()
                and ctx.channel.permissions_for(ctx.me).add_reactions):
            query: discord.Message = await ctx.send(
                "If anyone else would like to be reminded as well, click the bell below!"
            )
            self.me_too_reminders[query.id] = reminder
            await query.add_reaction(self.reminder_emoji)
            await asyncio.sleep(30)
            await delete(query)
            del self.me_too_reminders[query.id]
コード例 #8
0
ファイル: sanctuary.py プロジェクト: Heinral/SinbadCogs
 async def convert(cls, ctx: commands.Context, arg: str):
     maybe_td = commands.parse_timedelta(argument=arg)
     if not maybe_td:
         raise commands.BadArgument()
     return cls(maybe_td)