switch from db to api

This commit is contained in:
ShuriZma 2024-06-21 17:25:39 +02:00
parent 80d52f525e
commit 858343d7b0
Signed by: ShuriZma
GPG Key ID: 8D289758EE9B8074
9 changed files with 276 additions and 94 deletions

91
package-lock.json generated
View File

@ -10,6 +10,7 @@
"license": "ISC",
"dependencies": {
"@devraelfreeze/discordjs-pagination": "^2.7.6",
"axios": "^1.7.2",
"discord.js": "^14.14.1",
"mysql2": "^3.10.0",
"ts-node": "^10.9.2"
@ -265,11 +266,45 @@
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
@ -320,6 +355,38 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
@ -369,6 +436,25 @@
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mysql2": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.10.0.tgz",
@ -414,6 +500,11 @@
"node": ">=12"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",

View File

@ -11,6 +11,7 @@
"license": "ISC",
"dependencies": {
"@devraelfreeze/discordjs-pagination": "^2.7.6",
"axios": "^1.7.2",
"discord.js": "^14.14.1",
"mysql2": "^3.10.0",
"ts-node": "^10.9.2"

View File

@ -6,13 +6,10 @@ import {
Events,
GatewayIntentBits,
Message,
PermissionsBitField,
REST,
Routes,
User,
APIUser
} from 'discord.js';
import * as sql from 'mysql2';
import config from "./config";
import Fact from "./commands/fact";
import AddFact from "./commands/addFact";
@ -20,15 +17,19 @@ import RemoveFact from "./commands/removeFact";
import EnableFact from "./commands/enableFact";
import EditFact from "./commands/editFact";
import Facts from "./commands/facts";
import axios from 'axios';
import {pagination} from "@devraelfreeze/discordjs-pagination";
export class Bot {
private connection: sql.Connection;
public axiosClient;
private static instance: Bot;
public init() {
const client = new Client({intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent]});
this.connectDatabase(true);
this.axiosClient = axios.create({
baseURL: config.apiUrl,
});
this.axiosClient.defaults.headers.common['x-api-key'] = config.apiKey;
this.registerCommands();
const commands: Collection<any, any> = new Collection();
@ -108,31 +109,6 @@ export class Bot {
})();
}
private connectDatabase(closeConnection: boolean) {
this.connection = sql.createConnection({
host: config.dbHost,
user: config.dbUser,
password: config.dbPassword,
database: config.dbName,
port: config.dbPort,
})
this.connection.execute('CREATE TABLE if NOT EXISTS facts (id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, content TEXT NOT NULL, active TINYINT(1) NOT NULL DEFAULT 1, fake TINYINT(1) NOT NULL DEFAULT 1, counter INT UNSIGNED NOT NULL DEFAULT 0);');
if (closeConnection) {
this.endConection();
}
}
public getConnection() {
this.connectDatabase(false);
return this.connection;
}
public endConection() {
this.connection.end();
}
public static getInstance(): Bot {
if (!Bot.instance) {
Bot.instance = new Bot();
@ -142,13 +118,23 @@ export class Bot {
}
public async sendEmbed(msg: Message<boolean> | ChatInputCommandInteraction) {
const [results] = await this.getConnection().promise().execute('SELECT * FROM facts;');
this.endConection();
let facts = [];
try {
const responseActive = await this.axiosClient.get('/facts-active');
const responseInactive = await this.axiosClient.get('/facts-active');
facts = responseActive.data.facts.concat(responseInactive.data.facts);
} catch (error) {
console.log('There was an error while querying the facts! ' + error.response.data.error + ': ' + error.response.data.message);
return await msg.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
}
let fields = [];
let embeds = [];
for (let index in results) {
let result = results[index];
for (let index in facts) {
let result = facts[index];
fields.push({
name: 'content',
@ -169,8 +155,14 @@ export class Bot {
});
fields.push({
name: 'fake',
value: result.fake ? 'True' : 'False',
name: 'real',
value: result.real ? 'True' : 'False',
inline: true,
});
fields.push({
name: 'source',
value: result.source,
inline: true,
});

View File

@ -12,14 +12,19 @@ const factOption = (new SlashCommandStringOption())
.setDescription('The fact.')
.setRequired(true);
const sourceOption = (new SlashCommandStringOption())
.setName('source')
.setDescription('The source of the fact.')
.setRequired(true);
const activeOption = (new SlashCommandBooleanOption())
.setName('active')
.setDescription('Should the fact be used?')
.setRequired(false);
const fakeOption = (new SlashCommandBooleanOption())
.setName('fake')
.setDescription('Is this a fake fact?')
.setName('real')
.setDescription('Is this a real fact?')
.setRequired(false);
export default {
@ -27,25 +32,30 @@ export default {
.setName('addfact')
.setDescription('Add a logtastic fact.')
.addStringOption(factOption)
.addStringOption(sourceOption)
.addBooleanOption(activeOption)
.addBooleanOption(fakeOption)
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator),
execute: async function (interaction: ChatInputCommandInteraction) {
const bot = Bot.getInstance();
await bot.getConnection().promise().execute(
'INSERT INTO facts SET content = ?, active = ?, fake = ?;',
[
interaction.options.data.at(0).value,
interaction.options.data.at(1)?.value ?? true,
interaction.options.data.at(2)?.value ?? false,
]
);
bot.endConection();
console.log('Fact has been saved!');
await bot.axiosClient.post('/createfact', {
content: interaction.options.data.at(0)?.value,
source: interaction.options.data.at(1)?.value,
active: interaction.options.data.at(2)?.value ?? true,
real: interaction.options.data.at(3)?.value ?? true,
}).catch(async function (error) {
console.log('There was an error while adding the fact! ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
console.log('Fact has been saved!');
return await interaction.reply({
content: 'Done!',
ephemeral: true,
});
},
};

View File

@ -15,16 +15,21 @@ const idOption = (new SlashCommandIntegerOption())
const factOption = (new SlashCommandStringOption())
.setName('fact')
.setDescription('The fact.')
.setRequired(true);
.setRequired(false);
const sourceOption = (new SlashCommandStringOption())
.setName('source')
.setDescription('The source of the fact.')
.setRequired(false);
const activeOption = (new SlashCommandBooleanOption())
.setName('active')
.setDescription('Should the fact be enabled?')
.setRequired(false);
const fakeOption = (new SlashCommandBooleanOption())
.setName('fake')
.setDescription('Is this a fake fact?')
const realOption = (new SlashCommandBooleanOption())
.setName('real')
.setDescription('Is this a real fact?')
.setRequired(false);
export default {
@ -33,25 +38,46 @@ export default {
.setDescription('Edit a logtastic fact.')
.addIntegerOption(idOption)
.addStringOption(factOption)
.addStringOption(sourceOption)
.addBooleanOption(activeOption)
.addBooleanOption(fakeOption)
.addBooleanOption(realOption)
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator),
execute: async function (interaction: ChatInputCommandInteraction) {
const bot = Bot.getInstance();
await bot.getConnection().promise().execute(
'UPDATE facts SET content = ?, active = IF(? != NULL, ?, active), fake = IF(? != NULL, ?, fake) WHERE id = ?;',
[
interaction.options.data.at(1).value,
interaction.options.data.at(2)?.value ?? null,
interaction.options.data.at(2)?.value ?? null,
interaction.options.data.at(3)?.value ?? null,
interaction.options.data.at(3)?.value ?? null,
interaction.options.data.at(0).value,
]
);
bot.endConection();
console.log('Fact has been saved!');
const factId = interaction.options.data.at(0).value;
let response = await bot.axiosClient.get('/fact/' + factId)
.catch(async function (error) {
console.log('There was an error while querying the fact! Tried to query fact with id ' + factId + '. ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
if (response.data.error) {
console.log('There was an error while querying the fact! Tried to query fact with id ' + factId + '.');
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
}
const fact = response.data.fact;
response = await bot.axiosClient.patch('/updatefact/' + factId, {
content: interaction.options.data.at(1)?.value ?? fact.content,
source: interaction.options.data.at(2)?.value ?? fact.source,
active: interaction.options.data.at(3)?.value ?? fact.active,
real: interaction.options.data.at(4)?.value ?? fact.real,
}).catch(async function (error) {
console.log('There was an error while updating the fact! Tried to edit fact with id ' + factId + '. ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
console.log('Fact has been saved!');
return await interaction.reply({
content: 'Done!',
ephemeral: true,

View File

@ -20,13 +20,38 @@ export default {
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator),
execute: async function (interaction: ChatInputCommandInteraction) {
const bot = Bot.getInstance();
await bot.getConnection().promise().execute(
'UPDATE facts SET active = 1 WHERE id = ?;',
[interaction.options.data.at(0).value]
);
bot.endConection();
console.log('Fact has been enabled!');
const factId = interaction.options.data.at(0).value;
let response = await bot.axiosClient.get('/fact/' + factId)
.catch(async function (error) {
console.log('There was an error while querying the fact! Tried to query fact with id ' + factId + '. ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
if (response.data.error) {
console.log('There was an error while querying the fact! Tried to query fact with id ' + factId + '.');
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
}
const fact = response.data.fact;
response = await bot.axiosClient.patch('/updatefact/' + factId, {
content: fact.content,
source: fact.source,
active: true
}).catch(async function (error) {
console.log('There was an error while updating the fact! Tried to enable fact with id ' + factId + '. ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
console.log('Fact has been enabled!');
return await interaction.reply({
content: 'Done!',
ephemeral: true,

View File

@ -1,5 +1,5 @@
import {
ChatInputCommandInteraction,
ChatInputCommandInteraction, EmbedBuilder,
SlashCommandBuilder,
} from 'discord.js';
import {Bot} from "../bot";
@ -10,16 +10,26 @@ export default {
.setDescription('Get a logtastic fact.'),
execute: async function (interaction: ChatInputCommandInteraction) {
const bot = Bot.getInstance();
const [results] = await bot.getConnection().promise().execute('SELECT * FROM facts WHERE active = 1 ORDER BY RAND() LIMIT 1;');
bot.endConection();
let fact = results[0];
await bot.getConnection().promise().execute('UPDATE facts SET counter = counter + 1 WHERE id = ?', [fact.id]);
bot.endConection();
const response = await bot.axiosClient.get('/randomfact')
.catch(async function (error) {
console.log('There was an error while querying the fact! ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
const fact = response.data.fact;
const embed = new EmbedBuilder()
.setTitle('Random Fact')
.setDescription(fact.content)
.setURL(fact.source)
.setColor(0xffe600);
console.log('Sent beaver fact with id: ' + fact.id);
return await interaction.reply({
content: fact.content,
embeds: [embed],
});
},
};

View File

@ -26,22 +26,52 @@ export default {
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator),
execute: async function (interaction: ChatInputCommandInteraction) {
const bot = Bot.getInstance();
const factId = interaction.options.data.at(0).value;
let response = await bot.axiosClient.get('/fact/' + factId)
.catch(async function (error) {
console.log('There was an error while querying the fact! Tried to query fact with id ' + factId + '. ' + response.data.error + ': ' + response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
if (response.data.error) {
console.log('There was an error while querying the fact! Tried to query fact with id ' + factId + '.');
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
}
const fact = response.data.fact;
if (interaction.options.data.at(1)?.value ?? false) {
await bot.getConnection().promise().execute(
'DELETE FROM facts WHERE id = ?;',
[interaction.options.data.at(0).value]
);
const response = await bot.axiosClient.delete('/deletefact/' + factId)
.catch(async function (error) {
console.log('There was an error while deleting the fact! Tried to delete fact with id ' + factId + '. ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
console.log('Fact has been deleted!');
} else {
await bot.getConnection().promise().execute(
'UPDATE facts SET active = 0 WHERE id = ?;',
[interaction.options.data.at(0).value]
);
const response = await bot.axiosClient.patch('/updatefact/' + factId, {
content: fact.content,
source: fact.source,
active: false
}).catch(async function (error) {
console.log('There was an error while updating the fact! Tried to disable fact with id ' + factId + '. ' + error.response.data.error + ': ' + error.response.data.message);
return await interaction.reply({
content: 'There was an error while executing this command!',
ephemeral: true,
});
});
console.log('Fact has been disabled!');
}
bot.endConection();
return await interaction.reply({
content: 'Done!',

View File

@ -1,10 +1,7 @@
export default {
dbName: '',
dbHost: '',
dbPort: 3306,
dbUser: '',
dbPassword: '',
token: '',
guildId: '',
clientId: '',
apiKey: '',
apiUrl: ''
};