mirror of
https://github.com/NoiTheCat/WorldTime.git
synced 2024-11-23 17:04:12 +00:00
Change parameterless tz.list
This commit is contained in:
parent
82f956f47a
commit
2db1cd05ac
3 changed files with 53 additions and 103 deletions
97
commands.py
97
commands.py
|
@ -1,12 +1,13 @@
|
|||
# Command handlers
|
||||
# Incoming commands are fully handled by functions defined here.
|
||||
|
||||
from common import BotVersion
|
||||
from common import BotVersion, tzPrint
|
||||
from textwrap import dedent
|
||||
import discord
|
||||
import pytz
|
||||
from datetime import datetime
|
||||
import re
|
||||
import collections
|
||||
|
||||
from userdb import UserDatabase
|
||||
from common import tzlcmap, logPrint
|
||||
|
@ -34,47 +35,6 @@ class WtCommands:
|
|||
|
||||
# ------
|
||||
# Helper methods
|
||||
|
||||
def _tzPrint(self, zone : str):
|
||||
"""
|
||||
Returns a string displaying the current time in the given time zone.
|
||||
String begins with four numbers for sorting purposes and must be trimmed before output.
|
||||
"""
|
||||
now_time = datetime.now(pytz.timezone(zone))
|
||||
return "{:s}● {:s}".format(now_time.strftime("%m%d"), now_time.strftime("%d-%b %H:%M %Z (UTC%z)"))
|
||||
|
||||
def _userResolve(self, 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 " → This text should never appear."
|
||||
|
||||
# Try given entries. For each entry tried, attempt to get their nickname
|
||||
# or username. Failed attempts are anonymized instead of discarded.
|
||||
namesProcessed = 0
|
||||
namesSkipped = 0
|
||||
processedNames = []
|
||||
while namesProcessed < 4 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 " → {0} user{1}.".format(leftovers, "s" if leftovers != 1 else "")
|
||||
result = " → "
|
||||
while len(processedNames) > 0:
|
||||
result += processedNames.pop() + ", "
|
||||
if leftovers != 0:
|
||||
result += "{0} other{1}.".format(leftovers, "s" if leftovers != 1 else "")
|
||||
else:
|
||||
result = result[:-2] + "."
|
||||
return result
|
||||
|
||||
def _userFormat(self, member: discord.Member):
|
||||
"""
|
||||
|
@ -236,26 +196,33 @@ class WtCommands:
|
|||
# Supplemental command functions
|
||||
|
||||
async def _list_noparam(self, guild: discord.Guild, channel: discord.TextChannel):
|
||||
rawlist = self.userdb.get_list2(guild.id)
|
||||
if len(rawlist) == 0:
|
||||
userlist = self.userdb.get_users(guild.id)
|
||||
if len(userlist) == 0:
|
||||
await channel.send(':x: No users with registered time zones have been active in the last 30 days.')
|
||||
return
|
||||
if guild.large:
|
||||
# Get full user data here if not available (used by _userResolve)
|
||||
await self.dclient.request_offline_members(guild)
|
||||
resultData = []
|
||||
for key, value in rawlist.items():
|
||||
resultData.append(self._tzPrint(key) + '\n' + self._userResolve(guild, value))
|
||||
resultData.sort()
|
||||
resultFinal = '```\n'
|
||||
for i in resultData:
|
||||
resultFinal += i + '\n'
|
||||
resultFinal += '```'
|
||||
await channel.send(resultFinal)
|
||||
|
||||
orderedList = collections.OrderedDict(sorted(userlist.items()))
|
||||
result = ''
|
||||
|
||||
for k, v in orderedList.items():
|
||||
foundUsers = 0
|
||||
line = k[4:] + ": "
|
||||
for id in v:
|
||||
member = await self._resolve_member(guild, id)
|
||||
if member is None:
|
||||
continue
|
||||
if foundUsers > 10:
|
||||
line += "and others... "
|
||||
foundUsers += 1
|
||||
line += self._userFormat(member) + ", "
|
||||
if foundUsers > 0: result += line[:-2] + "\n"
|
||||
|
||||
em = discord.Embed(description=result.strip())
|
||||
await channel.send(embed=em)
|
||||
|
||||
async def _list_userparam(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, param):
|
||||
param = str(param)
|
||||
usersearch = self._resolve_member(guild, param)
|
||||
usersearch = await self._resolve_member(guild, param)
|
||||
if usersearch is None:
|
||||
await channel.send(':x: Cannot find the specified user.')
|
||||
return
|
||||
|
@ -266,23 +233,23 @@ class WtCommands:
|
|||
if ownsearch: await channel.send(':x: You do not have a time zone. Set it with `tz.set`.')
|
||||
else: await channel.send(':x: The given user does not have a time zone set.')
|
||||
return
|
||||
em = discord.Embed(description=self._tzPrint(res)[4:] + ": " + self._userFormat(usersearch))
|
||||
em = discord.Embed(description=tzPrint(res)[4:] + ": " + self._userFormat(usersearch))
|
||||
await channel.send(embed=em)
|
||||
|
||||
def _resolve_member(self, guild: discord.Guild, inputstr: str):
|
||||
async def _resolve_member(self, guild: discord.Guild, inputstr: str):
|
||||
"""
|
||||
Takes a string input and attempts to find the corresponding member.
|
||||
"""
|
||||
await self.dclient.request_offline_members(guild)
|
||||
idsearch = None
|
||||
try:
|
||||
idsearch = int(inputstr)
|
||||
except ValueError:
|
||||
pass
|
||||
if inputstr.startswith('<@!') and inputstr.endswith('>'):
|
||||
idsearch = int(inputstr[3:][:-1])
|
||||
elif inputstr.startswith('<@') and inputstr.endswith('>'):
|
||||
idsearch = int(inputstr[2:][:-1])
|
||||
|
||||
if inputstr.startswith('<@!') and inputstr.endswith('>'):
|
||||
idsearch = int(inputstr[3:][:-1])
|
||||
elif inputstr.startswith('<@') and inputstr.endswith('>'):
|
||||
idsearch = int(inputstr[2:][:-1])
|
||||
|
||||
if idsearch is not None:
|
||||
return guild.get_member(idsearch)
|
||||
|
||||
|
|
12
common.py
12
common.py
|
@ -4,7 +4,7 @@ import pytz
|
|||
from datetime import datetime
|
||||
|
||||
# Bot's current version (as a string), for use in the help command
|
||||
BotVersion = "1.2.1"
|
||||
BotVersion = "1.3.0"
|
||||
|
||||
# For case-insensitive time zone lookup, map lowercase tzdata entries with
|
||||
# entires with proper case. pytz is case sensitive.
|
||||
|
@ -15,4 +15,12 @@ def logPrint(label, line):
|
|||
Print with timestamp in a way that resembles some of my other projects
|
||||
"""
|
||||
resultstr = datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S') + ' [' + label + '] ' + line
|
||||
print(resultstr)
|
||||
print(resultstr)
|
||||
|
||||
def tzPrint(zone : str):
|
||||
"""
|
||||
Returns a string displaying the current time in the given time zone.
|
||||
String begins with four numbers for sorting purposes and must be trimmed before output.
|
||||
"""
|
||||
now_time = datetime.now(pytz.timezone(zone))
|
||||
return "{:s}● {:s}".format(now_time.strftime("%m%d"), now_time.strftime("%d-%b %H:%M %Z (UTC%z)"))
|
47
userdb.py
47
userdb.py
|
@ -1,6 +1,7 @@
|
|||
# User database abstractions
|
||||
|
||||
import psycopg2
|
||||
from common import tzPrint
|
||||
|
||||
class UserDatabase:
|
||||
def __init__(self, connstr):
|
||||
|
@ -63,7 +64,7 @@ class UserDatabase:
|
|||
|
||||
def get_user(self, serverid, userid):
|
||||
'''
|
||||
Retrieves the time zone name of a single user
|
||||
Retrieves the time zone name of a single user.
|
||||
'''
|
||||
c = self.db.cursor()
|
||||
c.execute("""
|
||||
|
@ -75,36 +76,12 @@ class UserDatabase:
|
|||
if result is None: return None
|
||||
return result[0]
|
||||
|
||||
|
||||
def get_list(self, serverid, userid=None):
|
||||
'''
|
||||
Retrieves a list of recent time zones based on
|
||||
recent activity per user. For use in the list command.
|
||||
'''
|
||||
c = self.db.cursor()
|
||||
if userid is None:
|
||||
c.execute("""
|
||||
SELECT zone, count(*) as ct FROM userdata
|
||||
WHERE guild_id = %s
|
||||
AND last_active >= now() - INTERVAL '30 DAYS' -- only users active in the last 30 days
|
||||
GROUP BY zone -- separate by popularity
|
||||
ORDER BY ct DESC LIMIT 20 -- top 20 zones are given
|
||||
""", (serverid))
|
||||
else:
|
||||
c.execute("""
|
||||
SELECT zone, '0' as ct FROM userdata
|
||||
WHERE guild_id = %s AND user_id = %s
|
||||
""", (serverid, userid))
|
||||
|
||||
results = c.fetchall()
|
||||
c.close()
|
||||
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.
|
||||
'''
|
||||
def get_users(self, serverid):
|
||||
"""
|
||||
Retrieves all user time zones for all recently active members.
|
||||
Users not present are not filtered here. Must be handled by the caller.
|
||||
Returns a dictionary of lists - Key is formatted zone, value is list of users represented.
|
||||
"""
|
||||
c = self.db.cursor()
|
||||
c.execute("""
|
||||
SELECT zone, user_id
|
||||
|
@ -125,11 +102,9 @@ class UserDatabase:
|
|||
""", {'guild': 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])
|
||||
resultrow = tzPrint(row[0])
|
||||
result[resultrow] = result.get(resultrow, list())
|
||||
result[resultrow].append(row[1])
|
||||
c.close()
|
||||
return result
|
||||
|
||||
|
|
Loading…
Reference in a new issue