mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-27 13:34:28 +00:00
Aggiunto comando dndspell (#50)
This commit is contained in:
parent
2bdb6c7729
commit
5a59c09cba
7 changed files with 164 additions and 31 deletions
|
@ -21,6 +21,7 @@ from .smecds import SmecdsCommand
|
|||
from .summon import SummonCommand
|
||||
from .videochannel import VideochannelCommand
|
||||
from .dnditem import DnditemCommand
|
||||
from .dndspell import DndspellCommand
|
||||
|
||||
__all__ = [
|
||||
"CiaoruoziCommand",
|
||||
|
@ -40,5 +41,6 @@ __all__ = [
|
|||
"SmecdsCommand",
|
||||
"SummonCommand",
|
||||
"VideochannelCommand",
|
||||
"DnditemCommand"
|
||||
"DnditemCommand",
|
||||
"DndspellCommand"
|
||||
]
|
||||
|
|
|
@ -5,6 +5,7 @@ from ..command import Command
|
|||
from ..commandargs import CommandArgs
|
||||
from ..commanddata import CommandData
|
||||
from ..commandinterface import CommandInterface
|
||||
from ...utils import parse_5etools_entry
|
||||
|
||||
|
||||
class DnditemCommand(Command):
|
||||
|
@ -36,32 +37,6 @@ class DnditemCommand(Command):
|
|||
for item in j["baseitem"]:
|
||||
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:
|
||||
if self._dnddata is None:
|
||||
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'\n'
|
||||
for entry in result.get("entries", []):
|
||||
string += self._parse_entry(entry)
|
||||
string += parse_5etools_entry(entry)
|
||||
string += "\n\n"
|
||||
await data.reply(string)
|
||||
|
|
111
royalnet/commands/royalgames/dndspell.py
Normal file
111
royalnet/commands/royalgames/dndspell.py
Normal 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))
|
|
@ -34,7 +34,8 @@ commands = [
|
|||
SmecdsCommand,
|
||||
SummonCommand,
|
||||
VideochannelCommand,
|
||||
DnditemCommand
|
||||
DnditemCommand,
|
||||
DndspellCommand
|
||||
]
|
||||
|
||||
# noinspection PyUnreachableCode
|
||||
|
|
|
@ -6,8 +6,9 @@ from .safeformat import safeformat
|
|||
from .classdictjanitor import cdj
|
||||
from .sleepuntil import sleep_until
|
||||
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",
|
||||
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat",
|
||||
"telegram_escape", "discord_escape", "splitstring"]
|
||||
"telegram_escape", "discord_escape", "splitstring", "parse_5etools_entry", "ordinalformat"]
|
||||
|
|
|
@ -78,3 +78,15 @@ def splitstring(s: str, max: int) -> typing.List[str]:
|
|||
l.append(s[:max])
|
||||
s = s[max:]
|
||||
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"
|
||||
|
|
31
royalnet/utils/parse5etoolsentry.py
Normal file
31
royalnet/utils/parse5etoolsentry.py
Normal 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
|
Loading…
Reference in a new issue