Preliminary front/switch tracking
This commit is contained in:
		| @@ -3,6 +3,7 @@ import re | ||||
| from urllib.parse import urlparse | ||||
|  | ||||
| import discord | ||||
| import humanize | ||||
|  | ||||
| from pluralkit import db | ||||
| 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) | ||||
|         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.") | ||||
| 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) | ||||
|     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): | ||||
|     embed = discord.Embed() | ||||
|   | ||||
| @@ -20,7 +20,7 @@ def db_wrap(func): | ||||
|         res = await func(*args, **kwargs) | ||||
|         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 inner | ||||
|  | ||||
| @@ -177,6 +177,18 @@ async def delete_message(conn, message_id: str): | ||||
|     logger.debug("Deleting message (id={})".format(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): | ||||
|     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, | ||||
|         member      serial references members(id) on delete restrict, | ||||
|         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 ( | ||||
|         channel     bigint primary key, | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import random | ||||
| import re | ||||
| import string | ||||
| import time | ||||
|  | ||||
| import asyncio | ||||
| import asyncpg | ||||
| import discord | ||||
| import humanize | ||||
|  | ||||
| from pluralkit import db | ||||
| from pluralkit.bot import client, logger | ||||
| @@ -82,10 +82,7 @@ command_map = {} | ||||
| def command(cmd, subcommand, usage=None, description=None): | ||||
|     def wrap(func): | ||||
|         async def wrapper(conn, message, args): | ||||
|             before = time.perf_counter() | ||||
|             res = await func(conn, message, args) | ||||
|             after = time.perf_counter() | ||||
|             time_ms = (after - before) * 1000 | ||||
|  | ||||
|             if res is not None: | ||||
|                 if not isinstance(res, tuple): | ||||
| @@ -162,6 +159,11 @@ async def generate_system_info_card(conn, system: asyncpg.Record) -> discord.Emb | ||||
|     if 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 | ||||
|     async def get_name(account_id): | ||||
|         account = await client.get_user_info(account_id) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user