Add hub settings and setup maybe?
This commit is contained in:
parent
197f497652
commit
192d1431c1
9
.env.example
Normal file
9
.env.example
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
SESSION_SECRET=superlongandsecretrandomstring
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_USER=mystore
|
||||||
|
DB_PASS=mystore
|
||||||
|
DB_NAME=mystoredb
|
||||||
|
NODE_ENV=production
|
||||||
|
DISCORD_TOKEN=my discord bot token
|
||||||
|
BASE_URL=https://np.example.com
|
10
commands.js
10
commands.js
|
@ -220,6 +220,16 @@ module.exports = {
|
||||||
{
|
{
|
||||||
name: "hub",
|
name: "hub",
|
||||||
description: "Get the hub URL.",
|
description: "Get the hub URL.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "setup",
|
||||||
|
description: "Setup the bot for this server",
|
||||||
|
default_member_permissions: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "settings",
|
||||||
|
description: "View and manage hub settings",
|
||||||
|
default_member_permissions: 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
admin: []
|
admin: []
|
||||||
|
|
|
@ -9,7 +9,7 @@ const execute = async (interaction) => {
|
||||||
const [pairing] = await pool.query('SELECT * FROM users WHERE pairingCode = ?', [pairingCode]);
|
const [pairing] = await pool.query('SELECT * FROM users WHERE pairingCode = ?', [pairingCode]);
|
||||||
if (!pairing) return interaction.reply({ content: "Invalid pairing code", ephemeral: true });
|
if (!pairing) return interaction.reply({ content: "Invalid pairing code", ephemeral: true });
|
||||||
await pool.query('UPDATE users SET discordId = ?, discordDisplayName = ?, pairingCode = NULL WHERE pairingCode = ?', [discordID, interaction.user.displayName, pairingCode]);
|
await pool.query('UPDATE users SET discordId = ?, discordDisplayName = ?, pairingCode = NULL WHERE pairingCode = ?', [discordID, interaction.user.displayName, pairingCode]);
|
||||||
return interaction.reply({ content: "Successfully linked your account", ephemeral: true });
|
return interaction.reply({ content: "Successfully linked your account. Please relaunch the hub!", ephemeral: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { execute }
|
module.exports = { execute }
|
47
commands/settings.js
Normal file
47
commands/settings.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
const client = global.discord_client
|
||||||
|
const pool = global.db_pool;
|
||||||
|
const hubSettingsHandler = require('../messageHandlers/hub_settings.js');
|
||||||
|
|
||||||
|
if (!global.productCreationData) global.productCreationData = {};
|
||||||
|
|
||||||
|
const execute = async (interaction) => {
|
||||||
|
if (!interaction.guildId) return interaction.reply({ content: "This command can only be used in a server", ephemeral: true });
|
||||||
|
if (global.hubSettingsHandlers[interaction.user.id]) return interaction.reply({ content: "See DMs!", ephemeral: true });
|
||||||
|
try {
|
||||||
|
const guildId = interaction.guildId;
|
||||||
|
const hubResult = await pool.query(`SELECT * FROM hubs WHERE discordGuild = ?`, [guildId]);
|
||||||
|
if (hubResult.length === 0) {
|
||||||
|
delete global.hubSettingsHandlers[interaction.user.id];
|
||||||
|
return interaction.reply({ content: "This guild does not have a hub set up!", ephemeral: true });
|
||||||
|
}
|
||||||
|
// Proceed with settings menu
|
||||||
|
await interaction.reply({ ephemeral: true, content: "Getting things ready..." });
|
||||||
|
await interaction.user.send({ embeds: [{
|
||||||
|
title: `Hub Settings for ${hubResult[0].name}`,
|
||||||
|
description: `**Short Description:** ${hubResult[0].shortDescription}\n**Long Description:** ${hubResult[0].longDescription}\n**Allow Gift Purchase:** ${hubResult[0].allowGiftPurchase ? "Yes" : "No"}\n**Terms of Service:** ${hubResult[0].tos}\n\nHub Secret Key: ||${hubResult[0].secretKey}||`,
|
||||||
|
color: 0x00AE86,
|
||||||
|
fields: [
|
||||||
|
{ name: "Main Menu", value: "Type an option number, or `cancel` to close." },
|
||||||
|
{ name: "1. Edit Short Description", value: "Change the short description of the hub." },
|
||||||
|
{ name: "2. Edit Long Description", value: "Change the long description of the hub." },
|
||||||
|
{ name: "3. Toggle Allow Gift Purchase", value: "Enable or disable allowing users to buy gifts for others on this hub." },
|
||||||
|
{ name: "4. Edit Terms of Service", value: "Change the terms of service for this hub." },
|
||||||
|
{ name: "5. Regenerate Secret Key", value: "Generate a new secret key for this hub. (Old key will be invalidated)" },
|
||||||
|
{ name: "6. Parcel Auto-Import", value: "Set up automatic importing of Parcel purchases when linking." }
|
||||||
|
]
|
||||||
|
}] });
|
||||||
|
await interaction.user.send({ content: "Please provide a description for the product. Say `cancel` to exit." });
|
||||||
|
interaction.editReply({ephemeral: true, content: "Check your DMs!"});
|
||||||
|
global.hubSettingsHandlers[interaction.user.id] = {
|
||||||
|
step: 1,
|
||||||
|
hub: hubResult[0].id
|
||||||
|
};
|
||||||
|
global.dmHandlers[interaction.user.id] = hubSettingsHandler;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
delete global.productCreationData[interaction.user.id];
|
||||||
|
return interaction.editReply({ content: "An error occurred.", ephemeral: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { execute }
|
46
commands/setup.js
Normal file
46
commands/setup.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
const client = global.discord_client
|
||||||
|
const pool = global.db_pool;
|
||||||
|
// /setup command to initialize a hub in the server
|
||||||
|
/* Hub table schema
|
||||||
|
CREATE TABLE IF NOT EXISTS hubs (
|
||||||
|
id CHAR(36) PRIMARY KEY DEFAULT UUID(),
|
||||||
|
ownerId BIGINT, -- Owner of the hub (Discord ID)
|
||||||
|
discordGuild BIGINT, -- Discord Guild ID
|
||||||
|
name VARCHAR(128), -- Name of the hub
|
||||||
|
shortDescription VARCHAR(256), -- Short description of the hub
|
||||||
|
longDescription TEXT, -- Long description of the hub
|
||||||
|
allowGiftPurchase BOOLEAN DEFAULT TRUE, -- Allow users to buy gifts for others on this hub.
|
||||||
|
tos TEXT DEFAULT 'This Hub does not have any Terms of Service yet. If you are the Hub owner, you can update this under settings.', -- Terms of Service
|
||||||
|
bgmId BIGINT DEFAULT NULL, -- Background Music ID
|
||||||
|
secretKey VARCHAR(128) UNIQUE NOT NULL -- Secret key for the hub to authenticate
|
||||||
|
)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const log = require('../utils/logger.js');
|
||||||
|
|
||||||
|
const execute = async (interaction) => {
|
||||||
|
if (!interaction.guildId) return interaction.reply({ content: "This command can only be used in a server", ephemeral: true });
|
||||||
|
try {
|
||||||
|
const guildId = interaction.guildId;
|
||||||
|
const [existingHub] = await pool.query('SELECT * FROM hubs WHERE discordGuild = ?', [guildId]);
|
||||||
|
if (existingHub) return interaction.reply({ content: "This server already has a hub set up.", ephemeral: true });
|
||||||
|
const ownerId = interaction.user.id;
|
||||||
|
const name = interaction.guild.name;
|
||||||
|
const shortDescription = "Our super cool product hub!";
|
||||||
|
const longDescription = "Welcome to our super cool product hub! We offer a variety of awesome products for you to explore and purchase. Enjoy your stay!";
|
||||||
|
const [result] = await pool.query('INSERT INTO hubs (ownerId, discordGuild, name, shortDescription, longDescription, secretKey) VALUES (?, ?, ?, ?, ?, ?)', [ownerId, guildId, name, shortDescription, longDescription, crypto.randomBytes(64).toString('hex')]);
|
||||||
|
|
||||||
|
if (result.affectedRows === 1) {
|
||||||
|
return interaction.reply({ content: `Hub successfully created with ID: \`${result.insertId}\`. Get details via the /settings command!`, ephemeral: true });
|
||||||
|
} else {
|
||||||
|
return interaction.reply({ content: "An error occurred while creating the hub. Please try again later.", ephemeral: true });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error);
|
||||||
|
return interaction.reply({ content: "An error occurred while creating the hub. Please try again later.", ephemeral: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { execute }
|
128
messageHandlers/hub_settings.js
Normal file
128
messageHandlers/hub_settings.js
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
const client = global.discord_client
|
||||||
|
const pool = global.db_pool;
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
|
||||||
|
const { pipeline } = require('stream');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
|
||||||
|
const streamPipeline = promisify(pipeline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads a file from a URL to a specified destination.
|
||||||
|
* @param {string} url - The URL to download the file from.
|
||||||
|
* @param {string} dest - The destination file path to save the file.
|
||||||
|
* @param {function} cb - Callback function called on completion or error.
|
||||||
|
*/
|
||||||
|
async function download(url, dest, cb) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
await streamPipeline(response.body, fs.createWriteStream(dest));
|
||||||
|
cb(null); // Signal success
|
||||||
|
} catch (error) {
|
||||||
|
cb(error); // Pass error to callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancel = (user) => {
|
||||||
|
delete global.hubSettingsHandlers[user.id];
|
||||||
|
delete global.dmHandlers[user.id];
|
||||||
|
user.send('Closing hub settings.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = { // Map of option number to step number
|
||||||
|
1: {step: 21, exec: () => {
|
||||||
|
return 'Please provide the new short description. Say `cancel` to exit.';
|
||||||
|
}},
|
||||||
|
2: {step: 22, exec: () => {
|
||||||
|
return 'Please provide the new long description. Say `cancel` to exit.';
|
||||||
|
}},
|
||||||
|
3: {step: 23, exec: async (hubId) => {
|
||||||
|
const [hub] = await pool.query('SELECT allowGiftPurchase FROM hubs WHERE id = ?', [hubId]);
|
||||||
|
if (!hub) return 'Error fetching hub data.';
|
||||||
|
const newValue = hub.allowGiftPurchase ? 0 : 1;
|
||||||
|
await pool.query('UPDATE hubs SET allowGiftPurchase = ? WHERE id = ?', [newValue, hubId]);
|
||||||
|
return `Allow Gift Purchase is now set to: ${newValue ? "Yes" : "No"}.\n\nType another option number, or \`cancel\` to exit.`;
|
||||||
|
}},
|
||||||
|
4: {step: 24, exec: () => {
|
||||||
|
return 'Please provide the new Terms of Service. Say `cancel` to exit.';
|
||||||
|
}},
|
||||||
|
5: {step: 25, exec: async (hubId) => {
|
||||||
|
const newKey = crypto.randomBytes(16).toString('hex');
|
||||||
|
await pool.query('UPDATE hubs SET secretKey = ? WHERE id = ?', [newKey, hubId]);
|
||||||
|
return `New secret key generated: ||${newKey}||\n\nType another option number, or \`cancel\` to exit.`;
|
||||||
|
}},
|
||||||
|
6: {step: 26, exec: () => {
|
||||||
|
return 'Parcel Auto-Import setup is not yet implemented. Type another option number, or `cancel` to exit.';
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
const execute = async (message) => {
|
||||||
|
switch (global.hubSettingsHandlers[message.author.id].step) {
|
||||||
|
case 1: // Main Menu
|
||||||
|
if (message.content.toLowerCase() === 'cancel') {
|
||||||
|
cancel(message.author);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const option = parseInt(message.content.trim());
|
||||||
|
if (!opts[option]) {
|
||||||
|
message.channel.send('Invalid option. Please enter a valid option number or `cancel` to exit.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
global.hubSettingsHandlers[message.author.id].step = opts[option].step;
|
||||||
|
const response = await opts[option].exec(global.hubSettingsHandlers[message.author.id].hub);
|
||||||
|
message.channel.send(response);
|
||||||
|
break;
|
||||||
|
case 21: // Edit Short Description
|
||||||
|
const shortDesc = message.content.trim();
|
||||||
|
if (shortDesc.toLowerCase() === 'cancel') {
|
||||||
|
cancel(message.author);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (shortDesc.length > 256) {
|
||||||
|
message.channel.send('Short description is too long. Please limit to 256 characters.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await pool.query('UPDATE hubs SET shortDescription = ? WHERE id = ?', [shortDesc, global.hubSettingsHandlers[message.author.id].hub]);
|
||||||
|
global.hubSettingsHandlers[message.author.id].step = 1;
|
||||||
|
message.channel.send('Short description updated.\n\nType an option number, or `cancel` to exit.');
|
||||||
|
break;
|
||||||
|
case 22: // Edit Long Description
|
||||||
|
const longDesc = message.content.trim();
|
||||||
|
if (longDesc.toLowerCase() === 'cancel') {
|
||||||
|
cancel(message.author);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (longDesc.length > 5000) {
|
||||||
|
message.channel.send('Long description is too long. Please limit to 5000 characters.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await pool.query('UPDATE hubs SET longDescription = ? WHERE id = ?', [longDesc, global.hubSettingsHandlers[message.author.id].hub]);
|
||||||
|
global.hubSettingsHandlers[message.author.id].step = 1;
|
||||||
|
message.channel.send('Long description updated.\n\nType an option number, or `cancel` to exit.');
|
||||||
|
break;
|
||||||
|
case 24: // Edit Terms of Service
|
||||||
|
const tos = message.content.trim();
|
||||||
|
if (tos.toLowerCase() === 'cancel') {
|
||||||
|
cancel(message.author);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tos.length > 10000) {
|
||||||
|
message.channel.send('Terms of Service is too long. Please limit to 10000 characters.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await pool.query('UPDATE hubs SET tos = ? WHERE id = ?', [tos, global.hubSettingsHandlers[message.author.id].hub]);
|
||||||
|
global.hubSettingsHandlers[message.author.id].step = 1;
|
||||||
|
message.channel.send('Terms of Service updated.\n\nType an option number, or `cancel` to exit.');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message.channel.send('Invalid step.');
|
||||||
|
cancel(message.author);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = execute
|
Loading…
Reference in a new issue