WIP basic card dropping
This commit is contained in:
@@ -39,7 +39,7 @@ module.exports = {
|
|||||||
message += `------------------------ \n`;
|
message += `------------------------ \n`;
|
||||||
}
|
}
|
||||||
interaction.reply({
|
interaction.reply({
|
||||||
content: message,
|
content: message.substring(0, 1500),
|
||||||
ephemeral: false
|
ephemeral: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js");
|
const { SlashCommandBuilder, ComponentType, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js");
|
||||||
const { customAlphabet } = require("nanoid");
|
const { customAlphabet } = require("nanoid");
|
||||||
|
const { Card, User, Character } = require("../models");
|
||||||
|
const Util = require("../util/cards");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
@@ -9,20 +11,12 @@ module.exports = {
|
|||||||
option
|
option
|
||||||
.setName("feature")
|
.setName("feature")
|
||||||
.setDescription("The command to debug")
|
.setDescription("The command to debug")
|
||||||
.setRequired(true)
|
.setRequired(false)
|
||||||
),
|
),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const row = new ActionRowBuilder()
|
const identifier = Util.generateIdentifier();
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId('primary')
|
|
||||||
.setLabel('Primary')
|
|
||||||
.setStyle(ButtonStyle.Primary),
|
|
||||||
);
|
|
||||||
|
|
||||||
await interaction.reply({ content: 'Pong!', components: [row] });
|
|
||||||
return;
|
|
||||||
switch (interaction.options.getString("feature")) {
|
switch (interaction.options.getString("feature")) {
|
||||||
case "ping":
|
case "ping":
|
||||||
interaction.reply({
|
interaction.reply({
|
||||||
@@ -42,6 +36,15 @@ module.exports = {
|
|||||||
ephemeral: false
|
ephemeral: false
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "clear_cards":
|
||||||
|
const cards = await Card.findAll();
|
||||||
|
for (let i = 0; i < cards.length; i++) {
|
||||||
|
await cards[i].destroy();
|
||||||
|
}
|
||||||
|
interaction.reply({
|
||||||
|
content: `Cleared ${cards.length} cards`,
|
||||||
|
ephemeral: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
48
commands/debugDrop.js
Normal file
48
commands/debugDrop.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
const { SlashCommandBuilder } = require("discord.js");
|
||||||
|
const { Card, User } = require("../models");
|
||||||
|
const { customAlphabet } = require("nanoid");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("debug_drop")
|
||||||
|
.setDescription("Drop a card")
|
||||||
|
.addIntegerOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("id")
|
||||||
|
.setDescription("The id of the character to drop")
|
||||||
|
.setRequired(true)
|
||||||
|
),
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
//get user id from database given the userID
|
||||||
|
const user = await User.findOne({
|
||||||
|
where: {
|
||||||
|
discordId: interaction.member.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//create new card with the given character id, and the user id
|
||||||
|
const nanoid = customAlphabet('23456789ABCDEFGHJKLMNPRSTUVWXYZ',6); //Up to 887.503.681
|
||||||
|
const identifier = nanoid();
|
||||||
|
const existingCharacterCount = await Card.count({
|
||||||
|
where: {
|
||||||
|
characterId: interaction.options.getInteger("id")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const card = await Card.create({
|
||||||
|
characterId: interaction.options.getInteger("id"),
|
||||||
|
identifier: identifier,
|
||||||
|
quality: 1,
|
||||||
|
printNr: existingCharacterCount + 1,
|
||||||
|
userId: user.id
|
||||||
|
});
|
||||||
|
|
||||||
|
//reply with the new card id
|
||||||
|
interaction.reply({
|
||||||
|
content: `Dropped card ${card.id}`,
|
||||||
|
ephemeral: false
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
104
commands/drop.js
104
commands/drop.js
@@ -1,47 +1,93 @@
|
|||||||
const { SlashCommandBuilder } = require("discord.js");
|
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, ComponentType } = require("discord.js");
|
||||||
const { Card, User } = require("../models");
|
const { Card, User, Character } = require("../models");
|
||||||
const { customAlphabet } = require("nanoid");
|
const { customAlphabet } = require("nanoid");
|
||||||
|
const { CardUtils, UserUtils, ReplyUtils } = require("../util");
|
||||||
|
const card = require("../models/card");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("drop")
|
.setName("drop")
|
||||||
.setDescription("Drop a card")
|
.setDescription("Drop a card"),
|
||||||
.addIntegerOption((option) =>
|
|
||||||
option
|
|
||||||
.setName("id")
|
|
||||||
.setDescription("The id of the character to drop")
|
|
||||||
.setRequired(true)
|
|
||||||
),
|
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
//get user id from database given the userID
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
where: {
|
where: {
|
||||||
discordId: interaction.member.id
|
discordId: interaction.member.id
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//create new card with the given character id, and the user id
|
//Generate 3 cards, each is persisted with an initial userId of NULL
|
||||||
const nanoid = customAlphabet('23456789ABCDEFGHJKLMNPRSTUVWXYZ',6); //Up to 887.503.681
|
const cards = [];
|
||||||
const identifier = nanoid();
|
for (let i = 0; i < 3; i++) {
|
||||||
const existingCharacterCount = await Card.count({
|
//get number of characters in database
|
||||||
where: {
|
const characterId = Math.floor(Math.random() * await CardUtils.getCharacterCount()) + 1;
|
||||||
characterId: interaction.options.getInteger("id")
|
console.log(`characterId: ${characterId}`);
|
||||||
|
|
||||||
|
let newCard = await Card.create({
|
||||||
|
characterId: characterId,
|
||||||
|
identifier: CardUtils.generateIdentifier(),
|
||||||
|
quality: 1,
|
||||||
|
printNr: await CardUtils.getNextPrintNumber(characterId),
|
||||||
|
|
||||||
|
});
|
||||||
|
cards.push(newCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
let reply = "You have dropped the following cards: \n";
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder();
|
||||||
|
|
||||||
|
for (const [i, card] of cards.entries()) {
|
||||||
|
let character = await Character.findOne({
|
||||||
|
where: {
|
||||||
|
id: card.characterId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
reply += `IID: ${card.id} - ID:${card.identifier} \nP: ${card.printNr} Q: ${card.quality} \nC: ${character.name} \n----------\n`;
|
||||||
|
|
||||||
|
//Add claim button for each card
|
||||||
|
row.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId(`claim-${i}-${card.identifier}`)
|
||||||
|
.setLabel(`Claim ${i+1}`)
|
||||||
|
.setStyle(ButtonStyle.Primary),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = await interaction.reply({ content: reply, components: [row], fetchReply: true });
|
||||||
|
|
||||||
|
const filter = m => m.author.id === interaction.user.id;
|
||||||
|
const collector = message.createMessageComponentCollector({ componentType: ComponentType.Button, time: 15000 });
|
||||||
|
|
||||||
|
collector.on('collect', async i => {
|
||||||
|
let cardId = i.customId.split("-")[1];
|
||||||
|
if (await cards[cardId].userId) { i.reply({ content: "This card has already been claimed!", ephemeral: true }); return; }
|
||||||
|
|
||||||
|
let claimUser = await UserUtils.getUserByDiscordId(i.user.id);
|
||||||
|
if (claimUser) {
|
||||||
|
//Update card with the user id
|
||||||
|
cards[cardId].userId = claimUser.id;
|
||||||
|
await cards[cardId].save();
|
||||||
|
//fetch character name from database given the character id
|
||||||
|
let character = await Character.findOne({
|
||||||
|
attributes: ["name"],
|
||||||
|
where: {
|
||||||
|
id: cards[cardId].characterId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
i.reply({ content: `${i.user} (${claimUser.id}) claimed ${character.name}`, ephemeral: false });
|
||||||
|
let newRow = ReplyUtils.recreateComponents(i.message.components);
|
||||||
|
newRow.components[cardId].setLabel("Claimed");
|
||||||
|
newRow.components[cardId].setStyle(ButtonStyle.Success);
|
||||||
|
newRow.components[cardId].setDisabled(true);
|
||||||
|
|
||||||
|
message.edit({ components: [newRow] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const card = await Card.create({
|
collector.on('end', collected => {
|
||||||
characterId: interaction.options.getInteger("id"),
|
console.log(`Collected ${collected.size} interactions.`);
|
||||||
identifier: identifier,
|
message.interaction.editReply({ components: [], deferred: true });
|
||||||
quality: 1,
|
|
||||||
printNr: existingCharacterCount + 1,
|
|
||||||
userId: user.id
|
|
||||||
});
|
|
||||||
|
|
||||||
//reply with the new card id
|
|
||||||
interaction.reply({
|
|
||||||
content: `Dropped card ${card.id}`,
|
|
||||||
ephemeral: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ require("dotenv").config();
|
|||||||
const { REST } = require("@discordjs/rest");
|
const { REST } = require("@discordjs/rest");
|
||||||
const { Routes } = require("discord-api-types/v10")
|
const { Routes } = require("discord-api-types/v10")
|
||||||
const { Guild, User } = require("../models");
|
const { Guild, User } = require("../models");
|
||||||
|
const { UserUtils } = require("../util");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: "interactionCreate",
|
name: "interactionCreate",
|
||||||
async execute (interaction) {
|
async execute (interaction) {
|
||||||
|
if (!UserUtils.registrationCheck(interaction)) return;
|
||||||
if (!interaction.isCommand()) return;
|
if (!interaction.isCommand()) return;
|
||||||
|
|
||||||
const guild = await interaction.guild;
|
const guild = await interaction.guild;
|
||||||
@@ -30,19 +32,6 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
//check if the user exists in the database, if not tell him to use the /register command
|
|
||||||
let user = await User.findOne({
|
|
||||||
where: {
|
|
||||||
discordId: interaction.member.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!user && interaction.commandName !== "register") {
|
|
||||||
interaction.reply({
|
|
||||||
content: `You are not registered, use the /register command`,
|
|
||||||
ephemeral: false
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = interaction.client.commands.get(interaction.commandName);
|
const command = interaction.client.commands.get(interaction.commandName);
|
||||||
|
|
||||||
@@ -53,7 +42,7 @@ module.exports = {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err) console.log(err);
|
if (err) console.log(err);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `An error occured processing the command :(\n \`\`\`${JSON.stringify(err, null, 2)}\`\`\``,
|
content: `An error occured processing the command :(\n \`\`\`${err.stack}\`\`\``,
|
||||||
ephemeral: false
|
ephemeral: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
18
migrations/20220818130258-make-card-userid-nullable.js
Normal file
18
migrations/20220818130258-make-card-userid-nullable.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async up (queryInterface, Sequelize) {
|
||||||
|
await queryInterface.changeColumn('Cards', 'userId', {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: null
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async down (queryInterface, Sequelize) {
|
||||||
|
await queryInterface.changeColumn('Cards', 'userId', {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -15,7 +15,6 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Band.init({
|
Band.init({
|
||||||
uniqueId: DataTypes.INTEGER,
|
|
||||||
name: DataTypes.STRING,
|
name: DataTypes.STRING,
|
||||||
description: DataTypes.TEXT,
|
description: DataTypes.TEXT,
|
||||||
imageURL: DataTypes.STRING,
|
imageURL: DataTypes.STRING,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
* The `models/index` file will call this method automatically.
|
* The `models/index` file will call this method automatically.
|
||||||
*/
|
*/
|
||||||
static associate(models) {
|
static associate(models) {
|
||||||
Character.belongsToMany(models.Card, { through: 'CardCharacter' });
|
|
||||||
Character.belongsTo(models.Band, { foreignKey: 'bandId', });
|
Character.belongsTo(models.Band, { foreignKey: 'bandId', });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
util/cards.js
Normal file
23
util/cards.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const { customAlphabet } = require("nanoid");
|
||||||
|
const { Card, Character } = require("../models");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "CardUtils",
|
||||||
|
generateIdentifier: function() {
|
||||||
|
const nanoid = customAlphabet('6789BCDFGHJKLMNPQRTW',6);
|
||||||
|
return nanoid();
|
||||||
|
},
|
||||||
|
|
||||||
|
getNextPrintNumber: async function(characterId) {
|
||||||
|
let count = await Card.count({
|
||||||
|
where: {
|
||||||
|
characterId: characterId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return count + 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
getCharacterCount: async function(characterId) {
|
||||||
|
return await Character.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,9 @@ async function syncDb() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
name: "DbUtils",
|
||||||
getDb,
|
getDb,
|
||||||
syncDb
|
syncDb
|
||||||
}
|
}
|
||||||
25
util/index.js
Normal file
25
util/index.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const basename = path.basename(__filename);
|
||||||
|
const utils = {};
|
||||||
|
|
||||||
|
fs
|
||||||
|
.readdirSync(__dirname)
|
||||||
|
.filter(file => {
|
||||||
|
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
|
||||||
|
})
|
||||||
|
.forEach(file => {
|
||||||
|
const util = require(path.join(__dirname, file));
|
||||||
|
utils[util.name] = util;
|
||||||
|
console.log(`Registered util: ${util.name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(utils).forEach(modelName => {
|
||||||
|
if (utils[modelName].associate) {
|
||||||
|
utils[modelName].associate(utils);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = utils;
|
||||||
27
util/reply.js
Normal file
27
util/reply.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
const { ActionRowBuilder, ButtonBuilder, ButtonStyle, ComponentType } = require("discord.js");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "ReplyUtils",
|
||||||
|
recreateComponents: function(components) {
|
||||||
|
console.log("Recreating components");
|
||||||
|
for (let i = 0; i < components.length; i++) {
|
||||||
|
let row = new ActionRowBuilder();
|
||||||
|
for (let j = 0; j < components[i].components.length; j++) {
|
||||||
|
console.log(components[i].components[j]);
|
||||||
|
console.log(`Recreating button ${components[i].components[j].customId}`);
|
||||||
|
let button = new ButtonBuilder();
|
||||||
|
button.setCustomId(components[i].components[j].customId);
|
||||||
|
button.setLabel(components[i].components[j].label);
|
||||||
|
button.setStyle(components[i].components[j].style);
|
||||||
|
if (components[i].components[j].emoji) {
|
||||||
|
button.setEmoji(components[i].components[j].emoji);
|
||||||
|
}
|
||||||
|
if (components[i].components[j].disabled) {
|
||||||
|
button.setDisabled(components[i].components[j].disabled);
|
||||||
|
}
|
||||||
|
row.addComponents(button);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
28
util/users.js
Normal file
28
util/users.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const { User } = require("../models");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: "UserUtils",
|
||||||
|
getUserByDiscordId: async function(discordId) {
|
||||||
|
return await User.findOne({
|
||||||
|
where: {
|
||||||
|
discordId: discordId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
registrationCheck: async function(interaction) {
|
||||||
|
let user = await this.getUserByDiscordId(interaction.member.id);
|
||||||
|
if (user) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!interaction.isButton() && interaction.commandName === "register") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
interaction.reply({
|
||||||
|
content: `${interaction.member} You are not registered, use the /register command`,
|
||||||
|
ephemeral: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user