mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-16 14:11:50 +00:00
Add command to add servers from invites with eligibility check
This commit is contained in:
parent
3b09d2d679
commit
f13695c524
7 changed files with 151 additions and 39 deletions
|
@ -250,6 +250,13 @@ connect().then(async () => {
|
||||||
|
|
||||||
async getConfig(id) {
|
async getConfig(id) {
|
||||||
const key = id === "global" ? "global" : `guild-${id}`;
|
const key = id === "global" ? "global" : `guild-${id}`;
|
||||||
|
if (id !== "global") {
|
||||||
|
const allowedGuild = await allowedGuilds.find(id);
|
||||||
|
if (!allowedGuild) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const row = await guildConfigs.getActiveByKey(key);
|
const row = await guildConfigs.getActiveByKey(key);
|
||||||
if (row) {
|
if (row) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -19,12 +19,14 @@ import { RemoveDashboardUserCmd } from "./commands/RemoveDashboardUserCmd";
|
||||||
import { ServersCmd } from "./commands/ServersCmd";
|
import { ServersCmd } from "./commands/ServersCmd";
|
||||||
import { BotControlPluginType, ConfigSchema } from "./types";
|
import { BotControlPluginType, ConfigSchema } from "./types";
|
||||||
import { PerformanceCmd } from "./commands/PerformanceCmd";
|
import { PerformanceCmd } from "./commands/PerformanceCmd";
|
||||||
|
import { AddServerFromInviteCmd } from "./commands/AddServerFromInviteCmd";
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
config: {
|
config: {
|
||||||
can_use: false,
|
can_use: false,
|
||||||
can_eligible: false,
|
can_eligible: false,
|
||||||
can_performance: false,
|
can_performance: false,
|
||||||
|
can_add_server_from_invite: false,
|
||||||
update_cmd: null,
|
update_cmd: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -48,6 +50,7 @@ export const BotControlPlugin = zeppelinGlobalPlugin<BotControlPluginType>()({
|
||||||
ListDashboardPermsCmd,
|
ListDashboardPermsCmd,
|
||||||
EligibleCmd,
|
EligibleCmd,
|
||||||
PerformanceCmd,
|
PerformanceCmd,
|
||||||
|
AddServerFromInviteCmd,
|
||||||
],
|
],
|
||||||
|
|
||||||
async afterLoad(pluginData) {
|
async afterLoad(pluginData) {
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { ApiPermissions } from "@shared/apiPermissions";
|
||||||
|
import { TextChannel } from "discord.js";
|
||||||
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
|
import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
|
import { DBDateFormat, isGuildInvite, isSnowflake, resolveInvite } from "../../../utils";
|
||||||
|
import { botControlCmd } from "../types";
|
||||||
|
import moment from "moment-timezone";
|
||||||
|
import { isEligible } from "../functions/isEligible";
|
||||||
|
|
||||||
|
export const AddServerFromInviteCmd = botControlCmd({
|
||||||
|
trigger: ["add_server_from_invite", "allow_server_from_invite"],
|
||||||
|
permission: "can_add_server_from_invite",
|
||||||
|
|
||||||
|
signature: {
|
||||||
|
user: ct.resolvedUser(),
|
||||||
|
inviteCode: ct.string(),
|
||||||
|
},
|
||||||
|
|
||||||
|
async run({ pluginData, message: msg, args }) {
|
||||||
|
const invite = await resolveInvite(pluginData.client, args.inviteCode, true);
|
||||||
|
if (!invite || !isGuildInvite(invite)) {
|
||||||
|
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not resolve invite"); // :D
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = await pluginData.state.allowedGuilds.find(invite.guild.id);
|
||||||
|
if (existing) {
|
||||||
|
sendErrorMessage(pluginData, msg.channel as TextChannel, "Server is already allowed!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result, explanation } = await isEligible(pluginData, args.user, invite);
|
||||||
|
if (!result) {
|
||||||
|
sendErrorMessage(
|
||||||
|
pluginData,
|
||||||
|
msg.channel as TextChannel,
|
||||||
|
`Could not add server because it's not eligible: ${explanation}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await pluginData.state.allowedGuilds.add(invite.guild.id, { name: invite.guild.name });
|
||||||
|
await pluginData.state.configs.saveNewRevision(`guild-${invite.guild.id}`, "plugins: {}", msg.author.id);
|
||||||
|
|
||||||
|
await pluginData.state.apiPermissionAssignments.addUser(invite.guild.id, args.user.id, [
|
||||||
|
ApiPermissions.ManageAccess,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (args.user.id !== msg.author.id) {
|
||||||
|
// Add temporary access to user who added server
|
||||||
|
await pluginData.state.apiPermissionAssignments.addUser(
|
||||||
|
invite.guild.id,
|
||||||
|
msg.author.id,
|
||||||
|
[ApiPermissions.ManageAccess],
|
||||||
|
moment
|
||||||
|
.utc()
|
||||||
|
.add(1, "hour")
|
||||||
|
.format(DBDateFormat),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSuccessMessage(
|
||||||
|
pluginData,
|
||||||
|
msg.channel as TextChannel,
|
||||||
|
"Server was eligible and is now allowed to use Zeppelin!",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
|
@ -2,8 +2,9 @@ import { ApiPermissions } from "@shared/apiPermissions";
|
||||||
import { TextChannel } from "discord.js";
|
import { TextChannel } from "discord.js";
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
import { isSnowflake } from "../../../utils";
|
import { DBDateFormat, isSnowflake } from "../../../utils";
|
||||||
import { botControlCmd } from "../types";
|
import { botControlCmd } from "../types";
|
||||||
|
import moment from "moment-timezone";
|
||||||
|
|
||||||
export const AllowServerCmd = botControlCmd({
|
export const AllowServerCmd = botControlCmd({
|
||||||
trigger: ["allow_server", "allowserver", "add_server", "addserver"],
|
trigger: ["allow_server", "allowserver", "add_server", "addserver"],
|
||||||
|
@ -38,7 +39,20 @@ export const AllowServerCmd = botControlCmd({
|
||||||
await pluginData.state.configs.saveNewRevision(`guild-${args.guildId}`, "plugins: {}", msg.author.id);
|
await pluginData.state.configs.saveNewRevision(`guild-${args.guildId}`, "plugins: {}", msg.author.id);
|
||||||
|
|
||||||
if (args.userId) {
|
if (args.userId) {
|
||||||
await pluginData.state.apiPermissionAssignments.addUser(args.guildId, args.userId, [ApiPermissions.EditConfig]);
|
await pluginData.state.apiPermissionAssignments.addUser(args.guildId, args.userId, [ApiPermissions.ManageAccess]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.userId !== msg.author.id) {
|
||||||
|
// Add temporary access to user who added server
|
||||||
|
await pluginData.state.apiPermissionAssignments.addUser(
|
||||||
|
args.guildId,
|
||||||
|
msg.author.id,
|
||||||
|
[ApiPermissions.ManageAccess],
|
||||||
|
moment
|
||||||
|
.utc()
|
||||||
|
.add(1, "hour")
|
||||||
|
.format(DBDateFormat),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSuccessMessage(pluginData, msg.channel as TextChannel, "Server is now allowed to use Zeppelin!");
|
sendSuccessMessage(pluginData, msg.channel as TextChannel, "Server is now allowed to use Zeppelin!");
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { TextChannel } from "discord.js";
|
import { Guild, TextChannel } from "discord.js";
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
import { resolveInvite, verboseUserMention } from "../../../utils";
|
import { GuildInvite, isGuildInvite, resolveInvite, verboseUserMention } from "../../../utils";
|
||||||
import { botControlCmd } from "../types";
|
import { botControlCmd } from "../types";
|
||||||
|
import { isEligible } from "../functions/isEligible";
|
||||||
const REQUIRED_MEMBER_COUNT = 5000;
|
|
||||||
|
|
||||||
export const EligibleCmd = botControlCmd({
|
export const EligibleCmd = botControlCmd({
|
||||||
trigger: ["eligible", "is_eligible", "iseligible"],
|
trigger: ["eligible", "is_eligible", "iseligible"],
|
||||||
|
@ -16,45 +15,19 @@ export const EligibleCmd = botControlCmd({
|
||||||
},
|
},
|
||||||
|
|
||||||
async run({ pluginData, message: msg, args }) {
|
async run({ pluginData, message: msg, args }) {
|
||||||
if ((await pluginData.state.apiPermissionAssignments.getByUserId(args.user.id)).length) {
|
|
||||||
sendSuccessMessage(
|
|
||||||
pluginData,
|
|
||||||
msg.channel as TextChannel,
|
|
||||||
`${verboseUserMention(args.user)} is an existing bot operator. They are eligible!`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const invite = await resolveInvite(pluginData.client, args.inviteCode, true);
|
const invite = await resolveInvite(pluginData.client, args.inviteCode, true);
|
||||||
if (!invite || !invite.guild) {
|
if (!invite || !isGuildInvite(invite)) {
|
||||||
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not resolve server from invite");
|
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not resolve invite");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invite.guild.features.includes("PARTNERED")) {
|
const { result, explanation } = await isEligible(pluginData, args.user, invite);
|
||||||
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Server is partnered. It is eligible!`);
|
|
||||||
|
if (result) {
|
||||||
|
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Server is eligible: ${explanation}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invite.guild.features.includes("VERIFIED")) {
|
sendErrorMessage(pluginData, msg.channel as TextChannel, `Server is **NOT** eligible: ${explanation}`);
|
||||||
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Server is verified. It is eligible!`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const memberCount = invite.memberCount || 0;
|
|
||||||
if (memberCount >= REQUIRED_MEMBER_COUNT) {
|
|
||||||
sendSuccessMessage(
|
|
||||||
pluginData,
|
|
||||||
msg.channel as TextChannel,
|
|
||||||
`Server has ${memberCount} members, which is equal or higher than the required ${REQUIRED_MEMBER_COUNT}. It is eligible!`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendErrorMessage(
|
|
||||||
pluginData,
|
|
||||||
msg.channel as TextChannel,
|
|
||||||
`Server **${invite.guild.name}** (\`${invite.guild.id}\`) is not eligible`,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
46
backend/src/plugins/BotControl/functions/isEligible.ts
Normal file
46
backend/src/plugins/BotControl/functions/isEligible.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { User } from "discord.js";
|
||||||
|
import { BotControlPluginType } from "../types";
|
||||||
|
import { GlobalPluginData } from "knub";
|
||||||
|
import { GuildInvite } from "../../../utils";
|
||||||
|
|
||||||
|
const REQUIRED_MEMBER_COUNT = 5000;
|
||||||
|
|
||||||
|
export async function isEligible(
|
||||||
|
pluginData: GlobalPluginData<BotControlPluginType>,
|
||||||
|
user: User,
|
||||||
|
invite: GuildInvite,
|
||||||
|
): Promise<{ result: boolean; explanation: string }> {
|
||||||
|
if ((await pluginData.state.apiPermissionAssignments.getByUserId(user.id)).length) {
|
||||||
|
return {
|
||||||
|
result: true,
|
||||||
|
explanation: "User is an existing bot operator",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invite.guild.features.includes("PARTNERED")) {
|
||||||
|
return {
|
||||||
|
result: true,
|
||||||
|
explanation: "Server is partnered",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invite.guild.features.includes("VERIFIED")) {
|
||||||
|
return {
|
||||||
|
result: true,
|
||||||
|
explanation: "Server is verified",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberCount = invite.memberCount || 0;
|
||||||
|
if (memberCount >= REQUIRED_MEMBER_COUNT) {
|
||||||
|
return {
|
||||||
|
result: true,
|
||||||
|
explanation: `Server has ${memberCount} members, which is equal or higher than the required ${REQUIRED_MEMBER_COUNT}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
result: false,
|
||||||
|
explanation: "Server does not meet requirements",
|
||||||
|
};
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ export const ConfigSchema = t.type({
|
||||||
can_use: t.boolean,
|
can_use: t.boolean,
|
||||||
can_eligible: t.boolean,
|
can_eligible: t.boolean,
|
||||||
can_performance: t.boolean,
|
can_performance: t.boolean,
|
||||||
|
can_add_server_from_invite: t.boolean,
|
||||||
update_cmd: tNullable(t.string),
|
update_cmd: tNullable(t.string),
|
||||||
});
|
});
|
||||||
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
|
||||||
|
|
Loading…
Add table
Reference in a new issue