import { Client , Collection , GuildMember } from "discord.js" ; import { EventEmitter } from "events" ; import { readdirSync } from "fs" ; import { sep } from "path" ; import { AntiRaidOptions , Cooldown , ActionType , AntiRaidEvent } from "./interfaces" ; import { defaultAntiRaidOptions , AUDIT_LOG } from "./Constants" ; /**
 * AntiRaid
 */ class AntiRaid extends EventEmitter { readonly client : Client ; options : AntiRaidOptions ; cooldown : Collection < string , Array < Cooldown > > ; readonly actionType : ActionType ; param { Client } client param { AntiRaidOptions } options constructor ( client , options ) { super ( ) ; if ( ! client ) throw new Error ( 'Client is a required option.' ) ; type { Client } this . client = client ; type { AntiRaidOptions } this . options = options || defaultAntiRaidOptions ; type { Collection } this . cooldown = new Collection ( ) ; type { AUDIT_LOG } this . actionType = AUDIT_LOG ; this . init ( ) ; } ignore private init ( ) { readdirSync ( `${ __dirname }${ sep }events${ sep }` ) . forEach ( ( dir ) => { if ( dir [ 0 ] !== "." ) { readdirSync ( `${ __dirname }${ sep }events${ sep }${ dir }` ) . filter ( ( f ) => f . endsWith ( ".js" ) ) . forEach ( ( f , i ) => { try { const event = require ( `./events/${ dir }/${ f }` ) [ f . replace ( ".js" , "" ) ] ; this . client . on ( event . name , event . run . bind ( null , this ) ) ; } catch ( error ) { console . error ( error ) ; } } ) ; } } ) ; } param { GuildMember } member param { string } event param { Cooldown } oldCase param { number } startAt return { Promise < any > } async addCaseToCooldown ( member , event , oldCase , startAt ) { const options = await this . getOptionsFromDB ( member . guild . id ) ; if ( ! options || typeof options !== "object" ) throw new Error ( "Options need to be valid object" ) ; const cooldown = this . getCooldown ( member . guild . id ) ; cooldown . push ( { id : member . id , guild : member . guild . id , event : event , startedAt : startAt , rate : oldCase && oldCase . rate ? oldCase . rate ++ : 1 } ) ; this . saveCooldown ( member . guild . id , cooldown ) ; let index = cooldown . indexOf ( { id : member . id , startedAt : startAt } ) ; setTimeout ( async ( ) => { cooldown . splice ( index ) ; } , options . time || 10000 ) ; this . saveCooldown ( member . guild . id , cooldown ) ; } param { GuildMember } member param { Cooldown } caseToCheck return { Promise < boolean > } async punishable ( member , caseToCheck ) { const options = await this . getOptionsFromDB ( member . guild . id ) ; if ( ! options || typeof options !== "object" ) throw new Error ( "Options need to be valid object" ) ; if ( ! options || ! options . rateLimit ) throw new Error ( "Cannot found options.rateLimit" ) ; return caseToCheck && caseToCheck . rate >= options . rateLimit - 1 ; } param { GuildMember } member return { Promise < any > } example async punish ( member ) { const options = await this . getOptionsFromDB ( member . guild . id ) ; if ( ! options || typeof options !== "object" ) throw new Error ( "Options need to be valid object" ) ; if ( ! options . ban && ! options . kick && ! options . unrank ) throw new Error ( "Please provide sanction between ban, kick or unrank (boolean)" ) ; if ( options . ban ) { return member . ban ( { reason : options . reason } ) ; } else if ( options . kick ) { return member . kick ( options . reason ) ; } if ( options . unrank ) { member . roles . cache . forEach ( role => { member . roles . remove ( role ) . catch ( e => null ) ; } ) ; } event param { GuildMember } member param { AntiRaidOptions . reason } reason param { string } sanction example this . emit ( "punish" , member , options . reason , options . ban ? "ban" : options . kick ? "kick" : options . unrank ? "unrank" : false ) ; } param { string } id return { AntiRaidOptions } async getOptionsFromDB ( id ) { return this . options ; } param { string } id return { Array < Cooldown > } getCooldown ( id ) { let cooldown = this . cooldown . get ( id ) ; if ( ! cooldown ) this . cooldown . set ( id , [ ] ) ; return this . cooldown . get ( id ) ; } param { string } id param { Array < Cooldown > } cooldownToSave return { void } saveCooldown ( id , cooldownToSave ) { this . cooldown . set ( id , cooldownToSave ) ; } param { GuildMember } member param { string } event return { boolean } example async checkExempt ( member , event ? ) { if ( member . id === member . guild . ownerID ) return true ; const options = await this . getOptionsFromDB ( member . guild . id ) ; if ( ! options || typeof options !== "object" ) throw new Error ( "Options need to be valid object" ) ; if ( ! options . ban && ! options . kick && ! options . unrank ) throw new Error ( "Please provide sanction between ban, kick or unrank (boolean)" ) ; if ( options . exemptMembers . length > 0 || options . exemptRoles . length > 0 ) { options . exemptRoles . forEach ( r => { if ( member . roles . cache . has ( r ) ) return true ; } ) ; if ( options . exemptMembers . includes ( member . id ) || ( event && options . exemptEvent . includes ( event ) ) ) return true ; } } param { GuildMember } member param { string } event return { Cooldown } search ( member , event ) { return this . getCooldown ( member . guild . id ) . find ( ( c ) => c . id === member . id && c . guild === member . guild . id && c . event === event ) ; } } export { AntiRaid } ;