From 5541a7c12813dc394067eedeb4523e2cd2538fab Mon Sep 17 00:00:00 2001 From: Zac Herd Date: Tue, 26 Feb 2019 14:22:57 +0000 Subject: [PATCH] v1.3.0, added .spell command to search for D&D 5e spells --- bot.py | 5 ++++- commands.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ common.py | 5 ++++- helpers.py | 8 ++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 1d95e26..1f03403 100644 --- a/bot.py +++ b/bot.py @@ -44,11 +44,14 @@ def on_ready(): print('User: ' + client.user.name) print('ID: ' + client.user.id) + # populate D&D spells list + for spell in requests.get('http://dnd5eapi.co/api/spells/').json()['results']: + spellslist[spell['name']] = spell['url'] + # set "Now Playing" to print version game = discord.Game(name=version) yield from client.change_presence(game=game) - # called when message received @client.event @asyncio.coroutine diff --git a/commands.py b/commands.py index 590b266..1f3452b 100644 --- a/commands.py +++ b/commands.py @@ -13,6 +13,8 @@ import re import requests import random import subprocess +import itertools +import ftfy # LOCAL IMPORTS from common import * @@ -197,6 +199,52 @@ def cmd_roll(client, msg): @asyncio.coroutine +def cmd_spell(client, msg): + searchterm = msg.content[7:] + + # perform search on user input + results = [] + for result in itertools.islice(search(spellslist, searchterm), 3): + results.append(result) + + # default response is an error + response = "Couldn't find any matching spells!" + + # otherwise, grab spell data and generate response text + if results: + result = requests.get(results[0][1]).json() + + response = "**Spell:** " + result['name'] + if result['concentration'] is "yes": + response += " *(C)*" + response += " " + str(result['components']) + response += "\n\n**Level:** " + str(result['level']) + response += "\n\n**Description:**" + for s in result['desc']: + response += '\n' + s + if 'higher_level' in result: + response += "\n\n**Higher Level:**" + for s in result['higher_level']: + response += '\n' + s + response += "\n\n**Range:** " + result['range'] + response += "\n\n**Casting Time:** " + result['casting_time'] + response += "\n\n**Duration:** " + result['duration'] + + # repair encoding errors from API + response = ftfy.fix_text(response) + + # append next search matches, if any + matches = [] + for k,_ in results[1:]: + matches.append(k) + + if matches: + response += "\n\n*Possible Matches: " + str(matches) + "*" + + yield from discord_send(client, msg, response) + + +@asyncio.coroutine def cmd_qr(client, msg): tmp = msg.content[4:] @@ -358,6 +406,7 @@ commands = { "sayy": cmd_sayy, "markov": cmd_markov, "roll": cmd_roll, + "spell": cmd_spell, "qr": cmd_qr, "np": cmd_np, "steam": cmd_steam, diff --git a/common.py b/common.py index 6c07716..0a656de 100644 --- a/common.py +++ b/common.py @@ -10,7 +10,7 @@ import os import json # bot version -version = "v1.2.3" +version = "v1.3.0" # TODO: generate this on the fly and make it look acceptable # text shown by .help command @@ -27,6 +27,7 @@ My commands are: **.sayy ** | say something a e s t h e t i c a l l y **.markov []** | generate markov chain over chat history for you or another user **.roll d** | roll x number of y sided dice +**.spell ** | search for a D&D spell **.qr ** | generate a QR code **.np []** | fetch now playing from last.fm for you or a specific username **.steam []** | fetch steam status for you or a specific vanityname @@ -43,3 +44,5 @@ if os.path.isfile('hist.json'): # quiet modes quiet = {} + +spellslist = {} diff --git a/helpers.py b/helpers.py index 1f003db..73ecc0f 100644 --- a/helpers.py +++ b/helpers.py @@ -42,6 +42,14 @@ def logger(): logger.addHandler(handler) +# fuzzy search over dictionary +def search(dict, term): + s = term.lower() + + for item in dict.items(): + if s in item[0].lower(): + yield item + # send_message wrapper (deals with Discord's shit API) @asyncio.coroutine def discord_send(client, message, response):