blob: 5369bf40ceed209266cb6608c15acc03a7990820 [file] [log] [blame]
PineaFan752af462022-12-31 21:59:38 +00001import type { NucleusClient } from "../utils/client.js";
Skyler Grey11236ba2022-08-08 21:13:33 +01002import { LinkCheck, MalwareCheck, NSFWCheck, SizeCheck, TestString, TestImage } from "../reflex/scanners.js";
pineafan63fc5e22022-08-04 22:04:10 +01003import logAttachment from "../premium/attachmentLogs.js";
PineaFan0d06edc2023-01-17 22:10:31 +00004import { messageException } from "../utils/createTemporaryStorage.js";
pineafan63fc5e22022-08-04 22:04:10 +01005import getEmojiByName from "../utils/getEmojiByName.js";
6import client from "../utils/client.js";
pineafan0f5cc782022-08-12 21:55:42 +01007import { callback as statsChannelUpdate } from "../reflex/statsChannelUpdate.js";
Skyler Grey3331c9f2023-03-05 07:34:15 +00008import { ChannelType, Message, ThreadChannel } from "discord.js";
TheCodedProfb7a7b992023-03-05 16:11:59 -05009import singleNotify from "../utils/singleNotify.js";
pineafan813bdf42022-07-24 10:39:10 +010010
pineafan63fc5e22022-08-04 22:04:10 +010011export const event = "messageCreate";
pineafan813bdf42022-07-24 10:39:10 +010012
PineaFan752af462022-12-31 21:59:38 +000013export async function callback(_client: NucleusClient, message: Message) {
Skyler Grey75ea9172022-08-06 10:22:23 +010014 if (!message.guild) return;
PineappleFan13892c62023-03-05 07:00:07 +000015 const config = await client.memory.readGuildInfo(message.guild.id);
Skyler9f5fca82023-03-05 09:12:03 +000016
Skyler Greyda16adf2023-03-05 10:22:12 +000017 if (
18 config.autoPublish.enabled &&
19 config.autoPublish.channels.includes(message.channel.id) &&
20 message.channel.type === ChannelType.GuildAnnouncement &&
21 message.reference === null
Skyler9f5fca82023-03-05 09:12:03 +000022 ) {
Skyler Grey67691762023-03-06 09:58:19 +000023 if (message.channel.permissionsFor(message.guild.members.me!)!.has("ManageMessages")) {
TheCodedProfb7a7b992023-03-05 16:11:59 -050024 await message.crosspost();
25 } else {
Skyler Greyf4f21c42023-03-08 14:36:29 +000026 await singleNotify(
27 `Nucleus does not have Manage Messages in <#${message.channel.id}>`,
28 message.guild.id,
29 true
30 );
TheCodedProfb7a7b992023-03-05 16:11:59 -050031 }
PineappleFan13892c62023-03-05 07:00:07 +000032 }
33
pineafan63fc5e22022-08-04 22:04:10 +010034 if (message.author.bot) return;
PineaFan538d3752023-01-12 21:48:23 +000035 if (message.channel.isDMBased()) return;
Skyler Grey75ea9172022-08-06 10:22:23 +010036 try {
pineafan6de4da52023-03-07 20:43:44 +000037 await statsChannelUpdate((await message.guild.members.fetch(message.author.id)).user, message.guild);
Skyler Grey75ea9172022-08-06 10:22:23 +010038 } catch (e) {
39 console.log(e);
40 }
pineafan813bdf42022-07-24 10:39:10 +010041
TheCodedProf6ec331b2023-02-20 12:13:06 -050042 const { log, isLogging, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
pineafan813bdf42022-07-24 10:39:10 +010043
pineafan63fc5e22022-08-04 22:04:10 +010044 const fileNames = await logAttachment(message);
pineafan813bdf42022-07-24 10:39:10 +010045
pineafan63fc5e22022-08-04 22:04:10 +010046 const content = message.content.toLowerCase() || "";
Skyler Greyda16adf2023-03-05 10:22:12 +000047 if (config.filters.clean.channels.includes(message.channel.id)) {
48 const memberRoles = message.member!.roles.cache.map((role) => role.id);
49 const roleAllow = config.filters.clean.allowed.roles.some((role) => memberRoles.includes(role));
TheCodedProff8ef7942023-03-03 15:32:32 -050050 const userAllow = config.filters.clean.allowed.users.includes(message.author.id);
Skyler Greyda16adf2023-03-05 10:22:12 +000051 if (!roleAllow && !userAllow) return await message.delete();
TheCodedProfad0b8202023-02-14 14:27:09 -050052 }
TheCodedProfbaee2c12023-02-18 16:11:06 -050053
pineafan63fc5e22022-08-04 22:04:10 +010054 const filter = getEmojiByName("ICONS.FILTER");
55 let attachmentJump = "";
Skyler Grey75ea9172022-08-06 10:22:23 +010056 if (config.logging.attachments.saved[message.channel.id + message.id]) {
Skyler Grey11236ba2022-08-08 21:13:33 +010057 attachmentJump = ` [[View attachments]](${config.logging.attachments.saved[message.channel.id + message.id]})`;
Skyler Grey75ea9172022-08-06 10:22:23 +010058 }
pineafan63fc5e22022-08-04 22:04:10 +010059 const list = {
pineafan813bdf42022-07-24 10:39:10 +010060 messageId: entry(message.id, `\`${message.id}\``),
61 sentBy: entry(message.author.id, renderUser(message.author)),
62 sentIn: entry(message.channel.id, renderChannel(message.channel)),
TheCodedProf6ec331b2023-02-20 12:13:06 -050063 deleted: entry(Date.now(), renderDelta(Date.now())),
pineafan813bdf42022-07-24 10:39:10 +010064 mentions: message.mentions.users.size,
Skyler Grey11236ba2022-08-08 21:13:33 +010065 attachments: entry(message.attachments.size, message.attachments.size + attachmentJump),
pineafan813bdf42022-07-24 10:39:10 +010066 repliedTo: entry(
PineaFan538d3752023-01-12 21:48:23 +000067 (message.reference ? message.reference.messageId : null) ?? null,
Skyler Grey75ea9172022-08-06 10:22:23 +010068 message.reference
69 ? `[[Jump to message]](https://discord.com/channels/${message.guild.id}/${message.channel.id}/${message.reference.messageId})`
70 : "None"
pineafan813bdf42022-07-24 10:39:10 +010071 )
pineafan63fc5e22022-08-04 22:04:10 +010072 };
pineafan813bdf42022-07-24 10:39:10 +010073
74 if (config.filters.invite.enabled) {
Skyler Grey11236ba2022-08-08 21:13:33 +010075 if (!config.filters.invite.allowed.channels.includes(message.channel.id)) {
76 if (/(?:https?:\/\/)?discord(?:app)?\.(?:com\/invite|gg)\/[a-zA-Z0-9]+\/?/.test(content)) {
PineaFan0d06edc2023-01-17 22:10:31 +000077 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyf4f21c42023-03-08 14:36:29 +000078 await message.delete();
pineafan63fc5e22022-08-04 22:04:10 +010079 const data = {
pineafan813bdf42022-07-24 10:39:10 +010080 meta: {
pineafan63fc5e22022-08-04 22:04:10 +010081 type: "messageDelete",
pineafanfa445992023-03-06 16:21:51 +000082 displayName: "Message Deleted",
pineafan63fc5e22022-08-04 22:04:10 +010083 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +010084 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +010085 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -050086 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +010087 },
88 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +010089 start:
90 filter +
91 " Contained invite\n\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +010092 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +010093 },
94 list: list,
95 hidden: {
96 guild: message.channel.guild.id
97 }
pineafan63fc5e22022-08-04 22:04:10 +010098 };
pineafan813bdf42022-07-24 10:39:10 +010099 return log(data);
100 }
101 }
102 }
103
104 if (fileNames.files.length > 0) {
pineafan63fc5e22022-08-04 22:04:10 +0100105 for (const element of fileNames.files) {
pineafan63fc5e22022-08-04 22:04:10 +0100106 const url = element.url ? element.url : element.local;
Skyler Greyda16adf2023-03-05 10:22:12 +0000107 if (
108 /\.(j(pe?g|fif)|a?png|gifv?|w(eb[mp]|av)|mp([34]|eg-\d)|ogg|avi|h\.26(4|5)|cda)$/.test(
109 url.toLowerCase()
110 )
111 ) {
TheCodedProf16113672023-02-03 16:05:23 -0500112 // jpg|jpeg|png|apng|gif|gifv|webm|webp|mp4|wav|mp3|ogg|jfif|MPEG-#|avi|h.264|h.265
Skyler Grey75ea9172022-08-06 10:22:23 +0100113 if (
Skyler Greyc634e2b2022-08-06 17:50:48 +0100114 config.filters.images.NSFW &&
Skyler Grey11236ba2022-08-08 21:13:33 +0100115 !(message.channel instanceof ThreadChannel ? message.channel.parent?.nsfw : message.channel.nsfw)
Skyler Grey75ea9172022-08-06 10:22:23 +0100116 ) {
Skyler Greyc634e2b2022-08-06 17:50:48 +0100117 if (await NSFWCheck(url)) {
PineaFan0d06edc2023-01-17 22:10:31 +0000118 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100119 await message.delete();
120 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100121 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100122 type: "messageDelete",
123 displayName: "Message Deleted",
124 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100125 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100126 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500127 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100128 },
129 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100130 start:
131 filter +
Skyler Greyc634e2b2022-08-06 17:50:48 +0100132 " Image detected as NSFW\n\n" +
Skyler Grey75ea9172022-08-06 10:22:23 +0100133 (content
134 ? `**Message:**\n\`\`\`${content}\`\`\``
135 : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100136 },
137 list: list,
138 hidden: {
139 guild: message.channel.guild.id
140 }
pineafan63fc5e22022-08-04 22:04:10 +0100141 };
pineafan813bdf42022-07-24 10:39:10 +0100142 return log(data);
143 }
144 }
Skyler Greyc634e2b2022-08-06 17:50:48 +0100145 if (config.filters.wordFilter.enabled) {
146 const text = await TestImage(url);
147 const check = TestString(
148 text ?? "",
149 config.filters.wordFilter.words.loose,
150 config.filters.wordFilter.words.strict
151 );
152 if (check !== null) {
PineaFan0d06edc2023-01-17 22:10:31 +0000153 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100154 await message.delete();
155 const data = {
156 meta: {
157 type: "messageDelete",
158 displayName: "Message Deleted",
159 calculateType: "autoModeratorDeleted",
160 color: NucleusColors.red,
161 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500162 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100163 },
164 separate: {
165 start:
166 filter +
167 " Image contained filtered word\n\n" +
168 (content
169 ? `**Message:**\n\`\`\`${content}\`\`\``
170 : "**Message:** *Message had no content*")
171 },
172 list: list,
173 hidden: {
174 guild: message.channel.guild.id
175 }
176 };
177 return log(data);
178 }
179 }
180 if (config.filters.images.size) {
181 if (url.match(/\.+(webp|png|jpg)$/gi)) {
182 if (!(await SizeCheck(element))) {
PineaFan0d06edc2023-01-17 22:10:31 +0000183 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100184 await message.delete();
185 const data = {
186 meta: {
187 type: "messageDelete",
188 displayName: "Message Deleted",
189 calculateType: "autoModeratorDeleted",
190 color: NucleusColors.red,
191 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500192 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100193 },
194 separate: {
195 start:
196 filter +
197 " Image was too small\n\n" +
198 (content
199 ? `**Message:**\n\`\`\`${content}\`\`\``
200 : "**Message:** *Message had no content*")
201 },
202 list: list,
203 hidden: {
204 guild: message.channel.guild.id
205 }
206 };
207 return log(data);
208 }
209 }
210 }
211 }
212 if (config.filters.malware) {
213 if (!(await MalwareCheck(url))) {
PineaFan0d06edc2023-01-17 22:10:31 +0000214 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100215 await message.delete();
216 const data = {
217 meta: {
218 type: "messageDelete",
219 displayName: "Message Deleted",
220 calculateType: "autoModeratorDeleted",
221 color: NucleusColors.red,
222 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500223 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100224 },
225 separate: {
226 start:
227 filter +
228 " File detected as malware\n\n" +
229 (content
230 ? `**Message:**\n\`\`\`${content}\`\`\``
231 : "**Message:** *Message had no content*")
232 },
233 list: list,
234 hidden: {
235 guild: message.channel.guild.id
236 }
237 };
238 return log(data);
239 }
pineafan813bdf42022-07-24 10:39:10 +0100240 }
pineafan63fc5e22022-08-04 22:04:10 +0100241 }
pineafan813bdf42022-07-24 10:39:10 +0100242 }
pineafan813bdf42022-07-24 10:39:10 +0100243
pineafan63fc5e22022-08-04 22:04:10 +0100244 const linkDetectionTypes = await LinkCheck(message);
pineafan813bdf42022-07-24 10:39:10 +0100245 if (linkDetectionTypes.length > 0) {
PineaFan0d06edc2023-01-17 22:10:31 +0000246 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100247 await message.delete();
248 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100249 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100250 type: "messageDelete",
251 displayName: "Message Deleted",
252 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100253 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100254 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500255 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100256 },
257 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100258 start:
259 filter +
260 ` Link filtered as ${linkDetectionTypes[0]?.toLowerCase()}\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100261 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100262 },
263 list: list,
264 hidden: {
265 guild: message.channel.guild.id
266 }
pineafan63fc5e22022-08-04 22:04:10 +0100267 };
pineafan813bdf42022-07-24 10:39:10 +0100268 return log(data);
269 }
pineafane23c4ec2022-07-27 21:56:27 +0100270
pineafan813bdf42022-07-24 10:39:10 +0100271 if (config.filters.wordFilter.enabled) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100272 const check = TestString(
273 content,
274 config.filters.wordFilter.words.loose,
275 config.filters.wordFilter.words.strict
276 );
277 if (check !== null) {
PineaFan0d06edc2023-01-17 22:10:31 +0000278 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100279 await message.delete();
280 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100281 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100282 type: "messageDelete",
283 displayName: "Message Deleted",
284 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100285 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100286 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500287 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100288 },
289 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100290 start:
291 filter +
292 " Message contained filtered word\n\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +0100293 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100294 },
295 list: list,
296 hidden: {
297 guild: message.channel.guild.id
298 }
pineafan63fc5e22022-08-04 22:04:10 +0100299 };
pineafan813bdf42022-07-24 10:39:10 +0100300 return log(data);
301 }
302 }
303
pineafane23c4ec2022-07-27 21:56:27 +0100304 if (config.filters.pings.everyone && message.mentions.everyone) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000305 if (!(await isLogging(message.guild.id, "messageMassPing"))) return;
pineafan63fc5e22022-08-04 22:04:10 +0100306 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100307 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100308 type: "everyonePing",
309 displayName: "Everyone Pinged",
310 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100311 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100312 emoji: "MESSAGE.PING.EVERYONE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500313 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100314 },
315 separate: {
Skyler Grey11236ba2022-08-08 21:13:33 +0100316 start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100317 },
318 list: list,
319 hidden: {
320 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100321 }
pineafan63fc5e22022-08-04 22:04:10 +0100322 };
pineafane23c4ec2022-07-27 21:56:27 +0100323 return log(data);
324 }
325 if (config.filters.pings.roles) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100326 for (const roleId in message.mentions.roles) {
pineafan63fc5e22022-08-04 22:04:10 +0100327 if (!config.filters.pings.allowed.roles.includes(roleId)) {
PineaFan0d06edc2023-01-17 22:10:31 +0000328 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100329 await message.delete();
Skyler Greyda16adf2023-03-05 10:22:12 +0000330 if (!(await isLogging(message.guild.id, "messageMassPing"))) return;
pineafan63fc5e22022-08-04 22:04:10 +0100331 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100332 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100333 type: "rolePing",
334 displayName: "Role Pinged",
335 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100336 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100337 emoji: "MESSAGE.PING.ROLE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500338 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100339 },
340 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100341 start: content
342 ? `**Message:**\n\`\`\`${content}\`\`\``
343 : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100344 },
345 list: list,
346 hidden: {
347 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100348 }
pineafan63fc5e22022-08-04 22:04:10 +0100349 };
pineafane23c4ec2022-07-27 21:56:27 +0100350 return log(data);
pineafan813bdf42022-07-24 10:39:10 +0100351 }
352 }
pineafane23c4ec2022-07-27 21:56:27 +0100353 }
Skyler Grey11236ba2022-08-08 21:13:33 +0100354 if (message.mentions.users.size >= config.filters.pings.mass && config.filters.pings.mass) {
PineaFan0d06edc2023-01-17 22:10:31 +0000355 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100356 await message.delete();
Skyler Greyda16adf2023-03-05 10:22:12 +0000357 if (!(await isLogging(message.guild.id, "messageMassPing"))) return;
pineafan63fc5e22022-08-04 22:04:10 +0100358 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100359 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100360 type: "massPing",
361 displayName: "Mass Ping",
362 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100363 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100364 emoji: "MESSAGE.PING.MASS",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500365 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100366 },
367 separate: {
Skyler Grey11236ba2022-08-08 21:13:33 +0100368 start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100369 },
370 list: list,
371 hidden: {
372 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100373 }
pineafan63fc5e22022-08-04 22:04:10 +0100374 };
pineafane23c4ec2022-07-27 21:56:27 +0100375 return log(data);
pineafan813bdf42022-07-24 10:39:10 +0100376 }
377}