2021-08-19 14:19:14 +00:00
import { promises } from "fs" ;
import database from "../utils/database.js" ;
import { log , error as _error } from "../utils/logger.js" ;
import { prefixCache , aliases , disabledCache , disabledCmdCache , commands } from "../utils/collections.js" ;
import parseCommand from "../utils/parseCommand.js" ;
import { clean } from "../utils/misc.js" ;
2019-09-13 20:02:41 +00:00
// run when someone sends a message
2021-08-19 14:19:14 +00:00
export default async ( client , cluster , worker , ipc , message ) => {
2021-08-12 23:45:17 +00:00
// ignore other bots
2019-09-13 20:02:41 +00:00
if ( message . author . bot ) return ;
2019-12-16 23:14:29 +00:00
// don't run command if bot can't send messages
2021-03-12 20:42:07 +00:00
if ( message . channel . guild && ! message . channel . permissionsOf ( client . user . id ) . has ( "sendMessages" ) ) return ;
2019-12-16 23:14:29 +00:00
2020-12-18 02:32:19 +00:00
let prefixCandidate ;
2021-08-13 03:28:09 +00:00
let guildDB ;
2020-12-26 18:17:10 +00:00
if ( message . channel . guild ) {
2021-08-19 14:19:14 +00:00
const cachedPrefix = prefixCache . get ( message . channel . guild . id ) ;
2021-08-07 20:28:39 +00:00
if ( cachedPrefix ) {
prefixCandidate = cachedPrefix ;
2020-12-26 18:17:10 +00:00
} else {
2021-08-13 03:28:09 +00:00
guildDB = await database . getGuild ( message . channel . guild . id ) ;
2021-08-10 00:09:32 +00:00
if ( ! guildDB ) {
2021-08-13 03:28:09 +00:00
guildDB = await database . fixGuild ( message . channel . guild ) ;
2020-12-26 18:17:10 +00:00
}
prefixCandidate = guildDB . prefix ;
2021-08-19 14:19:14 +00:00
prefixCache . set ( message . channel . guild . id , guildDB . prefix ) ;
2020-12-18 02:32:19 +00:00
}
2020-11-05 21:40:18 +00:00
}
2020-12-18 02:32:19 +00:00
2021-03-18 14:29:03 +00:00
let prefix ;
let isMention = false ;
if ( message . channel . guild ) {
const user = message . channel . guild . members . get ( client . user . id ) ;
if ( message . content . startsWith ( user . mention ) ) {
prefix = ` ${ user . mention } ` ;
isMention = true ;
} else if ( message . content . startsWith ( ` <@ ${ client . user . id } > ` ) ) { // workaround for member.mention not accounting for both mention types
prefix = ` <@ ${ client . user . id } > ` ;
isMention = true ;
} else {
prefix = prefixCandidate ;
}
} else {
2022-06-14 05:03:18 +00:00
prefix = process . env . PREFIX ;
2021-03-18 14:29:03 +00:00
}
2019-09-13 20:02:41 +00:00
// ignore other stuff
2021-08-12 23:45:17 +00:00
if ( ! message . content . startsWith ( prefix ) ) return ;
2019-09-13 20:02:41 +00:00
// separate commands and args
2022-03-20 04:20:42 +00:00
const replace = isMention ? ` @ ${ ( message . channel . guild ? message . channel . guild . members . get ( client . user . id ) . nick : client . user . username ) ? ? client . user . username } ` : prefix ;
2021-03-18 14:29:03 +00:00
const content = message . cleanContent . substring ( replace . length ) . trim ( ) ;
2021-03-16 20:45:10 +00:00
const rawContent = message . content . substring ( prefix . length ) . trim ( ) ;
2021-07-02 04:42:12 +00:00
const preArgs = content . split ( /\s+/g ) ;
preArgs . shift ( ) ;
2021-04-14 21:42:18 +00:00
const command = rawContent . split ( /\s+/g ) . shift ( ) . toLowerCase ( ) ;
2021-07-02 04:42:12 +00:00
const parsed = parseCommand ( preArgs ) ;
2021-08-19 14:19:14 +00:00
const aliased = aliases . get ( command ) ;
2019-09-13 20:02:41 +00:00
2020-04-10 02:40:52 +00:00
// don't run if message is in a disabled channel
2020-12-26 18:17:10 +00:00
if ( message . channel . guild ) {
2021-08-19 14:19:14 +00:00
const disabled = disabledCache . get ( message . channel . guild . id ) ;
2021-08-13 03:28:09 +00:00
if ( disabled ) {
2020-12-26 18:17:10 +00:00
if ( disabled . includes ( message . channel . id ) && command != "channel" ) return ;
2021-08-13 03:28:09 +00:00
} else {
guildDB = await database . getGuild ( message . channel . guild . id ) ;
2021-08-19 14:19:14 +00:00
disabledCache . set ( message . channel . guild . id , guildDB . disabled ) ;
2020-12-26 18:17:10 +00:00
if ( guildDB . disabled . includes ( message . channel . id ) && command !== "channel" ) return ;
}
2021-08-13 03:28:09 +00:00
2021-08-19 14:19:14 +00:00
const disabledCmds = disabledCmdCache . get ( message . channel . guild . id ) ;
2021-08-13 03:28:09 +00:00
if ( disabledCmds ) {
2022-01-15 05:26:38 +00:00
if ( disabledCmds . includes ( aliased ? ? command ) ) return ;
2021-08-13 03:28:09 +00:00
} else {
guildDB = await database . getGuild ( message . channel . guild . id ) ;
2022-01-15 05:26:38 +00:00
disabledCmdCache . set ( message . channel . guild . id , guildDB . disabled _commands ? ? guildDB . disabledCommands ) ;
if ( ( guildDB . disabled _commands ? ? guildDB . disabledCommands ) . includes ( aliased ? ? command ) ) return ;
2021-08-13 03:28:09 +00:00
}
2020-12-18 02:32:19 +00:00
}
2020-04-10 02:40:52 +00:00
2021-08-13 03:28:09 +00:00
// check if command exists and if it's enabled
2022-01-15 05:26:38 +00:00
const cmd = commands . get ( aliased ? ? command ) ;
2019-09-13 20:02:41 +00:00
if ( ! cmd ) return ;
2022-06-28 21:15:31 +00:00
// block certain commands from running in DMs
if ( ! cmd . directAllowed && ! message . channel . guild ) return ;
2019-09-13 20:02:41 +00:00
// actually run the command
2022-03-31 05:42:03 +00:00
log ( "log" , ` ${ message . author . username } ( ${ message . author . id } ) ran classic command ${ command } ` ) ;
2021-05-11 16:12:01 +00:00
const reference = {
messageReference : {
channelID : message . channel . id ,
messageID : message . id ,
guildID : message . channel . guild ? message . channel . guild . id : undefined ,
failIfNotExists : false
} ,
allowedMentions : {
repliedUser : false
}
} ;
2019-09-13 20:02:41 +00:00
try {
2022-01-15 05:26:38 +00:00
await database . addCount ( aliases . get ( command ) ? ? command ) ;
2021-03-05 18:03:17 +00:00
const startTime = new Date ( ) ;
2021-07-02 04:42:12 +00:00
// eslint-disable-next-line no-unused-vars
2022-03-22 20:43:26 +00:00
const commandClass = new cmd ( client , cluster , worker , ipc , { type : "classic" , message , args : parsed . _ , content : message . content . substring ( prefix . length ) . trim ( ) . replace ( command , "" ) . trim ( ) , specialArgs : ( ( { _ , ... o } ) => o ) ( parsed ) } ) ; // we also provide the message content as a parameter for cases where we need more accuracy
2021-06-18 05:10:11 +00:00
const result = await commandClass . run ( ) ;
2021-03-05 18:03:17 +00:00
const endTime = new Date ( ) ;
2021-05-11 16:12:01 +00:00
if ( ( endTime - startTime ) >= 180000 ) reference . allowedMentions . repliedUser = true ;
if ( typeof result === "string" ) {
reference . allowedMentions . repliedUser = true ;
await client . createMessage ( message . channel . id , Object . assign ( {
content : result
} , reference ) ) ;
2021-11-12 23:21:43 +00:00
} else if ( typeof result === "object" && result . embeds ) {
2021-05-11 16:12:01 +00:00
await client . createMessage ( message . channel . id , Object . assign ( result , reference ) ) ;
2020-04-12 19:51:48 +00:00
} else if ( typeof result === "object" && result . file ) {
2021-10-15 16:05:58 +00:00
let fileSize = 8388119 ;
if ( message . channel . guild ) {
switch ( message . channel . guild . premiumTier ) {
case 2 :
fileSize = 52428308 ;
break ;
case 3 :
fileSize = 104856616 ;
break ;
}
}
if ( result . file . length > fileSize ) {
2022-02-23 21:51:20 +00:00
if ( process . env . TEMPDIR && process . env . TEMPDIR !== "" ) {
2021-10-15 16:05:58 +00:00
const filename = ` ${ Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 ) } . ${ result . name . split ( "." ) [ 1 ] } ` ;
await promises . writeFile ( ` ${ process . env . TEMPDIR } / ${ filename } ` , result . file ) ;
2022-01-16 20:27:59 +00:00
const imageURL = ` ${ process . env . TMP _DOMAIN || "https://tmp.projectlounge.pw" } / ${ filename } ` ;
2021-10-15 16:05:58 +00:00
await client . createMessage ( message . channel . id , Object . assign ( {
2021-11-10 04:09:10 +00:00
embeds : [ {
2021-10-15 16:05:58 +00:00
color : 16711680 ,
title : "Here's your image!" ,
url : imageURL ,
image : {
url : imageURL
} ,
footer : {
text : "The result image was more than 8MB in size, so it was uploaded to an external site instead."
} ,
2021-11-10 04:09:10 +00:00
} ]
2021-10-15 16:05:58 +00:00
} , reference ) ) ;
2022-03-10 21:24:24 +00:00
if ( process . env . THRESHOLD ) {
2022-06-11 19:30:04 +00:00
process . env . DIRSIZECACHE += result . file . length ;
if ( process . env . DIRSIZECACHE > process . env . THRESHOLD ) {
const files = ( await promises . readdir ( process . env . TEMPDIR ) ) . map ( ( file ) => {
return new Promise ( ( resolve , reject ) => {
promises . stat ( ` ${ process . env . TEMPDIR } / ${ file } ` ) . then ( ( fstats ) => {
resolve ( {
name : file ,
size : fstats . size ,
ctime : fstats . ctime
} ) ;
} ) . catch ( reject ) ;
2022-03-10 21:24:24 +00:00
} ) ;
2022-06-11 19:30:04 +00:00
} ) ;
Promise . all ( files ) . then ( ( files ) => {
process . env . DIRSIZECACHE = files . reduce ( ( a , b ) => {
return a + b . size ;
} , 0 ) ;
const oldestFile = files . sort ( ( a , b ) => a . ctime - b . ctime ) [ 0 ] . name ;
promises . rm ( ` ${ process . env . TEMPDIR } / ${ oldestFile } ` ) ;
log ( ` Removed oldest image file: ${ oldestFile } ` ) ;
} ) ;
2022-03-10 21:24:24 +00:00
}
}
2022-02-23 21:51:20 +00:00
} else {
await client . createMessage ( message . channel . id , "The resulting image was more than 8MB in size, so I can't upload it." ) ;
2021-10-15 16:05:58 +00:00
}
2020-04-20 20:52:22 +00:00
} else {
2021-05-11 16:12:01 +00:00
await client . createMessage ( message . channel . id , Object . assign ( {
content : result . text ? result . text : undefined
} , reference ) , result ) ;
2020-04-20 20:52:22 +00:00
}
2019-09-13 20:02:41 +00:00
}
} catch ( error ) {
2020-07-17 00:54:03 +00:00
if ( error . toString ( ) . includes ( "Request entity too large" ) ) {
2021-05-11 16:12:01 +00:00
await client . createMessage ( message . channel . id , Object . assign ( {
content : "The resulting file was too large to upload. Try again with a smaller image if possible."
} , reference ) ) ;
} else if ( error . toString ( ) . includes ( "Job ended prematurely" ) ) {
await client . createMessage ( message . channel . id , Object . assign ( {
content : "Something happened to the image servers before I could receive the image. Try running your command again."
} , reference ) ) ;
2020-07-17 00:54:03 +00:00
} else if ( error . toString ( ) . includes ( "Timed out" ) ) {
2021-05-11 16:12:01 +00:00
await client . createMessage ( message . channel . id , Object . assign ( {
content : "The request timed out before I could download that image. Try uploading your image somewhere else or reducing its size."
} , reference ) ) ;
2020-07-17 00:54:03 +00:00
} else {
2022-06-28 13:16:57 +00:00
_error ( ` Error occurred with command message ${ message . cleanContent } : ${ typeof error === "object" ? JSON . stringify ( error ) : error . toString ( ) } ` ) ;
2021-04-15 00:57:35 +00:00
try {
2021-05-11 16:12:01 +00:00
await client . createMessage ( message . channel . id , Object . assign ( {
content : "Uh oh! I ran into an error while running this command. Please report the content of the attached file at the following link or on the esmBot Support server: <https://github.com/esmBot/esmBot/issues>"
} , reference ) , [ {
2021-07-31 18:36:00 +00:00
file : ` Message: ${ await clean ( error ) } \n \n Stack Trace: ${ await clean ( error . stack ) } ` ,
2021-04-15 00:57:35 +00:00
name : "error.txt"
} ] ) ;
} catch { /* silently ignore */ }
2020-02-25 21:07:36 +00:00
}
2019-09-13 20:02:41 +00:00
}
} ;