mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-25 18:25:03 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
04e91aa87a
14 changed files with 287 additions and 24 deletions
|
@ -25,7 +25,7 @@ export const BanAction = automodAction({
|
|||
const reason = actionConfig.reason || "Kicked automatically";
|
||||
const duration = actionConfig.duration ? convertDelayStringToMS(actionConfig.duration)! : undefined;
|
||||
const contactMethods = actionConfig.notify ? resolveActionContactMethods(pluginData, actionConfig) : undefined;
|
||||
const deleteMessageDays = actionConfig.deleteMessageDays || undefined;
|
||||
const deleteMessageDays = actionConfig.deleteMessageDays ?? undefined;
|
||||
|
||||
const caseArgs: Partial<CaseArgs> = {
|
||||
modId: pluginData.client.user!.id,
|
||||
|
|
|
@ -72,7 +72,7 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
|
|||
return (
|
||||
asSingleLine(`
|
||||
Matched attachment type \`${Util.escapeInlineCode(matchResult.extra.matchedType)}\`
|
||||
(${matchResult.extra.mode === "blacklist" ? "(blacklisted)" : "(not in whitelist)"})
|
||||
(${matchResult.extra.mode === "blacklist" ? "blacklisted" : "not in whitelist"})
|
||||
in message (\`${contexts[0].message!.id}\`) in ${prettyChannel}:
|
||||
`) + messageSummary(contexts[0].message!)
|
||||
);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import type { Snowflake } from "discord-api-types/globals";
|
||||
import { GuildPluginData } from "knub";
|
||||
import { logger } from "../../../logger";
|
||||
import { resolveUser } from "../../../utils";
|
||||
|
@ -13,9 +14,11 @@ export async function createCase(pluginData: GuildPluginData<CasesPluginType>, a
|
|||
const modName = mod.tag;
|
||||
|
||||
let ppName: string | null = null;
|
||||
let ppId: Snowflake | null = null;
|
||||
if (args.ppId) {
|
||||
const pp = await resolveUser(pluginData.client, args.ppId);
|
||||
ppName = pp.tag;
|
||||
ppId = pp.id;
|
||||
}
|
||||
|
||||
if (args.auditLogId) {
|
||||
|
@ -28,20 +31,20 @@ export async function createCase(pluginData: GuildPluginData<CasesPluginType>, a
|
|||
|
||||
const createdCase = await pluginData.state.cases.create({
|
||||
type: args.type,
|
||||
user_id: args.userId,
|
||||
user_id: user.id,
|
||||
user_name: userName,
|
||||
mod_id: args.modId,
|
||||
mod_id: mod.id,
|
||||
mod_name: modName,
|
||||
audit_log_id: args.auditLogId,
|
||||
pp_id: args.ppId,
|
||||
pp_id: ppId,
|
||||
pp_name: ppName,
|
||||
is_hidden: Boolean(args.hide),
|
||||
});
|
||||
|
||||
if (args.reason || (args.noteDetails && args.noteDetails.length)) {
|
||||
if (args.reason || args.noteDetails?.length) {
|
||||
await createCaseNote(pluginData, {
|
||||
caseId: createdCase.id,
|
||||
modId: args.modId,
|
||||
modId: mod.id,
|
||||
body: args.reason || "",
|
||||
automatic: args.automatic,
|
||||
postInCaseLogOverride: false,
|
||||
|
@ -53,7 +56,7 @@ export async function createCase(pluginData: GuildPluginData<CasesPluginType>, a
|
|||
for (const extraNote of args.extraNotes) {
|
||||
await createCaseNote(pluginData, {
|
||||
caseId: createdCase.id,
|
||||
modId: args.modId,
|
||||
modId: mod.id,
|
||||
body: extraNote,
|
||||
automatic: args.automatic,
|
||||
postInCaseLogOverride: false,
|
||||
|
|
|
@ -85,7 +85,7 @@ export async function banUserId(
|
|||
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_BAN, userId);
|
||||
ignoreEvent(pluginData, IgnoredEventType.Ban, userId);
|
||||
try {
|
||||
const deleteMessageDays = Math.min(30, Math.max(0, banOptions.deleteMessageDays ?? 1));
|
||||
const deleteMessageDays = Math.min(7, Math.max(0, banOptions.deleteMessageDays ?? 1));
|
||||
await pluginData.guild.bans.create(userId as Snowflake, {
|
||||
days: deleteMessageDays,
|
||||
reason: reason ?? undefined,
|
||||
|
|
|
@ -8,7 +8,7 @@ export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
|
|||
`),
|
||||
configurationGuide: trimPluginDescription(`
|
||||
### Getting started
|
||||
To get started, request an API key for Phisherman following the instructions at https://docs.phisherman.gg/#/api/getting-started?id=requesting-api-access.
|
||||
To get started, request an API key for Phisherman following the instructions at https://docs.phisherman.gg/guide/getting-started.html#requesting-api-access
|
||||
Then, add the api key to the plugin's config:
|
||||
|
||||
~~~yml
|
||||
|
|
|
@ -7,8 +7,9 @@ import { GuildArchives } from "../../data/GuildArchives";
|
|||
import { GuildLogs } from "../../data/GuildLogs";
|
||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
||||
import { GuildTags } from "../../data/GuildTags";
|
||||
import { GuildTagAliases } from "src/data/GuildTagAliases";
|
||||
import { mapToPublicFn } from "../../pluginUtils";
|
||||
import { convertDelayStringToMS } from "../../utils";
|
||||
import { convertDelayStringToMS, trimPluginDescription } from "../../utils";
|
||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
||||
import { TagCreateCmd } from "./commands/TagCreateCmd";
|
||||
|
@ -22,7 +23,8 @@ import { onMessageCreate } from "./util/onMessageCreate";
|
|||
import { onMessageDelete } from "./util/onMessageDelete";
|
||||
import { renderTagBody } from "./util/renderTagBody";
|
||||
import { LogsPlugin } from "../Logs/LogsPlugin";
|
||||
import { GuildTagAliases } from "src/data/GuildTagAliases";
|
||||
import { generateTemplateMarkdown } from "./docs";
|
||||
import { TemplateFunctions } from "./templateFunctions";
|
||||
|
||||
const defaultOptions: PluginOptions<TagsPluginType> = {
|
||||
config: {
|
||||
|
@ -59,6 +61,17 @@ export const TagsPlugin = zeppelinGuildPlugin<TagsPluginType>()({
|
|||
showInDocs: true,
|
||||
info: {
|
||||
prettyName: "Tags",
|
||||
description: "Tags are a way to store and reuse information.",
|
||||
configurationGuide: trimPluginDescription(`
|
||||
### Template Functions
|
||||
You can use template functions in your tags. These functions are called when the tag is rendered.
|
||||
You can use these functions to render dynamic content, or to access information from the message and/or user calling the tag.
|
||||
You use them by adding a \`{}\` on your tag.
|
||||
|
||||
Here are the functions you can use in your tags:
|
||||
|
||||
${generateTemplateMarkdown(TemplateFunctions)}
|
||||
`),
|
||||
},
|
||||
|
||||
configSchema: ConfigSchema,
|
||||
|
|
17
backend/src/plugins/Tags/docs.ts
Normal file
17
backend/src/plugins/Tags/docs.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { trimPluginDescription } from "src/utils";
|
||||
import { TemplateFunction } from "./types";
|
||||
|
||||
export function generateTemplateMarkdown(definitions: TemplateFunction[]): string {
|
||||
return definitions
|
||||
.map(def => {
|
||||
const usage = def.signature ?? `(${def.arguments.join(", ")})`;
|
||||
const examples = def.examples?.map(ex => `> \`{${ex}}\``).join("\n") ?? null;
|
||||
return trimPluginDescription(`
|
||||
## ${def.name}
|
||||
**${def.description}**\n
|
||||
__Usage__: \`{${def.name}${usage}}\`\n
|
||||
${examples ? `__Examples__:\n${examples}` : ""}\n\n
|
||||
`);
|
||||
})
|
||||
.join("\n\n");
|
||||
}
|
166
backend/src/plugins/Tags/templateFunctions.ts
Normal file
166
backend/src/plugins/Tags/templateFunctions.ts
Normal file
|
@ -0,0 +1,166 @@
|
|||
import { TemplateFunction } from "./types";
|
||||
|
||||
// TODO: Generate this dynamically, lmao
|
||||
export const TemplateFunctions: TemplateFunction[] = [
|
||||
{
|
||||
name: "if",
|
||||
description: "Checks if a condition is true or false and returns the corresponding ifTrue or ifFalse",
|
||||
returnValue: "boolean",
|
||||
arguments: ["condition", "ifTrue", "ifFalse"],
|
||||
examples: ['if(user.bot, "User is a bot", "User is not a bot")'],
|
||||
},
|
||||
{
|
||||
name: "and",
|
||||
description: "Checks if all provided conditions are true",
|
||||
returnValue: "boolean",
|
||||
arguments: ["condition1", "condition2", "..."],
|
||||
examples: ["and(user.bot, user.verified)"],
|
||||
},
|
||||
{
|
||||
name: "or",
|
||||
description: "Checks if atleast one of the provided conditions is true",
|
||||
returnValue: "boolean",
|
||||
arguments: ["condition1", "condition2", "..."],
|
||||
examples: ["or(user.bot, user.verified)"],
|
||||
},
|
||||
{
|
||||
name: "not",
|
||||
description: "Checks if the provided condition is false",
|
||||
returnValue: "boolean",
|
||||
arguments: ["condition"],
|
||||
examples: ["not(user.bot)"],
|
||||
},
|
||||
{
|
||||
name: "concat",
|
||||
description: "Concatenates several arguments into a string",
|
||||
returnValue: "string",
|
||||
arguments: ["argument1", "argument2", "..."],
|
||||
examples: ['concat("Hello ", user.username, "!")'],
|
||||
},
|
||||
{
|
||||
name: "concatArr",
|
||||
description: "Joins a array with the provided separator",
|
||||
returnValue: "string",
|
||||
arguments: ["array", "separator"],
|
||||
examples: ['concatArr(["Hello", "World"], " ")'],
|
||||
},
|
||||
{
|
||||
name: "eq",
|
||||
description: "Checks if all provided arguments are equal to each other",
|
||||
returnValue: "boolean",
|
||||
arguments: ["argument1", "argument2", "..."],
|
||||
examples: ['eq(user.id, "106391128718245888")'],
|
||||
},
|
||||
{
|
||||
name: "gt",
|
||||
description: "Checks if the first argument is greater than the second",
|
||||
returnValue: "boolean",
|
||||
arguments: ["argument1", "argument2"],
|
||||
examples: ["gt(5, 2)"],
|
||||
},
|
||||
{
|
||||
name: "gte",
|
||||
description: "Checks if the first argument is greater or equal to the second",
|
||||
returnValue: "boolean",
|
||||
arguments: ["argument1", "argument2"],
|
||||
examples: ["gte(2, 2)"],
|
||||
},
|
||||
{
|
||||
name: "lt",
|
||||
description: "Checks if the first argument is smaller than the second",
|
||||
returnValue: "boolean",
|
||||
arguments: ["argument1", "argument2"],
|
||||
examples: ["lt(2, 5)"],
|
||||
},
|
||||
{
|
||||
name: "lte",
|
||||
description: "Checks if the first argument is smaller or equal to the second",
|
||||
returnValue: "boolean",
|
||||
arguments: ["argument1", "argument2"],
|
||||
examples: ["lte(2, 2)"],
|
||||
},
|
||||
{
|
||||
name: "slice",
|
||||
description: "Slices a string argument at start and end",
|
||||
returnValue: "string",
|
||||
arguments: ["string", "start", "end"],
|
||||
examples: ['slice("Hello World", 0, 5)'],
|
||||
},
|
||||
{
|
||||
name: "lower",
|
||||
description: "Converts a string argument to lowercase",
|
||||
returnValue: "string",
|
||||
arguments: ["string"],
|
||||
examples: ['lower("Hello World")'],
|
||||
},
|
||||
{
|
||||
name: "upper",
|
||||
description: "Converts a string argument to uppercase",
|
||||
returnValue: "string",
|
||||
arguments: ["string"],
|
||||
examples: ['upper("Hello World")'],
|
||||
},
|
||||
{
|
||||
name: "upperFirst",
|
||||
description: "Converts the first character of a string argument to uppercase",
|
||||
returnValue: "string",
|
||||
arguments: ["string"],
|
||||
examples: ['upperFirst("hello World")'],
|
||||
},
|
||||
{
|
||||
name: "rand",
|
||||
description: "Returns a random number between from and to, optionally using seed",
|
||||
returnValue: "number",
|
||||
arguments: ["from", "to", "seed"],
|
||||
examples: ["rand(1, 10)"],
|
||||
},
|
||||
{
|
||||
name: "round",
|
||||
description: "Rounds a number to the given decimal places",
|
||||
returnValue: "number",
|
||||
arguments: ["number", "decimalPlaces"],
|
||||
examples: ["round(1.2345, 2)"],
|
||||
},
|
||||
{
|
||||
name: "add",
|
||||
description: "Adds two or more numbers",
|
||||
returnValue: "number",
|
||||
arguments: ["number1", "number2", "..."],
|
||||
examples: ["add(1, 2)"],
|
||||
},
|
||||
{
|
||||
name: "sub",
|
||||
description: "Subtracts two or more numbers",
|
||||
returnValue: "number",
|
||||
arguments: ["number1", "number2", "..."],
|
||||
examples: ["sub(3, 1)"],
|
||||
},
|
||||
{
|
||||
name: "mul",
|
||||
description: "Multiplies two or more numbers",
|
||||
returnValue: "number",
|
||||
arguments: ["number1", "number2", "..."],
|
||||
examples: ["mul(2, 3)"],
|
||||
},
|
||||
{
|
||||
name: "div",
|
||||
description: "Divides two or more numbers",
|
||||
returnValue: "number",
|
||||
arguments: ["number1", "number2", "..."],
|
||||
examples: ["div(6, 2)"],
|
||||
},
|
||||
{
|
||||
name: "cases",
|
||||
description: "Returns the argument at position",
|
||||
returnValue: "any",
|
||||
arguments: ["position", "argument1", "argument2", "..."],
|
||||
examples: ['cases(1, "Hello", "World")'],
|
||||
},
|
||||
{
|
||||
name: "choose",
|
||||
description: "Returns a random argument",
|
||||
returnValue: "any",
|
||||
arguments: ["argument1", "argument2", "..."],
|
||||
examples: ['choose("Hello", "World", "!")'],
|
||||
},
|
||||
];
|
|
@ -61,5 +61,14 @@ export interface TagsPluginType extends BasePluginType {
|
|||
};
|
||||
}
|
||||
|
||||
export interface TemplateFunction {
|
||||
name: string;
|
||||
description: string;
|
||||
arguments: string[];
|
||||
returnValue: string;
|
||||
signature?: string;
|
||||
examples?: string[];
|
||||
}
|
||||
|
||||
export const tagsCmd = typedGuildCommand<TagsPluginType>();
|
||||
export const tagsEvt = typedGuildEventListener<TagsPluginType>();
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { MessageEmbedOptions, Role } from "discord.js";
|
||||
import { MessageEmbedOptions, Permissions, Role } from "discord.js";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { GuildPluginData } from "knub";
|
||||
import moment from "moment-timezone";
|
||||
import { EmbedWith, preEmbedPadding, trimLines } from "../../../utils";
|
||||
import { PERMISSION_NAMES } from "../../../utils/permissionNames.js";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
import { UtilityPluginType } from "../types";
|
||||
|
||||
|
@ -35,14 +36,9 @@ export async function getRoleInfoEmbed(
|
|||
round: true,
|
||||
});
|
||||
|
||||
const rolePerms = Object.keys(role.permissions.toJSON()).map((p) =>
|
||||
p
|
||||
// Voice channel related permission names start with 'voice'
|
||||
.replace(/^voice/i, "")
|
||||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||||
.toLowerCase()
|
||||
.replace(/(^\w{1})|(\s{1}\w{1})/g, (l) => l.toUpperCase()),
|
||||
);
|
||||
const rolePerms = role.permissions.has(Permissions.FLAGS.ADMINISTRATOR)
|
||||
? [PERMISSION_NAMES.ADMINISTRATOR]
|
||||
: role.permissions.toArray().map((p) => PERMISSION_NAMES[p]);
|
||||
|
||||
// -1 because of the @everyone role
|
||||
const totalGuildRoles = pluginData.guild.roles.cache.size - 1;
|
||||
|
|
|
@ -16,6 +16,13 @@ import {
|
|||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
import { UtilityPluginType } from "../types";
|
||||
|
||||
const MAX_ROLES_TO_DISPLAY = 15;
|
||||
|
||||
const trimRoles = (roles: string[]) =>
|
||||
roles.length > MAX_ROLES_TO_DISPLAY
|
||||
? roles.slice(0, MAX_ROLES_TO_DISPLAY).join(", ") + `, and ${MAX_ROLES_TO_DISPLAY - roles.length} more roles`
|
||||
: roles.join(", ");
|
||||
|
||||
export async function getUserInfoEmbed(
|
||||
pluginData: GuildPluginData<UtilityPluginType>,
|
||||
userId: string,
|
||||
|
@ -109,7 +116,7 @@ export async function getUserInfoEmbed(
|
|||
name: preEmbedPadding + "Member information",
|
||||
value: trimLines(`
|
||||
${user.bot ? "Added" : "Joined"}: **${joinAge} ago** (\`${prettyJoinedAt}\`)
|
||||
${roles.length > 0 ? "Roles: " + roles.map((r) => `<@&${r.id}>`).join(", ") : ""}
|
||||
${roles.length > 0 ? "Roles: " + trimRoles(roles.map((r) => `<@&${r.id}>`)) : ""}
|
||||
`),
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue