2017-12-24 15:04:08 -05:00
const Eris = require ( 'eris' ) ;
const config = require ( './config' ) ;
const bot = require ( './bot' ) ;
2018-09-20 16:31:14 -04:00
const { messageQueue } = require ( './queue' ) ;
2017-12-24 15:04:08 -05:00
const utils = require ( './utils' ) ;
const blocked = require ( './data/blocked' ) ;
const threads = require ( './data/threads' ) ;
2018-03-13 01:45:31 -04:00
const reply = require ( './modules/reply' ) ;
const close = require ( './modules/close' ) ;
const snippets = require ( './modules/snippets' ) ;
const logs = require ( './modules/logs' ) ;
const move = require ( './modules/move' ) ;
const block = require ( './modules/block' ) ;
const suspend = require ( './modules/suspend' ) ;
const webserver = require ( './modules/webserver' ) ;
const greeting = require ( './modules/greeting' ) ;
const typingProxy = require ( './modules/typingProxy' ) ;
2018-03-13 01:59:27 -04:00
const version = require ( './modules/version' ) ;
2018-04-07 19:56:30 -04:00
const newthread = require ( './modules/newthread' ) ;
2018-04-21 08:41:03 -04:00
const idModule = require ( './modules/id' ) ;
2018-04-21 09:39:38 -04:00
const alert = require ( './modules/alert' ) ;
2018-04-07 19:56:30 -04:00
2018-02-14 01:53:34 -05:00
const attachments = require ( "./data/attachments" ) ;
2018-02-18 15:52:37 -05:00
const { ACCIDENTAL _THREAD _MESSAGES } = require ( './data/constants' ) ;
2017-12-31 19:16:05 -05:00
2017-12-24 15:04:08 -05:00
// Once the bot has connected, set the status/"playing" message
bot . on ( 'ready' , ( ) => {
bot . editStatus ( null , { name : config . status } ) ;
2018-03-13 01:45:31 -04:00
console . log ( 'Connected! Now listening to DMs.' ) ;
2017-12-24 15:04:08 -05:00
} ) ;
2018-02-11 14:54:30 -05:00
/ * *
* When a moderator posts in a modmail thread ...
* 1 ) If alwaysReply is enabled , reply to the user
* 2 ) If alwaysReply is disabled , save that message as a chat message in the thread
* /
2017-12-31 19:16:05 -05:00
bot . on ( 'messageCreate' , async msg => {
if ( ! utils . messageIsOnInboxServer ( msg ) ) return ;
if ( msg . author . bot ) return ;
const thread = await threads . findByChannelId ( msg . channel . id ) ;
if ( ! thread ) return ;
2017-12-24 15:04:08 -05:00
2018-03-11 17:17:14 -04:00
if ( msg . content . startsWith ( config . prefix ) || msg . content . startsWith ( config . snippetPrefix ) ) {
// Save commands as "command messages"
if ( msg . content . startsWith ( config . snippetPrefix ) ) return ; // Ignore snippets
thread . saveCommandMessage ( msg ) ;
} else if ( config . alwaysReply ) {
2017-12-31 19:16:05 -05:00
// AUTO-REPLY: If config.alwaysReply is enabled, send all chat messages in thread channels as replies
2018-03-11 17:17:14 -04:00
if ( ! utils . isStaff ( msg . member ) ) return ; // Only staff are allowed to reply
2018-02-14 01:53:34 -05:00
if ( msg . attachments . length ) await attachments . saveAttachmentsInMessage ( msg ) ;
2019-02-23 15:55:26 -05:00
const replied = await thread . replyToUser ( msg . member , msg . content . trim ( ) , msg . attachments , config . alwaysReplyAnon || false ) ;
if ( replied ) msg . delete ( ) ;
2017-12-31 19:16:05 -05:00
} else {
// Otherwise just save the messages as "chat" in the logs
2018-02-11 14:54:30 -05:00
thread . saveChatMessage ( msg ) ;
2017-12-31 19:16:05 -05:00
}
} ) ;
2017-12-24 15:04:08 -05:00
2018-02-11 14:54:30 -05:00
/ * *
* When we get a private message ...
* 1 ) Find the open modmail thread for this user , or create a new one
* 2 ) Post the message as a user reply in the thread
* /
2017-12-24 15:04:08 -05:00
bot . on ( 'messageCreate' , async msg => {
if ( ! ( msg . channel instanceof Eris . PrivateChannel ) ) return ;
2018-02-11 14:54:30 -05:00
if ( msg . author . bot ) return ;
if ( msg . type !== 0 ) return ; // Ignore pins etc.
2017-12-24 15:04:08 -05:00
if ( await blocked . isBlocked ( msg . author . id ) ) return ;
// Private message handling is queued so e.g. multiple message in quick succession don't result in multiple channels being created
messageQueue . add ( async ( ) => {
2018-02-18 15:52:37 -05:00
let thread = await threads . findOpenThreadByUserId ( msg . author . id ) ;
// New thread
if ( ! thread ) {
// Ignore messages that shouldn't usually open new threads, such as "ok", "thanks", etc.
2018-02-20 05:57:34 -05:00
if ( config . ignoreAccidentalThreads && msg . content && ACCIDENTAL _THREAD _MESSAGES . includes ( msg . content . trim ( ) . toLowerCase ( ) ) ) return ;
2018-02-18 15:52:37 -05:00
thread = await threads . createNewThreadForUser ( msg . author ) ;
}
2018-07-10 05:59:29 -04:00
if ( thread ) await thread . receiveUserReply ( msg ) ;
2017-12-24 15:04:08 -05:00
} ) ;
} ) ;
2018-02-11 14:54:30 -05:00
/ * *
* When a message is edited ...
* 1 ) If that message was in DMs , and we have a thread open with that user , post the edit as a system message in the thread
* 2 ) If that message was moderator chatter in the thread , update the corresponding chat message in the DB
* /
2017-12-24 15:04:08 -05:00
bot . on ( 'messageUpdate' , async ( msg , oldMessage ) => {
2018-02-18 19:03:53 -05:00
if ( ! msg || ! msg . author ) return ;
2018-02-11 14:54:30 -05:00
if ( msg . author . bot ) return ;
2017-12-24 15:04:08 -05:00
if ( await blocked . isBlocked ( msg . author . id ) ) return ;
// Old message content doesn't persist between bot restarts
2018-02-18 15:30:10 -05:00
const oldContent = oldMessage && oldMessage . content || '*Unavailable due to bot restart*' ;
const newContent = msg . content ;
2017-12-24 15:04:08 -05:00
// Ignore bogus edit events with no changes
if ( newContent . trim ( ) === oldContent . trim ( ) ) return ;
2018-02-11 14:54:30 -05:00
// 1) Edit in DMs
if ( msg . channel instanceof Eris . PrivateChannel ) {
const thread = await threads . findOpenThreadByUserId ( msg . author . id ) ;
2018-05-03 07:22:38 -04:00
if ( ! thread ) return ;
2018-02-11 14:54:30 -05:00
const editMessage = utils . disableLinkPreviews ( ` **The user edited their message:** \n \` B: \` ${ oldContent } \n \` A: \` ${ newContent } ` ) ;
thread . postSystemMessage ( editMessage ) ;
}
// 2) Edit in the thread
else if ( utils . messageIsOnInboxServer ( msg ) && utils . isStaff ( msg . member ) ) {
const thread = await threads . findOpenThreadByChannelId ( msg . channel . id ) ;
if ( ! thread ) return ;
thread . updateChatMessage ( msg ) ;
}
} ) ;
/ * *
* When a staff message is deleted in a modmail thread , delete it from the database as well
* /
bot . on ( 'messageDelete' , async msg => {
2018-02-18 19:03:53 -05:00
if ( ! msg . author ) return ;
2018-02-11 14:54:30 -05:00
if ( msg . author . bot ) return ;
if ( ! utils . messageIsOnInboxServer ( msg ) ) return ;
if ( ! utils . isStaff ( msg . member ) ) return ;
const thread = await threads . findOpenThreadByChannelId ( msg . channel . id ) ;
2017-12-24 15:04:08 -05:00
if ( ! thread ) return ;
2018-02-11 14:54:30 -05:00
thread . deleteChatMessage ( msg . id ) ;
} ) ;
/ * *
* When the bot is mentioned on the main server , ping staff in the log channel about it
* /
bot . on ( 'messageCreate' , async msg => {
if ( ! utils . messageIsOnMainServer ( msg ) ) return ;
if ( ! msg . mentions . some ( user => user . id === bot . user . id ) ) return ;
2018-07-31 17:40:12 -04:00
if ( msg . author . bot ) return ;
2018-02-11 14:54:30 -05:00
2018-09-20 14:57:54 -04:00
if ( utils . messageIsOnInboxServer ( msg ) ) {
// For same server setups, check if the person who pinged modmail is staff. If so, ignore the ping.
if ( utils . isStaff ( msg . member ) ) return ;
} else {
// For separate server setups, check if the member is staff on the modmail server
const inboxMember = utils . getInboxGuild ( ) . members . get ( msg . author . id ) ;
if ( inboxMember && utils . isStaff ( inboxMember ) ) return ;
}
2018-02-11 14:54:30 -05:00
// If the person who mentioned the bot is blocked, ignore them
if ( await blocked . isBlocked ( msg . author . id ) ) return ;
2018-04-21 08:54:41 -04:00
let content ;
const mainGuilds = utils . getMainGuilds ( ) ;
2018-05-03 13:26:12 -04:00
const staffMention = ( config . pingOnBotMention ? utils . getInboxMention ( ) : '' ) ;
2018-04-21 08:54:41 -04:00
if ( mainGuilds . length === 1 ) {
2018-05-03 13:26:12 -04:00
content = ` ${ staffMention } Bot mentioned in ${ msg . channel . mention } by ** ${ msg . author . username } # ${ msg . author . discriminator } **: " ${ msg . cleanContent } " ` ;
2018-04-21 08:54:41 -04:00
} else {
2018-05-03 13:26:12 -04:00
content = ` ${ staffMention } Bot mentioned in ${ msg . channel . mention } ( ${ msg . channel . guild . name } ) by ** ${ msg . author . username } # ${ msg . author . discriminator } **: " ${ msg . cleanContent } " ` ;
2018-04-21 08:54:41 -04:00
}
2018-09-20 15:07:38 -04:00
bot . createMessage ( utils . getLogChannel ( ) . id , {
2018-04-21 08:54:41 -04:00
content ,
2018-02-11 14:54:30 -05:00
disableEveryone : false ,
} ) ;
2018-09-20 15:07:38 -04:00
// Send an auto-response to the mention, if enabled
if ( config . botMentionResponse ) {
2019-02-23 09:33:22 -05:00
bot . createMessage ( msg . channel . id , config . botMentionResponse . replace ( /{userMention}/g , ` <@ ${ msg . author . id } > ` ) ) ;
2018-09-20 15:07:38 -04:00
}
2017-12-24 15:04:08 -05:00
} ) ;
2018-02-11 14:54:30 -05:00
module . exports = {
async start ( ) {
2018-03-13 01:45:31 -04:00
// Load modules
console . log ( 'Loading modules...' ) ;
await reply ( bot ) ;
await close ( bot ) ;
await logs ( bot ) ;
await block ( bot ) ;
await move ( bot ) ;
2018-02-11 14:54:30 -05:00
await snippets ( bot ) ;
2018-03-13 01:45:31 -04:00
await suspend ( bot ) ;
2018-02-11 14:54:30 -05:00
await greeting ( bot ) ;
await webserver ( bot ) ;
2018-03-13 01:45:31 -04:00
await typingProxy ( bot ) ;
2018-03-13 01:59:27 -04:00
await version ( bot ) ;
2018-04-07 19:56:30 -04:00
await newthread ( bot ) ;
2018-04-21 08:41:03 -04:00
await idModule ( bot ) ;
2018-04-21 09:39:38 -04:00
await alert ( bot ) ;
2017-12-24 15:04:08 -05:00
2018-03-11 16:45:43 -04:00
// Connect to Discord
2018-02-11 14:54:30 -05:00
console . log ( 'Connecting to Discord...' ) ;
await bot . connect ( ) ;
2017-12-24 15:04:08 -05:00
}
} ;