Skip to content

Commit

Permalink
VERSION 1.0.0 - Move Bang Commands To Command Dispatcher (#193)
Browse files Browse the repository at this point in the history
* move the remaining ! commands (which are admin-only) to commands dispatcher

* use generate_local_channel_list for in-memory store rather than file

* version bump to 1.0.0 baybeeee

Co-authored-by: jp00p <asimovsghost@gmail.com>
  • Loading branch information
zmattingly and jp00p committed Jul 21, 2022
1 parent 5d350e3 commit faf0f9f
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 97 deletions.
4 changes: 2 additions & 2 deletions charts/agimus/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: agimus
description: A helm chart for a discord bot that also runs a mysql db
type: application
version: v0.2.30
appVersion: v0.2.30
version: v1.0.0
appVersion: v1.0.0
9 changes: 0 additions & 9 deletions cogs/ping.py

This file was deleted.

11 changes: 7 additions & 4 deletions commands/clear_media.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from common import *

import os
from glob import glob
from pathlib import Path

from common import *
from utils.check_channel_access import access_check

# Path to base bot directory
base_path = Path(__file__).parent.parent

Expand All @@ -12,7 +13,9 @@
# This function is the main entrypoint of the !clear_media command
# This will remove all .mp4 files from the data/clips and data/drops directories
# and allow the bot to re-load them as needed. Useful for debugging.
async def clear_media(message:discord.Message):
@bot.command()
@commands.check(access_check)
async def clear_media(ctx):
drop_files = glob(os.path.join(base_path, 'data/drops/', '*.mp4'))
clip_files = glob(os.path.join(base_path, 'data/clips/', '*.mp4'))

Expand All @@ -36,6 +39,6 @@ async def clear_media(message:discord.Message):
color=discord.Color.green()
)

await message.channel.send(embed=embed)
await ctx.send(embed=embed)


9 changes: 6 additions & 3 deletions commands/ping.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from common import *
from utils.check_channel_access import access_check

# ping() - Entrypoint for !ping command
# message[required]: discord.Message
# ctx[required]: discord.Context
# This function is the main entrypoint of the !ping command
# and will return the client's latency value in milliseconds
async def ping(message:discord.Message):
@bot.command()
@commands.check(access_check)
async def ping(ctx):
logger.info(f"{Fore.LIGHTYELLOW_EX}{Style.BRIGHT}Ping pong!{Style.RESET_ALL}{Fore.RESET}")
await message.channel.send("Pong! {}ms".format(round(bot.latency * 1000)))
await ctx.send("Pong! {}ms".format(round(bot.latency * 1000)))

41 changes: 23 additions & 18 deletions commands/q.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,53 @@
from common import *
from utils.check_channel_access import access_check

# qget() - Entrypoint for !qget command
# message[required]: discord.Message
# This function is the main entrypoint of the !qget command
# and will get a user's
async def qget(message:discord.Message):
selected_user = message.content.lower().replace("!qget ", "").replace("<@", "").replace(">","")
# and will get a user's DB details
@bot.command()
@commands.check(access_check)
async def qget(ctx, user:str):
selected_user = user.replace("<@", "").replace(">","")
if is_integer(selected_user):
await display_user(selected_user, message)
await display_user(selected_user, ctx)
else:
await message.channel.send("Usage: !qget [user]")
await ctx.send("Usage: !qget [user]")


# qset() - Entrypoint for !qset command
# message[required]: discord.Message
# This function is the main entrypoint of the !qset command
# and will get a user's
async def qset(message:discord.Message):
# and will set a user's DB details
@bot.command()
@commands.check(access_check)
async def qset(ctx, user:str, key:str, value:str):
f = open(config["commands"]["qget"]["data"])
f.close()
qspl = message.content.lower().replace("!qset ", "").split()
selected_user = qspl[0].replace("<@", "").replace(">","")
change_column = qspl[1]
change_value = qspl[2]
# qspl = message.content.lower().replace("!qset ", "").split()
selected_user = user.replace("<@", "").replace(">","")
change_column = key
change_value = value
this_user = get_user(selected_user)
modifiable_ints = ["score", "spins", "jackpots", "wager", "high_roller", "chips", "xp"]
modifiable_strings = ["profile_card", "profile_badge"]
logger.info(f"{Fore.LIGHTBLUE_EX}{message.author.display_name}{Fore.RESET} is using mysterious Q powers on {Fore.GREEN}{this_user['name']}{Fore.RESET}")
logger.info(f"{Fore.LIGHTBLUE_EX}{ctx.author.display_name}{Fore.RESET} is using mysterious Q powers on {Fore.GREEN}{this_user['name']}{Fore.RESET}")

if change_column not in modifiable_ints and change_column not in modifiable_strings:
await message.channel.send("Can only modify these values:```"+tabulate(modifiable_ints, headers="firstrow")+"``````"+tabulate(modifiable_strings, headers="firstrow")+"```")
await ctx.send("Can only modify these values:```"+tabulate(modifiable_ints, headers="firstrow")+"``````"+tabulate(modifiable_strings, headers="firstrow")+"```")
else:
if change_column in modifiable_ints:
if not is_integer(change_value):
await message.reply(f"`{change_value}` is not an integer!")
await ctx.reply(f"`{change_value}` is not an integer!")
return
else:
update_user(selected_user, change_column, change_value)
elif change_column in modifiable_strings:
update_user(selected_user, change_column, change_value)
await display_user(selected_user, message)
await display_user(selected_user, ctx)


