Preliminary front/switch tracking

This commit is contained in:
Ske 2018-07-12 02:14:32 +02:00
parent 64fa1f4e3c
commit 3efae634f9
4 changed files with 121 additions and 9 deletions

View File

@ -3,6 +3,7 @@ import re
from urllib.parse import urlparse from urllib.parse import urlparse
import discord import discord
import humanize
from pluralkit import db from pluralkit import db
from pluralkit.bot import client, logger from pluralkit.bot import client, logger
@ -197,6 +198,63 @@ async def system_unlink(conn, message, args):
await db.unlink_account(conn, system_id=system["id"], account_id=message.author.id) await db.unlink_account(conn, system_id=system["id"], account_id=message.author.id)
return True, "Account unlinked." return True, "Account unlinked."
@command(cmd="pk;system", subcommand="fronter", usage="[system]", description="Gets the current fronter in the system.")
async def system_fronter(conn, message, args):
if len(args) == 0:
system = await db.get_system_by_account(conn, message.author.id)
if system is None:
return False, "No system is registered to this account."
else:
system = await get_system_fuzzy(conn, args[0])
if system is None:
return False, "Can't find system \"{}\".".format(args[0])
current_fronter = await db.current_fronter(conn, system_id=system["id"])
if not current_fronter:
return True, make_default_embed(None).add_field(name="Current fronter", value="*(nobody)*")
fronter_name = "*(nobody)*"
if current_fronter["member"]:
member = await db.get_member(conn, member_id=current_fronter["member"])
fronter_name = member["name"]
if current_fronter["member_del"]:
fronter_name = "*(deleted member)*"
since = current_fronter["timestamp"]
embed = make_default_embed(None)
embed.add_field(name="Current fronter", value=fronter_name)
embed.add_field(name="Since", value="{} ({})".format(since.isoformat(sep=" ", timespec="seconds"), humanize.naturaltime(since)))
return True, embed
@command(cmd="pk;system", subcommand="fronthistory", usage="[system]", description="Shows the past 10 switches in the system.")
async def system_fronthistory(conn, message, args):
if len(args) == 0:
system = await db.get_system_by_account(conn, message.author.id)
if system is None:
return False, "No system is registered to this account."
else:
system = await get_system_fuzzy(conn, args[0])
if system is None:
return False, "Can't find system \"{}\".".format(args[0])
switches = await db.past_fronters(conn, system_id=system["id"], amount=10)
lines = []
for switch in switches:
since = switch["timestamp"]
time_text = since.isoformat(sep=" ", timespec="seconds")
rel_text = humanize.naturaltime(since)
lines.append("**{}** ({}, at {})".format(switch["name"], time_text, rel_text))
embed = make_default_embed("\n".join(lines))
embed.title = "Past switches"
return True, embed
@command(cmd="pk;member", subcommand="new", usage="<name>", description="Adds a new member to your system.") @command(cmd="pk;member", subcommand="new", usage="<name>", description="Adds a new member to your system.")
async def new_member(conn, message, args): async def new_member(conn, message, args):
@ -397,6 +455,45 @@ async def message_info(conn, message, args):
await client.send_message(message.channel, embed=embed) await client.send_message(message.channel, embed=embed)
return True return True
@command(cmd="pk;switch", subcommand=None, usage="<name|id>", description="Registers a switch and changes the current fronter.")
async def switch_member(conn, message, args):
if len(args) == 0:
return False
system = await db.get_system_by_account(conn, message.author.id)
if system is None:
return False, "No system is registered to this account."
# Find the member
member = await get_member_fuzzy(conn, system["id"], " ".join(args))
if not member:
return False, "Couldn't find member \"{}\".".format(args[0])
# Get current fronter
current_fronter = await db.current_fronter(conn, system_id=system["id"])
if current_fronter and current_fronter["member"] == member["id"]:
return False, "Member \"{}\" is already fronting.".format(member["name"])
# Log the switch
await db.add_switch(conn, system_id=system["id"], member_id=member["id"])
return True, "Switch registered. Current fronter is now {}.".format(member["name"])
@command(cmd="pk;switch", subcommand="out", description="Registers a switch out, and leaves current fronter blank.")
async def switch_out(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."
# Get current fronter
current_fronter = await db.current_fronter(conn, system_id=system["id"])
if not current_fronter or not current_fronter["member"]:
return False, "There's already no one in front."
# Log it
await db.add_switch(conn, system_id=system["id"], member_id=None)
return True, "Switch-out registered."
def make_help(cmds): def make_help(cmds):
embed = discord.Embed() embed = discord.Embed()

View File

@ -20,7 +20,7 @@ def db_wrap(func):
res = await func(*args, **kwargs) res = await func(*args, **kwargs)
after = time.perf_counter() after = time.perf_counter()
logger.debug(" - DB took {:.2f} ms".format((after - before) * 1000)) logger.debug(" - DB call {} took {:.2f} ms".format(func.__name__, (after - before) * 1000))
return res return res
return inner return inner
@ -177,6 +177,18 @@ async def delete_message(conn, message_id: str):
logger.debug("Deleting message (id={})".format(message_id)) logger.debug("Deleting message (id={})".format(message_id))
await conn.execute("delete from messages where mid = $1", int(message_id)) await conn.execute("delete from messages where mid = $1", int(message_id))
@db_wrap
async def current_fronter(conn, system_id: int):
return await conn.fetchrow("select *, members.name from switches left outer join members on (members.id = switches.member) where switches.system = $1 order by timestamp desc", system_id)
@db_wrap
async def past_fronters(conn, system_id: int, amount: int):
return await conn.fetch("select *, members.name from switches left outer join members on (members.id = switches.member) where switches.system = $1 order by timestamp desc limit $2", system_id, amount)
@db_wrap
async def add_switch(conn, system_id: int, member_id: int):
logger.debug("Adding switch (system={}, member={})".format(system_id, member_id))
return await conn.execute("insert into switches (system, member) values ($1, $2)", system_id, member_id)
async def create_tables(conn): async def create_tables(conn):
await conn.execute("""create table if not exists systems ( await conn.execute("""create table if not exists systems (
@ -216,7 +228,7 @@ async def create_tables(conn):
system serial not null references systems(id) on delete cascade, system serial not null references systems(id) on delete cascade,
member serial references members(id) on delete restrict, member serial references members(id) on delete restrict,
timestamp timestamp not null default current_timestamp, timestamp timestamp not null default current_timestamp,
member_del bool default false member_del bool not null default false
)""") )""")
await conn.execute("""create table if not exists webhooks ( await conn.execute("""create table if not exists webhooks (
channel bigint primary key, channel bigint primary key,

View File

@ -1,11 +1,11 @@
import random import random
import re import re
import string import string
import time
import asyncio import asyncio
import asyncpg import asyncpg
import discord import discord
import humanize
from pluralkit import db from pluralkit import db
from pluralkit.bot import client, logger from pluralkit.bot import client, logger
@ -82,10 +82,7 @@ command_map = {}
def command(cmd, subcommand, usage=None, description=None): def command(cmd, subcommand, usage=None, description=None):
def wrap(func): def wrap(func):
async def wrapper(conn, message, args): async def wrapper(conn, message, args):
before = time.perf_counter()
res = await func(conn, message, args) res = await func(conn, message, args)
after = time.perf_counter()
time_ms = (after - before) * 1000
if res is not None: if res is not None:
if not isinstance(res, tuple): if not isinstance(res, tuple):
@ -162,6 +159,11 @@ async def generate_system_info_card(conn, system: asyncpg.Record) -> discord.Emb
if system["tag"]: if system["tag"]:
card.add_field(name="Tag", value=system["tag"]) card.add_field(name="Tag", value=system["tag"])
current_fronter = await db.current_fronter(conn, system_id=system["id"])
if current_fronter and current_fronter["member"]:
fronter_val = "{} (for {})".format(current_fronter["name"], humanize.naturaldelta(current_fronter["timestamp"]))
card.add_field(name="Current fronter", value=fronter_val)
# Get names of all linked accounts # Get names of all linked accounts
async def get_name(account_id): async def get_name(account_id):
account = await client.get_user_info(account_id) account = await client.get_user_info(account_id)

View File

@ -1,4 +1,5 @@
discord.py
asyncpg
aiohttp aiohttp
aioinflux aioinflux
asyncpg
discord.py
humanize