mirror of
https://github.com/nx-bat/discordbot-ng.git
synced 2026-11-11 07:13:37 -05:00
Compare commits
7
Commits
master
..
dd8aec7f07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd8aec7f07 | ||
|
|
11c977591c | ||
|
|
200681e94b | ||
|
|
d5c7e9c207 | ||
|
|
276ba43c96 | ||
|
|
3800f71f4b | ||
|
|
0df04e9169 |
@@ -1,9 +0,0 @@
|
|||||||
--------------------------------------------------------------------------------
|
|
||||||
-- Up
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE settings DROP COLUMN devwatch_role_id;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
-- Down
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
ALTER TABLE settings ADD devwatch_role_id TEXT;
|
|
||||||
+25
-8
@@ -1,20 +1,37 @@
|
|||||||
import { ButtonInteraction, Client, MessageFlags } from 'discord.js';
|
import { ButtonInteraction, Client, MessageFlags } from 'discord.js';
|
||||||
|
import { Database } from '../shared/Database';
|
||||||
import { Button } from '../types';
|
import { Button } from '../types';
|
||||||
import { SetSeverity } from '../utils';
|
|
||||||
|
|
||||||
class DevWatchButton implements Button<Client> {
|
class DevWatchButton implements Button<Client> {
|
||||||
id = 'dev-watch';
|
id = 'dev-watch';
|
||||||
|
|
||||||
async execute(context: Client<boolean>, interaction: ButtonInteraction): Promise<void> {
|
async execute(context: Client<boolean>, interaction: ButtonInteraction): Promise<void> {
|
||||||
if (!interaction.inGuild()) return;
|
if (!interaction.inGuild()) return;
|
||||||
await interaction.reply({
|
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
||||||
embeds: [{
|
|
||||||
...SetSeverity('warning'),
|
|
||||||
description: 'DevWatch roles have been deprecated in favour of the `/role-buttons create` command. Please notify an administrator to setup a new role-button.'
|
|
||||||
}],
|
|
||||||
|
|
||||||
flags: MessageFlags.Ephemeral,
|
try {
|
||||||
});
|
const settings = await Database.getOrCreateSettings(interaction.guildId);
|
||||||
|
if (!settings.devwatch_role_id) throw new Error('`devwatch_role_id` was not configured. Please configure a role then try again.');
|
||||||
|
|
||||||
|
const guild = await context.guilds.fetch(interaction.guildId);
|
||||||
|
const member = await guild.members.fetch(interaction.user.id);
|
||||||
|
if (!member) throw new Error('Unable to fetch the member executing this command.');
|
||||||
|
|
||||||
|
const bot = await guild.members.fetchMe();
|
||||||
|
const role = await guild.roles.fetch(settings.devwatch_role_id);
|
||||||
|
if (!role) throw new Error('The configured `devwatch_role_id` does not exist.');
|
||||||
|
if (role.position > bot.roles.highest.position) throw new Error('The configured `devwatch_role_id` is higher than my highest role.');
|
||||||
|
|
||||||
|
if (member.roles.cache.has(settings.devwatch_role_id)) {
|
||||||
|
await member.roles.remove(settings.devwatch_role_id);
|
||||||
|
await interaction.editReply({ content: 'Removed role.' });
|
||||||
|
} else {
|
||||||
|
await member.roles.add(settings.devwatch_role_id);
|
||||||
|
await interaction.editReply({ content: 'Added role.' });
|
||||||
|
}
|
||||||
|
} catch (error: Error | any) {
|
||||||
|
await interaction.editReply({ content: error.message }).catch(() => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { ActionRowBuilder, ApplicationIntegrationType, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, Client, InteractionContextType, MessageFlags, PermissionFlagsBits, SlashCommandBuilder } from 'discord.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'devwatch',
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName('devwatch')
|
||||||
|
.setDescription('Sends a dev watch role toggle button.')
|
||||||
|
.setIntegrationTypes(ApplicationIntegrationType.GuildInstall)
|
||||||
|
.setContexts(InteractionContextType.Guild)
|
||||||
|
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
|
||||||
|
.addStringOption(option =>
|
||||||
|
option
|
||||||
|
.setName('content')
|
||||||
|
.setDescription('The content of the message.')
|
||||||
|
.setRequired(false)
|
||||||
|
)
|
||||||
|
.addStringOption(option =>
|
||||||
|
option
|
||||||
|
.setName('button-label')
|
||||||
|
.setDescription('The button label.')
|
||||||
|
.setRequired(false)
|
||||||
|
),
|
||||||
|
handler: async function (client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
|
if (!interaction.channel || !interaction.channel.isSendable())
|
||||||
|
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Missing permissions to send to channel.' });
|
||||||
|
|
||||||
|
const content = interaction.options.getString('content') ?? '';
|
||||||
|
const label = interaction.options.getString('button-label') ?? 'Toggle DevWatch Role';
|
||||||
|
|
||||||
|
const button = new ButtonBuilder()
|
||||||
|
.setCustomId('dev-watch')
|
||||||
|
.setStyle(ButtonStyle.Primary)
|
||||||
|
.setLabel(label);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||||
|
.addComponents(button);
|
||||||
|
|
||||||
|
await interaction.channel.send({ components: [row], content });
|
||||||
|
|
||||||
|
interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Sent.' });
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,61 +1,6 @@
|
|||||||
import { ApplicationIntegrationType, ChatInputCommandInteraction, Client, InteractionContextType, MessageFlags, PermissionFlagsBits, SlashCommandBuilder } from 'discord.js';
|
import { ApplicationIntegrationType, ChatInputCommandInteraction, Client, InteractionContextType, MessageFlags, PermissionFlagsBits, SlashCommandBuilder } from 'discord.js';
|
||||||
import { Database } from '../shared/Database';
|
import { Database } from '../shared/Database';
|
||||||
import { getIdFromInput, SetSeverity } from '../utils';
|
import { getIdFromInput } from '../utils';
|
||||||
|
|
||||||
const userRegex = new RegExp(/^\d{16,20}$/);
|
|
||||||
|
|
||||||
async function addUserMapping(interaction: ChatInputCommandInteraction) {
|
|
||||||
const githubUsername = interaction.options.getString('github-name', true);
|
|
||||||
const discordId = getIdFromInput(interaction.options.getString('discord-user', true));
|
|
||||||
if (!userRegex.test(discordId)) throw new Error('The provided Discord user ID is invalid.');
|
|
||||||
|
|
||||||
const existingMappingId = await Database.getGithubFromDiscordId(discordId);
|
|
||||||
const existingMappingName = await Database.getDiscordIdFromGithub(githubUsername);
|
|
||||||
|
|
||||||
if (existingMappingId) throw new Error(`<@${discordId}> (${discordId}) is already mapped to \`${existingMappingId}\``);
|
|
||||||
if (existingMappingName) throw new Error(`\`${githubUsername}\` is already mapped to <@${existingMappingName}> (${existingMappingName})`);
|
|
||||||
|
|
||||||
await Database.putGithubUserMapping(discordId, githubUsername);
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [{
|
|
||||||
...SetSeverity('success'),
|
|
||||||
|
|
||||||
title: 'GitHub/Discord Mapping | Add',
|
|
||||||
description: `\`${githubUsername}\` has been linked to <@${discordId}>`,
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removeUserMapping(interaction: ChatInputCommandInteraction) {
|
|
||||||
const discordId = getIdFromInput(interaction.options.getString('discord-user', true));
|
|
||||||
if (!userRegex.test(discordId)) throw new Error('The provided Discord user ID is invalid.');
|
|
||||||
|
|
||||||
if (!await Database.removeGithubUserMapping(discordId)) throw new Error('No existing GitHub mapping was found.');
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [{
|
|
||||||
...SetSeverity('success'),
|
|
||||||
|
|
||||||
title: 'GitHub/Discord Mapping | Remove',
|
|
||||||
description: `<@${discordId}> is no longer linked.`,
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listUserMapping(interaction: ChatInputCommandInteraction) {
|
|
||||||
const allMappings = await Database.getAllGithubUserMappings();
|
|
||||||
if (allMappings.length < 1) throw new Error('No GitHub mappings have been configured.');
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [{
|
|
||||||
...SetSeverity('success'),
|
|
||||||
|
|
||||||
title: 'GitHub/Discord Mapping | List',
|
|
||||||
description: allMappings.map(m => `- <@${m.discord_id}> (${m.discord_id}) - ${m.github_username}`).join('\n'),
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'github-mapping',
|
name: 'github-mapping',
|
||||||
@@ -99,17 +44,37 @@ export default {
|
|||||||
.setDescription('List all github-discord mappings.')
|
.setDescription('List all github-discord mappings.')
|
||||||
),
|
),
|
||||||
handler: async function (client: Client, interaction: ChatInputCommandInteraction) {
|
handler: async function (client: Client, interaction: ChatInputCommandInteraction) {
|
||||||
if (!interaction.inGuild()) return;
|
await interaction.deferReply({ flags: [MessageFlags.Ephemeral] });
|
||||||
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
|
|
||||||
|
|
||||||
try {
|
const subcommand = await interaction.options.getSubcommand(true);
|
||||||
switch (interaction.options.getSubcommand(true)) {
|
|
||||||
case 'add': return await addUserMapping(interaction);
|
if (subcommand == 'add') {
|
||||||
case 'remove': return await removeUserMapping(interaction);
|
const discordUserInput = interaction.options.getString('discord-user', true);
|
||||||
case 'list': return await listUserMapping(interaction);
|
|
||||||
}
|
const idToUse = getIdFromInput(discordUserInput);
|
||||||
} catch (error: Error | any) {
|
|
||||||
await interaction.editReply({ content: error.message }).catch(() => {});
|
const githubName = interaction.options.getString('github-name', true);
|
||||||
|
|
||||||
|
const existingMappingId = await Database.getGithubFromDiscordId(idToUse);
|
||||||
|
const existingMappingName = await Database.getDiscordIdFromGithub(githubName);
|
||||||
|
|
||||||
|
if (existingMappingId) return interaction.editReply(`Discord user id is already mapped to ${existingMappingId}`);
|
||||||
|
if (existingMappingName) return interaction.editReply(`Github username is already mapped to <@${existingMappingName}> (${existingMappingName})`);
|
||||||
|
|
||||||
|
Database.putGithubUserMapping(idToUse, githubName);
|
||||||
|
|
||||||
|
return interaction.editReply('Mapping added.');
|
||||||
|
} else if (subcommand == 'remove') {
|
||||||
|
const discordUserInput = interaction.options.getString('discord-user', true);
|
||||||
|
|
||||||
|
const idToUse = getIdFromInput(discordUserInput);
|
||||||
|
|
||||||
|
Database.removeGithubUserMapping(idToUse);
|
||||||
|
return interaction.editReply('Mapping removed.');
|
||||||
|
} else if (subcommand == 'list') {
|
||||||
|
const allMappings = await Database.getAllGithubUserMappings();
|
||||||
|
|
||||||
|
return interaction.editReply(allMappings.map(m => `- <@${m.discord_id}> (${m.discord_id}) - ${m.github_username}`).join('\n'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -75,7 +75,12 @@ export default {
|
|||||||
.setDescription('Set the private helper role.')
|
.setDescription('Set the private helper role.')
|
||||||
.setRequired(false)
|
.setRequired(false)
|
||||||
)
|
)
|
||||||
|
.addRoleOption(option =>
|
||||||
|
option
|
||||||
|
.setName('devwatch-role')
|
||||||
|
.setDescription('Set the DevWatch role.')
|
||||||
|
.setRequired(false)
|
||||||
|
)
|
||||||
.addChannelOption(option =>
|
.addChannelOption(option =>
|
||||||
option
|
option
|
||||||
.setName('add-staff-category')
|
.setName('add-staff-category')
|
||||||
@@ -199,6 +204,12 @@ export default {
|
|||||||
response.push(`**private_help_role_id** has been set to: ${privateHelperRole}.`);
|
response.push(`**private_help_role_id** has been set to: ${privateHelperRole}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devWatchRole = interaction.options.getRole('devwatch-role');
|
||||||
|
if (devWatchRole) {
|
||||||
|
await Database.updateSettings(interaction.guildId, 'devwatch_role_id', devWatchRole.id);
|
||||||
|
response.push(`**devwatch_role_id** has been set to ${devWatchRole}.`);
|
||||||
|
}
|
||||||
|
|
||||||
const addCategory = interaction.options.getChannel('add-staff-category');
|
const addCategory = interaction.options.getChannel('add-staff-category');
|
||||||
if (addCategory) {
|
if (addCategory) {
|
||||||
if (addCategory.type == ChannelType.GuildCategory) {
|
if (addCategory.type == ChannelType.GuildCategory) {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Client, Guild } from 'discord.js';
|
import { Client, Guild } from 'discord.js';
|
||||||
import { config } from '../../config';
|
|
||||||
import { Database } from '../../shared/Database';
|
import { Database } from '../../shared/Database';
|
||||||
import { Event } from '../../types';
|
import { Event } from '../../types';
|
||||||
|
|
||||||
@@ -7,11 +6,6 @@ class GuildCreateEvent implements Event<Client, 'guildCreate'> {
|
|||||||
event = 'guildCreate' as const;
|
event = 'guildCreate' as const;
|
||||||
|
|
||||||
async execute(context: Client<boolean>, guild: Guild): Promise<void> {
|
async execute(context: Client<boolean>, guild: Guild): Promise<void> {
|
||||||
if (guild.id != config.DISCORD_GUILD_ID) {
|
|
||||||
await guild.leave();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Database.getOrCreateSettings(guild.id);
|
await Database.getOrCreateSettings(guild.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,10 +126,6 @@ client.on('interactionCreate', async (interaction) => {
|
|||||||
client.on('clientReady', async () => {
|
client.on('clientReady', async () => {
|
||||||
console.log(`Logged in as ${client.user!.tag}!`);
|
console.log(`Logged in as ${client.user!.tag}!`);
|
||||||
|
|
||||||
for (const guild of client.guilds.cache.values()) {
|
|
||||||
if (guild.id != config.DISCORD_GUILD_ID) await guild.leave();
|
|
||||||
}
|
|
||||||
|
|
||||||
await loadHandlersFrom('commands', commands);
|
await loadHandlersFrom('commands', commands);
|
||||||
await loadHandlersFrom('context-menus', contextMenus);
|
await loadHandlersFrom('context-menus', contextMenus);
|
||||||
await loadHandlersFrom('menus', menus);
|
await loadHandlersFrom('menus', menus);
|
||||||
|
|||||||
@@ -364,9 +364,8 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async removeGithubUserMapping(discordId: string): Promise<boolean> {
|
static async removeGithubUserMapping(discordId: string) {
|
||||||
const result = await Database.db.run('DELETE FROM github_user_mapping WHERE discord_id_hash = ?', Encrypter.hash(discordId));
|
await Database.db.run('DELETE from github_user_mapping WHERE discord_id_hash = ?', Encrypter.encrypt(discordId));
|
||||||
return (result.changes ?? 0) > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|||||||
Vendored
+1
@@ -22,6 +22,7 @@ export type GuildSettings = {
|
|||||||
voice_logs_channel_id?: string
|
voice_logs_channel_id?: string
|
||||||
admin_role_id?: string
|
admin_role_id?: string
|
||||||
private_help_role_id?: string
|
private_help_role_id?: string
|
||||||
|
devwatch_role_id?: string
|
||||||
staff_categories?: string
|
staff_categories?: string
|
||||||
safe_channels?: string
|
safe_channels?: string
|
||||||
link_skip_channels?: string
|
link_skip_channels?: string
|
||||||
|
|||||||
Reference in New Issue
Block a user