async def display_user(user_id:discord.User, message:discord.Message):
async def display_user(user_id, ctx):
f = open(config["commands"]["qget"]["data"])
user_columns = json.load(f)
f.close()
Expand All @@ -60,6 +65,6 @@ async def display_user(user_id:discord.User, message:discord.Message):
name=header,
value=user_data[header]
)
member_info = await message.guild.fetch_member(user_id)
member_info = await ctx.guild.fetch_member(user_id)
embed.set_footer(text=f"User Joined: {member_info.joined_at.strftime('%A, %b %-d %Y - %I:%M %p')}; Top Role: {member_info.top_role.name}")
await message.channel.send(embed=embed)
await ctx.send(embed=embed)
20 changes: 11 additions & 9 deletions commands/update_status.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from common import *

from utils.check_channel_access import access_check

# change_presence functions
async def game_func(name):
Expand Down Expand Up @@ -31,23 +31,25 @@ async def watch_func(name):
# * listening
# * watching
# The remainder of the message will be used for the status text
async def update_status(message:discord.Message):
logger.info(f"{Fore.LIGHTGREEN_EX}Updating Status! Requested by {Style.BRIGHT}{message.author.display_name}{Fore.RESET}")
argument_list = message.content.lower().replace("!update_status ", "").split()
@bot.command()
@commands.check(access_check)
async def update_status(ctx, *, arg):
logger.info(f"{Fore.LIGHTGREEN_EX}Updating Status! Requested by {Style.BRIGHT}{ctx.author.display_name}{Fore.RESET}")
argument_list = arg.split()

