Skip to content

Commit 64aa6c5

Browse files
committed
better roll commands + limit to rolling 100 dice of size 100 max
1 parent bf77b1a commit 64aa6c5

2 files changed

Lines changed: 79 additions & 18 deletions

File tree

source/InteractionCreate.Commands/roll.js

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -105,25 +105,78 @@ export default {
105105
quantity = interaction.options.getInteger("quantity") ?? 1;
106106
}
107107

108-
const { results, total } = roll(`${quantity}d${sides}`);
109-
110-
const reply = `**Rolling \`${quantity}d${sides}\`...**\n${`\`${results.join(
111-
" + "
112-
)} = ${total}\``}`;
113-
114-
if (reply.length > 2000) {
115-
return interaction.followUp({
116-
content:
117-
"The result is too long to send as a message, here is a file instead.",
118-
files: [
119-
{
120-
attachment: Buffer.from(reply),
121-
name: "roll.md",
122-
},
123-
],
124-
});
108+
// Apply limits: max 100 dice, max 100 sides
109+
if (quantity > 100) {
110+
return interaction.editReply("❌ Maximum of 100 dice allowed per roll.");
125111
}
126112

127-
return interaction.followUp(reply);
113+
if (sides > 100) {
114+
return interaction.editReply("❌ Maximum of 100 sides allowed per die.");
115+
}
116+
117+
// For large calculations, process in chunks to avoid timeout
118+
const isLargeCalculation = quantity > 100 || (quantity * sides > 100000);
119+
120+
if (isLargeCalculation) {
121+
// Process in chunks to avoid timeout
122+
const chunkSize = Math.min(100, Math.max(1, Math.floor(10000 / sides)));
123+
let results = [];
124+
let total = 0;
125+
126+
for (let chunk = 0; chunk < quantity; chunk += chunkSize) {
127+
const currentChunkSize = Math.min(chunkSize, quantity - chunk);
128+
const chunkDice = `${currentChunkSize}d${sides}`;
129+
const chunkResult = roll(chunkDice);
130+
131+
results = results.concat(chunkResult.results);
132+
total += chunkResult.total;
133+
134+
// Yield control periodically to prevent blocking
135+
if (chunk % (chunkSize * 10) === 0) {
136+
await new Promise(resolve => setImmediate(resolve));
137+
}
138+
}
139+
140+
const reply = `**Rolling \`${quantity}d${sides}\`...**\n${`\`${results.join(
141+
" + "
142+
)} = ${total}\``}`;
143+
144+
if (reply.length > 2000) {
145+
return interaction.editReply({
146+
content:
147+
"The result is too long to send as a message, here is a file instead.",
148+
files: [
149+
{
150+
attachment: Buffer.from(reply),
151+
name: "roll.md",
152+
},
153+
],
154+
});
155+
}
156+
157+
return interaction.editReply(reply);
158+
} else {
159+
// For small calculations, use the original fast path
160+
const { results, total } = roll(`${quantity}d${sides}`);
161+
162+
const reply = `**Rolling \`${quantity}d${sides}\`...**\n${`\`${results.join(
163+
" + "
164+
)} = ${total}\``}`;
165+
166+
if (reply.length > 2000) {
167+
return interaction.editReply({
168+
content:
169+
"The result is too long to send as a message, here is a file instead.",
170+
files: [
171+
{
172+
attachment: Buffer.from(reply),
173+
name: "roll.md",
174+
},
175+
],
176+
});
177+
}
178+
179+
return interaction.editReply(reply);
180+
}
128181
},
129182
};

source/library/roll.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,12 @@ describe("roll", () => {
2727
expect(result.results.length).toBe(0);
2828
expect(result.total).toBe(0);
2929
});
30+
31+
test("should handle large quantities correctly", () => {
32+
const result = roll("1000d6");
33+
expect(result.results.length).toBe(1000);
34+
expect(result.total).toBeGreaterThanOrEqual(1000);
35+
expect(result.total).toBeLessThanOrEqual(6000);
36+
expect(result.results.every(r => r >= 1 && r <= 6)).toBe(true);
37+
});
3038
});

0 commit comments

Comments
 (0)