Compare commits
No commits in common. "main" and "mdiluz-patch-1" have entirely different histories.
main
...
mdiluz-pat
7 changed files with 49 additions and 203 deletions
|
@ -17,7 +17,7 @@ Matchy supports a bunch of user, `matcher` and bot owner commands. `/` commands
|
||||||
| /pause | user | Pauses the user for `days: int` days |
|
| /pause | user | Pauses the user for `days: int` days |
|
||||||
| /list | user | Lists the current matchees and scheduled matches |
|
| /list | user | Lists the current matchees and scheduled matches |
|
||||||
| /match | user* | Shares a preview of the matchee groups of size `group_min: int` with the user. *Offers a button to post the match to `matcher` users |
|
| /match | user* | Shares a preview of the matchee groups of size `group_min: int` with the user. *Offers a button to post the match to `matcher` users |
|
||||||
| /schedule | `matcher` | Schedules a match every week with `group_min: int` users on `weekday: int` and at `hour: int`, on a weekly `cadence: int`.<br>Can pass `cancel: True` to stop the schedule |
|
| /schedule | `matcher` | Schedules a match every week with `group_min: int` users on `weekday: int` day and at `hour: int` hour. Can pass `cancel: True` to stop the schedule |
|
||||||
| /cancel | `matcher` | Cancels any scheduled matches in this channel |
|
| /cancel | `matcher` | Cancels any scheduled matches in this channel |
|
||||||
| $sync | bot owner | Syncs bot command data with the discord servers |
|
| $sync | bot owner | Syncs bot command data with the discord servers |
|
||||||
| $close | bot owner | Closes the bot connection so the bot quits safely |
|
| $close | bot owner | Closes the bot connection so the bot quits safely |
|
||||||
|
|
|
@ -92,8 +92,8 @@ class MatcherCog(commands.Cog):
|
||||||
msg += "\n" + strings.paused_matchees(mentions) + "\n"
|
msg += "\n" + strings.paused_matchees(mentions) + "\n"
|
||||||
|
|
||||||
tasks = state.State.get_channel_match_tasks(interaction.channel.id)
|
tasks = state.State.get_channel_match_tasks(interaction.channel.id)
|
||||||
for (day, hour, min, cadence, cadence_start) in tasks:
|
for (day, hour, min) in tasks:
|
||||||
next_run = util.get_next_datetime_with_cadence(day, hour, datetime.now(), cadence, cadence_start)
|
next_run = util.get_next_datetime(day, hour)
|
||||||
msg += "\n" + strings.scheduled(next_run, min)
|
msg += "\n" + strings.scheduled(next_run, min)
|
||||||
|
|
||||||
if not msg:
|
if not msg:
|
||||||
|
@ -110,8 +110,7 @@ class MatcherCog(commands.Cog):
|
||||||
interaction: discord.Interaction,
|
interaction: discord.Interaction,
|
||||||
members_min: int | None = None,
|
members_min: int | None = None,
|
||||||
weekday: int | None = None,
|
weekday: int | None = None,
|
||||||
hour: int | None = None,
|
hour: int | None = None):
|
||||||
cadence: int | None = None):
|
|
||||||
"""Schedule a match using the input parameters"""
|
"""Schedule a match using the input parameters"""
|
||||||
|
|
||||||
# Set all the defaults
|
# Set all the defaults
|
||||||
|
@ -121,8 +120,6 @@ class MatcherCog(commands.Cog):
|
||||||
weekday = 0
|
weekday = 0
|
||||||
if hour is None:
|
if hour is None:
|
||||||
hour = 9
|
hour = 9
|
||||||
if cadence is None or cadence == 0:
|
|
||||||
cadence = 1
|
|
||||||
channel_id = str(interaction.channel.id)
|
channel_id = str(interaction.channel.id)
|
||||||
|
|
||||||
# Bail if not a matcher
|
# Bail if not a matcher
|
||||||
|
@ -132,19 +129,19 @@ class MatcherCog(commands.Cog):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Add the scheduled task and save
|
# Add the scheduled task and save
|
||||||
(_, _, _, _, cadence_start) = state.State.set_channel_match_task(
|
state.State.set_channel_match_task(
|
||||||
channel_id, members_min, weekday, hour, cadence)
|
channel_id, members_min, weekday, hour)
|
||||||
|
|
||||||
# Let the user know what happened
|
# Let the user know what happened
|
||||||
logger.info("Scheduled new match task in %s with min %s weekday %s hour %s and cadence %s",
|
logger.info("Scheduled new match task in %s with min %s weekday %s hour %s",
|
||||||
channel_id, members_min, weekday, hour, cadence)
|
channel_id, members_min, weekday, hour)
|
||||||
next_run = util.get_next_datetime_with_cadence(weekday, hour, datetime.now(), cadence, cadence_start)
|
next_run = util.get_next_datetime(weekday, hour)
|
||||||
|
|
||||||
view = discord.ui.View(timeout=None)
|
view = discord.ui.View(timeout=None)
|
||||||
view.add_item(ScheduleButton())
|
view.add_item(ScheduleButton())
|
||||||
|
|
||||||
await interaction.response.send_message(
|
await interaction.response.send_message(
|
||||||
strings.scheduled_success(next_run, cadence),
|
strings.scheduled_success(next_run),
|
||||||
ephemeral=True, silent=True, view=view)
|
ephemeral=True, silent=True, view=view)
|
||||||
|
|
||||||
@app_commands.command(description="Cancel all scheduled matches in this channel")
|
@app_commands.command(description="Cancel all scheduled matches in this channel")
|
||||||
|
@ -210,28 +207,15 @@ class MatcherCog(commands.Cog):
|
||||||
async def run_hourly_tasks(self):
|
async def run_hourly_tasks(self):
|
||||||
"""Run any hourly tasks we have"""
|
"""Run any hourly tasks we have"""
|
||||||
|
|
||||||
# Send a reminder for anything that will be active in 1 day
|
|
||||||
for (channel, _) in state.State.get_active_match_tasks(datetime.now() + timedelta(days=1)):
|
|
||||||
logger.info("Reminding about scheduled task in %s", channel)
|
|
||||||
msg_channel = self.bot.get_channel(int(channel))
|
|
||||||
await msg_channel.send(strings.reminder())
|
|
||||||
|
|
||||||
# Match groups for anything active right now
|
|
||||||
for (channel, min) in state.State.get_active_match_tasks():
|
for (channel, min) in state.State.get_active_match_tasks():
|
||||||
logger.info("Scheduled match task triggered in %s", channel)
|
logger.info("Scheduled match task triggered in %s", channel)
|
||||||
msg_channel = self.bot.get_channel(int(channel))
|
msg_channel = self.bot.get_channel(int(channel))
|
||||||
await match_groups_in_channel(msg_channel, min)
|
await match_groups_in_channel(msg_channel, min)
|
||||||
|
|
||||||
# Send a reminder to threads for a match that happened two days ago
|
for (channel, _) in state.State.get_active_match_tasks(datetime.now() + timedelta(days=1)):
|
||||||
for (channel, _) in state.State.get_active_match_tasks(datetime.now() - timedelta(days=2)):
|
logger.info("Reminding about scheduled task in %s", channel)
|
||||||
logger.info("Sending reminders to threads in %s", channel)
|
|
||||||
msg_channel = self.bot.get_channel(int(channel))
|
msg_channel = self.bot.get_channel(int(channel))
|
||||||
# Find any threads that need
|
await msg_channel.send(strings.reminder())
|
||||||
for thread in msg_channel.threads:
|
|
||||||
# Only regard threads the bot created
|
|
||||||
# And that have no additional messages
|
|
||||||
if thread.owner.id == self.bot.user.id and thread.message_count <= 1:
|
|
||||||
await thread.send(strings.thread_reminder())
|
|
||||||
|
|
||||||
|
|
||||||
# Increment when adjusting the custom_id so we don't confuse old users
|
# Increment when adjusting the custom_id so we don't confuse old users
|
||||||
|
@ -285,14 +269,11 @@ async def match_groups_in_channel(channel: discord.channel, min: int):
|
||||||
strings.matched_up([m.mention for m in group]))
|
strings.matched_up([m.mention for m in group]))
|
||||||
# Set up a thread for this match if the bot has permissions to do so
|
# Set up a thread for this match if the bot has permissions to do so
|
||||||
if channel.permissions_for(channel.guild.me).create_public_threads:
|
if channel.permissions_for(channel.guild.me).create_public_threads:
|
||||||
thread = await channel.create_thread(
|
await channel.create_thread(
|
||||||
name=strings.thread_title([m.display_name for m in group]),
|
name=strings.thread_title([m.display_name for m in group]),
|
||||||
message=message,
|
message=message,
|
||||||
reason="Creating a matching thread")
|
reason="Creating a matching thread")
|
||||||
|
|
||||||
# Send a message with a suggested time to the channel
|
|
||||||
await thread.send(f"{strings.thread_message()} {strings.time_suggestion()}")
|
|
||||||
|
|
||||||
# Close off with a message
|
# Close off with a message
|
||||||
await channel.send(strings.matching_done())
|
await channel.send(strings.matching_done())
|
||||||
# Save the groups to the history
|
# Save the groups to the history
|
||||||
|
@ -323,8 +304,8 @@ class ScheduleButton(discord.ui.Button):
|
||||||
msg += strings.scheduled_matches()
|
msg += strings.scheduled_matches()
|
||||||
|
|
||||||
if tasks:
|
if tasks:
|
||||||
for (day, hour, min, cadence, cadence_start) in tasks:
|
for (day, hour, min) in tasks:
|
||||||
next_run = util.get_next_datetime_with_cadence(day, hour, datetime.now(), cadence, cadence_start)
|
next_run = util.get_next_datetime(day, hour)
|
||||||
msg += strings.scheduled(next_run, min)
|
msg += strings.scheduled(next_run, min)
|
||||||
|
|
||||||
await interaction.channel.send(msg)
|
await interaction.channel.send(msg)
|
||||||
|
|
|
@ -85,11 +85,11 @@ def need_matcher_scope(): return [
|
||||||
|
|
||||||
|
|
||||||
@randomised
|
@randomised
|
||||||
def scheduled_success(d, cadence): return [
|
def scheduled_success(d): return [
|
||||||
f"Done :) Next run will be at {datetime_as_discord_time(d)} and every {cadence} week(s) after",
|
f"Done :) Next run will be at {datetime_as_discord_time(d)}",
|
||||||
f"Woohoo! Scheduled for {datetime_as_discord_time(d)} plus each {cadence} week(s) after",
|
f"Woohoo! Scheduled for {datetime_as_discord_time(d)}",
|
||||||
f"Yessir, will do a matcho every {cadence} week(s), first one is {datetime_as_discord_time(d)}",
|
f"Yessir, will do a matcho at {datetime_as_discord_time(d)}",
|
||||||
f"Arf Arf! Bork bork bark {datetime_as_discord_time(d)} berk {cadence} week(s) arf",
|
f"Arf Arf! Bork bork bark {datetime_as_discord_time(d)}",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,16 +145,6 @@ Make sure you're /pause'd if you need to be, or /join in ASAP!""",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@randomised
|
|
||||||
def thread_reminder(): return [
|
|
||||||
"Hey friends, just checking in! No worries if you're too busy this week",
|
|
||||||
"Bork bork, quick reminder in case y'all forgot!",
|
|
||||||
"Hey matchees, how's your week going?",
|
|
||||||
"Hey everyone, don't forget to check in with eachother!",
|
|
||||||
"Quick friendly nudge, how're you all doing?",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@randomised
|
@randomised
|
||||||
def matching(): return [
|
def matching(): return [
|
||||||
"Matchy is matching matchees...",
|
"Matchy is matching matchees...",
|
||||||
|
@ -184,36 +174,6 @@ def matched_up(ms): return [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@randomised
|
|
||||||
def thread_message(): return [
|
|
||||||
"Hey peeps :)",
|
|
||||||
"How is everyone?",
|
|
||||||
"Bork!",
|
|
||||||
"Hey kiddos :)",
|
|
||||||
"Ahoy!",
|
|
||||||
"Great to see y'all here.",
|
|
||||||
"Icebreaker! What's your favourite pokemon?",
|
|
||||||
"I'm hungry, would a lasagna count as a sandwich?",
|
|
||||||
"What's your favourite keyboard key?",
|
|
||||||
"I'm confused thinking... Is a train just a sideways elevator?",
|
|
||||||
"Humans are weird, why do you have moustaches above your eyes?"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@randomised
|
|
||||||
def time_suggestion(): return [
|
|
||||||
"Can I suggest a quick call on Wednesday?",
|
|
||||||
"Remember to organise a chat if you're up for it!",
|
|
||||||
"How about throwing something in the calendar for Friday?",
|
|
||||||
"Would 10am on Thursday work for people?",
|
|
||||||
"How about a call this afternoon?",
|
|
||||||
"Would a chat the start of a weekday work?",
|
|
||||||
"How's about organising a quick call sometime this week?",
|
|
||||||
"When's everyone available for a short hangout?",
|
|
||||||
"It's best to pick a time to drop in a call or meet up, if everyone is up for it!",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@randomised
|
@randomised
|
||||||
def thread_title(ms): return [
|
def thread_title(ms): return [
|
||||||
f"{format_list(ms)}",
|
f"{format_list(ms)}",
|
||||||
|
|
|
@ -16,7 +16,7 @@ logger = logging.getLogger("state")
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
# Warning: Changing any of the below needs proper thought to ensure backwards compatibility
|
# Warning: Changing any of the below needs proper thought to ensure backwards compatibility
|
||||||
_VERSION = 5
|
_VERSION = 4
|
||||||
|
|
||||||
|
|
||||||
def _migrate_to_v1(d: dict):
|
def _migrate_to_v1(d: dict):
|
||||||
|
@ -64,24 +64,12 @@ def _migrate_to_v4(d: dict):
|
||||||
del d[_Key._HISTORY]
|
del d[_Key._HISTORY]
|
||||||
|
|
||||||
|
|
||||||
def _migrate_to_v5(d: dict):
|
|
||||||
"""v5 added weekly cadence"""
|
|
||||||
tasks = d.get(_Key.TASKS, {})
|
|
||||||
for tasks in tasks.values():
|
|
||||||
match_tasks = tasks.get(_Key.MATCH_TASKS, [])
|
|
||||||
for match in match_tasks:
|
|
||||||
# All previous matches were every week starting from now
|
|
||||||
match[_Key.CADENCE] = 1
|
|
||||||
match[_Key.CADENCE_START] = datetime_to_ts(datetime.now())
|
|
||||||
|
|
||||||
|
|
||||||
# Set of migration functions to apply
|
# Set of migration functions to apply
|
||||||
_MIGRATIONS = [
|
_MIGRATIONS = [
|
||||||
_migrate_to_v1,
|
_migrate_to_v1,
|
||||||
_migrate_to_v2,
|
_migrate_to_v2,
|
||||||
_migrate_to_v3,
|
_migrate_to_v3,
|
||||||
_migrate_to_v4,
|
_migrate_to_v4,
|
||||||
_migrate_to_v5
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,8 +94,6 @@ class _Key(str):
|
||||||
MEMBERS_MIN = "members_min"
|
MEMBERS_MIN = "members_min"
|
||||||
WEEKDAY = "weekdays"
|
WEEKDAY = "weekdays"
|
||||||
HOUR = "hours"
|
HOUR = "hours"
|
||||||
CADENCE = "cadence"
|
|
||||||
CADENCE_START = "cadence_start"
|
|
||||||
|
|
||||||
# Unused
|
# Unused
|
||||||
_MATCHEES = "matchees"
|
_MATCHEES = "matchees"
|
||||||
|
@ -153,8 +139,6 @@ _SCHEMA = Schema(
|
||||||
_Key.MEMBERS_MIN: Use(int),
|
_Key.MEMBERS_MIN: Use(int),
|
||||||
_Key.WEEKDAY: Use(int),
|
_Key.WEEKDAY: Use(int),
|
||||||
_Key.HOUR: Use(int),
|
_Key.HOUR: Use(int),
|
||||||
_Key.CADENCE: Use(int),
|
|
||||||
_Key.CADENCE_START: Use(str),
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -232,12 +216,11 @@ class _State():
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def inner(self, *args, **kwargs):
|
def inner(self, *args, **kwargs):
|
||||||
tmp = _State(self._dict, self._file)
|
tmp = _State(self._dict, self._file)
|
||||||
ret = func(tmp, *args, **kwargs)
|
func(tmp, *args, **kwargs)
|
||||||
_SCHEMA.validate(tmp._dict)
|
_SCHEMA.validate(tmp._dict)
|
||||||
if tmp._file:
|
if tmp._file:
|
||||||
_save(tmp._file, tmp._dict)
|
_save(tmp._file, tmp._dict)
|
||||||
self._dict = tmp._dict
|
self._dict = tmp._dict
|
||||||
return ret
|
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
@ -341,10 +324,7 @@ class _State():
|
||||||
|
|
||||||
for channel, tasks in self._tasks.items():
|
for channel, tasks in self._tasks.items():
|
||||||
for match in tasks.get(_Key.MATCH_TASKS, []):
|
for match in tasks.get(_Key.MATCH_TASKS, []):
|
||||||
# Take into account the weekly cadence
|
if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour:
|
||||||
start = ts_to_datetime(match[_Key.CADENCE_START])
|
|
||||||
weeks = int((time - start).days / 7)
|
|
||||||
if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour and weeks % match[_Key.CADENCE] == 0:
|
|
||||||
yield (channel, match[_Key.MEMBERS_MIN])
|
yield (channel, match[_Key.MEMBERS_MIN])
|
||||||
|
|
||||||
def get_channel_match_tasks(self, channel_id: str) -> Generator[int, int, int]:
|
def get_channel_match_tasks(self, channel_id: str) -> Generator[int, int, int]:
|
||||||
|
@ -358,35 +338,30 @@ class _State():
|
||||||
)
|
)
|
||||||
for tasks in all_tasks:
|
for tasks in all_tasks:
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
yield _task_to_tuple(task)
|
yield (task[_Key.WEEKDAY], task[_Key.HOUR], task[_Key.MEMBERS_MIN])
|
||||||
|
|
||||||
@safe_write
|
@safe_write
|
||||||
def set_channel_match_task(self, channel_id: str, members_min: int, weekday: int, hour: int, cadence: int):
|
def set_channel_match_task(self, channel_id: str, members_min: int, weekday: int, hour: int):
|
||||||
"""Set up a match task on a channel"""
|
"""Set up a match task on a channel"""
|
||||||
channel = self._tasks.setdefault(str(channel_id), {})
|
channel = self._tasks.setdefault(str(channel_id), {})
|
||||||
matches = channel.setdefault(_Key.MATCH_TASKS, [])
|
matches = channel.setdefault(_Key.MATCH_TASKS, [])
|
||||||
|
|
||||||
for match_task in matches:
|
found = False
|
||||||
|
for match in matches:
|
||||||
# Specifically check for the combination of weekday and hour
|
# Specifically check for the combination of weekday and hour
|
||||||
if match_task[_Key.WEEKDAY] == weekday and match_task[_Key.HOUR] == hour:
|
if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour:
|
||||||
match_task[_Key.MEMBERS_MIN] = members_min
|
found = True
|
||||||
# If the cadence has changed, update it and reset the start
|
match[_Key.MEMBERS_MIN] = members_min
|
||||||
if cadence != match_task[_Key.CADENCE]:
|
# Return true as we've successfully changed the data in place
|
||||||
match_task[_Key.CADENCE] = cadence
|
return True
|
||||||
match_task[_Key.CADENCE_START] = datetime_to_ts(datetime.now())
|
|
||||||
# Return as we've successfully changed the data in place
|
|
||||||
return _task_to_tuple(match_task)
|
|
||||||
|
|
||||||
# If we didn't find it, add it to the schedule
|
# If we didn't find it, add it to the schedule
|
||||||
match_task = {
|
if not found:
|
||||||
_Key.MEMBERS_MIN: members_min,
|
matches.append({
|
||||||
_Key.WEEKDAY: weekday,
|
_Key.MEMBERS_MIN: members_min,
|
||||||
_Key.HOUR: hour,
|
_Key.WEEKDAY: weekday,
|
||||||
_Key.CADENCE: cadence,
|
_Key.HOUR: hour,
|
||||||
_Key.CADENCE_START: datetime_to_ts(datetime.now())
|
})
|
||||||
}
|
|
||||||
matches.append(match_task)
|
|
||||||
return _task_to_tuple(match_task)
|
|
||||||
|
|
||||||
@safe_write
|
@safe_write
|
||||||
def remove_channel_match_tasks(self, channel_id: str):
|
def remove_channel_match_tasks(self, channel_id: str):
|
||||||
|
@ -404,14 +379,6 @@ class _State():
|
||||||
return self._dict[_Key.TASKS]
|
return self._dict[_Key.TASKS]
|
||||||
|
|
||||||
|
|
||||||
def _task_to_tuple(task):
|
|
||||||
return (task[_Key.WEEKDAY],
|
|
||||||
task[_Key.HOUR],
|
|
||||||
task[_Key.MEMBERS_MIN],
|
|
||||||
task[_Key.CADENCE],
|
|
||||||
ts_to_datetime(task[_Key.CADENCE_START]))
|
|
||||||
|
|
||||||
|
|
||||||
def load_from_file(file: str) -> _State:
|
def load_from_file(file: str) -> _State:
|
||||||
"""
|
"""
|
||||||
Load the state from a files
|
Load the state from a files
|
||||||
|
|
|
@ -18,32 +18,20 @@ def format_list(list: list) -> str:
|
||||||
return list[0] if list else ''
|
return list[0] if list else ''
|
||||||
|
|
||||||
|
|
||||||
def get_next_datetime(weekday: int, hour: int, start: datetime) -> datetime:
|
def get_next_datetime(weekday, hour) -> datetime:
|
||||||
"""Get the next datetime for the given weekday and hour"""
|
"""Get the next datetime for the given weekday and hour"""
|
||||||
|
now = datetime.now()
|
||||||
days_until_next_week_run = (weekday - start.weekday() + 7) % 7
|
days_until_next_week = (weekday - now.weekday() + 7) % 7
|
||||||
|
|
||||||
# Account for when we're already beyond the time now
|
# Account for when we're already beyond the time now
|
||||||
if days_until_next_week_run == 0 and start.hour >= hour:
|
if days_until_next_week == 0 and now.hour >= hour:
|
||||||
days_until_next_week_run = 7
|
days_until_next_week = 7
|
||||||
|
|
||||||
# Calculate the next datetime
|
# Calculate the next datetime
|
||||||
next_date = start + timedelta(days=days_until_next_week_run)
|
next_date = now + timedelta(days=days_until_next_week)
|
||||||
|
next_date = next_date.replace(hour=hour, minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
return next_date.replace(hour=hour, minute=0, second=0, microsecond=0)
|
return next_date
|
||||||
|
|
||||||
|
|
||||||
def get_next_datetime_with_cadence(weekday: int, hour: int, start: datetime, cadence: int, cadence_start: datetime):
|
|
||||||
"""Get the next datetime for given weekday, hour and cadence values"""
|
|
||||||
|
|
||||||
# Get the first run based on the cadence
|
|
||||||
next_time = get_next_datetime(weekday, hour, cadence_start)
|
|
||||||
|
|
||||||
# Walk forwards until we get the actual time
|
|
||||||
while next_time < start:
|
|
||||||
next_time += timedelta(weeks=cadence)
|
|
||||||
|
|
||||||
return next_time
|
|
||||||
|
|
||||||
|
|
||||||
def datetime_as_discord_time(time: datetime) -> str:
|
def datetime_as_discord_time(time: datetime) -> str:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
coverage==7.6.10
|
coverage==7.6.1
|
||||||
discord.py==2.4.0
|
discord.py==2.4.0
|
||||||
dpytest==0.7.0
|
dpytest==0.7.0
|
||||||
flake8==7.1.1
|
flake8==7.1.1
|
||||||
pytest==8.3.3
|
pytest==8.3.3
|
||||||
pytest-asyncio==0.25.2
|
pytest-asyncio==0.24.0
|
||||||
pytest-cov==5.0.0
|
pytest-cov==5.0.0
|
||||||
schema==0.7.7
|
schema==0.7.7
|
|
@ -1,6 +1,4 @@
|
||||||
import matchy.util as util
|
import matchy.util as util
|
||||||
from datetime import datetime
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
|
|
||||||
def test_iterate_all_shifts():
|
def test_iterate_all_shifts():
|
||||||
|
@ -52,51 +50,3 @@ def test_randomized():
|
||||||
|
|
||||||
assert util.randomised(string)() == "foo"
|
assert util.randomised(string)() == "foo"
|
||||||
assert util.randomised(list)() in list()
|
assert util.randomised(list)() in list()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"weekday, hour, start, expected",
|
|
||||||
[
|
|
||||||
pytest.param(
|
|
||||||
0, 0, datetime(2024, 9, 22),
|
|
||||||
datetime(2024, 9, 23), id="tomorrow"
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
4, 16, datetime(2024, 9, 22),
|
|
||||||
datetime(2024, 9, 27, 16), id="complicated"
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_get_next_datetime(weekday, hour, start, expected):
|
|
||||||
value = util.get_next_datetime(weekday, hour, start)
|
|
||||||
assert value == expected
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"weekday, hour, start, cadence, cadence_start, expected",
|
|
||||||
[
|
|
||||||
pytest.param(
|
|
||||||
0, 0, datetime(2024, 9, 22),
|
|
||||||
1, datetime(2024, 9, 22),
|
|
||||||
datetime(2024, 9, 23), id="tomorrow"
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
0, 0, datetime(2024, 9, 22),
|
|
||||||
2, datetime(2024, 9, 22),
|
|
||||||
datetime(2024, 9, 23), id="every-other"
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
0, 0, datetime(2024, 9, 22),
|
|
||||||
2, datetime(2024, 9, 14),
|
|
||||||
datetime(2024, 9, 30), id="every-other-before"
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
0, 0, datetime(2024, 9, 22),
|
|
||||||
3, datetime(2024, 9, 14),
|
|
||||||
datetime(2024, 10, 7), id="every-third"
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_get_next_datetime_with_cadence(weekday, hour, start, expected, cadence, cadence_start):
|
|
||||||
value = util.get_next_datetime_with_cadence(weekday, hour, start, cadence, cadence_start)
|
|
||||||
assert value == expected
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue