3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-16 14:11:50 +00:00

use Util methods for escaping inline code and code blocks

This commit is contained in:
almeidx 2021-07-29 17:35:27 +01:00
parent 5e91a9fed3
commit 5de35f711d
No known key found for this signature in database
GPG key ID: 8558FBFF849BD664
11 changed files with 36 additions and 55 deletions

View file

@ -1,11 +1,9 @@
import { GuildChannel, GuildMember, Snowflake, User } from "discord.js"; import { GuildChannel, GuildMember, Snowflake, Util, User } from "discord.js";
import { baseCommandParameterTypeHelpers, baseTypeConverters, CommandContext, TypeConversionError } from "knub"; import { baseCommandParameterTypeHelpers, baseTypeConverters, CommandContext, TypeConversionError } from "knub";
import { createTypeHelper } from "knub-command-manager"; import { createTypeHelper } from "knub-command-manager";
import { import {
channelMentionRegex, channelMentionRegex,
convertDelayStringToMS, convertDelayStringToMS,
disableCodeBlocks,
disableInlineCode,
isValidSnowflake, isValidSnowflake,
resolveMember, resolveMember,
resolveUser, resolveUser,
@ -32,7 +30,7 @@ export const commandTypes = {
async resolvedUser(value, context: CommandContext<any>) { async resolvedUser(value, context: CommandContext<any>) {
const result = await resolveUser(context.pluginData.client, value); const result = await resolveUser(context.pluginData.client, value);
if (result == null || result instanceof UnknownUser) { if (result == null || result instanceof UnknownUser) {
throw new TypeConversionError(`User \`${disableCodeBlocks(value)}\` was not found`); throw new TypeConversionError(`User \`${Util.escapeCodeBlock(value)}\` was not found`);
} }
return result; return result;
}, },
@ -40,7 +38,7 @@ export const commandTypes = {
async resolvedUserLoose(value, context: CommandContext<any>) { async resolvedUserLoose(value, context: CommandContext<any>) {
const result = await resolveUser(context.pluginData.client, value); const result = await resolveUser(context.pluginData.client, value);
if (result == null) { if (result == null) {
throw new TypeConversionError(`Invalid user: \`${disableCodeBlocks(value)}\``); throw new TypeConversionError(`Invalid user: \`${Util.escapeCodeBlock(value)}\``);
} }
return result; return result;
}, },
@ -53,7 +51,7 @@ export const commandTypes = {
const result = await resolveMember(context.pluginData.client, context.message.channel.guild, value); const result = await resolveMember(context.pluginData.client, context.message.channel.guild, value);
if (result == null) { if (result == null) {
throw new TypeConversionError( throw new TypeConversionError(
`Member \`${disableCodeBlocks(value)}\` was not found or they have left the server`, `Member \`${Util.escapeCodeBlock(value)}\` was not found or they have left the server`,
); );
} }
return result; return result;
@ -64,7 +62,7 @@ export const commandTypes = {
const result = await resolveMessageTarget(context.pluginData, value); const result = await resolveMessageTarget(context.pluginData, value);
if (!result) { if (!result) {
throw new TypeConversionError(`Unknown message \`${disableInlineCode(value)}\``); throw new TypeConversionError(`Unknown message \`${Util.escapeInlineCode(value)}\``);
} }
return result; return result;
@ -84,20 +82,20 @@ export const commandTypes = {
return value as Snowflake; return value as Snowflake;
} }
throw new TypeConversionError(`Could not parse ID: \`${disableInlineCode(value)}\``); throw new TypeConversionError(`Could not parse ID: \`${Util.escapeInlineCode(value)}\``);
}, },
regex(value: string, context: CommandContext<any>): RegExp { regex(value: string, context: CommandContext<any>): RegExp {
try { try {
return inputPatternToRegExp(value); return inputPatternToRegExp(value);
} catch (e) { } catch (e) {
throw new TypeConversionError(`Could not parse RegExp: \`${disableInlineCode(e.message)}\``); throw new TypeConversionError(`Could not parse RegExp: \`${Util.escapeInlineCode(e.message)}\``);
} }
}, },
timezone(value: string) { timezone(value: string) {
if (!isValidTimezone(value)) { if (!isValidTimezone(value)) {
throw new TypeConversionError(`Invalid timezone: ${disableInlineCode(value)}`); throw new TypeConversionError(`Invalid timezone: ${Util.escapeInlineCode(value)}`);
} }
return value; return value;

View file

@ -1,6 +1,6 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake, TextChannel, Util } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { asSingleLine, disableInlineCode, messageSummary, verboseChannelMention } from "../../../utils"; import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";
interface MatchResultType { interface MatchResultType {
@ -73,7 +73,7 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
return ( return (
asSingleLine(` asSingleLine(`
Matched attachment type \`${disableInlineCode(matchResult.extra.matchedType)}\` 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}: in message (\`${contexts[0].message!.id}\`) in ${prettyChannel}:
`) + messageSummary(contexts[0].message!) `) + messageSummary(contexts[0].message!)

View file

@ -1,7 +1,8 @@
import { Util } from "discord.js";
import escapeStringRegexp from "escape-string-regexp"; import escapeStringRegexp from "escape-string-regexp";
import * as t from "io-ts"; import * as t from "io-ts";
import { allowTimeout } from "../../../RegExpRunner"; import { allowTimeout } from "../../../RegExpRunner";
import { disableInlineCode, getUrlsInString, tNullable } from "../../../utils"; import { getUrlsInString, tNullable } from "../../../utils";
import { TRegex } from "../../../validatorUtils"; import { TRegex } from "../../../validatorUtils";
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary"; import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage"; import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
@ -129,6 +130,6 @@ export const MatchLinksTrigger = automodTrigger<MatchResultType>()({
renderMatchInformation({ pluginData, contexts, matchResult }) { renderMatchInformation({ pluginData, contexts, matchResult }) {
const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]); const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]);
return `Matched link \`${disableInlineCode(matchResult.extra.link)}\` in ${partialSummary}`; return `Matched link \`${Util.escapeInlineCode(matchResult.extra.link)}\` in ${partialSummary}`;
}, },
}); });

View file

@ -1,6 +1,6 @@
import { Util } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { allowTimeout } from "../../../RegExpRunner"; import { allowTimeout } from "../../../RegExpRunner";
import { disableInlineCode } from "../../../utils";
import { normalizeText } from "../../../utils/normalizeText"; import { normalizeText } from "../../../utils/normalizeText";
import { stripMarkdown } from "../../../utils/stripMarkdown"; import { stripMarkdown } from "../../../utils/stripMarkdown";
import { TRegex } from "../../../validatorUtils"; import { TRegex } from "../../../validatorUtils";
@ -72,6 +72,6 @@ export const MatchRegexTrigger = automodTrigger<MatchResultType>()({
renderMatchInformation({ pluginData, contexts, matchResult }) { renderMatchInformation({ pluginData, contexts, matchResult }) {
const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]); const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]);
return `Matched regex \`${disableInlineCode(matchResult.extra.pattern)}\` in ${partialSummary}`; return `Matched regex \`${Util.escapeInlineCode(matchResult.extra.pattern)}\` in ${partialSummary}`;
}, },
}); });

