Display small list of users in list

This commit is contained in:
Noikoio 2018-08-28 11:17:22 -07:00
parent 0180dee93a
commit d06c3eb346
3 changed files with 102 additions and 21 deletions

View file

@ -4,13 +4,59 @@
from textwrap import dedent from textwrap import dedent
import discord import discord
import pytz
from datetime import datetime
from userdb import UserDatabase from userdb import UserDatabase
from common import tzlcmap, tzPrint, logPrint from common import tzlcmap, logPrint
# All command functions are expected to have this signature: # All command functions are expected to have this signature:
# def cmd_NAME(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str) # def cmd_NAME(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str)
def _tzPrint(zone : str):
"""
Returns a string displaying the current time in the given time zone.
Resulting string should be placed in a code block.
"""
padding = ''
now_time = datetime.now(pytz.timezone(zone))
if len(now_time.strftime("%Z")) != 4: padding = ' '
return "{:s}{:s} | {:s}".format(now_time.strftime("%H:%M %d-%b %Z%z"), padding, zone)
def _userResolve(guild: discord.Guild, userIds: list):
"""
Given a list with user IDs, returns a string, the second half of a
list entry, describing the users for which a zone is represented by.
"""
if len(userIds) == 0:
return " -- Representing 0 users. Bug?"
# Try given entries. For each entry tried, attempt to get their nickname
# or username. Failed attempts are anonymized instead of discarded.
# Attempt at most three entries.
namesProcessed = 0
namesSkipped = 0
processedNames = []
while namesProcessed < 3 and len(userIds) > 0:
namesProcessed += 1
uid = userIds.pop()
mem = guild.get_member(int(uid))
if mem is not None:
processedNames.append(mem.display_name)
else:
namesSkipped += 1
leftovers = namesSkipped + len(userIds)
if len(processedNames) == 0:
return " -- Representing {0} user{1}.".format(leftovers, "s" if leftovers != 1 else "")
result = " -- Representing "
while len(processedNames) > 0:
result += processedNames.pop() + ", "
if leftovers != 0:
result += "{0} other user{1}.".format(leftovers, "s" if leftovers != 1 else "")
else:
result = result[:-2] + "."
return result
class WtCommands: class WtCommands:
def __init__(self, userdb: UserDatabase, client: discord.Client): def __init__(self, userdb: UserDatabase, client: discord.Client):
self.userdb = userdb self.userdb = userdb
@ -31,9 +77,6 @@ class WtCommands:
logPrint('Command invoked', '{0}/{1}: tz.{2}'.format(message.guild, message.author, cmdBase)) logPrint('Command invoked', '{0}/{1}: tz.{2}'.format(message.guild, message.author, cmdBase))
await command(message.guild, message.channel, message.author, message.content) await command(message.guild, message.channel, message.author, message.content)
# ------
# Helper functions
# ------ # ------
# Individual command handlers # Individual command handlers
@ -68,7 +111,7 @@ class WtCommands:
except KeyError: except KeyError:
await channel.send(':x: Not a valid zone name.') await channel.send(':x: Not a valid zone name.')
return return
resultstr = '```\n' + tzPrint(zoneinput) + '\n```' resultstr = '```\n' + _tzPrint(zoneinput) + '\n```'
await channel.send(resultstr) await channel.send(resultstr)
async def cmd_set(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str): async def cmd_set(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
@ -88,7 +131,7 @@ class WtCommands:
async def cmd_list(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str): async def cmd_list(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
wspl = msgcontent.split(' ', 1) wspl = msgcontent.split(' ', 1)
if len(wspl) == 1: if len(wspl) == 1:
await self._list_noparam(guild, channel) await self._list_noparam2(guild, channel)
else: else:
await self._list_userparam(guild, channel, author, wspl[1]) await self._list_userparam(guild, channel, author, wspl[1])
@ -101,13 +144,14 @@ class WtCommands:
# Supplemental command functions # Supplemental command functions
async def _list_noparam(self, guild: discord.Guild, channel: discord.TextChannel): async def _list_noparam(self, guild: discord.Guild, channel: discord.TextChannel):
# To do: improve and merge into noparam2
clist = self.userdb.get_list(guild.id) clist = self.userdb.get_list(guild.id)
if len(clist) == 0: if len(clist) == 0:
await channel.send(':x: No users with known zones have been active in the last 72 hours.') await channel.send(':x: No users with known zones have been active in the last 72 hours.')
return return
resultarr = [] resultarr = []
for i in clist: for i in clist:
resultarr.append(tzPrint(i)) resultarr.append(_tzPrint(i))
resultarr.sort() resultarr.sort()
resultstr = '```\n' resultstr = '```\n'
for i in resultarr: for i in resultarr:
@ -115,6 +159,22 @@ class WtCommands:
resultstr += '```' resultstr += '```'
await channel.send(resultstr) await channel.send(resultstr)
async def _list_noparam2(self, guild: discord.Guild, channel: discord.TextChannel):
rawlist = self.userdb.get_list2(guild.id)
if len(rawlist) == 0:
await channel.send(':x: No users with known zones have been active in the last 72 hours.')
return
resultData = []
for key, value in rawlist.items():
resultData.append(_tzPrint(key) + '\n' + _userResolve(guild, value))
resultData.sort()
resultFinal = '```\n'
for i in resultData:
resultFinal += i + '\n'
resultFinal += '```'
await channel.send(resultFinal)
async def _list_userparam(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, param): async def _list_userparam(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, param):
# wishlist: search based on username/nickname # wishlist: search based on username/nickname
param = str(param) param = str(param)
@ -132,5 +192,5 @@ class WtCommands:
if spaghetti: await channel.send(':x: You do not have a time zone. Set it with `tz.set`.') if spaghetti: await channel.send(':x: You do not have a time zone. Set it with `tz.set`.')
else: await channel.send(':x: The given user has not set a time zone. Ask to set it with `tz.set`.') else: await channel.send(':x: The given user has not set a time zone. Ask to set it with `tz.set`.')
return return
resultstr = '```\n' + tzPrint(res[0]) + '\n```' resultstr = '```\n' + _tzPrint(res[0]) + '\n```'
await channel.send(resultstr) await channel.send(resultstr)

View file

@ -7,17 +7,6 @@ from datetime import datetime
# entires with proper case. pytz is case sensitive. # entires with proper case. pytz is case sensitive.
tzlcmap = {x.lower():x for x in pytz.common_timezones} tzlcmap = {x.lower():x for x in pytz.common_timezones}
timefmt = "%H:%M %d-%b %Z%z"
def tzPrint(zone : str):
"""
Returns a string displaying the current time in the given time zone.
Resulting string should be placed in a code block.
"""
padding = ''
now_time = datetime.now(pytz.timezone(zone))
if len(now_time.strftime("%Z")) != 4: padding = ' '
return "{:s}{:s} | {:s}".format(now_time.strftime(timefmt), padding, zone)
def logPrint(label, line): def logPrint(label, line):
""" """
Print with timestamp in a way that resembles some of my other projects Print with timestamp in a way that resembles some of my other projects

View file

@ -1,4 +1,4 @@
# Abstracts away details of the SQLite database that stores user information. # User database abstractions
import sqlite3 import sqlite3
@ -78,3 +78,35 @@ class UserDatabase:
results = c.fetchall() results = c.fetchall()
c.close() c.close()
return [i[0] for i in results] return [i[0] for i in results]
def get_list2(self, serverid):
'''
Retrieves data for the tz.list command.
Returns a dictionary. Keys are zone name, values are arrays with user IDs.
'''
c = self.db.cursor()
c.execute('''
SELECT zone, user
FROM users
WHERE
lastactive >= strftime('%s','now') - (72 * 60 * 60) -- only users active in the last 72 hrs
AND guild = '{0}'
AND zone in (SELECT zone from (
SELECT zone, count(*) as ct
FROM users
WHERE
guild = '{0}'
AND lastactive >= strftime('%s','now') - (72 * 60 * 60)
GROUP BY zone
LIMIT 10
))
ORDER BY RANDOM() -- Randomize display order (done by consumer)
'''.format(serverid))
result = {}
for row in c:
inlist = result.get(row[0])
if inlist is None:
result[row[0]] = []
inlist = result[row[0]]
inlist.append(row[1])
return result