if len(argument_list) < 2:
await message.reply(embed=discord.Embed(
await ctx.reply(embed=discord.Embed(
title="Usage:",
description="`!update_status [game|watch|listen] <status>`",
description="`!update_status [playing|listening|watching] <status>`",
color=discord.Color.blue()
))
return
else:
type = argument_list[0]
status = message.content.replace(f"!update_status {type} ", "")
status = ctx.message.content.replace(f"!update_status {type} ", "")

if type not in ['playing', 'listening', 'watching']:
await message.reply(embed=discord.Embed(
await ctx.reply(embed=discord.Embed(
title="Invalid <type> Provided",
description="Must provide one of: `playing`, `listening`, or `watching`",
color=discord.Color.red()
Expand All @@ -56,7 +58,7 @@ async def update_status(message:discord.Message):
return

await change_presence_funcs[type](status)
await message.reply(embed=discord.Embed(
await ctx.reply(embed=discord.Embed(
title="Status Updated Successfully!",
color=discord.Color.green()
))
Expand Down
17 changes: 7 additions & 10 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from tabulate import tabulate
from treys import Card, Deck, Evaluator, evaluator

from utils.config_utils import get_config
from utils.config_utils import get_config, deep_dict_update
from utils.disco_lights import LightHandler


Expand Down Expand Up @@ -81,7 +81,7 @@
intents=intents,
test_guilds=config["guild_ids"],
auto_sync_commands=True,
command_prefix="$"
command_prefix="!"
)

# Channel Helpers
Expand Down Expand Up @@ -322,7 +322,7 @@ def increase_jackpot(amt):

# generate_local_channel_list(client)
# client[required]: discord.Bot
# run this if you need a nice json list of channel names + ids for your config file
# This runs to apply the local channel list on top of the existing channel config
def generate_local_channel_list(client):
if client.guilds[0]:
channels = client.guilds[0].channels
Expand All @@ -331,13 +331,10 @@ def generate_local_channel_list(client):
if channel.type == discord.ChannelType.text:
channel_name = channel.name.encode("ascii", errors="ignore").decode().strip()
channel_list[channel_name] = channel.id
channel_list_json = json.dumps(channel_list, indent=2, sort_keys=True)
try:
with open('./local-channel-list.json', 'w') as f:
f.write(channel_list_json)
logger.info(f"{Style.BRIGHT}Local channel list has been written to {Fore.GREEN}./local-channel-list.json{Fore.RESET}{Style.RESET_ALL}")
except FileNotFoundError as e:
logger.info(f"{Fore.RED}Unable to create local channel list file:{Fore.RESET} {e}")
# channel_list_json = json.dumps(channel_list, indent=2, sort_keys=True)
updated_channel_list = deep_dict_update({ "channels": config['channels'] }, { "channels" : channel_list })

config["channels"] = updated_channel_list["channels"]

# get_emoji(emoji_name)
# emoji_name[required]: str
Expand Down
9 changes: 7 additions & 2 deletions configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@
"parameters": []
},
"ping": {
"channels": [],
"channels": [
"robot-diagnostics"
],
"enabled": true,
"data": null,
"parameters": []
Expand Down Expand Up @@ -295,14 +297,17 @@
},
"qget": {
"channels": [
"robot-diagnostics",
"mclaughlin-group"
],
"enabled": true,
"data": "data/user-info.json",
"parameters": []
},
"qset": {
"channels": [],
"channels": [
"robot-diagnostics"
],
"enabled": true,
"data": null,
"parameters": []
Expand Down
14 changes: 7 additions & 7 deletions data/help/convo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
A place to generate conversation prompts!

**COMMANDS**
`!tuvix` - create your own Tuvix
`!dustbuster` - beam em down, let god sort em out
`!randomep [trek|nontrek|any|tos|tas|tng|ds9|voy|enterprise|lowerdecks|disco|picard|friends|firefly|simpsons|sunny]` - pick a random episode from all trek everywhere
`!trektalk` - generate a conversation piece
`!trekduel` - who will win?
`!fmk` - you know the deal
`/tuvix` - create your own Tuvix
`/dustbuster` - beam em down, let god sort em out
`/randomep [trek|nontrek|any|tos|tas|tng|ds9|voy|enterprise|lowerdecks|disco|picard|friends|firefly|simpsons|sunny]` - pick a random episode from all trek everywhere
`/trektalk` - generate a conversation piece
`/trekduel` - who will win?
`/fmk` - you know the deal
`/profile` - see your profile card
`!info [tng|voy|ds9|friends|firefly|simpsons|enterprise|tos|lowerdecks|disco|picard|tas|sunny] [s##e##]` - Get information about a specific episode!
`/info [tng|voy|ds9|friends|firefly|simpsons|enterprise|tos|lowerdecks|disco|picard|tas|sunny] [s##e##]` - Get information about a specific episode!
2 changes: 1 addition & 1 deletion data/help/slots.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ You need to match three Star Trek characters/ships to win the jackpot!
`/slots jackpots` - see a history of jackpots
`/profile` - see your profile card
`/setwager [1-25]` - set your default wager
`!scores` - see the top scores
`/scores` - see the top scores
31 changes: 18 additions & 13 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,11 @@
from cogs.trivia import Trivia
from cogs.shop import Shop
from cogs.slots import Slots
from cogs.ping import Ping
from cogs.poker import Poker
from cogs.quiz import Quiz
bot.add_cog(Trivia(bot))
bot.add_cog(Shop(bot))
bot.add_cog(Slots(bot))
bot.add_cog(Ping(bot))
bot.add_cog(Poker(bot))
bot.add_cog(Quiz(bot))

Expand Down Expand Up @@ -83,6 +81,7 @@ async def on_message(message:discord.Message):
return

try:
# Process commands that use the command_prefix
await bot.process_commands(message)
except BaseException as e:
logger.info(f"{Fore.RED}<! ERROR: Encountered error in process_commands !> {e}{Fore.RESET}")
Expand Down Expand Up @@ -114,9 +113,8 @@ async def on_message(message:discord.Message):
logger.error(f"{Fore.RED}<! ERROR: Failed to process message for xp !> {e}{Fore.RESET}")
logger.error(traceback.format_exc())

# Bang Command Handling
#logger.debug(message)
if message.content.startswith("!") or any(message.content.lower().startswith(x) for x in ["computer:", "agimus:"]):
# Computer/AGIMUS Message Handling
if any(message.content.lower().startswith(x) for x in ["computer:", "agimus:"]):
logger.info(f"Attempting to process {Fore.CYAN}{message.author.display_name}{Fore.RESET}'s command: {Style.BRIGHT}{Fore.LIGHTGREEN_EX}{message.content}{Fore.RESET}{Style.RESET_ALL}")
try:
await process_command(message)
Expand All @@ -132,11 +130,7 @@ async def on_message(message:discord.Message):
await logging_channel.send(embed=exception_embed)

async def process_command(message:discord.Message):
# Split the user's command by space and remove "!"
split_string = message.content.lower().split(" ")
if message.content.startswith("!"):
user_command = split_string[0].replace("!","")
elif message.content.lower().startswith("agimus:"):
if message.content.lower().startswith("agimus:"):
user_command = "agimus"
elif message.content.lower().startswith("computer:"):
user_command = "computer"
Expand Down Expand Up @@ -250,10 +244,21 @@ async def on_application_command(ctx):
ALL_USERS.append(register_player(ctx.author))

@bot.event
async def on_application_command_error(ctx, exception):
async def on_application_command_error(ctx, error):
logger.error(f"{Fore.RED}Error encountered in slash command: /{ctx.command}")
logger.info(traceback.format_exc())
logger.exception(exception)
logger.info(traceback.print_exception(type(error), error, error.__traceback__))

# listen to context (!) command events
@bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.errors.CheckFailure):
# We don't care about check errors,
# it means the check is succeeding in blocking access
pass
else:
logger.error(f"{Fore.RED}Error encountered in ! command: !{ctx.command}")
logger.info(traceback.print_exception(type(error), error, error.__traceback__))


# Schedule Tasks
scheduled_tasks = [
Expand Down
Loading

0 comments on commit faf0f9f

Please sign in to comment.