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:
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 .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"
|
||||||
]
|
]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
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,
|
SmecdsCommand,
|
||||||
SummonCommand,
|
SummonCommand,
|
||||||
VideochannelCommand,
|
VideochannelCommand,
|
||||||
DnditemCommand
|
DnditemCommand,
|
||||||
|
DndspellCommand
|
||||||
]
|
]
|
||||||
|
|
||||||
# noinspection PyUnreachableCode
|
# noinspection PyUnreachableCode
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
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