blob: 7f8e5d1fe9c3f0592e3e47942c7de5fad0048d56 [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 Greyc634e2b2022-08-06 17:50:48 +01008import { Message, ThreadChannel } from "discord.js";
pineafan813bdf42022-07-24 10:39:10 +01009
pineafan63fc5e22022-08-04 22:04:10 +010010export const event = "messageCreate";
pineafan813bdf42022-07-24 10:39:10 +010011
PineaFan752af462022-12-31 21:59:38 +000012export async function callback(_client: NucleusClient, message: Message) {
Skyler Grey75ea9172022-08-06 10:22:23 +010013 if (!message.guild) return;
pineafan63fc5e22022-08-04 22:04:10 +010014 if (message.author.bot) return;
PineaFan538d3752023-01-12 21:48:23 +000015 if (message.channel.isDMBased()) return;
Skyler Grey75ea9172022-08-06 10:22:23 +010016 try {
pineafan0f5cc782022-08-12 21:55:42 +010017 await statsChannelUpdate(client, await message.guild.members.fetch(message.author.id));
Skyler Grey75ea9172022-08-06 10:22:23 +010018 } catch (e) {
19 console.log(e);
20 }
pineafan813bdf42022-07-24 10:39:10 +010021
TheCodedProf6ec331b2023-02-20 12:13:06 -050022 const { log, isLogging, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
pineafan813bdf42022-07-24 10:39:10 +010023
pineafan63fc5e22022-08-04 22:04:10 +010024 const fileNames = await logAttachment(message);
pineafan813bdf42022-07-24 10:39:10 +010025
pineafan63fc5e22022-08-04 22:04:10 +010026 const content = message.content.toLowerCase() || "";
27 const config = await client.memory.readGuildInfo(message.guild.id);
TheCodedProfad0b8202023-02-14 14:27:09 -050028 if(config.filters.clean.channels.includes(message.channel.id)) {
29 let memberRoles = message.member!.roles.cache.map(role => role.id);
30 let roleAllow = config.filters.clean.allowed.roles.some(role => memberRoles.includes(role));
31 let userAllow = config.filters.clean.allowed.user.includes(message.author.id);
32 if(!roleAllow && !userAllow) return await message.delete();
33 }
TheCodedProfbaee2c12023-02-18 16:11:06 -050034
35 if (config.autoPublish.enabled && config.autoPublish.channels.includes(message.channel.id)) {
36 await message.crosspost();
37 }
38
pineafan63fc5e22022-08-04 22:04:10 +010039 const filter = getEmojiByName("ICONS.FILTER");
40 let attachmentJump = "";
Skyler Grey75ea9172022-08-06 10:22:23 +010041 if (config.logging.attachments.saved[message.channel.id + message.id]) {
Skyler Grey11236ba2022-08-08 21:13:33 +010042 attachmentJump = ` [[View attachments]](${config.logging.attachments.saved[message.channel.id + message.id]})`;
Skyler Grey75ea9172022-08-06 10:22:23 +010043 }
pineafan63fc5e22022-08-04 22:04:10 +010044 const list = {
pineafan813bdf42022-07-24 10:39:10 +010045 messageId: entry(message.id, `\`${message.id}\``),
46 sentBy: entry(message.author.id, renderUser(message.author)),
47 sentIn: entry(message.channel.id, renderChannel(message.channel)),
TheCodedProf6ec331b2023-02-20 12:13:06 -050048 deleted: entry(Date.now(), renderDelta(Date.now())),
pineafan813bdf42022-07-24 10:39:10 +010049 mentions: message.mentions.users.size,
Skyler Grey11236ba2022-08-08 21:13:33 +010050 attachments: entry(message.attachments.size, message.attachments.size + attachmentJump),
pineafan813bdf42022-07-24 10:39:10 +010051 repliedTo: entry(
PineaFan538d3752023-01-12 21:48:23 +000052 (message.reference ? message.reference.messageId : null) ?? null,
Skyler Grey75ea9172022-08-06 10:22:23 +010053 message.reference
54 ? `[[Jump to message]](https://discord.com/channels/${message.guild.id}/${message.channel.id}/${message.reference.messageId})`
55 : "None"
pineafan813bdf42022-07-24 10:39:10 +010056 )
pineafan63fc5e22022-08-04 22:04:10 +010057 };
pineafan813bdf42022-07-24 10:39:10 +010058
59 if (config.filters.invite.enabled) {
Skyler Grey11236ba2022-08-08 21:13:33 +010060 if (!config.filters.invite.allowed.channels.includes(message.channel.id)) {
61 if (/(?:https?:\/\/)?discord(?:app)?\.(?:com\/invite|gg)\/[a-zA-Z0-9]+\/?/.test(content)) {
PineaFan0d06edc2023-01-17 22:10:31 +000062 messageException(message.guild.id, message.channel.id, message.id);
pineafan813bdf42022-07-24 10:39:10 +010063 message.delete();
pineafan63fc5e22022-08-04 22:04:10 +010064 const data = {
pineafan813bdf42022-07-24 10:39:10 +010065 meta: {
pineafan63fc5e22022-08-04 22:04:10 +010066 type: "messageDelete",
Skyler Grey11236ba2022-08-08 21:13:33 +010067 displayName: "Message Deleted (Automated, Contained Invite)",
pineafan63fc5e22022-08-04 22:04:10 +010068 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +010069 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +010070 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -050071 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +010072 },
73 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +010074 start:
75 filter +
76 " Contained invite\n\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +010077 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +010078 },
79 list: list,
80 hidden: {
81 guild: message.channel.guild.id
82 }
pineafan63fc5e22022-08-04 22:04:10 +010083 };
pineafan813bdf42022-07-24 10:39:10 +010084 return log(data);
85 }
86 }
87 }
88
89 if (fileNames.files.length > 0) {
pineafan63fc5e22022-08-04 22:04:10 +010090 for (const element of fileNames.files) {
pineafan63fc5e22022-08-04 22:04:10 +010091 const url = element.url ? element.url : element.local;
TheCodedProf16113672023-02-03 16:05:23 -050092 if (/\.(j(pe?g|fif)|a?png|gifv?|w(eb[mp]|av)|mp([34]|eg-\d)|ogg|avi|h\.26(4|5)|cda)$/.test(url.toLowerCase())) {
93 // 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 +010094 if (
Skyler Greyc634e2b2022-08-06 17:50:48 +010095 config.filters.images.NSFW &&
Skyler Grey11236ba2022-08-08 21:13:33 +010096 !(message.channel instanceof ThreadChannel ? message.channel.parent?.nsfw : message.channel.nsfw)
Skyler Grey75ea9172022-08-06 10:22:23 +010097 ) {
Skyler Greyc634e2b2022-08-06 17:50:48 +010098 if (await NSFWCheck(url)) {
PineaFan0d06edc2023-01-17 22:10:31 +000099 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100100 await message.delete();
101 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100102 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100103 type: "messageDelete",
104 displayName: "Message Deleted",
105 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100106 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100107 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500108 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100109 },
110 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100111 start:
112 filter +
Skyler Greyc634e2b2022-08-06 17:50:48 +0100113 " Image detected as NSFW\n\n" +
Skyler Grey75ea9172022-08-06 10:22:23 +0100114 (content
115 ? `**Message:**\n\`\`\`${content}\`\`\``
116 : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100117 },
118 list: list,
119 hidden: {
120 guild: message.channel.guild.id
121 }
pineafan63fc5e22022-08-04 22:04:10 +0100122 };
pineafan813bdf42022-07-24 10:39:10 +0100123 return log(data);
124 }
125 }
Skyler Greyc634e2b2022-08-06 17:50:48 +0100126 if (config.filters.wordFilter.enabled) {
127 const text = await TestImage(url);
128 const check = TestString(
129 text ?? "",
130 config.filters.wordFilter.words.loose,
131 config.filters.wordFilter.words.strict
132 );
133 if (check !== null) {
PineaFan0d06edc2023-01-17 22:10:31 +0000134 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100135 await message.delete();
136 const data = {
137 meta: {
138 type: "messageDelete",
139 displayName: "Message Deleted",
140 calculateType: "autoModeratorDeleted",
141 color: NucleusColors.red,
142 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500143 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100144 },
145 separate: {
146 start:
147 filter +
148 " Image contained filtered word\n\n" +
149 (content
150 ? `**Message:**\n\`\`\`${content}\`\`\``
151 : "**Message:** *Message had no content*")
152 },
153 list: list,
154 hidden: {
155 guild: message.channel.guild.id
156 }
157 };
158 return log(data);
159 }
160 }
161 if (config.filters.images.size) {
162 if (url.match(/\.+(webp|png|jpg)$/gi)) {
163 if (!(await SizeCheck(element))) {
PineaFan0d06edc2023-01-17 22:10:31 +0000164 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100165 await message.delete();
166 const data = {
167 meta: {
168 type: "messageDelete",
169 displayName: "Message Deleted",
170 calculateType: "autoModeratorDeleted",
171 color: NucleusColors.red,
172 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500173 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100174 },
175 separate: {
176 start:
177 filter +
178 " Image was too small\n\n" +
179 (content
180 ? `**Message:**\n\`\`\`${content}\`\`\``
181 : "**Message:** *Message had no content*")
182 },
183 list: list,
184 hidden: {
185 guild: message.channel.guild.id
186 }
187 };
188 return log(data);
189 }
190 }
191 }
192 }
193 if (config.filters.malware) {
194 if (!(await MalwareCheck(url))) {
PineaFan0d06edc2023-01-17 22:10:31 +0000195 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100196 await message.delete();
197 const data = {
198 meta: {
199 type: "messageDelete",
200 displayName: "Message Deleted",
201 calculateType: "autoModeratorDeleted",
202 color: NucleusColors.red,
203 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500204 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100205 },
206 separate: {
207 start:
208 filter +
209 " File detected as malware\n\n" +
210 (content
211 ? `**Message:**\n\`\`\`${content}\`\`\``
212 : "**Message:** *Message had no content*")
213 },
214 list: list,
215 hidden: {
216 guild: message.channel.guild.id
217 }
218 };
219 return log(data);
220 }
pineafan813bdf42022-07-24 10:39:10 +0100221 }
pineafan63fc5e22022-08-04 22:04:10 +0100222 }
pineafan813bdf42022-07-24 10:39:10 +0100223 }
pineafan813bdf42022-07-24 10:39:10 +0100224
pineafan63fc5e22022-08-04 22:04:10 +0100225 const linkDetectionTypes = await LinkCheck(message);
pineafan813bdf42022-07-24 10:39:10 +0100226 if (linkDetectionTypes.length > 0) {
PineaFan0d06edc2023-01-17 22:10:31 +0000227 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100228 await message.delete();
229 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100230 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100231 type: "messageDelete",
232 displayName: "Message Deleted",
233 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100234 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100235 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500236 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100237 },
238 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100239 start:
240 filter +
241 ` Link filtered as ${linkDetectionTypes[0]?.toLowerCase()}\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100242 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100243 },
244 list: list,
245 hidden: {
246 guild: message.channel.guild.id
247 }
pineafan63fc5e22022-08-04 22:04:10 +0100248 };
pineafan813bdf42022-07-24 10:39:10 +0100249 return log(data);
250 }
pineafane23c4ec2022-07-27 21:56:27 +0100251
pineafan813bdf42022-07-24 10:39:10 +0100252 if (config.filters.wordFilter.enabled) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100253 const check = TestString(
254 content,
255 config.filters.wordFilter.words.loose,
256 config.filters.wordFilter.words.strict
257 );
258 if (check !== null) {
PineaFan0d06edc2023-01-17 22:10:31 +0000259 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100260 await message.delete();
261 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100262 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100263 type: "messageDelete",
264 displayName: "Message Deleted",
265 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100266 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100267 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500268 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100269 },
270 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100271 start:
272 filter +
273 " Message contained filtered word\n\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +0100274 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100275 },
276 list: list,
277 hidden: {
278 guild: message.channel.guild.id
279 }
pineafan63fc5e22022-08-04 22:04:10 +0100280 };
pineafan813bdf42022-07-24 10:39:10 +0100281 return log(data);
282 }
283 }
284
pineafane23c4ec2022-07-27 21:56:27 +0100285 if (config.filters.pings.everyone && message.mentions.everyone) {
TheCodedProf6ec331b2023-02-20 12:13:06 -0500286 if(!await isLogging(message.guild.id, "messageMassPing")) return;
pineafan63fc5e22022-08-04 22:04:10 +0100287 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100288 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100289 type: "everyonePing",
290 displayName: "Everyone Pinged",
291 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100292 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100293 emoji: "MESSAGE.PING.EVERYONE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500294 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100295 },
296 separate: {
Skyler Grey11236ba2022-08-08 21:13:33 +0100297 start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100298 },
299 list: list,
300 hidden: {
301 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100302 }
pineafan63fc5e22022-08-04 22:04:10 +0100303 };
pineafane23c4ec2022-07-27 21:56:27 +0100304 return log(data);
305 }
306 if (config.filters.pings.roles) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100307 for (const roleId in message.mentions.roles) {
pineafan63fc5e22022-08-04 22:04:10 +0100308 if (!config.filters.pings.allowed.roles.includes(roleId)) {
PineaFan0d06edc2023-01-17 22:10:31 +0000309 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100310 await message.delete();
TheCodedProf6ec331b2023-02-20 12:13:06 -0500311 if(!await isLogging(message.guild.id, "messageMassPing")) return;
pineafan63fc5e22022-08-04 22:04:10 +0100312 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100313 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100314 type: "rolePing",
315 displayName: "Role Pinged",
316 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100317 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100318 emoji: "MESSAGE.PING.ROLE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500319 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100320 },
321 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100322 start: content
323 ? `**Message:**\n\`\`\`${content}\`\`\``
324 : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100325 },
326 list: list,
327 hidden: {
328 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100329 }
pineafan63fc5e22022-08-04 22:04:10 +0100330 };
pineafane23c4ec2022-07-27 21:56:27 +0100331 return log(data);
pineafan813bdf42022-07-24 10:39:10 +0100332 }
333 }
pineafane23c4ec2022-07-27 21:56:27 +0100334 }
Skyler Grey11236ba2022-08-08 21:13:33 +0100335 if (message.mentions.users.size >= config.filters.pings.mass && config.filters.pings.mass) {
PineaFan0d06edc2023-01-17 22:10:31 +0000336 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100337 await message.delete();
TheCodedProf6ec331b2023-02-20 12:13:06 -0500338 if(!await isLogging(message.guild.id, "messageMassPing")) return;
pineafan63fc5e22022-08-04 22:04:10 +0100339 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100340 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100341 type: "massPing",
342 displayName: "Mass Ping",
343 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100344 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100345 emoji: "MESSAGE.PING.MASS",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500346 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100347 },
348 separate: {
Skyler Grey11236ba2022-08-08 21:13:33 +0100349 start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100350 },
351 list: list,
352 hidden: {
353 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100354 }
pineafan63fc5e22022-08-04 22:04:10 +0100355 };
pineafane23c4ec2022-07-27 21:56:27 +0100356 return log(data);
pineafan813bdf42022-07-24 10:39:10 +0100357 }
358}