diff --git a/src/events/handle-message.ts b/src/events/handle-message.ts index 98c1d1f..91ddd0a 100644 --- a/src/events/handle-message.ts +++ b/src/events/handle-message.ts @@ -1,11 +1,8 @@ import { AllowedMentionsTypes, Message as DiscordMessage, GuildBasedChannel, GuildTextBasedChannel, OmitPartialGroupDMChannel, PartialMessage, ReadonlyCollection, spoiler } from 'discord.js'; import { config } from '../config'; import { E621Post } from '../types'; -import { getE621Post, getE621PostByMd5, getPostUrl, PostAction, spoilerOrBlacklist } from '../utils/e621-utils'; import { Database } from '../shared/Database'; -import { logDeletion, logEdit } from '../utils/event-log-utils'; -import { isEdited } from '../utils/message-utils'; -import { ALLOWED_MIMETYPES, blipIDRegex, calculateMD5FromURL, channelIgnoresLinks, channelIsInStaffCategory, channelIsSafe, commentIDRegex, forumTopicIDRegex, poolIDRegex, postIDRegex, recordIDRegex, searchLinkRegex, setIDRegex, takedownIDRegex, ticketIDRegex, userIDRegex, wikiLinkRegex } from '../utils'; +import { ALLOWED_MIMETYPES, blipIDRegex, calculateMD5FromURL, channelIgnoresLinks, channelIsInStaffCategory, channelIsSafe, commentIDRegex, forumTopicIDRegex, getE621Post, getE621PostByMd5, getPostUrl, isEdited, isInSpoilerTags, logDeletion, logEdit, poolIDRegex, PostAction, postIDRegex, recordIDRegex, searchLinkRegex, setIDRegex, spoilerOrBlacklist, takedownIDRegex, ticketIDRegex, userIDRegex, wikiLinkRegex } from '../utils'; export type Message = OmitPartialGroupDMChannel>; export type Partial = OmitPartialGroupDMChannel; @@ -243,18 +240,21 @@ async function blacklistIfNecessary(message: Message, posts: E621Post[]): Promis async function postIdHandler(message: Message, matchedGroups: RegExpExecArray[]): Promise { if (!message.guildId) return true; - const posts: E621Post[] = []; + const posts: { post: E621Post, spoilered: boolean }[] = []; for (const match of matchedGroups) { try { const post = await getE621Post(match[1]); - if (post) posts.push(post); + if (post) posts.push({ + spoilered: isInSpoilerTags(message.content, match.index), + post + }); } catch (e) { console.error(e); } } - if (await blacklistIfNecessary(message, posts)) return false; + if (await blacklistIfNecessary(message, posts.map(p => p.post))) return false; const skip = await channelIgnoresLinks(message.channel as GuildBasedChannel); @@ -262,10 +262,13 @@ async function postIdHandler(message: Message, matchedGroups: RegExpExecArray[]) const sfw = await channelIsSafe(message.channel as GuildBasedChannel); - const content = posts.map((post) => { - const shouldSpoiler = spoilerOrBlacklist(post); - if (sfw && post.rating != 's') return ` [NSFW] <${getPostUrl(post)}>`; - return shouldSpoiler.action == PostAction.Spoiler ? `${spoiler(getPostUrl(post))} (${shouldSpoiler.tag})` : getPostUrl(post); + const content = posts.map((postData) => { + if (sfw && postData.post.rating != 's') return ` [NSFW] <${getPostUrl(postData.post)}>`; + + const shouldSpoiler = spoilerOrBlacklist(postData.post); + if (shouldSpoiler.action == PostAction.Spoiler) return `${spoiler(getPostUrl(postData.post))} (${shouldSpoiler.tag})`; + + return postData.spoilered ? `[User Provided Spoiler] ${spoiler(getPostUrl(postData.post))}` : getPostUrl(postData.post); }).join('\n'); if (content.trim().length > 0) return content.trim(); diff --git a/src/utils/index.ts b/src/utils/index.ts index 2f45323..b36b7e4 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,9 +5,9 @@ export * from './ban-utils'; export * from './channel-utils'; export * from './commands'; export * from './e621-utils'; +export * from './event-log-utils'; export * from './file-utils'; export * from './interaction-utils'; -export * from './event-log-utils'; export * from './message-utils'; export * from './ms-to-human'; export * from './note-utils'; diff --git a/src/utils/message-utils.ts b/src/utils/message-utils.ts index 87e3c62..e971695 100644 --- a/src/utils/message-utils.ts +++ b/src/utils/message-utils.ts @@ -3,6 +3,8 @@ import { LoggedMessage } from '../types'; export const ARRAY_SEPARATOR = '$'; +const spoilerRegex = new RegExp('\\|\\|((?:[\\S]| )+?)\\|\\|', 'gi'); + export function serializeMessage(message: Message): string[] { const attachments = message.attachments.map(a => `${a.name}:${a.id}`); const stickers = message.stickers.map(s => `${s.name}:${s.id}`); @@ -40,4 +42,19 @@ export function isEdited(loggedMessage: LoggedMessage, newMessage: Message) { const { addedStickers, removedStickers } = getModifiedStickers(loggedMessage, newMessage); return addedStickers.length > 0 || removedStickers.length > 0; +} + +export function isInSpoilerTags(content: string, index: number): boolean { + if (!content.includes('||')) return false; + + let match: RegExpExecArray | null; + while ((match = spoilerRegex.exec(content)) != null) { + if (index >= match.index && index <= spoilerRegex.lastIndex) { + spoilerRegex.lastIndex = 0; + return true; + } + } + + spoilerRegex.lastIndex = 0; + return false; } \ No newline at end of file