Counters v0.9
Includes automod trigger/action. No user-facing commands yet.
This commit is contained in:
parent
ec37cf27a2
commit
c3407e2d5d
29 changed files with 1387 additions and 3 deletions
|
@ -28,6 +28,9 @@ import { LogType } from "../../data/LogType";
|
|||
import { logger } from "../../logger";
|
||||
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
|
||||
import { RunAutomodOnMemberUpdate } from "./events/RunAutomodOnMemberUpdate";
|
||||
import { CountersPlugin } from "../Counters/CountersPlugin";
|
||||
import { parseCondition } from "../../data/GuildCounters";
|
||||
import { runAutomodOnCounterTrigger } from "./events/runAutomodOnCounterTrigger";
|
||||
|
||||
const defaultOptions = {
|
||||
config: {
|
||||
|
@ -53,7 +56,7 @@ const defaultOptions = {
|
|||
};
|
||||
|
||||
/**
|
||||
* Config preprocessor to set default values for triggers
|
||||
* Config preprocessor to set default values for triggers and perform extra validation
|
||||
*/
|
||||
const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = options => {
|
||||
if (options.config?.rules) {
|
||||
|
@ -108,6 +111,15 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = options => {
|
|||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerName === "counter") {
|
||||
const parsedCondition = parseCondition(triggerObj[triggerName]!.condition);
|
||||
if (parsedCondition == null) {
|
||||
throw new StrictValidationError([
|
||||
`Invalid counter condition '${triggerObj[triggerName]!.condition}' in rule <${rule.name}>`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +163,7 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()("automod",
|
|||
showInDocs: true,
|
||||
info: pluginInfo,
|
||||
|
||||
dependencies: [LogsPlugin, ModActionsPlugin, MutesPlugin],
|
||||
dependencies: [LogsPlugin, ModActionsPlugin, MutesPlugin, CountersPlugin],
|
||||
|
||||
configSchema: ConfigSchema,
|
||||
defaultOptions,
|
||||
|
@ -204,6 +216,39 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()("automod",
|
|||
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
|
||||
},
|
||||
|
||||
async onAfterLoad(pluginData) {
|
||||
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
||||
|
||||
pluginData.state.onCounterTrigger = (name, condition, channelId, userId) => {
|
||||
console.log("trigger", name, condition, channelId, userId);
|
||||
runAutomodOnCounterTrigger(pluginData, name, condition, channelId, userId, false);
|
||||
};
|
||||
|
||||
pluginData.state.onCounterReverseTrigger = (name, condition, channelId, userId) => {
|
||||
console.log("reverseTrigger", name, condition, channelId, userId);
|
||||
runAutomodOnCounterTrigger(pluginData, name, condition, channelId, userId, true);
|
||||
};
|
||||
|
||||
const config = pluginData.config.get();
|
||||
for (const rule of Object.values(config.rules)) {
|
||||
for (const trigger of rule.triggers) {
|
||||
if (trigger.counter) {
|
||||
await countersPlugin.initCounterTrigger(trigger.counter.name, trigger.counter.condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
countersPlugin.onCounterEvent("trigger", pluginData.state.onCounterTrigger);
|
||||
countersPlugin.onCounterEvent("reverseTrigger", pluginData.state.onCounterReverseTrigger);
|
||||
},
|
||||
|
||||
async onBeforeUnload(pluginData) {
|
||||
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
||||
|
||||
countersPlugin.offCounterEvent("trigger", pluginData.state.onCounterTrigger);
|
||||
countersPlugin.offCounterEvent("reverseTrigger", pluginData.state.onCounterReverseTrigger);
|
||||
},
|
||||
|
||||
async onUnload(pluginData) {
|
||||
pluginData.state.queue.clear();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import { AddRolesAction } from "./addRoles";
|
|||
import { RemoveRolesAction } from "./removeRoles";
|
||||
import { SetAntiraidLevelAction } from "./setAntiraidLevel";
|
||||
import { ReplyAction } from "./reply";
|
||||
import { ChangeCounterAction } from "./changeCounter";
|
||||
|
||||
export const availableActions: Record<string, AutomodActionBlueprint<any>> = {
|
||||
clean: CleanAction,
|
||||
|
@ -26,6 +27,7 @@ export const availableActions: Record<string, AutomodActionBlueprint<any>> = {
|
|||
remove_roles: RemoveRolesAction,
|
||||
set_antiraid_level: SetAntiraidLevelAction,
|
||||
reply: ReplyAction,
|
||||
change_counter: ChangeCounterAction,
|
||||
};
|
||||
|
||||
export const AvailableActions = t.type({
|
||||
|
@ -41,4 +43,5 @@ export const AvailableActions = t.type({
|
|||
remove_roles: RemoveRolesAction.configType,
|
||||
set_antiraid_level: SetAntiraidLevelAction.configType,
|
||||
reply: ReplyAction.configType,
|
||||
change_counter: ChangeCounterAction.configType,
|
||||
});
|
||||
|
|
27
backend/src/plugins/Automod/actions/changeCounter.ts
Normal file
27
backend/src/plugins/Automod/actions/changeCounter.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import * as t from "io-ts";
|
||||
import { automodAction } from "../helpers";
|
||||
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
||||
|
||||
export const ChangeCounterAction = automodAction({
|
||||
configType: t.type({
|
||||
name: t.string,
|
||||
change: t.string,
|
||||
}),
|
||||
|
||||
defaultConfig: {},
|
||||
|
||||
async apply({ pluginData, contexts, actionConfig, matchResult }) {
|
||||
const change = parseInt(actionConfig.change, 10);
|
||||
if (Number.isNaN(change)) {
|
||||
throw new Error("Invalid change number");
|
||||
}
|
||||
|
||||
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
||||
countersPlugin.changeCounterValue(
|
||||
actionConfig.name,
|
||||
contexts[0].message?.channel_id || null,
|
||||
contexts[0].user?.id || null,
|
||||
change,
|
||||
);
|
||||
},
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
import { GuildPluginData } from "knub";
|
||||
import { AutomodContext, AutomodPluginType } from "../types";
|
||||
import { runAutomod } from "../functions/runAutomod";
|
||||
|
||||
export function runAutomodOnCounterTrigger(
|
||||
pluginData: GuildPluginData<AutomodPluginType>,
|
||||
counterName: string,
|
||||
condition: string,
|
||||
channelId: string | null,
|
||||
userId: string | null,
|
||||
reverse: boolean,
|
||||
) {
|
||||
const context: AutomodContext = {
|
||||
timestamp: Date.now(),
|
||||
counterTrigger: {
|
||||
name: counterName,
|
||||
condition,
|
||||
channelId,
|
||||
userId,
|
||||
reverse,
|
||||
},
|
||||
};
|
||||
|
||||
pluginData.state.queue.add(async () => {
|
||||
await runAutomod(pluginData, context);
|
||||
});
|
||||
}
|
|
@ -24,7 +24,7 @@ export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>,
|
|||
|
||||
for (const [ruleName, rule] of Object.entries(config.rules)) {
|
||||
if (rule.enabled === false) continue;
|
||||
if (!rule.affects_bots && (!user || user.bot)) continue;
|
||||
if (!rule.affects_bots && (!user || user.bot) && !context.counterTrigger) continue;
|
||||
|
||||
if (rule.cooldown && checkAndUpdateCooldown(pluginData, rule, context)) {
|
||||
return;
|
||||
|
|
|
@ -17,6 +17,7 @@ import { MemberJoinTrigger } from "./memberJoin";
|
|||
import { RoleAddedTrigger } from "./roleAdded";
|
||||
import { RoleRemovedTrigger } from "./roleRemoved";
|
||||
import { StickerSpamTrigger } from "./stickerSpam";
|
||||
import { CounterTrigger } from "./counter";
|
||||
|
||||
export const availableTriggers: Record<string, AutomodTriggerBlueprint<any, any>> = {
|
||||
match_words: MatchWordsTrigger,
|
||||
|
@ -37,6 +38,8 @@ export const availableTriggers: Record<string, AutomodTriggerBlueprint<any, any>
|
|||
character_spam: CharacterSpamTrigger,
|
||||
member_join_spam: MemberJoinSpamTrigger,
|
||||
sticker_spam: StickerSpamTrigger,
|
||||
|
||||
counter: CounterTrigger,
|
||||
};
|
||||
|
||||
export const AvailableTriggers = t.type({
|
||||
|
@ -58,4 +61,6 @@ export const AvailableTriggers = t.type({
|
|||
character_spam: CharacterSpamTrigger.configType,
|
||||
member_join_spam: MemberJoinSpamTrigger.configType,
|
||||
sticker_spam: StickerSpamTrigger.configType,
|
||||
|
||||
counter: CounterTrigger.configType,
|
||||
});
|
||||
|
|
46
backend/src/plugins/Automod/triggers/counter.ts
Normal file
46
backend/src/plugins/Automod/triggers/counter.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import * as t from "io-ts";
|
||||
import { automodTrigger } from "../helpers";
|
||||
import { consumeIgnoredRoleChange } from "../functions/ignoredRoleChanges";
|
||||
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
||||
import { tNullable } from "../../../utils";
|
||||
|
||||
// tslint:disable-next-line
|
||||
interface CounterTriggerResult {}
|
||||
|
||||
export const CounterTrigger = automodTrigger<CounterTriggerResult>()({
|
||||
configType: t.type({
|
||||
name: t.string,
|
||||
condition: t.string,
|
||||
reverse: tNullable(t.boolean),
|
||||
}),
|
||||
|
||||
defaultConfig: {},
|
||||
|
||||
async match({ triggerConfig, context, pluginData }) {
|
||||
if (!context.counterTrigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.counterTrigger.name !== triggerConfig.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.counterTrigger.condition !== triggerConfig.condition) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reverse = triggerConfig.reverse ?? false;
|
||||
if (context.counterTrigger.reverse !== reverse) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
extra: {},
|
||||
};
|
||||
},
|
||||
|
||||
renderMatchInformation({ matchResult, pluginData, contexts, triggerConfig }) {
|
||||
// TODO: Show user, channel, reverse
|
||||
return `Matched counter \`${triggerConfig.name} ${triggerConfig.condition}\``;
|
||||
},
|
||||
});
|
|
@ -13,6 +13,7 @@ import { GuildArchives } from "../../data/GuildArchives";
|
|||
import { RecentActionType } from "./constants";
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import { RegExpRunner } from "../../RegExpRunner";
|
||||
import { CounterEvents } from "../Counters/types";
|
||||
|
||||
export const Rule = t.type({
|
||||
enabled: t.boolean,
|
||||
|
@ -86,6 +87,9 @@ export interface AutomodPluginType extends BasePluginType {
|
|||
|
||||
onMessageCreateFn: any;
|
||||
onMessageUpdateFn: any;
|
||||
|
||||
onCounterTrigger: CounterEvents["trigger"];
|
||||
onCounterReverseTrigger: CounterEvents["reverseTrigger"];
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -93,6 +97,13 @@ export interface AutomodContext {
|
|||
timestamp: number;
|
||||
actioned?: boolean;
|
||||
|
||||
counterTrigger?: {
|
||||
name: string;
|
||||
condition: string;
|
||||
channelId: string | null;
|
||||
userId: string | null;
|
||||
reverse: boolean;
|
||||
};
|
||||
user?: User;
|
||||
message?: SavedMessage;
|
||||
member?: Member;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue