mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-16 06:35:03 +00:00
Merge remote-tracking branch 'origin/master' into iots_to_zod
This commit is contained in:
commit
59c5176cbd
39 changed files with 1420 additions and 2208 deletions
|
@ -10,6 +10,7 @@ import { CleanAction } from "./clean";
|
|||
import { KickAction } from "./kick";
|
||||
import { LogAction } from "./log";
|
||||
import { MuteAction } from "./mute";
|
||||
import { PauseInvitesAction } from "./pauseInvites";
|
||||
import { RemoveRolesAction } from "./removeRoles";
|
||||
import { ReplyAction } from "./reply";
|
||||
import { SetAntiraidLevelAction } from "./setAntiraidLevel";
|
||||
|
@ -37,4 +38,5 @@ export const availableActions = {
|
|||
start_thread: StartThreadAction,
|
||||
archive_thread: ArchiveThreadAction,
|
||||
change_perms: ChangePermsAction,
|
||||
pause_invites: PauseInvitesAction,
|
||||
} satisfies Record<string, AutomodActionBlueprint<any>>;
|
||||
|
|
17
backend/src/plugins/Automod/actions/pauseInvites.ts
Normal file
17
backend/src/plugins/Automod/actions/pauseInvites.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { GuildFeature } from "discord.js";
|
||||
import z from "zod";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
export const PauseInvitesAction = automodAction({
|
||||
configSchema: z.strictObject({
|
||||
paused: z.boolean(),
|
||||
}),
|
||||
|
||||
async apply({ pluginData, actionConfig }) {
|
||||
const hasInvitesDisabled = pluginData.guild.features.includes(GuildFeature.InvitesDisabled);
|
||||
|
||||
if (actionConfig.paused !== hasInvitesDisabled) {
|
||||
await pluginData.guild.disableInvites(actionConfig.paused);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -10,14 +10,17 @@ export const SetSlowmodeAction = automodAction({
|
|||
duration: zDelayString.nullable().default("10s"),
|
||||
}),
|
||||
|
||||
async apply({ pluginData, actionConfig }) {
|
||||
async apply({ pluginData, actionConfig, contexts }) {
|
||||
const slowmodeMs = Math.max(actionConfig.duration ? convertDelayStringToMS(actionConfig.duration)! : 0, 0);
|
||||
|
||||
for (const channelId of actionConfig.channels) {
|
||||
const channels: Snowflake[] = actionConfig.channels ?? [];
|
||||
if (channels.length === 0) {
|
||||
channels.push(...contexts.filter((c) => c.message?.channel_id).map((c) => c.message!.channel_id));
|
||||
}
|
||||
for (const channelId of channels) {
|
||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake);
|
||||
|
||||
// Only text channels and text channels within categories support slowmodes
|
||||
if (!channel || (!channel.isTextBased() && channel.type !== ChannelType.GuildCategory)) {
|
||||
|
||||
if (!channel?.isTextBased() && channel?.type !== ChannelType.GuildCategory) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,15 @@ import { AutomodContext, AutomodPluginType } from "../types";
|
|||
|
||||
export async function runAutomodOnAntiraidLevel(
|
||||
pluginData: GuildPluginData<AutomodPluginType>,
|
||||
level: string | null,
|
||||
newLevel: string | null,
|
||||
oldLevel: string | null,
|
||||
user?: User,
|
||||
) {
|
||||
const context: AutomodContext = {
|
||||
timestamp: Date.now(),
|
||||
antiraid: {
|
||||
level,
|
||||
level: newLevel,
|
||||
oldLevel,
|
||||
},
|
||||
user,
|
||||
};
|
||||
|
|
10
backend/src/plugins/Automod/functions/applyCooldown.ts
Normal file
10
backend/src/plugins/Automod/functions/applyCooldown.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { GuildPluginData } from "knub";
|
||||
import { convertDelayStringToMS } from "../../../utils";
|
||||
import { AutomodContext, AutomodPluginType, TRule } from "../types";
|
||||
|
||||
export function applyCooldown(pluginData: GuildPluginData<AutomodPluginType>, rule: TRule, context: AutomodContext) {
|
||||
const cooldownKey = `${rule.name}-${context.user?.id}`;
|
||||
|
||||
const cooldownTime = convertDelayStringToMS(rule.cooldown, "s");
|
||||
if (cooldownTime) pluginData.state.cooldownManager.setCooldown(cooldownKey, cooldownTime);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import { GuildPluginData } from "knub";
|
||||
import { convertDelayStringToMS } from "../../../utils";
|
||||
import { AutomodContext, AutomodPluginType, TRule } from "../types";
|
||||
|
||||
export function checkAndUpdateCooldown(
|
||||
pluginData: GuildPluginData<AutomodPluginType>,
|
||||
rule: TRule,
|
||||
context: AutomodContext,
|
||||
) {
|
||||
const cooldownKey = `${rule.name}-${context.user?.id}`;
|
||||
|
||||
if (cooldownKey) {
|
||||
if (pluginData.state.cooldownManager.isOnCooldown(cooldownKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const cooldownTime = convertDelayStringToMS(rule.cooldown, "s");
|
||||
if (cooldownTime) {
|
||||
pluginData.state.cooldownManager.setCooldown(cooldownKey, cooldownTime);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
8
backend/src/plugins/Automod/functions/checkCooldown.ts
Normal file
8
backend/src/plugins/Automod/functions/checkCooldown.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { GuildPluginData } from "knub";
|
||||
import { AutomodContext, AutomodPluginType, TRule } from "../types";
|
||||
|
||||
export function checkCooldown(pluginData: GuildPluginData<AutomodPluginType>, rule: TRule, context: AutomodContext) {
|
||||
const cooldownKey = `${rule.name}-${context.user?.id}`;
|
||||
|
||||
return pluginData.state.cooldownManager.isOnCooldown(cooldownKey);
|
||||
}
|
|
@ -7,7 +7,8 @@ import { CleanAction } from "../actions/clean";
|
|||
import { AutomodTriggerMatchResult } from "../helpers";
|
||||
import { availableTriggers } from "../triggers/availableTriggers";
|
||||
import { AutomodContext, AutomodPluginType } from "../types";
|
||||
import { checkAndUpdateCooldown } from "./checkAndUpdateCooldown";
|
||||
import { applyCooldown } from "./applyCooldown";
|
||||
import { checkCooldown } from "./checkCooldown";
|
||||
|
||||
export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) {
|
||||
const userId = context.user?.id || context.member?.id || context.message?.user_id;
|
||||
|
@ -46,7 +47,7 @@ export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>,
|
|||
}
|
||||
if (!rule.affects_self && userId && userId === pluginData.client.user?.id) continue;
|
||||
|
||||
if (rule.cooldown && checkAndUpdateCooldown(pluginData, rule, context)) {
|
||||
if (rule.cooldown && checkCooldown(pluginData, rule, context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,8 @@ export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>,
|
|||
}
|
||||
|
||||
if (matchResult) {
|
||||
if (rule.cooldown) applyCooldown(pluginData, rule, context);
|
||||
|
||||
contexts = [context, ...(matchResult.extraContexts || [])];
|
||||
|
||||
for (const _context of contexts) {
|
||||
|
|
|
@ -9,10 +9,11 @@ export async function setAntiraidLevel(
|
|||
newLevel: string | null,
|
||||
user?: User,
|
||||
) {
|
||||
const oldLevel = pluginData.state.cachedAntiraidLevel;
|
||||
pluginData.state.cachedAntiraidLevel = newLevel;
|
||||
await pluginData.state.antiraidLevels.set(newLevel);
|
||||
|
||||
runAutomodOnAntiraidLevel(pluginData, newLevel, user);
|
||||
runAutomodOnAntiraidLevel(pluginData, newLevel, oldLevel, user);
|
||||
|
||||
const logs = pluginData.getPlugin(LogsPlugin);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ interface AntiraidLevelTriggerResult {}
|
|||
|
||||
const configSchema = z.strictObject({
|
||||
level: z.nullable(z.string().max(100)),
|
||||
only_on_change: z.nullable(z.boolean()),
|
||||
});
|
||||
|
||||
export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()({
|
||||
|
@ -19,6 +20,14 @@ export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()
|
|||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
triggerConfig.only_on_change &&
|
||||
context.antiraid.oldLevel !== undefined &&
|
||||
context.antiraid.level === context.antiraid.oldLevel
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
extra: {},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { escapeInlineCode, Snowflake } from "discord.js";
|
||||
import z from "zod";
|
||||
import { extname } from "path";
|
||||
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
|
||||
import { automodTrigger } from "../helpers";
|
||||
|
||||
|
@ -44,7 +45,7 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
|
|||
}
|
||||
|
||||
for (const attachment of context.message.data.attachments) {
|
||||
const attachmentType = attachment.url.split(".").pop()!.toLowerCase();
|
||||
const attachmentType = extname(new URL(attachment.url).pathname).slice(1).toLowerCase();
|
||||
|
||||
const blacklist = trigger.blacklist_enabled
|
||||
? (trigger.filetype_blacklist || []).map((_t) => _t.toLowerCase())
|
||||
|
|
|
@ -41,7 +41,7 @@ export const MatchWordsTrigger = automodTrigger<MatchResultType>()({
|
|||
const looseMatchingThreshold = Math.min(Math.max(trigger.loose_matching_threshold, 1), 64);
|
||||
const patterns = trigger.words.map((word) => {
|
||||
let pattern = trigger.loose_matching
|
||||
? [...word].map((c) => escapeStringRegexp(c)).join(`(?:\\s*|.{0,${looseMatchingThreshold})`)
|
||||
? [...word].map((c) => escapeStringRegexp(c)).join(`(?:\\s*|.{0,${looseMatchingThreshold}})`)
|
||||
: escapeStringRegexp(word);
|
||||
|
||||
if (trigger.only_full_words) {
|
||||
|
|
|
@ -167,6 +167,7 @@ export interface AutomodContext {
|
|||
};
|
||||
antiraid?: {
|
||||
level: string | null;
|
||||
oldLevel?: string | null;
|
||||
};
|
||||
threadChange?: {
|
||||
created?: ThreadChannel;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue