WorldTime/commands.py

136 lines
5.8 KiB
Python
Raw Normal View History

# Command handlers
# Incoming messages that look like commands are passed into functions defined here.
from textwrap import dedent
import discord
from userdb import UserDatabase
from common import tzlcmap, tzPrint, logPrint
# All command functions are expected to have this signature:
# def cmd_NAME(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str)
class WtCommands:
def __init__(self, userdb: UserDatabase, client: discord.Client):
self.userdb = userdb
self.dclient = client
self.commandlist = {
'help' : self.cmd_help,
'list' : self.cmd_list,
'time' : self.cmd_time,
'set' : self.cmd_set,
'remove': self.cmd_remove
}
async def dispatch(self, cmdBase: str, message: discord.Message):
try:
command = self.commandlist[cmdBase]
except KeyError:
return
logPrint('Command invoked', '{0}/{1}: tz.{2}'.format(message.guild, message.author, cmdBase))
await command(message.guild, message.channel, message.author, message.content)
# ------
# Helper functions
# ------
# Individual command handlers
async def cmd_help(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
em = discord.Embed(
color=14742263,
title='Help & About',
description='This bot aims to answer the age-old question, "What time is it for everyone here?"')
em.set_footer(text='World Time', icon_url=self.dclient.user.avatar_url)
em.add_field(name='Commands', value=dedent('''
`tz.help` - This message.
`tz.list` - Displays current times for all recently active known users.
`tz.list [user]` - Displays the current time for the given *user*.
`tz.time` - Displays the current time in your time zone.
`tz.time [zone]` - Displays the current time in the given *zone*.
`tz.set [zone]` - Registers or updates your *zone* with the bot.
`tz.remove` - Removes your name from this bot.
'''))
em.add_field(name='Zones', value=dedent('''
This bot uses zone names from the tz database. Most common zones are supported. For a list of entries, see: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
'''))
await channel.send(embed=em)
async def cmd_time(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
wspl = msgcontent.split(' ', 1)
if len(wspl) == 1:
# No parameter. So, doing the same thing anyway...
await self._list_userparam(guild, channel, author, author.id)
else:
try:
zoneinput = tzlcmap[wspl[1].lower()]
except KeyError:
await channel.send(':x: Not a valid zone name.')
return
resultstr = '```\n' + tzPrint(zoneinput) + '\n```'
await channel.send(resultstr)
async def cmd_set(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
wspl = msgcontent.split(' ', 1)
if len(wspl) == 1:
# No parameter. But it's required
await channel.send(':x: Zone parameter is required.')
return
try:
zoneinput = tzlcmap[wspl[1].lower()]
except KeyError:
await channel.send(':x: Not a valid zone name.')
return
self.userdb.update_user(guild.id, author.id, zoneinput)
await channel.send(':white_check_mark: Your zone has been set.')
async def cmd_list(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
wspl = msgcontent.split(' ', 1)
if len(wspl) == 1:
await self._list_noparam(guild, channel)
else:
await self._list_userparam(guild, channel, author, wspl[1])
async def cmd_remove(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, msgcontent: str):
# To do: Check if there even is data to remove; react accordingly
self.userdb.delete_user(guild.id, author.id)
await channel.send(':white_check_mark: Your zone has been removed.')
# ------
# Supplemental command functions
async def _list_noparam(self, guild: discord.Guild, channel: discord.TextChannel):
clist = self.userdb.get_list(guild.id)
if len(clist) == 0:
await channel.send(':x: No users with known zones have been active in the last 72 hours.')
return
resultarr = []
for i in clist:
resultarr.append(tzPrint(i))
resultarr.sort()
resultstr = '```\n'
for i in resultarr:
resultstr += i + '\n'
resultstr += '```'
await channel.send(resultstr)
async def _list_userparam(self, guild: discord.Guild, channel: discord.TextChannel, author: discord.User, param):
# wishlist: search based on username/nickname
param = str(param)
if param.startswith('<@!') and param.endswith('>'):
param = param[3:][:-1]
if param.startswith('<@') and param.endswith('>'):
param = param[2:][:-1]
if not param.isnumeric():
# Didn't get an ID...
await channel.send(':x: You must specify a user by ID or `@` mention.')
return
res = self.userdb.get_list(guild.id, param)
if len(res) == 0:
spaghetti = author.id == param
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`.')
return
resultstr = '```\n' + tzPrint(res[0]) + '\n```'
await channel.send(resultstr)