Add a command for backdating switches

This commit is contained in:
Ske
2018-07-20 22:56:32 +02:00
parent acb11dd9d6
commit 26d89136b1
4 changed files with 85 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timezone
import io
import itertools
import json
@@ -6,6 +6,7 @@ import os
import re
from urllib.parse import urlparse
import dateparser
import discord
from discord.utils import oauth_url
import humanize
@@ -464,7 +465,7 @@ async def switch_member(conn, message, args):
if len(members) == 1:
return False, "{} is already fronting.".format(members[0]["name"])
return False, "Members {} are already fronting.".format(", ".join([m["name"] for m in members]))
# Log the switch
async with conn.transaction():
switch_id = await db.add_switch(conn, system_id=system["id"])
@@ -492,6 +493,70 @@ async def switch_out(conn, message, args):
await db.add_switch(conn, system_id=system["id"])
return True, "Switch-out registered."
@command(cmd="switch move", usage="<time>", description="Moves the most recent switch to a different point in time.", category="Switching commands")
async def switch_move(conn, message, args):
system = await db.get_system_by_account(conn, message.author.id)
if system is None:
return False, "No system is registered to this account."
if len(args) == 0:
return False
# Parse the time to move to
new_time = dateparser.parse(" ".join(args), languages=["en"], settings={
"TO_TIMEZONE": "UTC",
"RETURN_AS_TIMEZONE_AWARE": False
})
if not new_time:
return False, "{} can't be parsed as a valid time.".format(" ".join(args))
# Make sure the time isn't in the future
if new_time > datetime.now():
return False, "Can't move switch to a time in the future."
# Make sure it all runs in a big transaction for atomicity
async with conn.transaction():
# Get the last two switches to make sure the switch to move isn't before the second-last switch
last_two_switches = await get_front_history(conn, system["id"], count=2)
if len(last_two_switches) == 0:
return False, "There are no registered switches for this system."
last_timestamp, last_fronters = last_two_switches[0]
if len(last_two_switches) > 1:
second_last_timestamp, _ = last_two_switches[1]
if new_time < second_last_timestamp:
time_str = humanize.naturaltime(second_last_timestamp)
return False, "Can't move switch to before last switch time ({}), as it would cause conflicts.".format(time_str)
# Display the confirmation message w/ humanized times
members = ", ".join([member["name"] for member in last_fronters])
last_absolute = last_timestamp.isoformat(sep=" ", timespec="seconds")
last_relative = humanize.naturaltime(last_timestamp)
new_absolute = new_time.isoformat(sep=" ", timespec="seconds")
new_relative = humanize.naturaltime(new_time)
embed = make_default_embed("This will move the latest switch ({}) from {} ({}) to {} ({}). Is this OK?".format(members, last_absolute, last_relative, new_absolute, new_relative))
# Await and handle confirmation reactions
confirm_msg = await client.send_message(message.channel, embed=embed)
await client.add_reaction(confirm_msg, "")
await client.add_reaction(confirm_msg, "")
reaction = await client.wait_for_reaction(emoji=["", ""], message=confirm_msg, user=message.author, timeout=60.0)
if not reaction:
return False, "Switch move timed out."
if reaction.reaction.emoji == "":
return False, "Switch move cancelled."
# DB requires the actual switch ID which our utility method above doesn't return, do this manually
switch_id = (await db.front_history(conn, system["id"], count=1))[0]["id"]
# Change the switch in the DB
await db.move_last_switch(conn, system["id"], switch_id, naive_new_time)
return True, "Switch moved."
@command(cmd="mod log", usage="[channel]", description="Sets the bot to log events to a specified channel. Leave blank to disable.", category="Moderation commands")
async def set_log(conn, message, args):
if not message.author.server_permissions.administrator: