mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-10 20:35:02 +00:00
Run user-supplied regexes in worker threads with a timeout
This commit is contained in:
parent
19b97bc32b
commit
a7fa258f2a
15 changed files with 237 additions and 43 deletions
|
@ -11,7 +11,7 @@ import { StrictValidationError } from "../../validatorUtils";
|
|||
import { ConfigPreprocessorFn } from "knub/dist/config/configTypes";
|
||||
import { availableActions } from "./actions/availableActions";
|
||||
import { clearOldRecentActions } from "./functions/clearOldRecentActions";
|
||||
import { MINUTES, SECONDS } from "../../utils";
|
||||
import { disableCodeBlocks, MINUTES, SECONDS } from "../../utils";
|
||||
import { clearOldRecentSpam } from "./functions/clearOldRecentSpam";
|
||||
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
|
||||
import { GuildArchives } from "../../data/GuildArchives";
|
||||
|
@ -23,6 +23,10 @@ import { AntiraidClearCmd } from "./commands/AntiraidClearCmd";
|
|||
import { SetAntiraidCmd } from "./commands/SetAntiraidCmd";
|
||||
import { ViewAntiraidCmd } from "./commands/ViewAntiraidCmd";
|
||||
import { pluginInfo } from "./info";
|
||||
import { RegExpRunner } from "../../RegExpRunner";
|
||||
import { LogType } from "../../data/LogType";
|
||||
import { logger } from "../../logger";
|
||||
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
|
||||
|
||||
const defaultOptions = {
|
||||
config: {
|
||||
|
@ -161,6 +165,8 @@ export const AutomodPlugin = zeppelinPlugin<AutomodPluginType>()("automod", {
|
|||
async onLoad(pluginData) {
|
||||
pluginData.state.queue = new Queue();
|
||||
|
||||
pluginData.state.regexRunner = getRegExpRunner(`guild-${pluginData.guild.id}`);
|
||||
|
||||
pluginData.state.recentActions = [];
|
||||
pluginData.state.clearRecentActionsInterval = setInterval(() => clearOldRecentActions(pluginData), 1 * MINUTES);
|
||||
|
||||
|
@ -189,9 +195,11 @@ export const AutomodPlugin = zeppelinPlugin<AutomodPluginType>()("automod", {
|
|||
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
|
||||
},
|
||||
|
||||
onUnload(pluginData) {
|
||||
async onUnload(pluginData) {
|
||||
pluginData.state.queue.clear();
|
||||
|
||||
discardRegExpRunner(`guild-${pluginData.guild.id}`);
|
||||
|
||||
clearInterval(pluginData.state.clearRecentActionsInterval);
|
||||
|
||||
clearInterval(pluginData.state.clearRecentSpamInterval);
|
||||
|
|
|
@ -10,8 +10,9 @@ import {
|
|||
verboseChannelMention,
|
||||
} from "../../../utils";
|
||||
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
|
||||
import { TSafeRegex } from "../../../validatorUtils";
|
||||
import { TRegex } from "../../../validatorUtils";
|
||||
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
|
||||
import { allowTimeout } from "../../../RegExpRunner";
|
||||
|
||||
interface MatchResultType {
|
||||
type: MatchableTextType;
|
||||
|
@ -25,8 +26,8 @@ export const MatchLinksTrigger = automodTrigger<MatchResultType>()({
|
|||
include_subdomains: t.boolean,
|
||||
include_words: tNullable(t.array(t.string)),
|
||||
exclude_words: tNullable(t.array(t.string)),
|
||||
include_regex: tNullable(t.array(TSafeRegex)),
|
||||
exclude_regex: tNullable(t.array(TSafeRegex)),
|
||||
include_regex: tNullable(t.array(TRegex)),
|
||||
exclude_regex: tNullable(t.array(TRegex)),
|
||||
only_real_links: t.boolean,
|
||||
match_messages: t.boolean,
|
||||
match_embeds: t.boolean,
|
||||
|
@ -67,16 +68,18 @@ export const MatchLinksTrigger = automodTrigger<MatchResultType>()({
|
|||
// In order of specificity, regex > word > domain
|
||||
|
||||
if (trigger.exclude_regex) {
|
||||
for (const pattern of trigger.exclude_regex) {
|
||||
if (pattern.test(link.input)) {
|
||||
for (const sourceRegex of trigger.exclude_regex) {
|
||||
const matches = await pluginData.state.regexRunner.exec(sourceRegex, link.input).catch(allowTimeout);
|
||||
if (matches) {
|
||||
continue typeLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trigger.include_regex) {
|
||||
for (const pattern of trigger.include_regex) {
|
||||
if (pattern.test(link.input)) {
|
||||
for (const sourceRegex of trigger.include_regex) {
|
||||
const matches = await pluginData.state.regexRunner.exec(sourceRegex, link.input).catch(allowTimeout);
|
||||
if (matches) {
|
||||
return { extra: { type, link: link.input } };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@ import { transliterate } from "transliteration";
|
|||
import { automodTrigger } from "../helpers";
|
||||
import { disableInlineCode, verboseChannelMention } from "../../../utils";
|
||||
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
|
||||
import { TSafeRegex } from "../../../validatorUtils";
|
||||
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
|
||||
import { allowTimeout } from "../../../RegExpRunner";
|
||||
import { TRegex } from "../../../validatorUtils";
|
||||
|
||||
interface MatchResultType {
|
||||
pattern: string;
|
||||
|
@ -13,7 +14,7 @@ interface MatchResultType {
|
|||
|
||||
export const MatchRegexTrigger = automodTrigger<MatchResultType>()({
|
||||
configType: t.type({
|
||||
patterns: t.array(TSafeRegex),
|
||||
patterns: t.array(TRegex),
|
||||
case_sensitive: t.boolean,
|
||||
normalize: t.boolean,
|
||||
match_messages: t.boolean,
|
||||
|
@ -46,9 +47,9 @@ export const MatchRegexTrigger = automodTrigger<MatchResultType>()({
|
|||
}
|
||||
|
||||
for (const sourceRegex of trigger.patterns) {
|
||||
const regex = new RegExp(sourceRegex.source, trigger.case_sensitive ? "" : "i");
|
||||
const test = regex.test(str);
|
||||
if (test) {
|
||||
const regex = new RegExp(sourceRegex.source, trigger.case_sensitive && !sourceRegex.ignoreCase ? "" : "i");
|
||||
const matches = await pluginData.state.regexRunner.exec(regex, str).catch(allowTimeout);
|
||||
if (matches?.length) {
|
||||
return {
|
||||
extra: {
|
||||
pattern: sourceRegex.source,
|
||||
|
|
|
@ -12,6 +12,7 @@ import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
|
|||
import { GuildArchives } from "../../data/GuildArchives";
|
||||
import { RecentActionType } from "./constants";
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import { RegExpRunner } from "../../RegExpRunner";
|
||||
|
||||
export const Rule = t.type({
|
||||
enabled: t.boolean,
|
||||
|
@ -45,6 +46,11 @@ export interface AutomodPluginType extends BasePluginType {
|
|||
*/
|
||||
queue: Queue;
|
||||
|
||||
/**
|
||||
* Per-server regex runner
|
||||
*/
|
||||
regexRunner: RegExpRunner;
|
||||
|
||||
/**
|
||||
* Recent actions are used for spam triggers
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue