Une erreur est survenue de notre côté
Sélectionner une révision Git
-
Jonathan CROUZET a rédigéJonathan CROUZET a rédigé
discordcommandhandler.ts 6,55 Kio
/*
Copyright 2019 matrix-appservice-discord
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { DiscordBot } from "./bot";
import * as Discord from "better-discord.js";
import { Util, ICommandActions, ICommandParameters, CommandPermissonCheck } from "./util";
import { Log } from "./log";
import { Appservice } from "matrix-bot-sdk";
const log = new Log("DiscordCommandHandler");
export class DiscordCommandHandler {
constructor(
private bridge: Appservice,
private discord: DiscordBot,
) { }
public async Process(msg: Discord.Message) {
const chan = msg.channel as Discord.TextChannel;
if (!chan.guild) {
await msg.channel.send("**ERROR:** only available for guild channels");
return;
}
if (!msg.member) {
await msg.channel.send("**ERROR:** could not determine message member");
return;
}
const discordMember = msg.member;
const intent = this.bridge.botIntent;
const actions: ICommandActions = {
approve: {
description: "Approve a pending bridge request",
params: [],
permission: "MANAGE_WEBHOOKS",
run: async () => {
if (await this.discord.Provisioner.MarkApproved(chan, discordMember, true)) {
return "Thanks for your response! The matrix bridge has been approved.";
} else {
return "Thanks for your response, however" +
" it has arrived after the deadline - sorry!";
}
},
},
ban: {
description: "Bans a user on the matrix side",
params: ["name"],
permission: "BAN_MEMBERS",
run: this.ModerationActionGenerator(chan, "ban"),
},
deny: {
description: "Deny a pending bridge request",
params: [],
permission: "MANAGE_WEBHOOKS",
run: async () => {
if (await this.discord.Provisioner.MarkApproved(chan, discordMember, false)) {
return "Thanks for your response! The matrix bridge has been declined.";
} else {
return "Thanks for your response, however" +
" it has arrived after the deadline - sorry!";
}
},
},
kick: {
description: "Kicks a user on the matrix side",
params: ["name"],
permission: "KICK_MEMBERS",
run: this.ModerationActionGenerator(chan, "kick"),
},
unban: {
description: "Unbans a user on the matrix side",
params: ["name"],
permission: "BAN_MEMBERS",
run: this.ModerationActionGenerator(chan, "unban"),
},
unbridge: {
description: "Unbridge matrix rooms from this channel",
params: [],
permission: ["MANAGE_WEBHOOKS", "MANAGE_CHANNELS"],
run: async () => this.UnbridgeChannel(chan),
},
};
const parameters: ICommandParameters = {
name: {
description: "The display name or mxid of a matrix user",
get: async (name) => {
const channelMxids = await this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(msg.channel);
const mxUserId = await Util.GetMxidFromName(intent, name, channelMxids);
return mxUserId;
},
},
};
const permissionCheck: CommandPermissonCheck = async (permission: string|string[]) => {
if (!Array.isArray(permission)) {
permission = [permission];
}
return permission.every((p) => discordMember.hasPermission(p as Discord.PermissionResolvable));
};
const reply = await Util.ParseCommand("!matrix", msg.content, actions, parameters, permissionCheck);
await msg.channel.send(reply);
}
private ModerationActionGenerator(discordChannel: Discord.TextChannel, funcKey: "kick"|"ban"|"unban") {
return async ({name}) => {
let allChannelMxids: string[] = [];
await Promise.all(discordChannel.guild.channels.cache.map(async (chan) => {
try {
const chanMxids = await this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(chan);
allChannelMxids = allChannelMxids.concat(chanMxids);
} catch (e) {
// pass, non-text-channel
}
}));
let errorMsg = "";
await Promise.all(allChannelMxids.map(async (chanMxid) => {
try {
await this.bridge.botIntent.underlyingClient[funcKey + "User"](chanMxid, name);
} catch (e) {
// maybe we don't have permission to kick/ban/unban...?
errorMsg += `\nCouldn't ${funcKey} ${name} from ${chanMxid}`;
}
}));
if (errorMsg) {
throw Error(errorMsg);
}
const action = {
ban: "Banned",
kick: "Kicked",
unban: "Unbanned",
}[funcKey];
return `${action} ${name}`;
};
}
private async UnbridgeChannel(channel: Discord.TextChannel): Promise<string> {
try {
await this.discord.Provisioner.UnbridgeChannel(channel);
return "This channel has been unbridged";
} catch (err) {
if (err.message === "Channel is not bridged") {
return "This channel is not bridged to a plumbed matrix room";
}
log.error("Error while unbridging room " + channel.id);
log.error(err);
return "There was an error unbridging this room. " +
"Please try again later or contact the bridge operator.";
}
}
}