View file

@ -1,6 +1,6 @@
import { Util } from "discord.js";
import escapeStringRegexp from "escape-string-regexp"; import escapeStringRegexp from "escape-string-regexp";
import * as t from "io-ts"; import * as t from "io-ts";
import { disableInlineCode } from "../../../utils";
import { normalizeText } from "../../../utils/normalizeText"; import { normalizeText } from "../../../utils/normalizeText";
import { stripMarkdown } from "../../../utils/stripMarkdown"; import { stripMarkdown } from "../../../utils/stripMarkdown";
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary"; import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
@ -89,6 +89,6 @@ export const MatchWordsTrigger = automodTrigger<MatchResultType>()({
renderMatchInformation({ pluginData, contexts, matchResult }) { renderMatchInformation({ pluginData, contexts, matchResult }) {
const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]); const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]);
return `Matched word \`${disableInlineCode(matchResult.extra.word)}\` in ${partialSummary}`; return `Matched word \`${Util.escapeInlineCode(matchResult.extra.word)}\` in ${partialSummary}`;
}, },
}); });

View file

@ -7,7 +7,6 @@ import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { LogType } from "../../data/LogType"; import { LogType } from "../../data/LogType";
import { logger } from "../../logger"; import { logger } from "../../logger";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners"; import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { disableCodeBlocks } from "../../utils";
import { CasesPlugin } from "../Cases/CasesPlugin"; import { CasesPlugin } from "../Cases/CasesPlugin";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin"; import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint"; import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -37,6 +36,7 @@ import { log } from "./util/log";
import { onMessageDelete } from "./util/onMessageDelete"; import { onMessageDelete } from "./util/onMessageDelete";
import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk"; import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk";
import { onMessageUpdate } from "./util/onMessageUpdate"; import { onMessageUpdate } from "./util/onMessageUpdate";
import { Util } from "discord.js";
const defaultOptions: PluginOptions<LogsPluginType> = { const defaultOptions: PluginOptions<LogsPluginType> = {
config: { config: {
@ -147,7 +147,7 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()({
The following regex has taken longer than ${timeoutMs}ms for ${failedTimes} times and has been temporarily disabled: The following regex has taken longer than ${timeoutMs}ms for ${failedTimes} times and has been temporarily disabled:
`.trim() + `.trim() +
"\n```" + "\n```" +
disableCodeBlocks(regexSource) + Util.escapeCodeBlock(regexSource) +
"```", "```",
}); });
}; };

