3
0
Fork 0
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:
Dragory 2024-01-27 14:12:06 +02:00
commit 59c5176cbd
No known key found for this signature in database
39 changed files with 1420 additions and 2208 deletions

View file

@ -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>>;

View 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);
}
},
});

View file

@ -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;
}

View file

@ -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,
};

View 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);
}

View file

@ -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;
}

View 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);
}

View file

@ -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) {

View file

@ -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);

View file

@ -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: {},
};

View file

@ -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())

View file

@ -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) {

View file

@ -167,6 +167,7 @@ export interface AutomodContext {
};
antiraid?: {
level: string | null;
oldLevel?: string | null;
};
threadChange?: {
created?: ThreadChannel;