pretty format discord message

This commit is contained in:
Denis-Cosmin Nutiu 2024-01-24 13:26:30 +02:00
parent 739316f903
commit d0ee7a5e3e
7 changed files with 78 additions and 11 deletions

View file

@ -1,14 +1,32 @@
import typing
from datetime import datetime
import disnake
from disnake.ext import commands
from src.dice.dice import DiceRoller
from src.dice.dice import DiceRoller, DieExpressionResult
class DiceCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@staticmethod
def format_die_result_to_fields(
die_result: DieExpressionResult,
) -> list[typing.Tuple[str, str]]:
roll_fields = []
for index, die in enumerate(die_result.dies):
roll_fields.append(
(
f"- #{index+1} 🎲 ",
f"Res: {die.result}, Mod: {die.modifier}, Rolls: {die.rolls}",
)
)
return roll_fields
@commands.command(name="roll", aliases=["r"])
async def roll(self, ctx, dice_expression: str):
async def roll(self, ctx, _dice_expression: str):
"""
A die can be rolled using the following expression:
- 1d20 will roll a 20-faceted die and output the result a random number between 1 and 20.
@ -16,13 +34,30 @@ class DiceCog(commands.Cog):
- 2d20 will roll a two d20 dies and multiply the result by two.
- 2d20+5 will roll a two d20 dies and multiply the result by two and ads 5.
"""
try:
message: str = ctx.message.clean_content
dice_expression = message.split(" ", 1)[1]
if dice_expression == "":
return
if dice_expression == "0/0": # easter eggs
return await ctx.send("What do you expect me to do, destroy the universe?")
return await ctx.send(
"What do you expect me to do, destroy the universe?"
)
try:
roll_result = DiceRoller.roll_simple(dice_expression)
await ctx.send(f"You rolled: {roll_result}")
die_result: DieExpressionResult = DiceRoller.roll(dice_expression)
embed = disnake.Embed(
title="",
description=f"{dice_expression} = {die_result.total}",
timestamp=datetime.now(),
)
embed_fields = self.format_die_result_to_fields(die_result)
for title, value in embed_fields:
embed.add_field(title, value, inline=False)
await ctx.send(
f"The mighty **{ctx.author.name}** has rolled the dice for a total of **{die_result.total}**!",
embed=embed,
)
except ValueError as e:
await ctx.send(f"Roll failed: {e}")

View file

@ -57,4 +57,15 @@ class DiceRoller:
:return: The die result.
"""
result = DiceRoller._parser.parse(expression)
return DieExpressionResult(**result)
dies = []
for die in result.get("dies", []):
dies.append(
DieRollResult(
modifier=die.get("modifier", 0),
result=die.get("result"),
rolls=die.get("rolls"),
type=die.get("type"),
)
)
return DieExpressionResult(total=result.get("total"), dies=dies)

View file

@ -15,7 +15,10 @@ class DieSemantics:
return {"total": die.get("result"), "dies": [die]}
elif isinstance(die, list):
return_value = {"total": 0, "dies": copy.deepcopy(die)}
operators = deque(ast.get("op", []))
operators = ast.get("op", [])
if not isinstance(operators, list):
operators = [operators]
operators = deque(operators)
die_results = deque(map(lambda x: x.get("result"), die))
# Note: we may need to use a dequeue, the ops are quite inefficient.

0
tests/bot/__init__.py Normal file
View file

View file

View file

View file

@ -0,0 +1,18 @@
from src.bot.discord.commands.dice import DiceCog
from src.dice.dice import DieExpressionResult, DieRollResult
def test_format_die_result_to_message():
message = DiceCog.format_die_result_to_fields(
DieExpressionResult(
total=25,
dies=[
DieRollResult(result=10, modifier=5, rolls=[10], type="d"),
DieRollResult(result=15, modifier=0, rolls=[10, 5], type="d"),
],
),
)
assert message == [
("- #1 🎲 ", "Res: 10, Mod: 5, Rolls: [10]"),
("- #2 🎲 ", "Res: 15, Mod: 0, Rolls: [10, 5]"),
]