blob: e98477b4c72d7bac765491fd16f738760db062c4 [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";
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)) {
TheCodedProf1807fb32023-02-20 14:33:48 -050029 const memberRoles = message.member!.roles.cache.map(role => role.id);
30 const roleAllow = config.filters.clean.allowed.roles.some(role => memberRoles.includes(role));
TheCodedProff8ef7942023-03-03 15:32:32 -050031 const userAllow = config.filters.clean.allowed.users.includes(message.author.id);
TheCodedProfad0b8202023-02-14 14:27:09 -050032 if(!roleAllow && !userAllow) return await message.delete();
33 }
TheCodedProfbaee2c12023-02-18 16:11:06 -050034
Skyler Grey3331c9f2023-03-05 07:34:15 +000035 if (config.autoPublish.enabled
36 && config.autoPublish.channels.includes(message.channel.id)
37 && message.channel.type === ChannelType.GuildAnnouncement
38 && message.reference === null
39 ) {
TheCodedProfbaee2c12023-02-18 16:11:06 -050040 await message.crosspost();
41 }
42
pineafan63fc5e22022-08-04 22:04:10 +010043 const filter = getEmojiByName("ICONS.FILTER");
44 let attachmentJump = "";
Skyler Grey75ea9172022-08-06 10:22:23 +010045 if (config.logging.attachments.saved[message.channel.id + message.id]) {
Skyler Grey11236ba2022-08-08 21:13:33 +010046 attachmentJump = ` [[View attachments]](${config.logging.attachments.saved[message.channel.id + message.id]})`;
Skyler Grey75ea9172022-08-06 10:22:23 +010047 }
pineafan63fc5e22022-08-04 22:04:10 +010048 const list = {
pineafan813bdf42022-07-24 10:39:10 +010049 messageId: entry(message.id, `\`${message.id}\``),
50 sentBy: entry(message.author.id, renderUser(message.author)),
51 sentIn: entry(message.channel.id, renderChannel(message.channel)),
TheCodedProf6ec331b2023-02-20 12:13:06 -050052 deleted: entry(Date.now(), renderDelta(Date.now())),
pineafan813bdf42022-07-24 10:39:10 +010053 mentions: message.mentions.users.size,
Skyler Grey11236ba2022-08-08 21:13:33 +010054 attachments: entry(message.attachments.size, message.attachments.size + attachmentJump),
pineafan813bdf42022-07-24 10:39:10 +010055 repliedTo: entry(
PineaFan538d3752023-01-12 21:48:23 +000056 (message.reference ? message.reference.messageId : null) ?? null,
Skyler Grey75ea9172022-08-06 10:22:23 +010057 message.reference
58 ? `[[Jump to message]](https://discord.com/channels/${message.guild.id}/${message.channel.id}/${message.reference.messageId})`
59 : "None"
pineafan813bdf42022-07-24 10:39:10 +010060 )
pineafan63fc5e22022-08-04 22:04:10 +010061 };
pineafan813bdf42022-07-24 10:39:10 +010062
63 if (config.filters.invite.enabled) {
Skyler Grey11236ba2022-08-08 21:13:33 +010064 if (!config.filters.invite.allowed.channels.includes(message.channel.id)) {
65 if (/(?:https?:\/\/)?discord(?:app)?\.(?:com\/invite|gg)\/[a-zA-Z0-9]+\/?/.test(content)) {
PineaFan0d06edc2023-01-17 22:10:31 +000066 messageException(message.guild.id, message.channel.id, message.id);
pineafan813bdf42022-07-24 10:39:10 +010067 message.delete();
pineafan63fc5e22022-08-04 22:04:10 +010068 const data = {
pineafan813bdf42022-07-24 10:39:10 +010069 meta: {
pineafan63fc5e22022-08-04 22:04:10 +010070 type: "messageDelete",
Skyler Grey11236ba2022-08-08 21:13:33 +010071 displayName: "Message Deleted (Automated, Contained Invite)",
pineafan63fc5e22022-08-04 22:04:10 +010072 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +010073 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +010074 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -050075 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +010076 },
77 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +010078 start:
79 filter +
80 " Contained invite\n\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +010081 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +010082 },
83 list: list,
84 hidden: {
85 guild: message.channel.guild.id
86 }
pineafan63fc5e22022-08-04 22:04:10 +010087 };
pineafan813bdf42022-07-24 10:39:10 +010088 return log(data);
89 }
90 }
91 }
92
93 if (fileNames.files.length > 0) {
pineafan63fc5e22022-08-04 22:04:10 +010094 for (const element of fileNames.files) {
pineafan63fc5e22022-08-04 22:04:10 +010095 const url = element.url ? element.url : element.local;
TheCodedProf16113672023-02-03 16:05:23 -050096 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())) {
97 // 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 +010098 if (
Skyler Greyc634e2b2022-08-06 17:50:48 +010099 config.filters.images.NSFW &&
Skyler Grey11236ba2022-08-08 21:13:33 +0100100 !(message.channel instanceof ThreadChannel ? message.channel.parent?.nsfw : message.channel.nsfw)
Skyler Grey75ea9172022-08-06 10:22:23 +0100101 ) {
Skyler Greyc634e2b2022-08-06 17:50:48 +0100102 if (await NSFWCheck(url)) {
PineaFan0d06edc2023-01-17 22:10:31 +0000103 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100104 await message.delete();
105 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100106 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100107 type: "messageDelete",
108 displayName: "Message Deleted",
109 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100110 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100111 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500112 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100113 },
114 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100115 start:
116 filter +
Skyler Greyc634e2b2022-08-06 17:50:48 +0100117 " Image detected as NSFW\n\n" +
Skyler Grey75ea9172022-08-06 10:22:23 +0100118 (content
119 ? `**Message:**\n\`\`\`${content}\`\`\``
120 : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100121 },
122 list: list,
123 hidden: {
124 guild: message.channel.guild.id
125 }
pineafan63fc5e22022-08-04 22:04:10 +0100126 };
pineafan813bdf42022-07-24 10:39:10 +0100127 return log(data);
128 }
129 }
Skyler Greyc634e2b2022-08-06 17:50:48 +0100130 if (config.filters.wordFilter.enabled) {
131 const text = await TestImage(url);
132 const check = TestString(
133 text ?? "",
134 config.filters.wordFilter.words.loose,
135 config.filters.wordFilter.words.strict
136 );
137 if (check !== null) {
PineaFan0d06edc2023-01-17 22:10:31 +0000138 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100139 await message.delete();
140 const data = {
141 meta: {
142 type: "messageDelete",
143 displayName: "Message Deleted",
144 calculateType: "autoModeratorDeleted",
145 color: NucleusColors.red,
146 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500147 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100148 },
149 separate: {
150 start:
151 filter +
152 " Image contained filtered word\n\n" +
153 (content
154 ? `**Message:**\n\`\`\`${content}\`\`\``
155 : "**Message:** *Message had no content*")
156 },
157 list: list,
158 hidden: {
159 guild: message.channel.guild.id
160 }
161 };
162 return log(data);
163 }
164 }
165 if (config.filters.images.size) {
166 if (url.match(/\.+(webp|png|jpg)$/gi)) {
167 if (!(await SizeCheck(element))) {
PineaFan0d06edc2023-01-17 22:10:31 +0000168 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100169 await message.delete();
170 const data = {
171 meta: {
172 type: "messageDelete",
173 displayName: "Message Deleted",
174 calculateType: "autoModeratorDeleted",
175 color: NucleusColors.red,
176 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500177 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100178 },
179 separate: {
180 start:
181 filter +
182 " Image was too small\n\n" +
183 (content
184 ? `**Message:**\n\`\`\`${content}\`\`\``
185 : "**Message:** *Message had no content*")
186 },
187 list: list,
188 hidden: {
189 guild: message.channel.guild.id
190 }
191 };
192 return log(data);
193 }
194 }
195 }
196 }
197 if (config.filters.malware) {
198 if (!(await MalwareCheck(url))) {
PineaFan0d06edc2023-01-17 22:10:31 +0000199 messageException(message.guild.id, message.channel.id, message.id);
Skyler Greyc634e2b2022-08-06 17:50:48 +0100200 await message.delete();
201 const data = {
202 meta: {
203 type: "messageDelete",
204 displayName: "Message Deleted",
205 calculateType: "autoModeratorDeleted",
206 color: NucleusColors.red,
207 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500208 timestamp: Date.now()
Skyler Greyc634e2b2022-08-06 17:50:48 +0100209 },
210 separate: {
211 start:
212 filter +
213 " File detected as malware\n\n" +
214 (content
215 ? `**Message:**\n\`\`\`${content}\`\`\``
216 : "**Message:** *Message had no content*")
217 },
218 list: list,
219 hidden: {
220 guild: message.channel.guild.id
221 }
222 };
223 return log(data);
224 }
pineafan813bdf42022-07-24 10:39:10 +0100225 }
pineafan63fc5e22022-08-04 22:04:10 +0100226 }
pineafan813bdf42022-07-24 10:39:10 +0100227 }
pineafan813bdf42022-07-24 10:39:10 +0100228
pineafan63fc5e22022-08-04 22:04:10 +0100229 const linkDetectionTypes = await LinkCheck(message);
pineafan813bdf42022-07-24 10:39:10 +0100230 if (linkDetectionTypes.length > 0) {
PineaFan0d06edc2023-01-17 22:10:31 +0000231 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100232 await message.delete();
233 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100234 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100235 type: "messageDelete",
236 displayName: "Message Deleted",
237 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100238 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100239 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500240 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100241 },
242 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100243 start:
244 filter +
245 ` Link filtered as ${linkDetectionTypes[0]?.toLowerCase()}\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100246 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100247 },
248 list: list,
249 hidden: {
250 guild: message.channel.guild.id
251 }
pineafan63fc5e22022-08-04 22:04:10 +0100252 };
pineafan813bdf42022-07-24 10:39:10 +0100253 return log(data);
254 }
pineafane23c4ec2022-07-27 21:56:27 +0100255
pineafan813bdf42022-07-24 10:39:10 +0100256 if (config.filters.wordFilter.enabled) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100257 const check = TestString(
258 content,
259 config.filters.wordFilter.words.loose,
260 config.filters.wordFilter.words.strict
261 );
262 if (check !== null) {
PineaFan0d06edc2023-01-17 22:10:31 +0000263 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100264 await message.delete();
265 const data = {
pineafan813bdf42022-07-24 10:39:10 +0100266 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100267 type: "messageDelete",
268 displayName: "Message Deleted",
269 calculateType: "autoModeratorDeleted",
pineafan813bdf42022-07-24 10:39:10 +0100270 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +0100271 emoji: "MESSAGE.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500272 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +0100273 },
274 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100275 start:
276 filter +
277 " Message contained filtered word\n\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +0100278 (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
pineafan813bdf42022-07-24 10:39:10 +0100279 },
280 list: list,
281 hidden: {
282 guild: message.channel.guild.id
283 }
pineafan63fc5e22022-08-04 22:04:10 +0100284 };
pineafan813bdf42022-07-24 10:39:10 +0100285 return log(data);
286 }
287 }
288
pineafane23c4ec2022-07-27 21:56:27 +0100289 if (config.filters.pings.everyone && message.mentions.everyone) {
TheCodedProf6ec331b2023-02-20 12:13:06 -0500290 if(!await isLogging(message.guild.id, "messageMassPing")) return;
pineafan63fc5e22022-08-04 22:04:10 +0100291 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100292 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100293 type: "everyonePing",
294 displayName: "Everyone Pinged",
295 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100296 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100297 emoji: "MESSAGE.PING.EVERYONE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500298 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100299 },
300 separate: {
Skyler Grey11236ba2022-08-08 21:13:33 +0100301 start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100302 },
303 list: list,
304 hidden: {
305 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100306 }
pineafan63fc5e22022-08-04 22:04:10 +0100307 };
pineafane23c4ec2022-07-27 21:56:27 +0100308 return log(data);
309 }
310 if (config.filters.pings.roles) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100311 for (const roleId in message.mentions.roles) {
pineafan63fc5e22022-08-04 22:04:10 +0100312 if (!config.filters.pings.allowed.roles.includes(roleId)) {
PineaFan0d06edc2023-01-17 22:10:31 +0000313 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100314 await message.delete();
TheCodedProf6ec331b2023-02-20 12:13:06 -0500315 if(!await isLogging(message.guild.id, "messageMassPing")) return;
pineafan63fc5e22022-08-04 22:04:10 +0100316 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100317 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100318 type: "rolePing",
319 displayName: "Role Pinged",
320 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100321 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100322 emoji: "MESSAGE.PING.ROLE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500323 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100324 },
325 separate: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100326 start: content
327 ? `**Message:**\n\`\`\`${content}\`\`\``
328 : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100329 },
330 list: list,
331 hidden: {
332 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100333 }
pineafan63fc5e22022-08-04 22:04:10 +0100334 };
pineafane23c4ec2022-07-27 21:56:27 +0100335 return log(data);
pineafan813bdf42022-07-24 10:39:10 +0100336 }
337 }
pineafane23c4ec2022-07-27 21:56:27 +0100338 }
Skyler Grey11236ba2022-08-08 21:13:33 +0100339 if (message.mentions.users.size >= config.filters.pings.mass && config.filters.pings.mass) {
PineaFan0d06edc2023-01-17 22:10:31 +0000340 messageException(message.guild.id, message.channel.id, message.id);
pineafan63fc5e22022-08-04 22:04:10 +0100341 await message.delete();
TheCodedProf6ec331b2023-02-20 12:13:06 -0500342 if(!await isLogging(message.guild.id, "messageMassPing")) return;
pineafan63fc5e22022-08-04 22:04:10 +0100343 const data = {
pineafane23c4ec2022-07-27 21:56:27 +0100344 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100345 type: "massPing",
346 displayName: "Mass Ping",
347 calculateType: "messageMassPing",
pineafane23c4ec2022-07-27 21:56:27 +0100348 color: NucleusColors.yellow,
pineafan63fc5e22022-08-04 22:04:10 +0100349 emoji: "MESSAGE.PING.MASS",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500350 timestamp: Date.now()
pineafane23c4ec2022-07-27 21:56:27 +0100351 },
352 separate: {
Skyler Grey11236ba2022-08-08 21:13:33 +0100353 start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
pineafane23c4ec2022-07-27 21:56:27 +0100354 },
355 list: list,
356 hidden: {
357 guild: message.channel.guild.id
pineafan813bdf42022-07-24 10:39:10 +0100358 }
pineafan63fc5e22022-08-04 22:04:10 +0100359 };
pineafane23c4ec2022-07-27 21:56:27 +0100360 return log(data);
pineafan813bdf42022-07-24 10:39:10 +0100361 }
362}