1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

Aggiunto comando dndspell (#50)

This commit is contained in:
Steffo 2019-08-29 02:31:33 +02:00
parent 2bdb6c7729
commit 5a59c09cba
7 changed files with 164 additions and 31 deletions

View file

@ -21,6 +21,7 @@ from .smecds import SmecdsCommand
from .summon import SummonCommand from .summon import SummonCommand
from .videochannel import VideochannelCommand from .videochannel import VideochannelCommand
from .dnditem import DnditemCommand from .dnditem import DnditemCommand
from .dndspell import DndspellCommand
__all__ = [ __all__ = [
"CiaoruoziCommand", "CiaoruoziCommand",
@ -40,5 +41,6 @@ __all__ = [
"SmecdsCommand", "SmecdsCommand",
"SummonCommand", "SummonCommand",
"VideochannelCommand", "VideochannelCommand",
"DnditemCommand" "DnditemCommand",
"DndspellCommand"
] ]

View file

@ -5,6 +5,7 @@ from ..command import Command
from ..commandargs import CommandArgs from ..commandargs import CommandArgs
from ..commanddata import CommandData from ..commanddata import CommandData
from ..commandinterface import CommandInterface from ..commandinterface import CommandInterface
from ...utils import parse_5etools_entry
class DnditemCommand(Command): class DnditemCommand(Command):
@ -36,32 +37,6 @@ class DnditemCommand(Command):
for item in j["baseitem"]: for item in j["baseitem"]:
self._dnddata.add(item) self._dnddata.add(item)
def _parse_entry(self, entry):
if isinstance(entry, str):
return entry
elif isinstance(entry, dict):
string = ""
if entry["type"] == "entries":
string += f'[b]{entry.get("name", "")}[/b]\n'
for subentry in entry["entries"]:
string += self._parse_entry(subentry)
elif entry["type"] == "table":
string += "[i][table hidden][/i]"
# for label in entry["colLabels"]:
# string += f"| {label} "
# string += "|"
# for row in entry["rows"]:
# for column in row:
# string += f"| {self._parse_entry(column)} "
# string += "|\n"
elif entry["type"] == "cell":
return self._parse_entry(entry["entry"])
else:
string += "[i][unknown type][/i]"
else:
return "[/i][unknown data][/i]"
return string
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:
if self._dnddata is None: if self._dnddata is None:
await data.reply("⚠️ Il database degli oggetti di D&D non è ancora stato scaricato.") await data.reply("⚠️ Il database degli oggetti di D&D non è ancora stato scaricato.")
@ -78,6 +53,6 @@ class DnditemCommand(Command):
f'Rarity: [b]{result["rarity"] if result.get("rarity", "None") != "None" else "Mundane"}[/b]\n' \ f'Rarity: [b]{result["rarity"] if result.get("rarity", "None") != "None" else "Mundane"}[/b]\n' \
f'\n' f'\n'
for entry in result.get("entries", []): for entry in result.get("entries", []):
string += self._parse_entry(entry) string += parse_5etools_entry(entry)
string += "\n\n" string += "\n\n"
await data.reply(string) await data.reply(string)

View file

@ -0,0 +1,111 @@
import typing
import aiohttp
import sortedcontainers
from ..command import Command
from ..commandargs import CommandArgs
from ..commanddata import CommandData
from ..commandinterface import CommandInterface
from ...utils import parse_5etools_entry, ordinalformat
class DndspellCommand(Command):
name: str = "dndspell"
description: str = "Ottieni informazioni su una magia di D&D5e."
syntax = "(nomemagia)"
_dnddata: sortedcontainers.SortedKeyList = None
def __init__(self, interface: CommandInterface):
super().__init__(interface)
interface.loop.create_task(self._fetch_dnddata())
async def _fetch_dnddata(self):
self._dnddata = self._dnddata = sortedcontainers.SortedKeyList([], key=lambda i: i["name"].lower())
async with aiohttp.ClientSession() as session:
for url in [
"https://5e.tools/data/spells/spells-ai.json",
"https://5e.tools/data/spells/spells-ggr.json",
"https://5e.tools/data/spells/spells-llk.json",
"https://5e.tools/data/spells/spells-phb.json",
"https://5e.tools/data/spells/spells-scag.json",
"https://5e.tools/data/spells/spells-stream.json",
"https://5e.tools/data/spells/spells-ua-ar.json",
"https://5e.tools/data/spells/spells-ua-mm.json",
"https://5e.tools/data/spells/spells-ua-ss.json",
"https://5e.tools/data/spells/spells-ua-tobm.json",
"https://5e.tools/data/spells/spells-xge.json"
]:
async with session.get(url) as response:
j = await response.json()
for spell in j["spell"]:
self._dnddata.add(spell)
def _parse_spell(self, spell: dict) -> str:
string = f'✨ [b]{spell["name"]}[/b]\n'
if "source" in spell:
string += f'[i]{spell["source"]}, page {spell["page"]}[/i]\n'
string += "\n"
if spell["level"] == 0:
string += f'[b]Cantrip[/b] {spell["school"]}\n'
else:
string += f'[b]{ordinalformat(spell["level"])}[/b] level {spell["school"]}\n'
if "time" in spell:
for time in spell["time"]:
string += f'Cast time: ⌛️ [b]{time["number"]} {time["unit"]}[/b]\n'
if "range" in spell:
if spell["range"]["distance"]["type"] == "touch":
string += "Range: 👉 [b]Touch[/b]\n"
elif spell["range"]["distance"]["type"] == "self":
string += "Range: 👤 [b]Self[/b]\n"
else:
string += f'Range: 🏹 [b]{spell["range"]["distance"]["amount"]} {spell["range"]["distance"]["type"]}[/b] ({spell["range"]["type"]})\n'
if "components" in spell:
string += f'Components: '
if spell["components"].get("v", False):
string += "👄 [b]Verbal[/b] | "
if spell["components"].get("s", False):
string += "🤙 [b]Somatic[/b] | "
if spell["components"].get("r", False):
# TODO: wtf is this
string += "❓ [b]R...?[/b] | "
if spell["components"].get("m", False):
if "text" in spell["components"]["m"]:
string += f'💎 [b]Material[/b] ([i]{spell["components"]["m"]["text"]}[/i]) | '
else:
string += f'💎 [b]Material[/b] ([i]{spell["components"]["m"]}[/i]) | '
string += "\n"
string += "\n"
if "duration" in spell:
for duration in spell["duration"]:
if duration["type"] == "timed":
string += f'Duration: 🕒 [b]{duration["duration"]["amount"]} {duration["duration"]["type"]}[/b]'
elif duration["type"] == "instant":
string += 'Duration: ☁️ [b]Instantaneous[/b]'
elif duration["type"] == "special":
string += 'Duration: ⭐️ [b]Special[/b]'
else:
string += f'Duration: ⚠️[b]UNKNOWN[/b]'
if duration.get("concentration", False):
string += " (requires concentration)"
string += "\n"
if "meta" in spell:
if spell["meta"].get("ritual", False):
string += "Can be casted as ritual\n"
string += "\n"
for entry in spell.get("entries", []):
string += parse_5etools_entry(entry)
string += "\n\n"
for entry in spell.get("entriesHigherLevel", []):
string += parse_5etools_entry(entry)
string += "\n\n"
return string
async def run(self, args: CommandArgs, data: CommandData) -> None:
if self._dnddata is None:
await data.reply("⚠️ Il database degli oggetti di D&D non è ancora stato scaricato.")
return
search = args.joined().lower()
result = self._dnddata[self._dnddata.bisect_key_left(search)]
await data.reply(self._parse_spell(result))

View file

@ -34,7 +34,8 @@ commands = [
SmecdsCommand, SmecdsCommand,
SummonCommand, SummonCommand,
VideochannelCommand, VideochannelCommand,
DnditemCommand DnditemCommand,
DndspellCommand
] ]
# noinspection PyUnreachableCode # noinspection PyUnreachableCode

View file

@ -6,8 +6,9 @@ from .safeformat import safeformat
from .classdictjanitor import cdj from .classdictjanitor import cdj
from .sleepuntil import sleep_until from .sleepuntil import sleep_until
from .networkhandler import NetworkHandler from .networkhandler import NetworkHandler
from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat, splitstring from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat, splitstring, ordinalformat
from .parse5etoolsentry import parse_5etools_entry
__all__ = ["asyncify", "safeformat", "cdj", "sleep_until", "plusformat", __all__ = ["asyncify", "safeformat", "cdj", "sleep_until", "plusformat",
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat", "NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat",
"telegram_escape", "discord_escape", "splitstring"] "telegram_escape", "discord_escape", "splitstring", "parse_5etools_entry", "ordinalformat"]

View file

@ -78,3 +78,15 @@ def splitstring(s: str, max: int) -> typing.List[str]:
l.append(s[:max]) l.append(s[:max])
s = s[max:] s = s[max:]
return l return l
def ordinalformat(number: int):
if 10 <= number % 100 < 20:
return f"{number}th"
if number % 10 == 1:
return f"{number}st"
elif number % 10 == 2:
return f"{number}nd"
elif number % 10 == 3:
return f"{number}rd"
return f"{number}th"

View file

@ -0,0 +1,31 @@
def parse_5etools_entry(entry) -> str:
if isinstance(entry, str):
return entry
elif isinstance(entry, dict):
string = ""
if entry["type"] == "entries":
string += f'[b]{entry.get("name", "")}[/b]\n'
for subentry in entry["entries"]:
string += parse_5etools_entry(subentry)
string += "\n\n"
elif entry["type"] == "table":
string += "[i][table hidden][/i]"
# for label in entry["colLabels"]:
# string += f"| {label} "
# string += "|"
# for row in entry["rows"]:
# for column in row:
# string += f"| {self._parse_entry(column)} "
# string += "|\n"
elif entry["type"] == "cell":
return parse_5etools_entry(entry["entry"])
elif entry["type"] == "list":
string = ""
for item in entry["items"]:
string += f"- {parse_5etools_entry(item)}\n"
string.rstrip("\n")
else:
string += "[i]⚠️ [unknown type][/i]"
else:
return "[/i]⚠️ [unknown data][/i]"
return string