Skip to content

Commit

Permalink
feat(bot): dynamic configs
Browse files Browse the repository at this point in the history
  • Loading branch information
lastarc committed Jul 6, 2024
1 parent d9a8242 commit 510e12e
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 1 deletion.
5 changes: 4 additions & 1 deletion bot/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ node_modules
tmp
.env
.git
.gitignore
.gitignore

/cookies.txt
/config.json
2 changes: 2 additions & 0 deletions bot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/cookies.txt
/config.json
2 changes: 2 additions & 0 deletions bot/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ RUN apk add --no-cache yt-dlp
COPY . /app
WORKDIR /app

VOLUME /app/config.json

RUN pnpm install

CMD ["pnpm", "start"]
4 changes: 4 additions & 0 deletions bot/blame.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const configStore = require('./config-store');

/**
* @param client {import('discord.js').Client}
* @param channelId {import('discord.js').Message['id']}
*/
const onCommandFail = async (client, channelId) => {
if (configStore.getOr('blame.enabled', 'false') !== 'true') return;

const WHO_TO_BLAME = process.env.WHO_TO_BLAME;
if (!WHO_TO_BLAME) return;
const HEHE_EMOJI = process.env.HEHE_EMOJI || '';
Expand Down
19 changes: 19 additions & 0 deletions bot/commands/config/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { SlashCommandBuilder } = require('discord.js');
const configStore = require('../../config-store');

module.exports = {
data: new SlashCommandBuilder()
.setName('cfg-delete')
.setDescription('Deletes a key from the config store.')
.addStringOption(option => option.setName('key')
.setDescription('The key to delete.')
.setRequired(true)),
async execute(interaction) {
if (interaction.user.id !== process.env.OWNER_ID) {
await interaction.reply({ content: 'You do not have permission to run this command.', ephemeral: true });
return;
}
configStore.delete(interaction.options.getString('key'));
await interaction.reply(`Deleted \`${interaction.options.getString('key')}\`.`, { ephemeral: true });
},
};
18 changes: 18 additions & 0 deletions bot/commands/config/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const { SlashCommandBuilder } = require('discord.js');
const configStore = require('../../config-store');

module.exports = {
data: new SlashCommandBuilder()
.setName('cfg-get')
.setDescription('Gets a key from the config store.')
.addStringOption(option => option.setName('key')
.setDescription('The key to get.')
.setRequired(true)),
async execute(interaction) {
if (interaction.user.id !== process.env.OWNER_ID) {
await interaction.reply({ content: 'You do not have permission to run this command.', ephemeral: true });
return;
}
await interaction.reply(`The value of \`${interaction.options.getString('key')}\` is: \`${configStore.get(interaction.options.getString('key'))}\``, { ephemeral: true });
},
};
15 changes: 15 additions & 0 deletions bot/commands/config/list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const { SlashCommandBuilder } = require('discord.js');
const configStore = require('../../config-store');

module.exports = {
data: new SlashCommandBuilder()
.setName('cfg-list')
.setDescription('Lists all the keys in the config store.'),
async execute(interaction) {
if (interaction.user.id !== process.env.OWNER_ID) {
await interaction.reply({ content: 'You do not have permission to run this command.', ephemeral: true });
return;
}
await interaction.reply(`The keys in the config store are: \`${JSON.stringify(configStore.list())}\``, { ephemeral: true });
},
};
22 changes: 22 additions & 0 deletions bot/commands/config/set.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { SlashCommandBuilder } = require('discord.js');
const configStore = require('../../config-store');

module.exports = {
data: new SlashCommandBuilder()
.setName('cfg-set')
.setDescription('Sets a key in the config store.')
.addStringOption(option => option.setName('key')
.setDescription('The key to set.')
.setRequired(true))
.addStringOption(option => option.setName('value')
.setDescription('The value to set.')
.setRequired(true)),
async execute(interaction) {
if (interaction.user.id !== process.env.OWNER_ID) {
await interaction.reply({ content: 'You do not have permission to run this command.', ephemeral: true });
return;
}
configStore.set(interaction.options.getString('key'), interaction.options.getString('value'));
await interaction.reply(`Set \`${interaction.options.getString('key')}\` to \`${interaction.options.getString('value')}\`.`, { ephemeral: true });
},
};
6 changes: 6 additions & 0 deletions bot/commands/media/instagram.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const S3 = require('../../s3');
const crypto = require('crypto');
const EmbedProxyClient = require('../../embed-proxy-client');
const { onCommandFail } = require('../../blame');
const configStore = require('../../config-store');

const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME;
if (!S3_BUCKET_NAME) throw new Error('No bucket name provided');
Expand All @@ -27,6 +28,11 @@ module.exports = {
const force = interaction.options.getBoolean('force') || false;
console.log({ videoUrl, force });

if (configStore.getOr('instagram.enabled', 'true') !== 'true') {
await interaction.reply('Instagram support is disabled');
return;
}

const replyMsg = await interaction.reply('Processing Instagram link...');

// hash the videoUrl
Expand Down
6 changes: 6 additions & 0 deletions bot/commands/media/tiktok.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const S3 = require('../../s3');
const crypto = require('crypto');
const EmbedProxyClient = require('../../embed-proxy-client');
const { onCommandFail } = require('../../blame');
const configStore = require('../../config-store');

const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME;
if (!S3_BUCKET_NAME) throw new Error('No bucket name provided');
Expand All @@ -27,6 +28,11 @@ module.exports = {
const force = interaction.options.getBoolean('force') || false;
console.log({ videoUrl, force });

if (configStore.getOr('tiktok.enabled', 'true') !== 'true') {
await interaction.reply('TikTok support is disabled');
return;
}

const replyMsg = await interaction.reply('Processing TikTok link...');

// hash the videoUrl
Expand Down
56 changes: 56 additions & 0 deletions bot/config-store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const fs = require('node:fs');

class ConfigStore {
/**
* @param {string} fPath
*/
constructor(fPath) {
this.fPath = fPath;
if (!fs.existsSync(this.fPath)) {
fs.writeFileSync(this.fPath, '{}');
}
this.config = this.readFromFile();
}

readFromFile() {
return JSON.parse(fs.readFileSync(this.fPath, 'utf8'));
}

writeToFile() {
fs.writeFileSync(this.fPath, JSON.stringify(this.config, null, 2));
}

list() {
return Object.keys(this.config);
}

/**
* @param {string} key
*/
get(key) {
return this.config[key];
}

getOr(key, defaultValue) {
return this.config[key] || defaultValue;
}

/**
* @param {string} key
* @param {any} value
*/
set(key, value) {
this.config[key] = value;
this.writeToFile();
}

/**
* @param {string} key
*/
delete(key) {
delete this.config[key];
this.writeToFile();
}
}

module.exports = new ConfigStore('./config.json');

0 comments on commit 510e12e

Please sign in to comment.