aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Isom <[email protected]>2022-01-29 11:20:40 -0500
committerMax Isom <[email protected]>2022-01-29 11:20:40 -0500
commit1621b2c2815f7458df19320361a4a5a41c9cf4d3 (patch)
tree47c7c1377243c5d91a95c0c7d9217ad3a3b9cfdb /src
parent8e00726dc2c8179c7aa03f72e96544e78b4fb001 (diff)
downloadmuse-1621b2c2815f7458df19320361a4a5a41c9cf4d3.tar.xz
muse-1621b2c2815f7458df19320361a4a5a41c9cf4d3.zip
Add permissions system
Diffstat (limited to 'src')
-rw-r--r--src/bot.ts5
-rw-r--r--src/commands/config.ts103
-rw-r--r--src/commands/favorites.ts12
-rw-r--r--src/inversify.config.ts2
-rw-r--r--src/utils/update-permissions-for-guild.ts44
5 files changed, 162 insertions, 4 deletions
diff --git a/src/bot.ts b/src/bot.ts
index 3ba15bc..d6bf02f 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -13,6 +13,7 @@ import Config from './services/config.js';
import {generateDependencyReport} from '@discordjs/voice';
import {REST} from '@discordjs/rest';
import {Routes} from 'discord-api-types/v9';
+import updatePermissionsForGuild from './utils/update-permissions-for-guild.js';
@injectable()
export default class {
@@ -146,6 +147,10 @@ export default class {
);
}
+ // Update permissions
+ spinner.text = '📡 updating permissions...';
+ await Promise.all(this.client.guilds.cache.map(async guild => updatePermissionsForGuild(guild)));
+
spinner.succeed(`Ready! Invite the bot with https://discordapp.com/oauth2/authorize?client_id=${this.client.user?.id ?? ''}&scope=bot%20applications.commands&permissions=2184236096`);
});
diff --git a/src/commands/config.ts b/src/commands/config.ts
new file mode 100644
index 0000000..65aa36b
--- /dev/null
+++ b/src/commands/config.ts
@@ -0,0 +1,103 @@
+import {SlashCommandBuilder} from '@discordjs/builders';
+import {CommandInteraction, MessageEmbed} from 'discord.js';
+import {injectable} from 'inversify';
+import {prisma} from '../utils/db.js';
+import updatePermissionsForGuild from '../utils/update-permissions-for-guild.js';
+import Command from './index.js';
+
+@injectable()
+export default class implements Command {
+ public readonly slashCommand = new SlashCommandBuilder()
+ .setName('config')
+ .setDescription('configure bot settings')
+ .addSubcommand(subcommand => subcommand
+ .setName('set-playlist-limit')
+ .setDescription('set the maximum number of tracks that can be added from a playlist')
+ .addIntegerOption(option => option
+ .setName('limit')
+ .setDescription('maximum number of tracks')
+ .setRequired(true)))
+ .addSubcommand(subcommand => subcommand
+ .setName('set-role')
+ .setDescription('set the role that is allowed to use the bot')
+ .addRoleOption(option => option
+ .setName('role')
+ .setDescription('allowed role')
+ .setRequired(true)))
+ .addSubcommand(subcommand => subcommand
+ .setName('get')
+ .setDescription('show all settings'));
+
+ async execute(interaction: CommandInteraction) {
+ switch (interaction.options.getSubcommand()) {
+ case 'set-playlist-limit': {
+ const limit = interaction.options.getInteger('limit')!;
+
+ if (limit < 1) {
+ throw new Error('invalid limit');
+ }
+
+ await prisma.setting.update({
+ where: {
+ guildId: interaction.guild!.id,
+ },
+ data: {
+ playlistLimit: limit,
+ },
+ });
+
+ await interaction.reply('👍 limit updated');
+
+ break;
+ }
+
+ case 'set-role': {
+ const role = interaction.options.getRole('role')!;
+
+ await prisma.setting.update({
+ where: {
+ guildId: interaction.guild!.id,
+ },
+ data: {
+ roleId: role.id,
+ },
+ });
+
+ await updatePermissionsForGuild(interaction.guild!);
+
+ await interaction.reply('👍 role updated');
+
+ break;
+ }
+
+ case 'get': {
+ const embed = new MessageEmbed().setTitle('Config');
+
+ const config = await prisma.setting.findUnique({where: {guildId: interaction.guild!.id}});
+
+ if (!config) {
+ throw new Error('no config found');
+ }
+
+ const settingsToShow = {
+ 'Playlist Limit': config.playlistLimit,
+ Role: config.roleId ? `<@&${config.roleId}>` : 'not set',
+ };
+
+ let description = '';
+ for (const [key, value] of Object.entries(settingsToShow)) {
+ description += `**${key}**: ${value}\n`;
+ }
+
+ embed.setDescription(description);
+
+ await interaction.reply({embeds: [embed]});
+
+ break;
+ }
+
+ default:
+ throw new Error('unknown subcommand');
+ }
+ }
+}
diff --git a/src/commands/favorites.ts b/src/commands/favorites.ts
index b15a5c9..98f1ba9 100644
--- a/src/commands/favorites.ts
+++ b/src/commands/favorites.ts
@@ -75,6 +75,7 @@ export default class implements Command {
}
async handleAutocompleteInteraction(interaction: AutocompleteInteraction) {
+ const subcommand = interaction.options.getSubcommand();
const query = interaction.options.getString('name')!.trim();
const favorites = await prisma.favoriteQuery.findMany({
@@ -83,13 +84,16 @@ export default class implements Command {
},
});
- const names = favorites.map(favorite => favorite.name);
+ let results = query === '' ? favorites : favorites.filter(f => f.name.startsWith(query));
- const results = query === '' ? names : names.filter(name => name.startsWith(query));
+ if (subcommand === 'remove') {
+ // Only show favorites that user is allowed to remove
+ results = interaction.member?.user.id === interaction.guild?.ownerId ? results : results.filter(r => r.authorId === interaction.member!.user.id);
+ }
await interaction.respond(results.map(r => ({
- name: r,
- value: r,
+ name: r.name,
+ value: r.name,
})));
}
diff --git a/src/inversify.config.ts b/src/inversify.config.ts
index f423614..d29d3de 100644
--- a/src/inversify.config.ts
+++ b/src/inversify.config.ts
@@ -15,6 +15,7 @@ import GetSongs from './services/get-songs.js';
// Comands
import Command from './commands';
import Clear from './commands/clear.js';
+import Config from './commands/config.js';
import Disconnect from './commands/disconnect.js';
import Favorites from './commands/favorites.js';
import ForwardSeek from './commands/fseek.js';
@@ -54,6 +55,7 @@ container.bind<AddQueryToQueue>(TYPES.Services.AddQueryToQueue).to(AddQueryToQue
// Commands
[
Clear,
+ Config,
Disconnect,
Favorites,
ForwardSeek,
diff --git a/src/utils/update-permissions-for-guild.ts b/src/utils/update-permissions-for-guild.ts
new file mode 100644
index 0000000..ca7c427
--- /dev/null
+++ b/src/utils/update-permissions-for-guild.ts
@@ -0,0 +1,44 @@
+import {ApplicationCommandPermissionData, Guild} from 'discord.js';
+import {prisma} from './db.js';
+
+const COMMANDS_TO_LIMIT_TO_GUILD_OWNER = ['config'];
+
+const updatePermissionsForGuild = async (guild: Guild) => {
+ const settings = await prisma.setting.findUnique({
+ where: {
+ guildId: guild.id,
+ },
+ });
+
+ if (!settings) {
+ throw new Error('could not find settings for guild');
+ }
+
+ const permissions: ApplicationCommandPermissionData[] = [
+ {
+ id: guild.ownerId,
+ type: 'USER',
+ permission: true,
+ },
+ {
+ id: guild.roles.everyone.id,
+ type: 'ROLE',
+ permission: false,
+ },
+ ];
+ const commands = await guild.commands.fetch();
+
+ await guild.commands.permissions.set({fullPermissions: commands.map(command => ({
+ id: command.id,
+ permissions: COMMANDS_TO_LIMIT_TO_GUILD_OWNER.includes(command.name) ? permissions : [
+ ...permissions,
+ ...(settings.roleId ? [{
+ id: settings.roleId,
+ type: 'ROLE' as const,
+ permission: true,
+ }] : []),
+ ],
+ }))});
+};
+
+export default updatePermissionsForGuild;