Optimize reminders, changed how reminder time is chosen, closes #122

This commit is contained in:
Zeva Rose 2022-02-05 13:22:48 -07:00
parent 253d231d0a
commit db5a60a88f
4 changed files with 74 additions and 70 deletions

View file

@ -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)

View file

@ -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"}

View file

@ -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()

View file

@ -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]: