snapshot_poker_phase3
This commit is contained in:
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
node_modules
|
node_modules
|
||||||
.env
|
.env
|
||||||
backup/
|
backup/
|
||||||
*.bak
|
*.bak
|
||||||
|
tests/
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
const {
|
||||||
|
buildPokerHubEmbed,
|
||||||
|
buildPokerHubComponents,
|
||||||
|
deferPokerReply
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"crumbSaucerPoker",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
embeds: [
|
||||||
|
buildPokerHubEmbed()
|
||||||
|
],
|
||||||
|
components:
|
||||||
|
buildPokerHubComponents()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const {
|
||||||
|
executePokerAction
|
||||||
|
} = require("../../utils/pokerInteractions");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "pokerAllIn",
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
return executePokerAction(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
type: "all_in"
|
||||||
|
},
|
||||||
|
"✅ All-In."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
buildJoinPicker
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerBrowse",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tables =
|
||||||
|
await getPokerService()
|
||||||
|
.listJoinableTables({
|
||||||
|
guildId:
|
||||||
|
interaction.guildId,
|
||||||
|
channelId:
|
||||||
|
interaction.channelId
|
||||||
|
});
|
||||||
|
|
||||||
|
return interaction.editReply(
|
||||||
|
buildJoinPicker(
|
||||||
|
tables
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const {
|
||||||
|
executePokerAction
|
||||||
|
} = require("../../utils/pokerInteractions");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "pokerCall",
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
return executePokerAction(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
type: "call"
|
||||||
|
},
|
||||||
|
"✅ Called."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
const {
|
||||||
|
cardToString
|
||||||
|
} = require("../../utils/pokerEngine");
|
||||||
|
|
||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
POKER_CARD_RESPONSE_LIFETIME,
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
getPokerGameIdFromInteraction
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerCards",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker table is no longer active.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cards =
|
||||||
|
await getPokerService()
|
||||||
|
.viewCards({
|
||||||
|
gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content:
|
||||||
|
`🃏 Your cards: **${cards.map(cardToString).join(" ")}**`,
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(
|
||||||
|
() => {
|
||||||
|
interaction
|
||||||
|
.deleteReply()
|
||||||
|
.catch(() => {});
|
||||||
|
},
|
||||||
|
POKER_CARD_RESPONSE_LIFETIME
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
getPokerGameIdFromInteraction,
|
||||||
|
refreshPokerTableMessage
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerCashOut",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker table is no longer active.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result =
|
||||||
|
await getPokerService()
|
||||||
|
.cashOut({
|
||||||
|
gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
result.game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
`✅ Cashed out **${result.amount.toLocaleString()} Cookies** back to your vault.`,
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const {
|
||||||
|
executePokerAction
|
||||||
|
} = require("../../utils/pokerInteractions");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "pokerCheck",
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
return executePokerAction(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
type: "check"
|
||||||
|
},
|
||||||
|
"✅ Checked."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
publishPokerTable,
|
||||||
|
buildOpenTableLink
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerCreate",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const service =
|
||||||
|
getPokerService();
|
||||||
|
|
||||||
|
let game = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
game =
|
||||||
|
await service.createTable({
|
||||||
|
guildId:
|
||||||
|
interaction.guildId,
|
||||||
|
channelId:
|
||||||
|
interaction.channelId,
|
||||||
|
ownerId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
const published =
|
||||||
|
await publishPokerTable(
|
||||||
|
interaction,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
`✅ Poker table created. **${published.game.data.buyIn.toLocaleString()} Cookies** were moved into your Poker stack.`,
|
||||||
|
embeds: [],
|
||||||
|
components:
|
||||||
|
buildOpenTableLink(
|
||||||
|
published.game
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
if (game) {
|
||||||
|
try {
|
||||||
|
await service.cashOut({
|
||||||
|
gameId:
|
||||||
|
game.gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (refundError) {
|
||||||
|
console.error(
|
||||||
|
`[Poker] Failed to refund unpublished table ${game.gameId}:`,
|
||||||
|
refundError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const {
|
||||||
|
executePokerAction
|
||||||
|
} = require("../../utils/pokerInteractions");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "pokerFold",
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
return executePokerAction(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
type: "fold"
|
||||||
|
},
|
||||||
|
"✅ Folded."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
getPokerGameIdFromInteraction,
|
||||||
|
refreshPokerTableMessage,
|
||||||
|
buildOpenTableLink
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerJoinTable",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker table is no longer active.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const game =
|
||||||
|
await getPokerService()
|
||||||
|
.joinTable({
|
||||||
|
gameId,
|
||||||
|
guildId:
|
||||||
|
interaction.guildId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
`✅ Joined the Poker table for **${game.data.buyIn.toLocaleString()} Cookies**.`,
|
||||||
|
embeds: [],
|
||||||
|
components:
|
||||||
|
buildOpenTableLink(
|
||||||
|
game
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
refreshPokerTableMessage,
|
||||||
|
buildOpenTableLink
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerMyTable",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const game =
|
||||||
|
await getPokerService()
|
||||||
|
.getMyTable({
|
||||||
|
guildId:
|
||||||
|
interaction.guildId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!game) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ You are not currently seated at a Poker table.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"♠️ Your active Poker table:",
|
||||||
|
embeds: [],
|
||||||
|
components:
|
||||||
|
buildOpenTableLink(
|
||||||
|
game
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
const {
|
||||||
|
executeMinimumRaise
|
||||||
|
} = require("../../utils/pokerInteractions");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "pokerRaise",
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
return executeMinimumRaise(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
getPokerGameIdFromInteraction,
|
||||||
|
refreshPokerTableMessage
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerRefresh",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker table is no longer active.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const game =
|
||||||
|
await getPokerService()
|
||||||
|
.getTable({
|
||||||
|
gameId
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"✅ Poker table refreshed.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
getPokerGameIdFromInteraction,
|
||||||
|
refreshPokerTableMessage
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerStart",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker table is no longer active.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const game =
|
||||||
|
await getPokerService()
|
||||||
|
.startTableHand({
|
||||||
|
gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
`✅ Hand **#${game.data.handNumber}** started.`,
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -28,7 +28,8 @@ module.exports = {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
interaction.isMentionableSelectMenu() ||
|
interaction.isMentionableSelectMenu() ||
|
||||||
interaction.isUserSelectMenu()
|
interaction.isUserSelectMenu() ||
|
||||||
|
interaction.isStringSelectMenu()
|
||||||
) {
|
) {
|
||||||
return selectMenuHandler(interaction);
|
return selectMenuHandler(interaction);
|
||||||
}
|
}
|
||||||
@@ -174,6 +175,9 @@ async function sendInteractionError(interaction, content) {
|
|||||||
await interaction.reply(payload);
|
await interaction.reply(payload);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to send interaction error response:", error);
|
console.error(
|
||||||
|
"Failed to send interaction error response:",
|
||||||
|
error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
refreshPokerTableMessage
|
||||||
|
} = require("../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
const TURN_CHECK_INTERVAL =
|
||||||
|
5 * 1000;
|
||||||
|
|
||||||
|
const LOBBY_CHECK_INTERVAL =
|
||||||
|
30 * 1000;
|
||||||
|
|
||||||
|
const STARTUP_RECOVERY_DELAY =
|
||||||
|
10 * 1000;
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = client => {
|
||||||
|
setTimeout(
|
||||||
|
() => {
|
||||||
|
recoverPoker(
|
||||||
|
client
|
||||||
|
);
|
||||||
|
},
|
||||||
|
STARTUP_RECOVERY_DELAY
|
||||||
|
);
|
||||||
|
|
||||||
|
setInterval(
|
||||||
|
() => {
|
||||||
|
processPokerTurns(
|
||||||
|
client
|
||||||
|
);
|
||||||
|
},
|
||||||
|
TURN_CHECK_INTERVAL
|
||||||
|
);
|
||||||
|
|
||||||
|
setInterval(
|
||||||
|
() => {
|
||||||
|
processPokerLobbies(
|
||||||
|
client
|
||||||
|
);
|
||||||
|
},
|
||||||
|
LOBBY_CHECK_INTERVAL
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"[Poker] Recovery and timeout watcher initialized"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function refreshResultGame(
|
||||||
|
client,
|
||||||
|
result
|
||||||
|
) {
|
||||||
|
const game =
|
||||||
|
result?.game;
|
||||||
|
|
||||||
|
if (!game) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function processPokerTurns(
|
||||||
|
client
|
||||||
|
) {
|
||||||
|
if (!client.isReady()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const results =
|
||||||
|
await getPokerService()
|
||||||
|
.processExpiredTurns();
|
||||||
|
|
||||||
|
for (const result of results) {
|
||||||
|
if (result.processed) {
|
||||||
|
console.log(
|
||||||
|
`[Poker] Auto-folded ${result.userId} after turn timeout.`
|
||||||
|
);
|
||||||
|
|
||||||
|
await refreshResultGame(
|
||||||
|
client,
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[Poker] Turn watcher error:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function processPokerLobbies(
|
||||||
|
client
|
||||||
|
) {
|
||||||
|
if (!client.isReady()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const results =
|
||||||
|
await getPokerService()
|
||||||
|
.processExpiredLobbies();
|
||||||
|
|
||||||
|
for (const result of results) {
|
||||||
|
if (result.expired) {
|
||||||
|
console.log(
|
||||||
|
`[Poker] Expired waiting Poker table ${result.game?.gameId ?? "unknown"}.`
|
||||||
|
);
|
||||||
|
|
||||||
|
await refreshResultGame(
|
||||||
|
client,
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[Poker] Lobby watcher error:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function recoverPoker(
|
||||||
|
client
|
||||||
|
) {
|
||||||
|
if (!client.isReady()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const service =
|
||||||
|
getPokerService();
|
||||||
|
|
||||||
|
const result =
|
||||||
|
await service.recover();
|
||||||
|
|
||||||
|
for (
|
||||||
|
const turn
|
||||||
|
of result.turns ?? []
|
||||||
|
) {
|
||||||
|
if (turn.processed) {
|
||||||
|
await refreshResultGame(
|
||||||
|
client,
|
||||||
|
turn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
const lobby
|
||||||
|
of result.lobbies ?? []
|
||||||
|
) {
|
||||||
|
if (lobby.expired) {
|
||||||
|
await refreshResultGame(
|
||||||
|
client,
|
||||||
|
lobby
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
const closing
|
||||||
|
of result.closingTables ?? []
|
||||||
|
) {
|
||||||
|
await refreshResultGame(
|
||||||
|
client,
|
||||||
|
closing
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (
|
||||||
|
const cashout
|
||||||
|
of result.cashouts ?? []
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const game =
|
||||||
|
await service.getTable({
|
||||||
|
gameId:
|
||||||
|
cashout.gameId
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`[Poker] Recovery complete: ` +
|
||||||
|
`${result.memberships.length} membership(s), ` +
|
||||||
|
`${result.cashouts.length} cash-out(s), ` +
|
||||||
|
`${result.closingTables.length} closing table(s), ` +
|
||||||
|
`${result.turns.length} expired turn(s), ` +
|
||||||
|
`${result.lobbies.length} expired lobby/lobbies.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
console.error(
|
||||||
|
"[Poker] Startup recovery error:",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -4,7 +4,8 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "node --test",
|
||||||
|
"test:poker": "node --test tests/pokerEngine.test.js tests/crumbPoker.test.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("../../utils/crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
refreshPokerTableMessage,
|
||||||
|
buildOpenTableLink
|
||||||
|
} = require("../../utils/pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"pokerJoinSelect",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
interaction.values?.[0];
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ No Poker table was selected.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const game =
|
||||||
|
await getPokerService()
|
||||||
|
.joinTable({
|
||||||
|
gameId,
|
||||||
|
guildId:
|
||||||
|
interaction.guildId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
`✅ Joined the Poker table for **${game.data.buyIn.toLocaleString()} Cookies**.`,
|
||||||
|
embeds: [],
|
||||||
|
components:
|
||||||
|
buildOpenTableLink(
|
||||||
|
game
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -268,6 +268,251 @@ async function changeCookies(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* IDEMPOTENT COOKIE CHANGE
|
||||||
|
* ============================================================
|
||||||
|
*
|
||||||
|
* Applies a Cookie mutation at most once for a user-scoped
|
||||||
|
* operationId. This is useful for persistent game buy-ins and
|
||||||
|
* cash-outs that may be retried after a crash or restart.
|
||||||
|
*
|
||||||
|
* The Cookie balance mutation and operation marker are written
|
||||||
|
* atomically to the same user document.
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function changeCookiesOnce(
|
||||||
|
userId,
|
||||||
|
amount,
|
||||||
|
operationId
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!Number.isSafeInteger(
|
||||||
|
amount
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
"INVALID_COOKIE_AMOUNT"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof operationId !==
|
||||||
|
"string"
|
||||||
|
||
|
||||||
|
!/^[A-Za-z0-9:_-]{1,160}$/.test(
|
||||||
|
operationId
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
"INVALID_COOKIE_OPERATION_ID"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
amount ===
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
applied:
|
||||||
|
false,
|
||||||
|
balance:
|
||||||
|
await getCookieBalance(
|
||||||
|
userId
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
cookies
|
||||||
|
} =
|
||||||
|
getCollections();
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
userId,
|
||||||
|
appliedCookieOperations: {
|
||||||
|
$ne:
|
||||||
|
operationId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
amount <
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
filter.cookies = {
|
||||||
|
$gte:
|
||||||
|
Math.abs(
|
||||||
|
amount
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const update = {
|
||||||
|
$inc: {
|
||||||
|
cookies:
|
||||||
|
amount
|
||||||
|
},
|
||||||
|
$addToSet: {
|
||||||
|
appliedCookieOperations:
|
||||||
|
operationId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
amount >
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
update.$setOnInsert = {
|
||||||
|
userId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result =
|
||||||
|
await cookies.updateOne(
|
||||||
|
filter,
|
||||||
|
update,
|
||||||
|
{
|
||||||
|
upsert:
|
||||||
|
amount > 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
result.modifiedCount ===
|
||||||
|
1
|
||||||
|
||
|
||||||
|
result.upsertedCount ===
|
||||||
|
1
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
applied:
|
||||||
|
true,
|
||||||
|
balance:
|
||||||
|
await getCookieBalance(
|
||||||
|
userId
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
/*
|
||||||
|
* A concurrent positive retry can race an upsert.
|
||||||
|
* The unique userId index may reject the losing insert.
|
||||||
|
* Re-read below and treat an already-recorded operation
|
||||||
|
* as a successful idempotent retry.
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
error?.code !==
|
||||||
|
11000
|
||||||
|
) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const document =
|
||||||
|
await cookies.findOne(
|
||||||
|
{
|
||||||
|
userId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projection: {
|
||||||
|
cookies:
|
||||||
|
1,
|
||||||
|
appliedCookieOperations:
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const operations =
|
||||||
|
Array.isArray(
|
||||||
|
document
|
||||||
|
?.appliedCookieOperations
|
||||||
|
)
|
||||||
|
? document
|
||||||
|
.appliedCookieOperations
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
operations.includes(
|
||||||
|
operationId
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
applied:
|
||||||
|
false,
|
||||||
|
balance:
|
||||||
|
Math.max(
|
||||||
|
0,
|
||||||
|
Number(
|
||||||
|
document?.cookies ??
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
amount <
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
"INSUFFICIENT_COOKIES"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
"COOKIE_OPERATION_FAILED"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function hasCookieOperation(
|
||||||
|
userId,
|
||||||
|
operationId
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
typeof operationId !==
|
||||||
|
"string"
|
||||||
|
||
|
||||||
|
!/^[A-Za-z0-9:_-]{1,160}$/.test(
|
||||||
|
operationId
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
"INVALID_COOKIE_OPERATION_ID"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
cookies
|
||||||
|
} =
|
||||||
|
getCollections();
|
||||||
|
|
||||||
|
const document =
|
||||||
|
await cookies.findOne(
|
||||||
|
{
|
||||||
|
userId,
|
||||||
|
appliedCookieOperations:
|
||||||
|
operationId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projection: {
|
||||||
|
_id:
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Boolean(
|
||||||
|
document
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* COOKIE TRANSFER
|
* COOKIE TRANSFER
|
||||||
@@ -1188,6 +1433,8 @@ module.exports = {
|
|||||||
|
|
||||||
getCookieBalance,
|
getCookieBalance,
|
||||||
changeCookies,
|
changeCookies,
|
||||||
|
changeCookiesOnce,
|
||||||
|
hasCookieOperation,
|
||||||
transferCookies,
|
transferCookies,
|
||||||
|
|
||||||
getCooldown,
|
getCooldown,
|
||||||
|
|||||||
+2730
File diff suppressed because it is too large
Load Diff
+196
-56
@@ -14,48 +14,88 @@ const {
|
|||||||
requireInteractionSession
|
requireInteractionSession
|
||||||
} = require("./interactionSession");
|
} = require("./interactionSession");
|
||||||
|
|
||||||
async function showCrumbSaucer(interaction) {
|
|
||||||
if (interaction.isButton()) {
|
async function showCrumbSaucer(
|
||||||
const session = await requireInteractionSession(interaction);
|
interaction
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
interaction.isButton()
|
||||||
|
) {
|
||||||
|
const session =
|
||||||
|
await requireInteractionSession(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const balance = await getCookieBalance(interaction.user.id);
|
const balance =
|
||||||
const embed = buildMainMenuEmbed(interaction.user, balance);
|
await getCookieBalance(
|
||||||
|
interaction.user.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const embed =
|
||||||
|
buildMainMenuEmbed(
|
||||||
|
interaction.user,
|
||||||
|
balance
|
||||||
|
);
|
||||||
|
|
||||||
return interaction.update({
|
return interaction.update({
|
||||||
embeds: [embed],
|
embeds: [
|
||||||
components: buildMainMenuButtons()
|
embed
|
||||||
|
],
|
||||||
|
components:
|
||||||
|
buildMainMenuButtons()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const balance = await getCookieBalance(interaction.user.id);
|
const balance =
|
||||||
const embed = buildMainMenuEmbed(interaction.user, balance);
|
await getCookieBalance(
|
||||||
|
interaction.user.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const embed =
|
||||||
|
buildMainMenuEmbed(
|
||||||
|
interaction.user,
|
||||||
|
balance
|
||||||
|
);
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
embeds: [embed],
|
embeds: [
|
||||||
components: buildMainMenuButtons()
|
embed
|
||||||
|
],
|
||||||
|
components:
|
||||||
|
buildMainMenuButtons()
|
||||||
});
|
});
|
||||||
|
|
||||||
const message = await interaction.fetchReply();
|
const message =
|
||||||
|
await interaction.fetchReply();
|
||||||
|
|
||||||
await createInteractionSession(
|
await createInteractionSession(
|
||||||
interaction,
|
interaction,
|
||||||
{
|
{
|
||||||
messageId: message.id,
|
messageId:
|
||||||
ownerId: interaction.user.id,
|
message.id,
|
||||||
kind: "crumbSaucer"
|
ownerId:
|
||||||
|
interaction.user.id,
|
||||||
|
kind:
|
||||||
|
"crumbSaucer"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMainMenuEmbed(user, balance) {
|
|
||||||
|
function buildMainMenuEmbed(
|
||||||
|
user,
|
||||||
|
balance
|
||||||
|
) {
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.setTitle("🎰 The Crumb Saucer")
|
.setTitle(
|
||||||
|
"🎰 The Crumb Saucer"
|
||||||
|
)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
`Welcome, ${user}!`,
|
`Welcome, ${user}!`,
|
||||||
@@ -78,79 +118,178 @@ function buildMainMenuEmbed(user, balance) {
|
|||||||
"### 🏦 Vault Heist",
|
"### 🏦 Vault Heist",
|
||||||
"Attempt to breach ShaiBot's Cookie Vault.",
|
"Attempt to breach ShaiBot's Cookie Vault.",
|
||||||
"",
|
"",
|
||||||
|
"### ♠️ Poker",
|
||||||
|
"Create or join a 2–6 player Cookie Poker table.",
|
||||||
|
"",
|
||||||
"### 🛟 Bankruptcy",
|
"### 🛟 Bankruptcy",
|
||||||
"At exactly 0 Cookies, claim a 1,000 Cookie starter kit."
|
"At exactly 0 Cookies, claim a 1,000 Cookie starter kit."
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
.addFields({
|
.addFields({
|
||||||
name: "Your Vault",
|
name:
|
||||||
value: `**${balance.toLocaleString()} 🍪**`
|
"Your Vault",
|
||||||
|
value:
|
||||||
|
`**${balance.toLocaleString()} 🍪**`
|
||||||
})
|
})
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `crumbSaucer:${user.id}`
|
text:
|
||||||
|
`crumbSaucer:${user.id}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function buildMainMenuButtons() {
|
function buildMainMenuButtons() {
|
||||||
return [
|
return [
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerSlots")
|
.setCustomId(
|
||||||
.setLabel("Slots")
|
"crumbSaucerSlots"
|
||||||
.setEmoji("🎰")
|
)
|
||||||
.setStyle(ButtonStyle.Primary),
|
.setLabel(
|
||||||
|
"Slots"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🎰"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Primary
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerBlackjack")
|
.setCustomId(
|
||||||
.setLabel("Blackjack")
|
"crumbSaucerBlackjack"
|
||||||
.setEmoji("🃏")
|
)
|
||||||
.setStyle(ButtonStyle.Primary),
|
.setLabel(
|
||||||
|
"Blackjack"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🃏"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Primary
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerRoulette")
|
.setCustomId(
|
||||||
.setLabel("Roulette")
|
"crumbSaucerRoulette"
|
||||||
.setEmoji("🎡")
|
)
|
||||||
.setStyle(ButtonStyle.Primary),
|
.setLabel(
|
||||||
|
"Roulette"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🎡"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Primary
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerHeist")
|
.setCustomId(
|
||||||
.setLabel("Vault Heist")
|
"crumbSaucerHeist"
|
||||||
.setEmoji("🏦")
|
)
|
||||||
.setStyle(ButtonStyle.Danger)
|
.setLabel(
|
||||||
|
"Vault Heist"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🏦"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Danger
|
||||||
|
),
|
||||||
|
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId(
|
||||||
|
"crumbSaucerPoker"
|
||||||
|
)
|
||||||
|
.setLabel(
|
||||||
|
"Poker"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"♠️"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Success
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerCollectMenu")
|
.setCustomId(
|
||||||
.setLabel("Cookie Bakery")
|
"crumbSaucerCollectMenu"
|
||||||
.setEmoji("🍪")
|
)
|
||||||
.setStyle(ButtonStyle.Secondary),
|
.setLabel(
|
||||||
|
"Cookie Bakery"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🍪"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Secondary
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerBankruptcy")
|
.setCustomId(
|
||||||
.setLabel("Bankruptcy")
|
"crumbSaucerBankruptcy"
|
||||||
.setEmoji("🛟")
|
)
|
||||||
.setStyle(ButtonStyle.Secondary),
|
.setLabel(
|
||||||
|
"Bankruptcy"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🛟"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Secondary
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("crumbSaucerProfile")
|
.setCustomId(
|
||||||
.setLabel("Profile")
|
"crumbSaucerProfile"
|
||||||
.setEmoji("👤")
|
)
|
||||||
.setStyle(ButtonStyle.Secondary),
|
.setLabel(
|
||||||
|
"Profile"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"👤"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Secondary
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId("sessionClose")
|
.setCustomId(
|
||||||
.setLabel("Close")
|
"sessionClose"
|
||||||
.setEmoji("✖️")
|
)
|
||||||
.setStyle(ButtonStyle.Danger)
|
.setLabel(
|
||||||
|
"Close"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"✖️"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Danger
|
||||||
|
)
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCrumbSaucerSessionOwner(interaction) {
|
|
||||||
const footer = interaction.message?.embeds?.[0]?.footer?.text;
|
|
||||||
const parts = footer?.split(":") ?? [];
|
|
||||||
|
|
||||||
switch (parts[0]) {
|
function getCrumbSaucerSessionOwner(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
const footer =
|
||||||
|
interaction.message
|
||||||
|
?.embeds?.[0]
|
||||||
|
?.footer
|
||||||
|
?.text;
|
||||||
|
|
||||||
|
const parts =
|
||||||
|
footer?.split(":") ?? [];
|
||||||
|
|
||||||
|
switch (
|
||||||
|
parts[0]
|
||||||
|
) {
|
||||||
case "crumbSaucer":
|
case "crumbSaucer":
|
||||||
case "crumbSaucerCollect":
|
case "crumbSaucerCollect":
|
||||||
case "crumbSaucerSlots":
|
case "crumbSaucerSlots":
|
||||||
@@ -171,6 +310,7 @@ function getCrumbSaucerSessionOwner(interaction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
showCrumbSaucer,
|
showCrumbSaucer,
|
||||||
buildMainMenuEmbed,
|
buildMainMenuEmbed,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,168 @@
|
|||||||
|
const {
|
||||||
|
getPokerService
|
||||||
|
} = require("./crumbPoker");
|
||||||
|
|
||||||
|
const {
|
||||||
|
deferPokerReply,
|
||||||
|
editPokerError,
|
||||||
|
getPokerGameIdFromInteraction,
|
||||||
|
refreshPokerTableMessage
|
||||||
|
} = require("./pokerDiscord");
|
||||||
|
|
||||||
|
|
||||||
|
async function executePokerAction(
|
||||||
|
interaction,
|
||||||
|
action,
|
||||||
|
successText
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker control is no longer attached to an active table.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const service =
|
||||||
|
getPokerService();
|
||||||
|
|
||||||
|
const game =
|
||||||
|
await service.act({
|
||||||
|
gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id,
|
||||||
|
action
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
typeof successText ===
|
||||||
|
"function"
|
||||||
|
? successText(game)
|
||||||
|
: successText,
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function executeMinimumRaise(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
await deferPokerReply(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
const gameId =
|
||||||
|
getPokerGameIdFromInteraction(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gameId) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ This Poker control is no longer attached to an active table.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const service =
|
||||||
|
getPokerService();
|
||||||
|
|
||||||
|
const legal =
|
||||||
|
await service.getLegalPlayerActions({
|
||||||
|
gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
const type =
|
||||||
|
legal.actions?.includes(
|
||||||
|
"bet"
|
||||||
|
)
|
||||||
|
? "bet"
|
||||||
|
: legal.actions?.includes(
|
||||||
|
"raise"
|
||||||
|
)
|
||||||
|
? "raise"
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!type
|
||||||
|
||
|
||||||
|
!Number.isSafeInteger(
|
||||||
|
legal.minRaiseTo
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
"❌ A bet or raise is not available right now.",
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const game =
|
||||||
|
await service.act({
|
||||||
|
gameId,
|
||||||
|
userId:
|
||||||
|
interaction.user.id,
|
||||||
|
action: {
|
||||||
|
type,
|
||||||
|
amount:
|
||||||
|
legal.minRaiseTo
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await refreshPokerTableMessage(
|
||||||
|
interaction.client,
|
||||||
|
game
|
||||||
|
);
|
||||||
|
|
||||||
|
return interaction.editReply({
|
||||||
|
content:
|
||||||
|
`✅ ${type === "bet" ? "Bet" : "Raised to"} ${legal.minRaiseTo.toLocaleString()} 🍪`,
|
||||||
|
embeds: [],
|
||||||
|
components: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (error) {
|
||||||
|
return editPokerError(
|
||||||
|
interaction,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
executePokerAction,
|
||||||
|
executeMinimumRaise
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user