diff --git a/backend/src/data/DefaultLogMessages.json b/backend/src/data/DefaultLogMessages.json index 02b93494..1ef3091b 100644 --- a/backend/src/data/DefaultLogMessages.json +++ b/backend/src/data/DefaultLogMessages.json @@ -40,6 +40,7 @@ "VOICE_CHANNEL_MOVE": "🎙 ↔ {userMention(member)} moved from **{oldChannel.name}** to **{newChannel.name}**", "VOICE_CHANNEL_LEAVE": "🎙 🔴 {userMention(member)} left **{channel.name}**", "VOICE_CHANNEL_FORCE_MOVE": "\uD83C\uDF99 ✍ {userMention(member)} was moved from **{oldChannel.name}** to **{newChannel.name}** by {userMention(mod)}", + "VOICE_CHANNEL_FORCE_DISCONNECT": "\uD83C\uDF99 🚫 {userMention(member)} was forcefully disconnected from **{oldChannel.name}** by {userMention(mod)}", "COMMAND": "🤖 {userMention(member)} used command in {channelMention(channel)}:\n`{command}`", diff --git a/backend/src/data/LogType.ts b/backend/src/data/LogType.ts index 60f6f9f7..bc62cd02 100644 --- a/backend/src/data/LogType.ts +++ b/backend/src/data/LogType.ts @@ -53,6 +53,7 @@ export enum LogType { MEMBER_ROLE_CHANGES, VOICE_CHANNEL_FORCE_MOVE, + VOICE_CHANNEL_FORCE_DISCONNECT, CASE_UPDATE, diff --git a/backend/src/plugins/Utility/UtilityPlugin.ts b/backend/src/plugins/Utility/UtilityPlugin.ts index 41a81d0e..56a00b4d 100644 --- a/backend/src/plugins/Utility/UtilityPlugin.ts +++ b/backend/src/plugins/Utility/UtilityPlugin.ts @@ -34,6 +34,7 @@ import { InfoCmd } from "./commands/InfoCmd"; import { SnowflakeInfoCmd } from "./commands/SnowflakeInfoCmd"; import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners"; import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin"; +import { VcdisconnectCmd } from "./commands/VcdisconnectCmd"; const defaultOptions: PluginOptions = { config: { @@ -53,6 +54,7 @@ const defaultOptions: PluginOptions = { can_ping: false, can_source: false, can_vcmove: false, + can_vckick: false, can_help: false, can_about: false, can_context: false, @@ -78,6 +80,7 @@ const defaultOptions: PluginOptions = { can_snowflake: true, can_nickname: true, can_vcmove: true, + can_vckick: true, can_help: true, can_context: true, can_jumbo: true, @@ -120,6 +123,7 @@ export const UtilityPlugin = zeppelinGuildPlugin()("utility", SourceCmd, ContextCmd, VcmoveCmd, + VcdisconnectCmd, VcmoveAllCmd, HelpCmd, AboutCmd, diff --git a/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts b/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts new file mode 100644 index 00000000..0d5e6925 --- /dev/null +++ b/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts @@ -0,0 +1,58 @@ +import { utilityCmd } from "../types"; +import { commandTypeHelpers as ct } from "../../../commandTypes"; +import { + channelMentionRegex, + errorMessage, + isSnowflake, + simpleClosestStringMatch, + stripObjectToScalars, +} from "../../../utils"; +import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { VoiceChannel } from "eris"; +import { LogType } from "../../../data/LogType"; +import { resolveChannel } from "knub/dist/helpers"; + +export const VcdisconnectCmd = utilityCmd({ + trigger: ["vcdisconnect", "vcdisc", "vcdc", "vckick", "vck"], + description: "Disconnect a member from their voice channel", + usage: "!vcdc @Dark", + permission: "can_vckick", + + signature: { + member: ct.resolvedMember(), + }, + + async run({ message: msg, args, pluginData }) { + if (!canActOn(pluginData, msg.member, args.member)) { + sendErrorMessage(pluginData, msg.channel, "Cannot move: insufficient permissions"); + return; + } + + if (!args.member.voiceState || !args.member.voiceState.channelID) { + sendErrorMessage(pluginData, msg.channel, "Member is not in a voice channel"); + return; + } + const channel = (await resolveChannel(pluginData.guild, args.member.voiceState.channelID)) as VoiceChannel; + + try { + await args.member.edit({ + channelID: null, + }); + } catch (e) { + sendErrorMessage(pluginData, msg.channel, "Failed to disconnect member"); + return; + } + + pluginData.state.logs.log(LogType.VOICE_CHANNEL_FORCE_DISCONNECT, { + mod: stripObjectToScalars(msg.author), + member: stripObjectToScalars(args.member, ["user", "roles"]), + oldChannel: stripObjectToScalars(channel), + }); + + sendSuccessMessage( + pluginData, + msg.channel, + `**${args.member.user.username}#${args.member.user.discriminator}** disconnected from **${channel.name}**`, + ); + }, +}); diff --git a/backend/src/plugins/Utility/commands/VcmoveCmd.ts b/backend/src/plugins/Utility/commands/VcmoveCmd.ts index 4d82c0d0..aa9a9131 100644 --- a/backend/src/plugins/Utility/commands/VcmoveCmd.ts +++ b/backend/src/plugins/Utility/commands/VcmoveCmd.ts @@ -26,8 +26,6 @@ export const VcmoveCmd = utilityCmd({ async run({ message: msg, args, pluginData }) { let channel: VoiceChannel; - const foo = args.member; - if (isSnowflake(args.channel)) { // Snowflake -> resolve channel directly const potentialChannel = pluginData.guild.channels.get(args.channel); @@ -78,7 +76,7 @@ export const VcmoveCmd = utilityCmd({ channelID: channel.id, }); } catch (e) { - msg.channel.createMessage(errorMessage("Failed to move member")); + sendErrorMessage(pluginData, msg.channel, "Failed to move member"); return; } diff --git a/backend/src/plugins/Utility/types.ts b/backend/src/plugins/Utility/types.ts index 710fa788..8d6de6b4 100644 --- a/backend/src/plugins/Utility/types.ts +++ b/backend/src/plugins/Utility/types.ts @@ -24,6 +24,7 @@ export const ConfigSchema = t.type({ can_ping: t.boolean, can_source: t.boolean, can_vcmove: t.boolean, + can_vckick: t.boolean, can_help: t.boolean, can_about: t.boolean, can_context: t.boolean,