pretty format discord message
This commit is contained in:
parent
739316f903
commit
d0ee7a5e3e
7 changed files with 78 additions and 11 deletions
|
@ -1,14 +1,32 @@
|
||||||
|
import typing
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import disnake
|
||||||
from disnake.ext import commands
|
from disnake.ext import commands
|
||||||
|
|
||||||
from src.dice.dice import DiceRoller
|
from src.dice.dice import DiceRoller, DieExpressionResult
|
||||||
|
|
||||||
|
|
||||||
class DiceCog(commands.Cog):
|
class DiceCog(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = 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"])
|
@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:
|
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.
|
- 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 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.
|
- 2d20+5 will roll a two d20 dies and multiply the result by two and ads 5.
|
||||||
"""
|
"""
|
||||||
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?")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
roll_result = DiceRoller.roll_simple(dice_expression)
|
message: str = ctx.message.clean_content
|
||||||
await ctx.send(f"You rolled: {roll_result}")
|
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?"
|
||||||
|
)
|
||||||
|
|
||||||
|
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:
|
except ValueError as e:
|
||||||
await ctx.send(f"Roll failed: {e}")
|
await ctx.send(f"Roll failed: {e}")
|
||||||
|
|
|
@ -57,4 +57,15 @@ class DiceRoller:
|
||||||
:return: The die result.
|
:return: The die result.
|
||||||
"""
|
"""
|
||||||
result = DiceRoller._parser.parse(expression)
|
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)
|
||||||
|
|
|
@ -15,7 +15,10 @@ class DieSemantics:
|
||||||
return {"total": die.get("result"), "dies": [die]}
|
return {"total": die.get("result"), "dies": [die]}
|
||||||
elif isinstance(die, list):
|
elif isinstance(die, list):
|
||||||
return_value = {"total": 0, "dies": copy.deepcopy(die)}
|
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))
|
die_results = deque(map(lambda x: x.get("result"), die))
|
||||||
# Note: we may need to use a dequeue, the ops are quite inefficient.
|
# Note: we may need to use a dequeue, the ops are quite inefficient.
|
||||||
|
|
0
tests/bot/__init__.py
Normal file
0
tests/bot/__init__.py
Normal file
0
tests/bot/discord/__init__.py
Normal file
0
tests/bot/discord/__init__.py
Normal file
0
tests/bot/discord/commands/__init__.py
Normal file
0
tests/bot/discord/commands/__init__.py
Normal file
18
tests/bot/discord/commands/test_dice.py
Normal file
18
tests/bot/discord/commands/test_dice.py
Normal 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]"),
|
||||||
|
]
|
Loading…
Reference in a new issue