2022-08-28 17:04:31 +02:00
/ * T O D O :
* Make this shit work .
* /
2022-11-24 21:11:53 +01:00
import { ApplicationCommandOptionType , EmbedBuilder , PermissionFlagsBits } from 'discord.js' ;
2022-08-28 17:04:31 +02:00
import db from '../../models/index.js' ;
import { rand } from '../../utils/rand.js' ;
2022-12-18 23:30:25 +01:00
import ratelimiter from '../../utils/ratelimiter.js' ;
2022-08-28 17:04:31 +02:00
const { ownerId , prefix } = process . env ;
const prefixs = prefix . split ( ',' ) ;
export default {
name : 'messageCreate' ,
async execute ( message , client ) {
if ( message . partials ) {
await message . fetch ( ) ;
}
if ( message . author . bot ) return ;
/ * A u t o r e s p o n s e f e a t u r e & t a g
*
* This section contains autoresponse and tag feature
*
* /
// auto responses
if ( message . guild ) {
const autoresponseStat = await db . autoresponseStat . findOne ( { where : { serverID : message . guild . id , stat : 'enable' } } ) ;
if ( autoresponseStat ) {
// Infinite haha very yes
if ( message . content . toLowerCase ( ) . startsWith ( 'haha very' ) && message . content . toLowerCase ( ) . endsWith ( 'yes' ) ) {
let yes = message . content . toLowerCase ( ) . replace ( 'haha' , '' ) ;
yes = yes . replace ( 'yes' , '' ) ;
yes += 'very' ;
return message . channel . send ( ` haha ${ yes } yes ` ) ;
}
else if ( message . content . toLowerCase ( ) == 'haha yes' ) {
return message . channel . send ( 'haha very yes' ) ;
}
// Reply with images as attachement
const autoresponse = await db . autoresponse . findOne ( { where : { trigger : message . content . toLowerCase ( ) } } ) ;
if ( autoresponse ) {
db . autoresponse . findOne ( { where : { trigger : message . content . toLowerCase ( ) } } ) ;
const trigger = autoresponse . get ( 'trigger' ) ;
const type = autoresponse . get ( 'type' ) ;
const content = autoresponse . get ( 'response' ) ;
if ( trigger == message . content . toLowerCase ( ) && type == 'text' ) {
return message . channel . send ( content ) ;
}
else if ( trigger == message . content . toLowerCase ( ) && type == 'react' ) {
return message . react ( content ) ;
}
else if ( trigger == message . content . toLowerCase ( ) && type == 'image' ) {
return message . channel . send ( { files : [ content ] } ) ;
}
}
}
// User autoresponse
const tag = await db . Tag . findOne ( { where : { trigger : message . content . toLowerCase ( ) , serverID : message . guild . id } } ) ;
if ( tag ) {
db . Tag . findOne ( { where : { trigger : message . content . toLowerCase ( ) , serverID : message . guild . id } } ) ;
let text = tag . get ( 'response' ) ;
2023-04-04 19:51:36 +02:00
/ *
2022-08-28 17:04:31 +02:00
if ( text . includes ( '[ban]' ) ) {
message . member . ban ( 'Tag ban :^)' ) ;
}
else if ( text . includes ( '[kick]' ) ) {
message . member . kick ( 'Tag kick :^)' ) ;
}
2023-04-04 19:51:36 +02:00
else
* /
if ( text . includes ( '[delete]' ) ) {
2022-08-28 17:04:31 +02:00
message . delete ( ) ;
}
2022-09-04 02:26:02 +02:00
text = rand ( text , message ) ;
2022-08-28 17:04:31 +02:00
let attach = '' ;
if ( text . includes ( '[attach:' ) ) {
attach = text . split ( /(\[attach:.*?])/ ) ;
for ( let i = 0 , l = attach . length ; i < l ; i ++ ) {
if ( attach [ i ] . includes ( '[attach:' ) ) {
attach = attach [ i ] . replace ( '[attach:' , '' ) . slice ( 0 , - 1 ) ;
i = attach . length ;
}
}
text = text . replace ( /(\[attach:.*?])/ , '' ) ;
}
// THIS SECTION IS VERY VERY BAD MUST CHANGE
if ( text . includes ( '[embed]' ) ) {
text = text . replace ( /\[embed\]/ , ' ' ) ;
let title = '' ;
let desc = '' ;
let image ;
let thumbnail ;
let footer = '' ;
let color ;
if ( text . includes ( '[embedImage:' ) ) {
image = text . split ( /(\[embedImage:.*?])/ ) ;
for ( let i = 0 , l = image . length ; i < l ; i ++ ) {
if ( image [ i ] . includes ( '[embedImage:' ) ) {
image = image [ i ] . replace ( '[embedImage:' , '' ) . slice ( 0 , - 1 ) ;
text = text . replace ( /(\[embedimage:.*?])/g , '' ) ;
i = image . length ;
}
}
}
if ( text . includes ( '[embedThumbnail:' ) ) {
thumbnail = text . split ( /(\[embedThumbnail:.*?])/ ) ;
for ( let i = 0 , l = thumbnail . length ; i < l ; i ++ ) {
if ( thumbnail [ i ] . includes ( '[embedThumbnail:' ) ) {
thumbnail = thumbnail [ i ] . replace ( '[embedThumbnail:' , '' ) . slice ( 0 , - 1 ) ;
text = text . replace ( /(\[embedThumbnail:.*?])/g , '' ) ;
i = thumbnail . length ;
}
}
}
if ( text . includes ( '[embedColor:' ) ) {
color = text . split ( /(\[embedColor:.*?])/ ) ;
for ( let i = 0 , l = color . length ; i < l ; i ++ ) {
if ( color [ i ] . includes ( '[embedColor:' ) ) {
color = color [ i ] . replace ( '[embedColor:' , '' ) . slice ( 0 , - 1 ) ;
text = text . replace ( /(\[embedColor:.*?])/g , '' ) ;
i = color . length ;
}
}
}
if ( text . includes ( '[embedTitle:' ) ) {
title = text . split ( /(\[embedTitle:.*?])/ ) ;
for ( let i = 0 , l = title . length ; i < l ; i ++ ) {
if ( title [ i ] . includes ( '[embedTitle:' ) ) {
title = title [ i ] . replace ( '[embedTitle:' , '' ) . slice ( 0 , - 1 ) ;
text = text . replace ( /(\[embedTitle:.*?])/g , '' ) ;
i = title . length ;
}
}
}
if ( text . includes ( '[embedFooter:' ) ) {
footer = text . split ( /(\[embedFooter:.*?])/ ) ;
for ( let i = 0 , l = footer . length ; i < l ; i ++ ) {
if ( footer [ i ] . includes ( '[embedFooter:' ) ) {
footer = footer [ i ] . replace ( '[embedFooter:' , '' ) . slice ( 0 , - 1 ) ;
text = text . replace ( /(\[embedFooter:.*?])/g , '' ) ;
i = footer . length ;
}
}
}
if ( text . includes ( '[embedDesc:' ) ) {
desc = text . split ( /(\[embedDesc:.*?])/ ) ;
for ( let i = 0 , l = desc . length ; i < l ; i ++ ) {
if ( desc [ i ] . includes ( '[embedDesc:' ) ) {
desc = desc [ i ] . replace ( '[embedDesc:' , '' ) . slice ( 0 , - 1 ) ;
i = desc . length ;
}
}
}
const embed = new EmbedBuilder ( )
. setColor ( color )
. setTitle ( title )
. setImage ( image )
. setThumbnail ( thumbnail )
. setDescription ( desc )
. setFooter ( footer )
. setTimestamp ( ) ;
if ( attach ) {
return message . channel . send ( embed , { files : [ attach ] } ) ;
}
else {
return message . channel . send ( embed ) ;
}
}
if ( attach ) {
return message . channel . send ( text , { files : [ attach ] } ) ;
}
else {
return message . channel . send ( text ) ;
}
}
/ * Q u o t a t i o n f e a t u r e
*
* This section will contain the code for the quotation feature , it will detect link for it and send it as embed
*
* /
2022-08-29 20:56:26 +02:00
const isOptOut = await db . optout . findOne ( { where : { userID : message . author . id } } ) ;
if ( ! isOptOut ) {
const quotationstat = await db . quotationStat . findOne ( { where : { serverID : message . guild . id , stat : 'enable' } } ) ;
if ( quotationstat && ( message . content . includes ( 'discordapp.com/channels/' ) || message . content . includes ( 'discord.com/channels/' ) ) ) {
const url = message . content . split ( '/' ) ;
const guildID = url [ 4 ] ;
const channelID = url [ 5 ] ;
const messageID = url [ 6 ] . split ( ' ' ) [ 0 ] ;
// Verify if the guild, channel and message exist
const guild = client . guilds . resolve ( guildID ) ;
if ( ! guild ) return ;
const channel = client . channels . resolve ( channelID ) ;
if ( ! channel ) return ;
const quote = await channel . messages . fetch ( messageID )
. catch ( ( ) => {
return ;
} ) ;
if ( ! quote ) return ;
const Embed = new EmbedBuilder ( )
. setAuthor ( { name : quote . author . username , iconURL : quote . author . displayAvatarURL ( ) } )
2022-09-14 14:38:35 +02:00
. setColor ( message . member ? message . member . displayHexColor : 'Navy' )
2022-08-29 20:56:26 +02:00
. addFields (
{ name : 'Jump to' , value : ` [message](https://discordapp.com/channels/ ${ message . guild . id } / ${ channelID } / ${ messageID } ) ` , inline : true } ,
{ name : 'In channel' , value : quote . channel . name . toString ( ) , inline : true } ,
{ name : 'Quoted by' , value : message . author . toString ( ) , inline : true } ,
)
. setDescription ( quote . content )
. setTimestamp ( quote . createdTimestamp ) ;
if ( quote . member ) Embed . setAuthor ( { name : ` ${ quote . author . username } # ${ quote . author . discriminator } ` , iconURL : quote . author . displayAvatarURL ( ) } ) ;
if ( quote . author . bot ) Embed . setAuthor ( { name : ` ${ quote . author . username } # ${ quote . author . discriminator } (BOT) ` , iconURL : quote . author . displayAvatarURL ( ) } ) ;
if ( guild . id != message . guild . id ) Embed . addFields ( { name : 'In guild' , value : guild . name , inline : true } ) ;
const Attachment = Array . from ( message . attachments . values ( ) ) ;
if ( Attachment [ 0 ] ) Embed . setImage ( Attachment [ 0 ] . url ) ;
return message . channel . send ( { embeds : [ Embed ] } ) ;
}
2022-08-28 17:04:31 +02:00
}
}
// Command handling from message
2024-01-30 00:25:41 +01:00
// TODO: Moving that to a dedicated function that works for both messages and interactions
2022-08-28 17:04:31 +02:00
let hasPrefix = false ;
prefixs . forEach ( p => {
if ( message . content . toLowerCase ( ) . startsWith ( p ) ) {
hasPrefix = true ;
}
} ) ;
if ( ! hasPrefix ) return ;
const messageArray = message . content . match ( /"[^"]*"|\S+/g ) . map ( m => m . slice ( 0 , 1 ) === '"' ? m . slice ( 1 , - 1 ) : m ) ;
2022-08-29 20:37:38 +02:00
let commandName = messageArray [ 1 ] . toLowerCase ( ) ;
2022-09-01 01:43:59 +02:00
const messageArgs = messageArray . splice ( 2 , messageArray . length ) ;
2022-08-28 17:04:31 +02:00
2022-08-29 20:37:38 +02:00
// Search for alias
client . commands . find ( c => {
if ( c . alias ) {
if ( c . alias . includes ( commandName ) ) {
commandName = c . data . name ;
}
}
} ) ;
const command = client . commands . get ( commandName ) ;
if ( ! command ) return ;
2022-08-28 17:04:31 +02:00
const globalBlacklist = await db . Blacklists . findOne ( { where : { type : 'global' , uid : message . author . id } } ) ;
const commandBlacklist = await db . Blacklists . findOne ( { where : { type : commandName , uid : message . author . id } } ) ;
2024-06-30 20:05:09 +02:00
if ( message . guild ) {
const serverBlacklist = await db . Blacklists . findOne ( { where : { type : 'guild' , uid : message . guild . id } } ) ;
if ( serverBlacklist ) {
message . reply ( { content : ` This guild has been blacklisted for the following reason: \` ${ serverBlacklist . reason } \` ` , ephemeral : true } ) ;
return message . guild . leave ( ) ;
}
}
2022-08-28 17:04:31 +02:00
if ( globalBlacklist ) {
return message . reply ( { content : ` You are globally blacklisted for the following reason: \` ${ globalBlacklist . reason } \` ` , ephemeral : true } ) ;
2024-06-30 20:05:09 +02:00
}
2022-08-28 17:04:31 +02:00
else if ( commandBlacklist ) {
return message . reply ( { content : ` You are blacklisted for the following reason: \` ${ commandBlacklist . reason } \` ` , ephemeral : true } ) ;
}
2023-09-13 20:56:06 +02:00
const userTag = message . author . username ;
2022-08-28 17:04:31 +02:00
const userID = message . author . id ;
2023-04-04 00:34:24 +02:00
const isOptOut = await db . optout . findOne ( { where : { userID : message . author . id } } ) ;
2023-12-12 21:45:09 +01:00
const timestamp = new Date ( ) ;
2024-02-04 01:40:07 +01:00
console . log ( ` [ ${ timestamp . toISOString ( ) } ] \x 1b[33m ${ isOptOut ? 'A user' : ` ${ userTag } ( ${ userID } ) ` } \x 1b[0m launched command \x 1b[33m ${ commandName } \x 1b[0m using prefix ` ) ;
2023-12-12 21:45:09 +01:00
2022-08-28 17:04:31 +02:00
// Owner only check
if ( command . ownerOnly && message . author . id !== ownerId ) {
return message . reply ( { content : '❌ This command is reserved for the owner!' , ephemeral : true } ) ;
}
2023-04-14 17:46:12 +02:00
// Guild only check
if ( command . guildOnly && ! message . guild ) {
return message . reply ( { content : '❌ This command only work in a server!' , ephemeral : true } ) ;
}
2022-08-28 17:04:31 +02:00
// Check if the bot has the needed permissions
if ( command . clientPermissions ) {
const clientMember = await message . guild . members . fetch ( client . user . id ) ;
if ( ! clientMember . permissions . has ( command . clientPermissions ) ) {
return message . reply ( { content : ` ❌ I am missing one of the following permission(s): \` ${ new PermissionFlagsBits ( command . clientPermissions ) . toArray ( ) } \` ` , ephemeral : true } ) ;
}
}
// Check if the user has the needed permissions
2022-08-30 22:58:23 +02:00
if ( command . default _member _permissions ) {
if ( ! message . member . permissions . has ( command . default _member _permissions ) ) {
2022-08-28 17:04:31 +02:00
return message . reply ( { content : ` ❌ You are missing one of the following permission(s): \` ${ new PermissionFlagsBits ( command . userPermissions ) . toArray ( ) } \` ` , ephemeral : true } ) ;
}
}
2023-12-12 21:20:48 +01:00
// Check if the limit of parallel execution has been reached
if ( command . parallelLimit ) {
2024-02-04 01:51:17 +01:00
const doParallelLimit = await ratelimiter . checkParallel ( message . author , commandName , command ) ;
2023-12-14 00:23:49 +01:00
if ( doParallelLimit . limited ) {
2024-02-04 01:51:17 +01:00
return await message . reply ( { content : doParallelLimit . msg , ephemeral : true } ) ;
2023-12-12 21:20:48 +01:00
}
ratelimiter . addParallel ( commandName ) ;
}
2022-12-18 23:30:25 +01:00
// Check the ratelimit
2024-02-04 01:51:17 +01:00
const doRateLimit = await ratelimiter . check ( message . author , commandName , command ) ;
2022-12-18 23:30:25 +01:00
if ( doRateLimit ) {
return message . reply ( { content : doRateLimit , ephemeral : true } ) ;
2022-12-18 22:53:23 +01:00
2022-12-18 23:30:25 +01:00
}
2022-08-28 17:04:31 +02:00
2022-12-18 23:30:25 +01:00
try {
2022-08-28 17:04:31 +02:00
message . user = message . author ;
message . isMessage = true ;
2022-11-24 21:34:54 +01:00
message . prefix = ` ${ messageArray [ 0 ] } ` ;
2022-08-28 17:04:31 +02:00
let waitingmsg ;
const toDelete = [ ] ;
message . deferReply = async function ( ) {
waitingmsg = await message . reply ( 'The bot is thinking...' ) ;
} ;
message . followUp = async function ( payload ) {
if ( payload . ephemeral ) {
toDelete . push ( await message . channel . send ( payload ) ) ;
}
else {
await message . channel . send ( payload ) ;
}
} ;
message . editReply = async function ( payload ) {
if ( waitingmsg ) {
await waitingmsg . delete ( ) ;
}
await message . channel . send ( payload ) ;
} ;
message . deleteReply = async function ( ) {
if ( waitingmsg ) {
await waitingmsg . delete ( )
. catch ( ( ) => { return ; } ) ;
}
} ;
message . cleanUp = async function ( ) {
toDelete . forEach ( async msg => {
msg . delete ( ) ;
} ) ;
} ;
2022-11-24 21:34:54 +01:00
2022-09-01 01:43:59 +02:00
const args = { } ;
2022-11-24 21:11:53 +01:00
2022-12-21 21:54:23 +01:00
let argsToDelete = 0 ;
2022-11-24 21:11:53 +01:00
command . data . options . forEach ( obj => {
if ( obj . type === ApplicationCommandOptionType . Attachment ) {
args [ obj . name ] = message . attachments . first ( ) ;
2022-12-21 21:54:23 +01:00
delete command . data . options [ command . data . options . indexOf ( obj ) ] ;
argsToDelete ++ ;
2022-11-24 21:11:53 +01:00
}
} ) ;
2022-12-21 21:54:23 +01:00
const argsLength = command . data . options . length - argsToDelete ;
2022-10-13 16:48:23 +02:00
for ( let i = 0 , j = 0 ; i < argsLength ; i ++ , j ++ ) {
2022-09-02 22:31:53 +02:00
if ( ! messageArgs [ i ] ) continue ;
2022-09-14 11:31:43 +02:00
const arg = command . data . options [ j ] ;
2022-12-21 21:54:23 +01:00
2022-11-24 21:11:53 +01:00
if ( arg . type === ApplicationCommandOptionType . Attachment ) continue ;
2022-12-21 21:54:23 +01:00
2022-09-14 11:31:43 +02:00
let payloadName = arg . name ;
2022-09-01 01:43:59 +02:00
let payload = messageArgs [ i ] ;
2022-11-24 21:11:53 +01:00
2022-10-13 16:48:23 +02:00
if ( i >= argsLength - 1 ) {
payload = messageArgs . slice ( i ) . join ( ' ' ) ;
}
2022-09-12 11:36:51 +02:00
2024-01-28 21:55:19 +01:00
if ( arg . type === ApplicationCommandOptionType . Boolean && ! messageArgs [ i ] . startsWith ( '--' ) ) {
continue ;
}
else if ( messageArgs [ i ] . startsWith ( '--' ) ) {
2022-09-14 11:31:43 +02:00
payloadName = payload . substring ( 2 ) ;
2022-09-12 11:36:51 +02:00
payload = true ;
2022-09-14 11:31:43 +02:00
j -- ;
2022-09-12 11:36:51 +02:00
}
2022-11-24 21:11:53 +01:00
2024-01-28 21:55:19 +01:00
if ( arg . type === ApplicationCommandOptionType . Mentionable || arg . type === ApplicationCommandOptionType . User ) {
2022-10-13 16:48:23 +02:00
await message . guild . members . fetch ( ) ;
payload = message . mentions . members . first ( ) ? message . mentions . members . first ( ) : message . guild . members . cache . find ( u => u . user . username . toLowerCase ( ) . includes ( payload . toLowerCase ( ) ) ) ;
2022-08-28 17:04:31 +02:00
}
2022-09-02 09:18:52 +02:00
2022-09-14 11:31:43 +02:00
args [ payloadName ] = payload ;
2022-08-28 17:04:31 +02:00
}
2023-04-04 00:34:24 +02:00
2023-04-07 02:25:46 +02:00
if ( ! isOptOut && argsLength > 0 ) {
2023-12-14 00:23:49 +01:00
console . log ( ` [ ${ timestamp . toISOString ( ) } ] \x 1b[33m⤷ \x 1b[0m with args ${ JSON . stringify ( args ) } ` ) ;
2023-04-04 00:34:24 +02:00
}
2023-12-12 21:20:48 +01:00
await command . execute ( message , args , client )
2024-02-04 01:51:17 +01:00
. then ( async ( ) => {
const hasPrallelLimit = await ratelimiter . checkParallel ( message . author , commandName , command ) ;
2023-12-12 21:20:48 +01:00
if ( hasPrallelLimit ) ratelimiter . removeParallel ( commandName ) ;
} ) ;
2022-08-28 17:04:31 +02:00
}
catch ( error ) {
console . error ( error ) ;
2024-01-30 00:25:41 +01:00
await message . reply ( { content : ` There was an error while executing this command! \n \` ${ error } \` ` } )
. catch ( async ( ) => {
await message . channel . send ( { content : ` There was an error while executing this command! \n \` ${ error } \` ` } ) ;
} ) ;
2022-08-28 17:04:31 +02:00
}
} ,
} ;