From 05804cb78a0399d6d5eed2c702b8f2e3f13d103a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Gro=C3=9F?= Date: Wed, 17 Aug 2022 19:36:47 +0200 Subject: [PATCH] Updated models and migrations to new spec --- IdeaDump.md | 16 +++++++ README.md | 1 + commands/collection.js | 29 ++++++------ commands/drop.js | 19 ++++++-- commands/register.js | 7 ++- commands/userlist.js | 2 +- events/interactionCreate.js | 13 ++--- migrations/20220317121527-create-band.js | 40 ++++++++++++++++ migrations/20220417130917-create-guild.js | 21 +++++---- migrations/20220417132721-create-user.js | 22 +++++---- migrations/20220417155941-create-character.js | 27 +++++++---- migrations/20220417160003-create-card.js | 27 ++++++++--- migrations/20220817100736-create-bot.js | 36 ++++++++++++++ models/band.js | 28 +++++++++++ models/bot.js | 24 ++++++++++ models/card.js | 20 ++++---- models/character.js | 12 ++--- models/guild.js | 6 +-- models/user.js | 7 +-- package-lock.json | 17 +++++++ package.json | 1 + .../20220817134849-test-band-and-character.js | 47 +++++++++++++++++++ 22 files changed, 336 insertions(+), 86 deletions(-) create mode 100644 migrations/20220317121527-create-band.js create mode 100644 migrations/20220817100736-create-bot.js create mode 100644 models/band.js create mode 100644 models/bot.js create mode 100644 seeders/20220817134849-test-band-and-character.js diff --git a/IdeaDump.md b/IdeaDump.md index 8158774..cd76f77 100644 --- a/IdeaDump.md +++ b/IdeaDump.md @@ -34,6 +34,22 @@ Completed bands reward cosmetics and XP (scaled to band size) Band levels by collecting duplicates (?) as a long term hook +### Guild - Single guild the bot has joined +- int guildID +- int active | 0 inactive, 1 active, 2 banned/blocked +- int adminRoleId | role can configure server specific bot options +- date created +- date updated + +### Core - Global bot settings +- bool maintenance +- int[] adminIDs + +### User +- int userID +- int active | 0 inactive, 1 active, 2 banned/blocked +- int privacy | 0 public, 1 private + ## Profile Steal profile layout from Amaan with more customization diff --git a/README.md b/README.md index 5916f90..49c07fd 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,5 @@ If ran outside the container, DB_HOST must be set to localhost or the container' ```bash $npx sequelize db:migrate +$npx sequelize db:seed:all ``` diff --git a/commands/collection.js b/commands/collection.js index 28d8c20..5d0f70d 100644 --- a/commands/collection.js +++ b/commands/collection.js @@ -7,26 +7,19 @@ module.exports = { .setName("collection") .setDescription("List all cards in your collection"), async execute(interaction) { - //fetch the user given the userID + //fetch the user given the userID and include his cards const user = await User.findOne({ where: { - userID: interaction.member.id - } - }); - - //fetch all cards give the user id - const cards = await Card.findAll({ - where: { - ownerID: user.id + discordId: interaction.member.id }, - include: [{ - model: Character, - as: "character" + include: [{ + model: Card, + include: [Character] }] }); //if the user has no cards, tell him - if (cards.length === 0) { + if (user.Cards.length === 0) { interaction.reply({ content: "You have no cards in your collection", ephemeral: true @@ -36,8 +29,14 @@ module.exports = { //if the user has cards, list them let message = ""; - for (let i = 0; i < cards.length; i++) { - message += `${cards[i].id} - ${cards[i].characterID} ${cards[i].character.name} \n`; + for (let i = 0; i < user.Cards.length; i++) { + message += `${user.Cards[i].id} - ${user.Cards[i].characterId} \n`; + message += `Identifier: ${user.Cards[i].identifier} \n`; + message += `Name: ${user.Cards[i].Character.name} \n`; + message += `Image: ${user.Cards[i].Character.imageURL} \n`; + message += `Quality: ${user.Cards[i].quality} \n`; + message += `Print number: ${user.Cards[i].printNr} \n`; + message += `------------------------ \n`; } interaction.reply({ content: message, diff --git a/commands/drop.js b/commands/drop.js index 68304bc..45ed7fd 100644 --- a/commands/drop.js +++ b/commands/drop.js @@ -1,5 +1,6 @@ const { SlashCommandBuilder } = require("@discordjs/builders"); const { Card, User } = require("../models"); +const { customAlphabet } = require("nanoid"); module.exports = { data: new SlashCommandBuilder() @@ -16,15 +17,25 @@ module.exports = { //get user id from database given the userID const user = await User.findOne({ where: { - userID: interaction.member.id + 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: "00000", - ownerID: user.id, + characterId: interaction.options.getInteger("id"), + identifier: identifier, + quality: 1, + printNr: existingCharacterCount + 1, + userId: user.id }); //reply with the new card id diff --git a/commands/register.js b/commands/register.js index 4d64eda..a725609 100644 --- a/commands/register.js +++ b/commands/register.js @@ -9,7 +9,7 @@ module.exports = { async execute(interaction) { let user = await User.findOne({ where: { - userID: interaction.user.id + discordId: interaction.user.id } }); if (user) { @@ -19,9 +19,8 @@ module.exports = { }); } else { await User.create({ - userID: interaction.user.id, - banned: false, - registredAt: new Date() + discordId: interaction.user.id, + active: 1, }); interaction.reply({ content: "You are now registered", diff --git a/commands/userlist.js b/commands/userlist.js index b13b1da..8a3e041 100644 --- a/commands/userlist.js +++ b/commands/userlist.js @@ -10,7 +10,7 @@ module.exports = { let users = await User.findAll(); let userList = ""; for (let i = 0; i < users.length; i++) { - let username = await interaction.client.users.fetch(users[i].userID); + let username = await interaction.client.users.fetch(users[i].discordId); userList += `${username.username}#${username.discriminator}`; } if (userList === "") { diff --git a/events/interactionCreate.js b/events/interactionCreate.js index d2e4465..e6d7788 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -12,15 +12,16 @@ module.exports = { //check if guild exists in database let guildData = await Guild.findOne({ where: { - guildID: guild.id + guildId: guild.id } }); if (!guildData) { //create guild in database await Guild.create({ - guildID: guild.id, - ownerID: guild.ownerId, + guildId: guild.id, + adminRoleId: null, + active: 1 }); //send guild registered message to the interations channel interaction.channel.send({ @@ -32,7 +33,7 @@ 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: { - userID: interaction.member.id + discordId: interaction.member.id } }); if (!user && interaction.commandName !== "register") { @@ -52,8 +53,8 @@ module.exports = { } catch (err) { if (err) console.log(err); await interaction.reply({ - content: "An error occured processing the command", - ephemeral: true + content: `An error occured processing the command :(\n \`\`\`${JSON.stringify(err, null, 2)}\`\`\``, + ephemeral: false }); } } diff --git a/migrations/20220317121527-create-band.js b/migrations/20220317121527-create-band.js new file mode 100644 index 0000000..8c2883d --- /dev/null +++ b/migrations/20220317121527-create-band.js @@ -0,0 +1,40 @@ +'use strict'; +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('Bands', { + id: { + allowNull: false, + autoIncrement: false, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + description: { + type: Sequelize.TEXT + }, + imageURL: { + type: Sequelize.STRING + }, + enabled: { + allowNull: false, + type: Sequelize.BOOLEAN, + defaultValue: false + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('Bands'); + } +}; \ No newline at end of file diff --git a/migrations/20220417130917-create-guild.js b/migrations/20220417130917-create-guild.js index 6c438ab..fac346b 100644 --- a/migrations/20220417130917-create-guild.js +++ b/migrations/20220417130917-create-guild.js @@ -8,22 +8,27 @@ module.exports = { primaryKey: true, type: Sequelize.INTEGER }, - guildID: { - type: Sequelize.STRING + guildId: { + type: Sequelize.BIGINT, + allowNull: false }, - adminRoleID: { - type: Sequelize.STRING + adminRoleId: { + type: Sequelize.BIGINT, }, - owderID: { - type: Sequelize.STRING + active: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, updatedAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') } }); }, diff --git a/migrations/20220417132721-create-user.js b/migrations/20220417132721-create-user.js index 1be8460..4d0b92c 100644 --- a/migrations/20220417132721-create-user.js +++ b/migrations/20220417132721-create-user.js @@ -8,23 +8,29 @@ module.exports = { primaryKey: true, type: Sequelize.INTEGER }, - userID: { - type: Sequelize.STRING, + discordId: { + type: Sequelize.BIGINT, allowNull: false }, - banned: { - type: Sequelize.BOOLEAN + active: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 }, - registredAt: { - type: Sequelize.DATE + privacy: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 0 }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, updatedAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') } }); }, diff --git a/migrations/20220417155941-create-character.js b/migrations/20220417155941-create-character.js index 6b7efbe..e739361 100644 --- a/migrations/20220417155941-create-character.js +++ b/migrations/20220417155941-create-character.js @@ -4,32 +4,41 @@ module.exports = { await queryInterface.createTable('Characters', { id: { allowNull: false, - autoIncrement: true, + autoIncrement: false, primaryKey: true, type: Sequelize.INTEGER }, + bandId: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Bands', + key: 'id' + } + }, name: { type: Sequelize.STRING }, - rarity: { - type: Sequelize.INTEGER - }, description: { - type: Sequelize.STRING + type: Sequelize.TEXT }, imageURL: { type: Sequelize.STRING }, - imageHash: { - type: Sequelize.STRING + enabled: { + allowNull: false, + type: Sequelize.BOOLEAN, + defaultValue: false }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, updatedAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') } }); }, diff --git a/migrations/20220417160003-create-card.js b/migrations/20220417160003-create-card.js index 9f799c8..5e8b224 100644 --- a/migrations/20220417160003-create-card.js +++ b/migrations/20220417160003-create-card.js @@ -10,9 +10,10 @@ module.exports = { }, identifier: { allowNull: false, - type: Sequelize.STRING + type: Sequelize.STRING, + unique: true }, - characterID: { + characterId: { allowNull: false, type: Sequelize.INTEGER, references: { @@ -20,7 +21,11 @@ module.exports = { key: 'id' } }, - ownerID: { + quality: { + allowNull: false, + type: Sequelize.INTEGER + }, + userId: { type: Sequelize.INTEGER, allowNull: false, references: { @@ -28,17 +33,27 @@ module.exports = { key: 'id' } }, + imageHash: { + type: Sequelize.STRING + }, enabled: { allowNull: false, - type: Sequelize.BOOLEAN + type: Sequelize.BOOLEAN, + defaultValue: true + }, + printNr: { + allowNull: false, + type: Sequelize.INTEGER, }, createdAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, updatedAt: { allowNull: false, - type: Sequelize.DATE + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') } }); }, diff --git a/migrations/20220817100736-create-bot.js b/migrations/20220817100736-create-bot.js new file mode 100644 index 0000000..fbf5a9e --- /dev/null +++ b/migrations/20220817100736-create-bot.js @@ -0,0 +1,36 @@ +'use strict'; + +module.exports = { + async up (queryInterface, Sequelize) { + await queryInterface.createTable('Bot', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + maintenance: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + adminIDs: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }); + }, + + async down (queryInterface, Sequelize) { + await queryInterface.dropTable('Bot'); + } +}; diff --git a/models/band.js b/models/band.js new file mode 100644 index 0000000..bc66f81 --- /dev/null +++ b/models/band.js @@ -0,0 +1,28 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Band extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + Band.hasMany(models.Character); + } + } + Band.init({ + uniqueId: DataTypes.INTEGER, + name: DataTypes.STRING, + description: DataTypes.TEXT, + imageURL: DataTypes.STRING, + enabled: DataTypes.BOOLEAN + }, { + sequelize, + modelName: 'Band', + }); + return Band; +}; \ No newline at end of file diff --git a/models/bot.js b/models/bot.js new file mode 100644 index 0000000..b489f9a --- /dev/null +++ b/models/bot.js @@ -0,0 +1,24 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Bot extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + } + Bot.init({ + maintenance: DataTypes.BOOLEAN, + adminIDs: DataTypes.STRING + }, { + sequelize, + modelName: 'Guild', + }); + return Bot; +}; \ No newline at end of file diff --git a/models/card.js b/models/card.js index f21b0b7..7765b9d 100644 --- a/models/card.js +++ b/models/card.js @@ -10,22 +10,18 @@ module.exports = (sequelize, DataTypes) => { * The `models/index` file will call this method automatically. */ static associate(models) { - Card.belongsTo(models.Character, { - foreignKey: 'characterID', - as: 'character' - }); - Card.belongsTo(models.User, { - foreignKey: 'ownerID', - key: 'userId', - as: 'owner' - }); + Card.belongsTo(models.User); + Card.belongsTo(models.Character); } } Card.init({ - ownerID: DataTypes.STRING, identifier: DataTypes.STRING, - characterID: DataTypes.INTEGER, - enabled: { type: DataTypes.BOOLEAN, defaultValue: true } + characterId: DataTypes.INTEGER, + quality: DataTypes.INTEGER, + userId: DataTypes.STRING, + imageHash: DataTypes.STRING, + enabled: { type: DataTypes.BOOLEAN, defaultValue: true }, + printNr: DataTypes.INTEGER, }, { sequelize, modelName: 'Card', diff --git a/models/character.js b/models/character.js index 2c773d5..064def9 100644 --- a/models/character.js +++ b/models/character.js @@ -10,18 +10,16 @@ module.exports = (sequelize, DataTypes) => { * The `models/index` file will call this method automatically. */ static associate(models) { - Character.hasMany(models.Card, { - foreignKey: 'characterID', - as: 'cards' - }); + Character.belongsToMany(models.Card, { through: 'CardCharacter' }); + Character.belongsTo(models.Band, { foreignKey: 'bandId', }); } } Character.init({ name: DataTypes.STRING, - rarity: DataTypes.INTEGER, - description: DataTypes.STRING, + bandId: DataTypes.INTEGER, imageURL: DataTypes.STRING, - imageHash: DataTypes.STRING + description: DataTypes.TEXT, + enabled: DataTypes.BOOLEAN }, { sequelize, modelName: 'Character', diff --git a/models/guild.js b/models/guild.js index 276ca66..2232662 100644 --- a/models/guild.js +++ b/models/guild.js @@ -14,9 +14,9 @@ module.exports = (sequelize, DataTypes) => { } } Guild.init({ - guildID: DataTypes.STRING, - adminRoleID: DataTypes.STRING, - owderID: DataTypes.STRING + guildId: DataTypes.BIGINT, + adminRoleId: DataTypes.BIGINT, + active: DataTypes.INTEGER, }, { sequelize, modelName: 'Guild', diff --git a/models/user.js b/models/user.js index 21f935e..268db2a 100644 --- a/models/user.js +++ b/models/user.js @@ -11,12 +11,13 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { // define association here + User.hasMany(models.Card); } } User.init({ - userID: DataTypes.STRING, - banned: DataTypes.BOOLEAN, - registredAt: DataTypes.DATE + discordId: DataTypes.BIGINT, + active: DataTypes.INTEGER, + privacy: DataTypes.INTEGER }, { sequelize, modelName: 'User', diff --git a/package-lock.json b/package-lock.json index 3c018c8..86da4cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "discord.js": "^13.6.0", "dotenv": "^16.0.0", "mysql2": "^2.3.3", + "nanoid": "^3.0.0", "nodemon": "^2.0.15", "sequelize": "^6.19.0", "sequelize-cli": "^6.4.1" @@ -1401,6 +1402,17 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -3319,6 +3331,11 @@ } } }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, "next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", diff --git a/package.json b/package.json index 125604e..085a553 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "discord.js": "^13.6.0", "dotenv": "^16.0.0", "mysql2": "^2.3.3", + "nanoid": "^3.0.0", "nodemon": "^2.0.15", "sequelize": "^6.19.0", "sequelize-cli": "^6.4.1" diff --git a/seeders/20220817134849-test-band-and-character.js b/seeders/20220817134849-test-band-and-character.js new file mode 100644 index 0000000..49f9e3b --- /dev/null +++ b/seeders/20220817134849-test-band-and-character.js @@ -0,0 +1,47 @@ +'use strict'; + +module.exports = { + async up (queryInterface, Sequelize) { + /** + * Add seed commands here. + * + * Example: + * await queryInterface.bulkInsert('People', [{ + * name: 'John Doe', + * isBetaMember: false + * }], {}); + */ + await queryInterface.bulkInsert('Bands', [{ + id: 1, + name: 'BAND-MAID', + description: 'Band-Maid (stylized as BAND-MAID) is an all girl rock band from Tokyo that formed in July 2013. The band combines a rock sound with a maid image modeled on Japanese maid cafés.', + imageURL: 'https://cdn.discordapp.com/attachments/851543504831119380/1009467684490063892/unknown.png', + enabled: true + }]); + await queryInterface.bulkInsert('Characters', [{ + id: 1, + bandId: 1, + name: 'Miku Kobato', + description: 'Miku Kobato is a Japanese singer, songwriter and guitarist. She is the initial founding member and main lyricist for BAND-MAID.', + imageURL: 'https://cdn.discordapp.com/attachments/851543504831119380/1009468495077048330/unknown.png', + enabled: true + }, + { + id: 2, + bandId: 1, + name: 'Akane Hirose', + description: 'Akane Hirose is a Japanese drummer and founding member of BAND-MAID.', + imageURL: 'https://cdn.discordapp.com/attachments/851543504831119380/1009469985296490568/unknown.png', + enabled: true + }]); + }, + + async down (queryInterface, Sequelize) { + /** + * Add commands to revert seed here. + * + * Example: + * await queryInterface.bulkDelete('People', null, {}); + */ + } +};