mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-14 21:31:50 +00:00
Port BotControl
This commit is contained in:
parent
b66e601cef
commit
f500034729
10 changed files with 237 additions and 2 deletions
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Member } from "eris";
|
import { Member } from "eris";
|
||||||
import { configUtils, helpers, PluginBlueprint, PluginData, PluginOptions } from "knub";
|
import { CommandContext, configUtils, helpers, PluginBlueprint, PluginData, PluginOptions } from "knub";
|
||||||
import { decodeAndValidateStrict, StrictValidationError, validate } from "./validatorUtils";
|
import { decodeAndValidateStrict, StrictValidationError, validate } from "./validatorUtils";
|
||||||
import { deepKeyIntersect, errorMessage, successMessage, tNullable } from "./utils";
|
import { deepKeyIntersect, errorMessage, successMessage, tNullable } from "./utils";
|
||||||
import { ZeppelinPluginBlueprint } from "./plugins/ZeppelinPluginBlueprint";
|
import { ZeppelinPluginBlueprint } from "./plugins/ZeppelinPluginBlueprint";
|
||||||
|
@ -125,3 +125,7 @@ export function isOwner(pluginData: PluginData<any>, userId: string) {
|
||||||
|
|
||||||
return owners.includes(userId);
|
return owners.includes(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isOwnerPreFilter = (_, context: CommandContext<any>) => {
|
||||||
|
return isOwner(context.pluginData, context.message.author.id);
|
||||||
|
};
|
||||||
|
|
41
backend/src/plugins/BotControl/BotControlPlugin.ts
Normal file
41
backend/src/plugins/BotControl/BotControlPlugin.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { zeppelinPlugin } from "../ZeppelinPluginBlueprint";
|
||||||
|
import { BotControlPluginType, ConfigSchema } from "./types";
|
||||||
|
import { GuildArchives } from "../../data/GuildArchives";
|
||||||
|
import { TextChannel } from "eris";
|
||||||
|
import { sendSuccessMessage } from "../../pluginUtils";
|
||||||
|
import { getActiveReload, resetActiveReload } from "./activeReload";
|
||||||
|
import { ReloadGlobalPluginsCmd } from "./commands/ReloadGlobalPluginsCmd";
|
||||||
|
import { ServersCmd } from "./commands/ServersCmd";
|
||||||
|
import { LeaveServerCmd } from "./commands/LeaveServerCmd";
|
||||||
|
import { ReloadServerCmd } from "./commands/ReloadServerCmd";
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
config: {
|
||||||
|
can_use: false,
|
||||||
|
update_cmd: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BotControlPlugin = zeppelinPlugin<BotControlPluginType>()("bot_control", {
|
||||||
|
configSchema: ConfigSchema,
|
||||||
|
defaultOptions,
|
||||||
|
|
||||||
|
commands: [ReloadGlobalPluginsCmd, ServersCmd, LeaveServerCmd, ReloadServerCmd],
|
||||||
|
|
||||||
|
onLoad(pluginData) {
|
||||||
|
pluginData.state.archives = new GuildArchives(0);
|
||||||
|
|
||||||
|
if (getActiveReload()) {
|
||||||
|
const [guildId, channelId] = getActiveReload();
|
||||||
|
resetActiveReload();
|
||||||
|
|
||||||
|
const guild = pluginData.client.guilds.get(guildId);
|
||||||
|
if (guild) {
|
||||||
|
const channel = guild.channels.get(channelId);
|
||||||
|
if (channel instanceof TextChannel) {
|
||||||
|
sendSuccessMessage(pluginData, channel, "Global plugins reloaded!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
13
backend/src/plugins/BotControl/activeReload.ts
Normal file
13
backend/src/plugins/BotControl/activeReload.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
let activeReload: [string, string] = null;
|
||||||
|
|
||||||
|
export function getActiveReload() {
|
||||||
|
return activeReload;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setActiveReload(guildId: string, channelId: string) {
|
||||||
|
activeReload = [guildId, channelId];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetActiveReload() {
|
||||||
|
activeReload = null;
|
||||||
|
}
|
35
backend/src/plugins/BotControl/commands/LeaveServerCmd.ts
Normal file
35
backend/src/plugins/BotControl/commands/LeaveServerCmd.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { command } from "knub";
|
||||||
|
import { BotControlPluginType } from "../types";
|
||||||
|
import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
|
|
||||||
|
export const LeaveServerCmd = command<BotControlPluginType>()({
|
||||||
|
trigger: ["leave_server", "leave_guild"],
|
||||||
|
permission: null,
|
||||||
|
config: {
|
||||||
|
preFilters: [isOwnerPreFilter],
|
||||||
|
},
|
||||||
|
|
||||||
|
signature: {
|
||||||
|
guildId: ct.string(),
|
||||||
|
},
|
||||||
|
|
||||||
|
async run({ pluginData, message: msg, args }) {
|
||||||
|
if (!pluginData.client.guilds.has(args.guildId)) {
|
||||||
|
sendErrorMessage(pluginData, msg.channel, "I am not in that guild");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const guildToLeave = pluginData.client.guilds.get(args.guildId);
|
||||||
|
const guildName = guildToLeave.name;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await pluginData.client.leaveGuild(args.guildId);
|
||||||
|
} catch (e) {
|
||||||
|
sendErrorMessage(pluginData, msg.channel, `Failed to leave guild: ${e.message}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSuccessMessage(pluginData, msg.channel, `Left guild **${guildName}**`);
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { command } from "knub";
|
||||||
|
import { BotControlPluginType } from "../types";
|
||||||
|
import { isOwnerPreFilter } from "../../../pluginUtils";
|
||||||
|
import { getActiveReload, setActiveReload } from "../activeReload";
|
||||||
|
import { TextChannel } from "eris";
|
||||||
|
|
||||||
|
export const ReloadGlobalPluginsCmd = command<BotControlPluginType>()({
|
||||||
|
trigger: "bot_reload_global_plugins",
|
||||||
|
permission: null,
|
||||||
|
config: {
|
||||||
|
preFilters: [isOwnerPreFilter],
|
||||||
|
},
|
||||||
|
|
||||||
|
async run({ pluginData, message }) {
|
||||||
|
if (getActiveReload()) return;
|
||||||
|
|
||||||
|
setActiveReload((message.channel as TextChannel).guild?.id, message.channel.id);
|
||||||
|
await message.channel.createMessage("Reloading global plugins...");
|
||||||
|
|
||||||
|
pluginData.getKnubInstance().reloadAllGlobalPlugins();
|
||||||
|
},
|
||||||
|
});
|
33
backend/src/plugins/BotControl/commands/ReloadServerCmd.ts
Normal file
33
backend/src/plugins/BotControl/commands/ReloadServerCmd.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { command } from "knub";
|
||||||
|
import { BotControlPluginType } from "../types";
|
||||||
|
import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
|
|
||||||
|
export const ReloadServerCmd = command<BotControlPluginType>()({
|
||||||
|
trigger: ["reload_server", "reload_guild"],
|
||||||
|
permission: null,
|
||||||
|
config: {
|
||||||
|
preFilters: [isOwnerPreFilter],
|
||||||
|
},
|
||||||
|
|
||||||
|
signature: {
|
||||||
|
guildId: ct.string(),
|
||||||
|
},
|
||||||
|
|
||||||
|
async run({ pluginData, message: msg, args }) {
|
||||||
|
if (!pluginData.client.guilds.has(args.guildId)) {
|
||||||
|
sendErrorMessage(pluginData, msg.channel, "I am not in that guild");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await pluginData.getKnubInstance().reloadGuild(args.guildId);
|
||||||
|
} catch (e) {
|
||||||
|
sendErrorMessage(pluginData, msg.channel, `Failed to reload guild: ${e.message}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const guild = pluginData.client.guilds.get(args.guildId);
|
||||||
|
sendSuccessMessage(pluginData, msg.channel, `Reloaded guild **${guild?.name || "???"}**`);
|
||||||
|
},
|
||||||
|
});
|
69
backend/src/plugins/BotControl/commands/ServersCmd.ts
Normal file
69
backend/src/plugins/BotControl/commands/ServersCmd.ts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { command } from "knub";
|
||||||
|
import { BotControlPluginType } from "../types";
|
||||||
|
import { isOwnerPreFilter } from "../../../pluginUtils";
|
||||||
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
|
import escapeStringRegexp from "escape-string-regexp";
|
||||||
|
import { createChunkedMessage, sorter } from "../../../utils";
|
||||||
|
|
||||||
|
export const ServersCmd = command<BotControlPluginType>()({
|
||||||
|
trigger: ["servers", "guilds"],
|
||||||
|
permission: null,
|
||||||
|
config: {
|
||||||
|
preFilters: [isOwnerPreFilter],
|
||||||
|
},
|
||||||
|
|
||||||
|
signature: {
|
||||||
|
search: ct.string({ catchAll: true, required: false }),
|
||||||
|
|
||||||
|
all: ct.switchOption({ shortcut: "a" }),
|
||||||
|
initialized: ct.switchOption({ shortcut: "i" }),
|
||||||
|
uninitialized: ct.switchOption({ shortcut: "u" }),
|
||||||
|
},
|
||||||
|
|
||||||
|
async run({ pluginData, message: msg, args }) {
|
||||||
|
const showList = Boolean(args.all || args.initialized || args.uninitialized || args.search);
|
||||||
|
const search = args.search && new RegExp([...args.search].map(s => escapeStringRegexp(s)).join(".*"), "i");
|
||||||
|
|
||||||
|
const joinedGuilds = Array.from(pluginData.client.guilds.values());
|
||||||
|
const loadedGuilds = pluginData.getKnubInstance().getLoadedGuilds();
|
||||||
|
const loadedGuildsMap = loadedGuilds.reduce((map, guildData) => map.set(guildData.guildId, guildData), new Map());
|
||||||
|
|
||||||
|
if (showList) {
|
||||||
|
let filteredGuilds = Array.from(joinedGuilds);
|
||||||
|
|
||||||
|
if (args.initialized) {
|
||||||
|
filteredGuilds = filteredGuilds.filter(g => loadedGuildsMap.has(g.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.uninitialized) {
|
||||||
|
filteredGuilds = filteredGuilds.filter(g => !loadedGuildsMap.has(g.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.search) {
|
||||||
|
filteredGuilds = filteredGuilds.filter(g => search.test(`${g.id} ${g.name}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filteredGuilds.length) {
|
||||||
|
filteredGuilds.sort(sorter(g => g.name.toLowerCase()));
|
||||||
|
const longestId = filteredGuilds.reduce((longest, guild) => Math.max(longest, guild.id.length), 0);
|
||||||
|
const lines = filteredGuilds.map(g => {
|
||||||
|
const paddedId = g.id.padEnd(longestId, " ");
|
||||||
|
return `\`${paddedId}\` **${g.name}** (${loadedGuildsMap.has(g.id) ? "initialized" : "not initialized"}) (${
|
||||||
|
g.memberCount
|
||||||
|
} members)`;
|
||||||
|
});
|
||||||
|
createChunkedMessage(msg.channel, lines.join("\n"));
|
||||||
|
} else {
|
||||||
|
msg.channel.createMessage("No servers matched the filters");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const total = joinedGuilds.length;
|
||||||
|
const initialized = joinedGuilds.filter(g => loadedGuildsMap.has(g.id)).length;
|
||||||
|
const unInitialized = total - initialized;
|
||||||
|
|
||||||
|
msg.channel.createMessage(
|
||||||
|
`I am on **${total} total servers**, of which **${initialized} are initialized** and **${unInitialized} are not initialized**`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
17
backend/src/plugins/BotControl/types.ts
Normal file
17
backend/src/plugins/BotControl/types.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import * as t from "io-ts";
|
||||||
|
import { tNullable } from "../../utils";
|
||||||
|
import { BasePluginType } from "knub";
|
||||||
|
import { GuildArchives } from "../../data/GuildArchives";
|
||||||
|
|
||||||
|
export const ConfigSchema = t.type({
|
||||||
|
can_use: t.boolean,
|
||||||
|
update_cmd: tNullable(t.string),
|
||||||
|
});
|
||||||
|
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||||
|
|
||||||
|
export interface BotControlPluginType extends BasePluginType {
|
||||||
|
config: TConfigSchema;
|
||||||
|
state: {
|
||||||
|
archives: GuildArchives;
|
||||||
|
};
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import { ReactionRolesPlugin } from "./ReactionRoles/ReactionRolesPlugin";
|
||||||
import { AutomodPlugin } from "./Automod/AutomodPlugin";
|
import { AutomodPlugin } from "./Automod/AutomodPlugin";
|
||||||
import { CompanionChannelsPlugin } from "./CompanionChannels/CompanionChannelsPlugin";
|
import { CompanionChannelsPlugin } from "./CompanionChannels/CompanionChannelsPlugin";
|
||||||
import { CustomEventsPlugin } from "./CustomEvents/CustomEventsPlugin";
|
import { CustomEventsPlugin } from "./CustomEvents/CustomEventsPlugin";
|
||||||
|
import { BotControlPlugin } from "./BotControl/BotControlPlugin";
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
||||||
|
@ -66,4 +67,5 @@ export const guildPlugins: Array<ZeppelinPluginBlueprint<any>> = [
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
export const globalPlugins = [
|
export const globalPlugins = [
|
||||||
GuildConfigReloaderPlugin,
|
GuildConfigReloaderPlugin,
|
||||||
|
BotControlPlugin,
|
||||||
];
|
];
|
||||||
|
|
|
@ -34,7 +34,6 @@ import { either } from "fp-ts/lib/Either";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { SimpleCache } from "./SimpleCache";
|
import { SimpleCache } from "./SimpleCache";
|
||||||
import { logger } from "./logger";
|
import { logger } from "./logger";
|
||||||
import { Awaitable } from "knub/dist/utils";
|
|
||||||
|
|
||||||
const fsp = fs.promises;
|
const fsp = fs.promises;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue