Optimize reminders, changed how reminder time is chosen, closes #122
This commit is contained in:
parent
253d231d0a
commit
db5a60a88f
4 changed files with 74 additions and 70 deletions
|
@ -2,14 +2,16 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import re
|
import re
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import List, Optional
|
from typing import List
|
||||||
|
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from dis_snek import InteractionContext, Snake
|
from dis_snek import InteractionContext, Snake
|
||||||
|
from dis_snek.models.discord.channel import GuildChannel
|
||||||
from dis_snek.models.discord.components import ActionRow, Select, SelectOption
|
from dis_snek.models.discord.components import ActionRow, Select, SelectOption
|
||||||
from dis_snek.models.discord.embed import Embed, EmbedField
|
from dis_snek.models.discord.embed import Embed, EmbedField
|
||||||
from dis_snek.models.snek.application_commands import (
|
from dis_snek.models.snek.application_commands import (
|
||||||
OptionTypes,
|
OptionTypes,
|
||||||
|
SlashCommandChoice,
|
||||||
slash_command,
|
slash_command,
|
||||||
slash_option,
|
slash_option,
|
||||||
)
|
)
|
||||||
|
@ -19,6 +21,7 @@ from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cachecog import CacheCog
|
from jarvis.utils.cachecog import CacheCog
|
||||||
|
|
||||||
valid = re.compile(r"[\w\s\-\\/.!@#$%^*()+=<>,\u0080-\U000E0FFF]*")
|
valid = re.compile(r"[\w\s\-\\/.!@#$%^*()+=<>,\u0080-\U000E0FFF]*")
|
||||||
|
time_pattern = re.compile(r"(\d+\.?\d?[s|m|h|d|w]{1})\s?")
|
||||||
invites = re.compile(
|
invites = re.compile(
|
||||||
r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", # noqa: E501
|
r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", # noqa: E501
|
||||||
flags=re.IGNORECASE,
|
flags=re.IGNORECASE,
|
||||||
|
@ -39,35 +42,29 @@ class RemindmeCog(CacheCog):
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="weeks",
|
name="delay",
|
||||||
description="Number of weeks?",
|
description="How long? (i.e. 1w 3d 7h 5m 20s)",
|
||||||
opt_type=OptionTypes.INTEGER,
|
opt_type=OptionTypes.STRING,
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="days", description="Number of days?", opt_type=OptionTypes.INTEGER, required=False
|
name="private",
|
||||||
)
|
description="Send as DM?",
|
||||||
@slash_option(
|
opt_type=OptionTypes.STRING,
|
||||||
name="hours",
|
|
||||||
description="Number of hours?",
|
|
||||||
opt_type=OptionTypes.INTEGER,
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="minutes",
|
|
||||||
description="Number of minutes?",
|
|
||||||
opt_type=OptionTypes.INTEGER,
|
|
||||||
required=False,
|
required=False,
|
||||||
|
choices=[
|
||||||
|
SlashCommandChoice(name="Yes", value="y"),
|
||||||
|
SlashCommandChoice(name="No", value="n"),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
async def _remindme(
|
async def _remindme(
|
||||||
self,
|
self,
|
||||||
ctx: InteractionContext,
|
ctx: InteractionContext,
|
||||||
message: Optional[str] = None,
|
message: str,
|
||||||
weeks: Optional[int] = 0,
|
delay: str,
|
||||||
days: Optional[int] = 0,
|
private: str = "n",
|
||||||
hours: Optional[int] = 0,
|
|
||||||
minutes: Optional[int] = 0,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
|
private = private == "y"
|
||||||
if len(message) > 100:
|
if len(message) > 100:
|
||||||
await ctx.send("Reminder cannot be > 100 characters.", ephemeral=True)
|
await ctx.send("Reminder cannot be > 100 characters.", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
@ -81,31 +78,22 @@ class RemindmeCog(CacheCog):
|
||||||
await ctx.send("Hey, you should probably make this readable", ephemeral=True)
|
await ctx.send("Hey, you should probably make this readable", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not any([weeks, days, hours, minutes]):
|
units = {"w": "weeks", "d": "days", "h": "hours", "m": "minutes", "s": "seconds"}
|
||||||
|
delta = {"weeks": 0, "days": 0, "hours": 0, "minutes": 0, "seconds": 0}
|
||||||
|
|
||||||
|
if times := time_pattern.findall(delay, flags=re.I):
|
||||||
|
for t in times:
|
||||||
|
delta[units[t[-1]]] += float(t[:-1])
|
||||||
|
else:
|
||||||
|
await ctx.send(
|
||||||
|
"Invalid time string, please follow example: `1w 3d 7h 5m 20s`", ephemeral=True
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not any(value for value in delta.items()):
|
||||||
await ctx.send("At least one time period is required", ephemeral=True)
|
await ctx.send("At least one time period is required", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
weeks = abs(weeks)
|
|
||||||
days = abs(days)
|
|
||||||
hours = abs(hours)
|
|
||||||
minutes = abs(minutes)
|
|
||||||
|
|
||||||
if weeks and weeks > 4:
|
|
||||||
await ctx.send("Cannot be farther than 4 weeks out!", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
elif days and days > 6:
|
|
||||||
await ctx.send("Use weeks instead of 7+ days, please.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
elif hours and hours > 23:
|
|
||||||
await ctx.send("Use days instead of 24+ hours, please.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
elif minutes and minutes > 59:
|
|
||||||
await ctx.send("Use hours instead of 59+ minutes, please.", ephemeral=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
reminders = Reminder.objects(user=ctx.author.id, active=True).count()
|
reminders = Reminder.objects(user=ctx.author.id, active=True).count()
|
||||||
if reminders >= 5:
|
if reminders >= 5:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
|
@ -115,12 +103,7 @@ class RemindmeCog(CacheCog):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
remind_at = datetime.utcnow() + timedelta(
|
remind_at = datetime.now() + timedelta(**delta)
|
||||||
weeks=weeks,
|
|
||||||
days=days,
|
|
||||||
hours=hours,
|
|
||||||
minutes=minutes,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = Reminder(
|
_ = Reminder(
|
||||||
user=ctx.author_id,
|
user=ctx.author_id,
|
||||||
|
@ -128,6 +111,7 @@ class RemindmeCog(CacheCog):
|
||||||
guild=ctx.guild.id,
|
guild=ctx.guild.id,
|
||||||
message=message,
|
message=message,
|
||||||
remind_at=remind_at,
|
remind_at=remind_at,
|
||||||
|
private=private,
|
||||||
active=True,
|
active=True,
|
||||||
).save()
|
).save()
|
||||||
|
|
||||||
|
@ -150,7 +134,7 @@ class RemindmeCog(CacheCog):
|
||||||
)
|
)
|
||||||
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed, ephemeral=private)
|
||||||
|
|
||||||
async def get_reminders_embed(
|
async def get_reminders_embed(
|
||||||
self, ctx: InteractionContext, reminders: List[Reminder]
|
self, ctx: InteractionContext, reminders: List[Reminder]
|
||||||
|
@ -158,13 +142,22 @@ class RemindmeCog(CacheCog):
|
||||||
"""Build embed for paginator."""
|
"""Build embed for paginator."""
|
||||||
fields = []
|
fields = []
|
||||||
for reminder in reminders:
|
for reminder in reminders:
|
||||||
fields.append(
|
if reminder.private and isinstance(ctx.channel, GuildChannel):
|
||||||
EmbedField(
|
fields.embed(
|
||||||
name=reminder.remind_at.strftime("%Y-%m-%d %H:%M UTC"),
|
EmbedField(
|
||||||
value=f"{reminder.message}\n\u200b",
|
name=reminder.remind_at.strftime("%Y-%m-%d %H:%M UTC"),
|
||||||
inline=False,
|
value="Please DM me this command to view the content of this reminder",
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
fields.append(
|
||||||
|
EmbedField(
|
||||||
|
name=reminder.remind_at.strftime("%Y-%m-%d %H:%M UTC"),
|
||||||
|
value=f"{reminder.message}\n\u200b",
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title=f"{len(reminders)} Active Reminder(s)",
|
title=f"{len(reminders)} Active Reminder(s)",
|
||||||
|
@ -246,13 +239,22 @@ class RemindmeCog(CacheCog):
|
||||||
|
|
||||||
fields = []
|
fields = []
|
||||||
for reminder in filter(lambda x: str(x.id) in context.context.values, reminders):
|
for reminder in filter(lambda x: str(x.id) in context.context.values, reminders):
|
||||||
fields.append(
|
if reminder.private and isinstance(ctx.channel, GuildChannel):
|
||||||
EmbedField(
|
fields.append(
|
||||||
name=reminder.remind_at.strftime("%Y-%m-%d %H:%M UTC"),
|
EmbedField(
|
||||||
value=reminder.message,
|
name=reminder.remind_at.strftime("%Y-%m-%d %H:%M UTC"),
|
||||||
inline=False,
|
value="Private reminder",
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
fields.append(
|
||||||
|
EmbedField(
|
||||||
|
name=reminder.remind_at.strftime("%Y-%m-%d %H:%M UTC"),
|
||||||
|
value=reminder.message,
|
||||||
|
inline=False,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Deleted Reminder(s)",
|
title="Deleted Reminder(s)",
|
||||||
description="",
|
description="",
|
||||||
|
@ -260,7 +262,7 @@ class RemindmeCog(CacheCog):
|
||||||
)
|
)
|
||||||
|
|
||||||
embed.set_author(
|
embed.set_author(
|
||||||
name=ctx.author.username + "#" + ctx.author.discriminator,
|
name=ctx.author.display_name + "#" + ctx.author.discriminator,
|
||||||
icon_url=ctx.author.display_avatar.url,
|
icon_url=ctx.author.display_avatar.url,
|
||||||
)
|
)
|
||||||
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
||||||
|
|
|
@ -155,6 +155,7 @@ class Reminder(Document):
|
||||||
message = StringField(max_length=100, required=True)
|
message = StringField(max_length=100, required=True)
|
||||||
remind_at = DateTimeField(required=True)
|
remind_at = DateTimeField(required=True)
|
||||||
created_at = DateTimeField(default=datetime.utcnow)
|
created_at = DateTimeField(default=datetime.utcnow)
|
||||||
|
private = BooleanField(default=False)
|
||||||
|
|
||||||
meta = {"db_alias": "main"}
|
meta = {"db_alias": "main"}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ async def _remind() -> None:
|
||||||
fields=[],
|
fields=[],
|
||||||
)
|
)
|
||||||
embed.set_author(
|
embed.set_author(
|
||||||
name=user.name + "#" + user.discriminator, icon_url=user.display_avatar.url
|
name=user.username + "#" + user.discriminator, icon_url=user.avatar.url
|
||||||
)
|
)
|
||||||
embed.set_thumbnail(url=user.display_avatar.url)
|
embed.set_thumbnail(url=user.display_avatar.url)
|
||||||
try:
|
try:
|
||||||
|
@ -33,8 +33,13 @@ async def _remind() -> None:
|
||||||
except Exception:
|
except Exception:
|
||||||
guild = jarvis.jarvis.fetch_guild(reminder.guild)
|
guild = jarvis.jarvis.fetch_guild(reminder.guild)
|
||||||
channel = guild.get_channel(reminder.channel) if guild else None
|
channel = guild.get_channel(reminder.channel) if guild else None
|
||||||
if channel:
|
if channel and not reminder.private:
|
||||||
await channel.send(f"{user.mention}", embed=embed)
|
await channel.send(f"{user.mention}", embed=embed)
|
||||||
|
else:
|
||||||
|
await channel.send(
|
||||||
|
f"{user.mention}, you had a private reminder set for now, "
|
||||||
|
"but I couldn't send it to you."
|
||||||
|
)
|
||||||
finally:
|
finally:
|
||||||
reminder.delete()
|
reminder.delete()
|
||||||
|
|
||||||
|
|
|
@ -125,11 +125,7 @@ def find_all(predicate: Callable, sequence: Iterable) -> List[Any]:
|
||||||
A list of matches
|
A list of matches
|
||||||
|
|
||||||
"""
|
"""
|
||||||
matches = []
|
return [el for el in sequence if predicate(el)]
|
||||||
for el in sequence:
|
|
||||||
if predicate(el):
|
|
||||||
matches.append(el)
|
|
||||||
return matches
|
|
||||||
|
|
||||||
|
|
||||||
def get(sequence: Iterable, **kwargs: Any) -> Optional[Any]:
|
def get(sequence: Iterable, **kwargs: Any) -> Optional[Any]:
|
||||||
|
|
Loading…
Add table
Reference in a new issue