Added front percent breakdown command

This commit is contained in:
Ske 2018-08-02 11:10:09 +02:00
parent 944f0093a9
commit 3d2d6b0ea6
2 changed files with 101 additions and 11 deletions

View File

@ -1,11 +1,11 @@
import logging
from datetime import datetime
from typing import List
from urllib.parse import urlparse
import dateparser
import humanize
import pluralkit.utils
from pluralkit.bot import utils
from pluralkit.bot.commands import *
logger = logging.getLogger("pluralkit.commands")
@ -22,7 +22,7 @@ async def system_info(ctx: CommandContext, args: List[str]):
if system is None:
raise CommandError("Unable to find system \"{}\".".format(args[0]))
await ctx.reply(embed=await utils.generate_system_info_card(ctx.conn, ctx.client, system))
@command(cmd="system new", usage="[name]", description="Registers a new system to this account.", category="System commands", system_required=False)
@ -46,7 +46,7 @@ async def new_system(ctx: CommandContext, args: List[str]):
@command(cmd="system set", usage="<name|description|tag|avatar> [value]", description="Edits a system property. Leave [value] blank to clear.", category="System commands")
async def system_set(ctx: CommandContext, args: List[str]):
if len(args) == 0:
if len(args) == 0:
raise InvalidCommandSyntax()
allowed_properties = ["name", "description", "tag", "avatar"]
@ -96,7 +96,7 @@ async def system_set(ctx: CommandContext, args: List[str]):
db_prop = db_properties[prop]
await db.update_system_field(ctx.conn, system_id=ctx.system.id, field=db_prop, value=value)
response = utils.make_default_embed("{} system {}.".format("Updated" if value else "Cleared", prop))
if prop == "avatar" and value:
response.set_image(url=value)
@ -150,10 +150,10 @@ async def system_fronter(ctx: CommandContext, args: List[str]):
system = ctx.system
else:
system = await utils.get_system_fuzzy(ctx.conn, ctx.client, args[0])
if system is None:
raise CommandError("Can't find system \"{}\".".format(args[0]))
fronters, timestamp = await pluralkit.utils.get_fronters(ctx.conn, system_id=system.id)
fronter_names = [member.name for member in fronters]
@ -178,10 +178,10 @@ async def system_fronthistory(ctx: CommandContext, args: List[str]):
system = ctx.system
else:
system = await utils.get_system_fuzzy(ctx.conn, ctx.client, args[0])
if system is None:
raise CommandError("Can't find system \"{}\".".format(args[0]))
lines = []
front_history = await pluralkit.utils.get_front_history(ctx.conn, system.id, count=10)
for i, (timestamp, members) in enumerate(front_history):
@ -215,4 +215,85 @@ async def system_delete(ctx: CommandContext, args: List[str]):
await db.remove_system(ctx.conn, system_id=ctx.system.id)
return "System deleted."
else:
return "System deletion cancelled."
return "System deletion cancelled."
@command(cmd="system frontpercent", usage="[time]",
description="Shows the fronting percentage of every member, averaged over the given time",
category="System commands")
async def system_frontpercent(ctx: CommandContext, args: List[str]):
# Parse the time limit (will go this far back)
before = dateparser.parse(" ".join(args), languages=["en"], settings={
"TO_TIMEZONE": "UTC",
"RETURN_AS_TIMEZONE_AWARE": False
})
# If time is in the future, just kinda discard
if before and before > datetime.utcnow():
before = None
# Fetch list of switches
all_switches = await pluralkit.utils.get_front_history(ctx.conn, ctx.system.id, 99999)
if not all_switches:
raise CommandError("No switches registered to this system.")
# Cull the switches *ending* before the limit, if given
# We'll need to find the first switch starting before the limit, then cut off every switch *before* that
if before:
for last_stamp, _ in all_switches:
if last_stamp < before:
break
all_switches = [(stamp, members) for stamp, members in all_switches if stamp >= last_stamp]
start_times = [stamp for stamp, _ in all_switches]
end_times = [datetime.utcnow()] + start_times
switch_members = [members for _, members in all_switches]
# Gonna save a list of members by ID for future lookup too
members_by_id = {}
# Using the ID as a key here because it's a simple number that can be hashed and used as a key
member_times = {}
for start_time, end_time, members in zip(start_times, end_times, switch_members):
# Cut off parts of the switch that occurs before the time limit (will only happen if this is the last switch)
if before and start_time < before:
start_time = before
# Calculate length of the switch
switch_length = end_time - start_time
def add_switch(member_id, length):
if member_id not in member_times:
member_times[member_id] = length
else:
member_times[member_id] += length
for member in members:
# Add the switch length to the currently registered time for that member
add_switch(member.id, switch_length)
# Also save the member in the ID map for future reference
members_by_id[member.id] = member
# Also register a no-fronter switch with the key None
if not members:
add_switch(None, switch_length)
# Find the total timespan of the range
span_start = max(start_times[-1], before) if before else start_times[-1]
total_time = datetime.utcnow() - span_start
embed = utils.make_default_embed(None)
for member_id, front_time in sorted(member_times.items(), key=lambda x: x[1], reverse=True):
member = members_by_id[member_id] if member_id else None
# Calculate percent
fraction = front_time / total_time
percent = int(fraction * 100)
embed.add_field(name=member.name if member else "(no fronter)",
value="{}% ({})".format(percent, humanize.naturaldelta(front_time)))
embed.set_footer(text="Since {}".format(span_start.isoformat(sep=" ", timespec="seconds")))
return embed

View File

@ -137,7 +137,16 @@ For example:
`pk;system fronter` - Shows the current fronter(s) in your own system.
`pk;system fronter abcde` - Shows the current fronter in the system with the ID `abcde`.
`pk;system fronthistory` - Shows the past 10 switches in your own system.
`pk;system fronthistory @JohnsAccount` - Shows the past 10 switches in the system linked to @JohnsAccount.""")
`pk;system fronthistory @JohnsAccount` - Shows the past 10 switches in the system linked to @JohnsAccount."""),
("Viewing a front breakdown",
"""To see a per-member breakdown of your switches, use the `pk;system frontpercent` command. You can optionally give it a time limit to only count switches after that point.
For example:
`pk;system frontpercent` - Shows a front breakdown for your system since you started logging switches
`pk;system frontpercent 1 day` - Shows a front breakdown for your system for the past day
`pk;system frontpercent Jan 1st 2018` - Shows a front breakdown for your system since January 1st, 2018
Note that the percentages don't necessarily add up to 100%, as multiple members can be listed as fronting at a time.""")
],
"mod": [
(None, "Note that all moderation commands require you to have administrator privileges on the server they're used on."),