View file

@ -1,13 +1,7 @@
import { Util } from "discord.js";
import humanizeDuration from "humanize-duration"; import humanizeDuration from "humanize-duration";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { import { createChunkedMessage, DBDateFormat, deactivateMentions, sorter, trimLines } from "../../../utils";
createChunkedMessage,
DBDateFormat,
deactivateMentions,
disableCodeBlocks,
sorter,
trimLines,
} from "../../../utils";
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
import { postCmd } from "../types"; import { postCmd } from "../types";
@ -33,7 +27,7 @@ export const ScheduledPostsListCmd = postCmd({
const isTruncated = previewText.length > SCHEDULED_POST_PREVIEW_TEXT_LENGTH; const isTruncated = previewText.length > SCHEDULED_POST_PREVIEW_TEXT_LENGTH;
previewText = disableCodeBlocks(deactivateMentions(previewText)) previewText = Util.escapeCodeBlock(deactivateMentions(previewText))
.replace(/\s+/g, " ") .replace(/\s+/g, " ")
.slice(0, SCHEDULED_POST_PREVIEW_TEXT_LENGTH); .slice(0, SCHEDULED_POST_PREVIEW_TEXT_LENGTH);
@ -61,7 +55,7 @@ export const ScheduledPostsListCmd = postCmd({
const finalMessage = trimLines(` const finalMessage = trimLines(`
${postLines.join("\n")} ${postLines.join("\n")}
Use \`scheduled_posts <num>\` to view a scheduled post in full Use \`scheduled_posts <num>\` to view a scheduled post in full
Use \`scheduled_posts delete <num>\` to delete a scheduled post Use \`scheduled_posts delete <num>\` to delete a scheduled post
`); `);

View file

@ -1,7 +1,8 @@
import { Util } from "discord.js";
import { ChannelTypeStrings } from "src/types"; import { ChannelTypeStrings } from "src/types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { asSingleLine, disableInlineCode } from "../../../utils"; import { asSingleLine } from "../../../utils";
import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions"; import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions";
import { missingPermissionError } from "../../../utils/missingPermissionError"; import { missingPermissionError } from "../../../utils/missingPermissionError";
import { BOT_SLOWMODE_CLEAR_PERMISSIONS } from "../requiredPermissions"; import { BOT_SLOWMODE_CLEAR_PERMISSIONS } from "../requiredPermissions";
@ -57,7 +58,7 @@ export const SlowmodeClearCmd = slowmodeCmd({
msg.channel, msg.channel,
asSingleLine(` asSingleLine(`
Failed to clear slowmode from **${args.user.tag}** in <#${args.channel.id}>: Failed to clear slowmode from **${args.user.tag}** in <#${args.channel.id}>:
\`${disableInlineCode(e.message)}\` \`${Util.escapeInlineCode(e.message)}\`
`), `),
); );
return; return;

View file

@ -1,9 +1,9 @@
import { Permissions, TextChannel, ThreadChannel } from "discord.js"; import { Permissions, TextChannel, ThreadChannel, Util } from "discord.js";
import humanizeDuration from "humanize-duration"; import humanizeDuration from "humanize-duration";
import { ChannelTypeStrings } from "src/types"; import { ChannelTypeStrings } from "src/types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { asSingleLine, DAYS, disableInlineCode, HOURS, MINUTES } from "../../../utils"; import { asSingleLine, DAYS, HOURS, MINUTES } from "../../../utils";
import { getMissingPermissions } from "../../../utils/getMissingPermissions"; import { getMissingPermissions } from "../../../utils/getMissingPermissions";
import { missingPermissionError } from "../../../utils/missingPermissionError"; import { missingPermissionError } from "../../../utils/missingPermissionError";
import { BOT_SLOWMODE_PERMISSIONS, NATIVE_SLOWMODE_PERMISSIONS } from "../requiredPermissions"; import { BOT_SLOWMODE_PERMISSIONS, NATIVE_SLOWMODE_PERMISSIONS } from "../requiredPermissions";
@ -133,7 +133,7 @@ export const SlowmodeSetCmd = slowmodeCmd({
rateLimitPerUser: rateLimitSeconds, rateLimitPerUser: rateLimitSeconds,
}); });
} catch (e) { } catch (e) {
sendErrorMessage(pluginData, msg.channel, `Failed to set native slowmode: ${disableInlineCode(e.message)}`); sendErrorMessage(pluginData, msg.channel, `Failed to set native slowmode: ${Util.escapeInlineCode(e.message)}`);
return; return;
} }
} else { } else {

View file

@ -1,6 +1,7 @@
import { Util } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { disableInlineCode, trimLines } from "../../../utils"; import { trimLines } from "../../../utils";
import { parseFuzzyTimezone } from "../../../utils/parseFuzzyTimezone"; import { parseFuzzyTimezone } from "../../../utils/parseFuzzyTimezone";
import { timeAndDateCmd } from "../types"; import { timeAndDateCmd } from "../types";
@ -19,7 +20,7 @@ export const SetTimezoneCmd = timeAndDateCmd({
pluginData, pluginData,
message.channel, message.channel,
trimLines(` trimLines(`
Invalid timezone: \`${disableInlineCode(args.timezone)}\` Invalid timezone: \`${Util.escapeInlineCode(args.timezone)}\`
Zeppelin uses timezone locations rather than specific timezone names. Zeppelin uses timezone locations rather than specific timezone names.
See the **TZ database name** column at <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones> for a list of valid options. See the **TZ database name** column at <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones> for a list of valid options.
`), `),

View file

@ -22,6 +22,7 @@ import {
TextChannel, TextChannel,
ThreadChannel, ThreadChannel,
User, User,
Util,
} from "discord.js"; } from "discord.js";
import emojiRegex from "emoji-regex"; import emojiRegex from "emoji-regex";
import { either } from "fp-ts/lib/Either"; import { either } from "fp-ts/lib/Either";
@ -785,21 +786,6 @@ export function deactivateMentions(content: string): string {
return content.replace(/@/g, "@\u200b"); return content.replace(/@/g, "@\u200b");
} }
/**
* Disable inline code in the given string by replacing backticks/grave accents with acute accents
* FIXME: Find a better way that keeps the grave accents? Can't use the code block approach here since it's just 1 character.
*/
export function disableInlineCode(content: string): string {
return content.replace(/`/g, "\u00b4");
}
/**
* Disable code blocks in the given string by adding invisible unicode characters between backticks
*/
export function disableCodeBlocks(content: string): string {
return content.replace(/`/g, "`\u200b");
}
export function useMediaUrls(content: string): string { export function useMediaUrls(content: string): string {
return content.replace(/cdn\.discord(app)?\.com/g, "media.discordapp.net"); return content.replace(/cdn\.discord(app)?\.com/g, "media.discordapp.net");
} }
@ -1336,11 +1322,11 @@ export async function confirm(channel: TextChannel, userId: string, content: Mes
export function messageSummary(msg: SavedMessage) { export function messageSummary(msg: SavedMessage) {
// Regular text content // Regular text content
let result = "```\n" + (msg.data.content ? disableCodeBlocks(msg.data.content) : "<no text content>") + "```"; let result = "```\n" + (msg.data.content ? Util.escapeCodeBlock(msg.data.content) : "<no text content>") + "```";
// Rich embed // Rich embed
const richEmbed = (msg.data.embeds || []).find(e => (e as MessageEmbed).type === "rich"); const richEmbed = (msg.data.embeds || []).find(e => (e as MessageEmbed).type === "rich");
if (richEmbed) result += "Embed:```" + disableCodeBlocks(JSON.stringify(richEmbed)) + "```"; if (richEmbed) result += "Embed:```" + Util.escapeCodeBlock(JSON.stringify(richEmbed)) + "```";
// Attachments // Attachments
if (msg.data.attachments) { if (msg.data.attachments) {