2020-06-04 19:59:09 +02:00
const { Util } = require ( '../../../util/' ) ;
const Constants = {
MaxCharacters : 1024 // Max embed description is 2048 characters, however some of those description characters are going to usernames, types, filler text, etc.
} ;
2020-04-17 09:03:53 +02:00
class Infraction {
constructor ( client , opts = { } ) {
this . client = client ;
2020-06-02 12:09:28 +02:00
this . message = opts . message ;
this . arguments = opts . arguments ;
2020-04-17 09:03:53 +02:00
this . target = opts . target ; //User or channel being targeted.
2020-04-17 22:18:29 +02:00
this . targetType = opts . targetType ; // 'user' or 'channel'.
2020-04-17 09:03:53 +02:00
this . executor = opts . executor ; //Whoever executed the command.
this . guild = opts . guild ;
this . channel = opts . channel ;
this . case = null ;
this . type = opts . type ; //What type of infraction (mute, kick, etc.)
2020-06-16 00:15:13 +02:00
this . timestamp = Date . now ( ) ;
this . duration = isNaN ( opts . duration ) ? null : opts . duration ; //How long the action will last. Must be in milliseconds.
2020-06-04 19:59:09 +02:00
this . reason = opts . reason . length ? opts . reason : 'N/A' ;
this . silent = opts . silent ;
2020-06-02 12:09:28 +02:00
this . points = 0 ;
2020-06-04 19:59:09 +02:00
this . totalPoints = 0 ;
this . expiration = 0 ;
2020-04-17 09:03:53 +02:00
2020-06-16 00:15:13 +02:00
this . data = { } ; //Miscellaneous data that may need to be saved for future use.
2020-04-17 09:03:53 +02:00
this . color = opts . color ; //Infraction-defined hexadecimal value to dictate what color the embed is.
2020-06-02 12:09:28 +02:00
this . dictionary = opts . dictionary || { } ; // { past: 'banned', present: 'ban' } Infraction-defined object for the correct spellings.
2020-06-16 00:15:13 +02:00
this . hyperlink = opts . hyperlink || null ; // To overwrite hyperlink (if it's auto-resolving)
2020-06-02 12:09:28 +02:00
2020-06-04 19:59:09 +02:00
this . _logMessage = null ; //The message embed sent in the moderation-log. Full message, not the ID.
this . _dmMessage = null ; //The message embed sent in the target's direct messages. Full message, not the ID.
2020-06-16 00:15:13 +02:00
this . _moderationLog = null ; //Moderation log channel
2020-04-17 09:03:53 +02:00
}
2020-06-04 19:59:09 +02:00
async log ( ) {
if ( this . silent ) {
try {
await this . message . delete ( ) ;
} catch ( e ) { } //eslint-disable-line no-empty
}
2020-04-17 09:03:53 +02:00
2020-06-02 12:09:28 +02:00
const { moderationLog , moderationPoints } = this . guild . _settings ;
2020-06-04 19:59:09 +02:00
/* Handling */
if ( moderationPoints . enabled ) {
if ( this . arguments . points ) {
this . points = parseInt ( this . arguments . points . value ) ;
} else {
this . points = moderationPoints . points [ this . type ] || 0 ;
}
if ( this . arguments . expiration ) {
this . expiration = parseInt ( this . arguments . expiration . value ) ;
} else {
this . expiration = moderationPoints . expirations [ this . type ] || 0 ;
}
if ( this . targetType === 'user' ) {
2020-06-16 00:15:13 +02:00
this . totalPoints = await this . target . totalPoints ( this . guild , { points : this . points , expiration : this . expiration , timestamp : this . timestamp } ) ;
2020-06-04 19:59:09 +02:00
}
}
this . guild . _settings . caseId ++ ;
this . case = this . guild . _settings . caseId ;
await this . guild . _updateSettings ( {
caseId : this . case
} ) ;
console . log ( ` points: ${ this . points } , total points: ${ this . totalPoints } , expiration: ${ this . expiration } ` ) ;
/* Logging */
2020-06-02 12:09:28 +02:00
if ( moderationLog . channel ) {
if ( moderationLog . infractions . includes ( this . type . toLowerCase ( ) ) ) {
2020-06-19 15:38:56 +02:00
this . _moderationLog = await this . client . resolver . resolveChannel ( moderationLog . channel , true , this . guild ) ;
2020-06-16 00:15:13 +02:00
if ( ! this . _moderationLog ) return undefined ;
this . _logMessage = await this . _moderationLog . send ( '' , { embed : this . embed ( ) } ) ;
2020-06-02 12:09:28 +02:00
} else {
this . client . logger . debug ( ` Did not log infraction ${ this . type } because it is not in the infractions. ` ) ;
}
}
2020-06-04 19:59:09 +02:00
if ( this . guild . _settings . dmInfraction . enabled
2020-06-02 12:09:28 +02:00
&& this . targetType === 'user' ) {
2020-06-04 19:59:09 +02:00
let message = this . guild . _settings . dmInfraction . custom [ this . type ] || this . guild . _settings . dmInfraction . custom . default ;
if ( ! message ) message = "" ;
message = message
. replace ( /\{(guild|server)\}/ugim , this . guild . name )
. replace ( /\{user\}/ugim , this . target . tag )
. replace ( /\{infraction\}/ugim , this . dictionary . past ) ; //add more if you want i should probably add a better system for this...
2020-06-02 12:09:28 +02:00
try {
2020-06-04 19:59:09 +02:00
this . _dmMessage = await this . target . send ( message , {
2020-06-02 12:09:28 +02:00
embed : this . embed ( )
} ) ;
} catch ( e ) { } //eslint-disable-line no-empty
}
2020-06-04 19:59:09 +02:00
//might be useful for automod related stuff
// this.client.emit('infractionUpdate', {
// action: 'new',
// infraction: this
// });
return this . save ( ) ;
2020-04-17 09:03:53 +02:00
}
2020-04-17 22:18:29 +02:00
async save ( ) {
2020-05-06 01:40:46 +02:00
await this . client . transactionHandler . send ( {
2020-04-17 22:18:29 +02:00
provider : 'mongodb' ,
request : {
type : 'insertOne' ,
2020-06-04 19:59:09 +02:00
collection : 'infractions' ,
2020-06-02 12:09:28 +02:00
data : this . json
2020-04-17 22:18:29 +02:00
}
2020-06-02 12:09:28 +02:00
} ) . catch ( ( error ) => {
this . client . logger . error ( ` There was an issue saving infraction data to the database. \n ${ error . stack || error } ` ) ;
} ) ;
}
2020-06-04 19:59:09 +02:00
embed ( ) {
2020-06-02 12:09:28 +02:00
let description = this . message . format ( 'INFRACTION_DESCRIPTION' , {
2020-06-04 19:59:09 +02:00
type : this . dictionary . past . toUpperCase ( ) ,
moderator : ` ${ Util . escapeMarkdown ( this . executor . tag ) } ` ,
reason : this . reason . length > Constants . MaxCharacters ? ` ${ this . reason . substring ( 0 , Constants . MaxCharacters - 3 ) } ... ` : this . reason
2020-06-02 12:09:28 +02:00
} ) ;
if ( this . duration ) {
2020-06-16 00:15:13 +02:00
description += ` \n ${ this . message . format ( 'INFRACTION_DESCRIPTIONDURATION' , { duration : Util . duration ( this . duration ) } )} ` ;
2020-06-02 12:09:28 +02:00
}
2020-06-04 19:59:09 +02:00
if ( this . points ) {
description += ` \n ${ this . message . format ( 'INFRACTION_DESCRIPTIONPOINTS' , { points : this . points , total : this . totalPoints } )} ` ;
}
if ( ! this . silent ) {
2020-06-16 00:15:13 +02:00
description += ` \n ${ this . message . format ( 'INFRACTION_DESCRIPTIONJUMPTO' , { name : 'Message' , link : this . hyperlink ? this . hyperlink : ` https://discord.com/channels/ ${ this . guild . id } / ${ this . channel . id } / ${ this . message . id } ` } )} ` ;
2020-06-02 12:09:28 +02:00
}
return {
author : {
name : ` ${ this . targetName } ( ${ this . target . id } ) ` ,
icon _url : this . targetIcon //eslint-disable-line camelcase
} ,
timestamp : new Date ( ) ,
color : this . color ,
footer : {
text : ` 》 Case ${ this . case } `
} ,
description
} ;
2020-04-17 22:18:29 +02:00
}
2020-06-02 12:09:28 +02:00
get json ( ) {
2020-04-17 09:03:53 +02:00
return {
id : ` ${ this . guild . id } : ${ this . case } ` ,
guild : this . guild . id ,
channel : this . channel ? this . channel . id : null ,
message : this . message ? this . message . id : null ,
executor : this . executor . id ,
target : this . target . id ,
targetType : this . targetType ,
type : this . type ,
case : this . case ,
duration : this . duration ,
reason : this . reason ,
2020-06-04 19:59:09 +02:00
timestamp : this . timestamp ,
points : this . points ,
2020-06-16 00:15:13 +02:00
expiration : this . expiration ,
data : this . data ,
actions : this . actions ,
logMessage : this . _logMessage ? this . _logMessage . id : null , //the message id sent in modlog channel
dmMessage : this . _dmMessage ? this . _dmMessage . id : null , //the message id of the dm message, if there is one
moderationLog : this . _moderationLog ? this . _moderationLog . id : null ,
expired : false
2020-04-17 22:18:29 +02:00
} ;
2020-04-17 09:03:53 +02:00
}
get targetName ( ) {
return this . targetType === 'user'
? this . target . tag
2020-04-17 22:18:29 +02:00
: ` # ${ this . target . name } ` ;
2020-04-17 09:03:53 +02:00
}
2020-06-02 12:09:28 +02:00
get targetIcon ( ) {
return this . targetType === 'user'
? this . target . displayAvatarURL ( )
: this . guild . iconURL ( ) ;
}
2020-06-16 00:15:13 +02:00
get actions ( ) {
const actions = [ ] ;
for ( const argument of Object . values ( this . arguments ) ) {
if ( [ 'silent' , 'prune' , 'force' ] . includes ( argument ) ) actions . push ( argument ) ;
}
return actions ;
}
2020-06-04 19:59:09 +02:00
get _reason ( ) {
let str = ` [targetId: ${ this . target . id } ] Executed by ${ this . executor . tag } ( ${ this . executor . id } ) because: ${ this . reason } ` ;
if ( str . length > 512 ) str = ` ${ this . reason . substring ( 0 , 509 ) } ... ` ;
return str ;
}
2020-06-02 12:09:28 +02:00
//Super Functions
_succeed ( ) {
return {
error : false ,
infraction : this
} ;
}
2020-06-16 00:15:13 +02:00
_fail ( message , fatal = false ) {
2020-06-02 12:09:28 +02:00
return {
error : true ,
infraction : this ,
2020-06-16 00:15:13 +02:00
reason : message ,
fatal
2020-06-02 12:09:28 +02:00
} ;
}
2020-04-17 09:03:53 +02:00
}
module . exports = Infraction ;