import { DOn , DDiscord , DGuard , Client , ArgsOf , DiscordEvents , Modifier , DIService , DSlash , DOption , Method } from "../.." ; import { DGroup } from "../../decorators" ; export class MetadataStorage { private static _instance : MetadataStorage ; private _events : DOn [ ] = [ ] ; private _guards : DGuard [ ] = [ ] ; private _slashes : DSlash [ ] = [ ] ; private _allSlashes : DSlash [ ] = [ ] ; private _options : DOption [ ] = [ ] ; private _discords : DDiscord [ ] = [ ] ; private _modifiers : Modifier < any > [ ] = [ ] ; private _groups : DGroup < DSlash > [ ] = [ ] ; private _subGroups : DGroup < DOption > [ ] = [ ] ; static get instance ( ) { if ( ! this . _instance ) { this . _instance = new MetadataStorage ( ) ; } return this . _instance ; } static clear ( ) { this . _instance = new MetadataStorage ( ) ; } get events ( ) { return this . _events as readonly DOn [ ] ; } /**
     * Get the list of used events without duplications
     */ get usedEvents ( ) { return this . events . reduce < DOn [ ] > ( ( prev , event , index ) => { const found = this . events . find ( ( event2 ) => event . event === event2 . event ) ; const foundIndex = this . events . indexOf ( found ) ; if ( foundIndex === index || found . once !== event . once ) { prev . push ( event ) ; } return prev ; } , [ ] ) as readonly DOn [ ] ; } get discords ( ) { return this . _discords as readonly DDiscord [ ] ; } get slashes ( ) { return this . _slashes as readonly DSlash [ ] ; } get allSlashes ( ) { return this . _allSlashes as readonly DSlash [ ] ; } get groups ( ) { return this . _groups as readonly DGroup [ ] ; } get subGroups ( ) { return this . _subGroups as readonly DGroup [ ] ; } private get discordMembers ( ) : readonly Method [ ] { return [ ... this . _slashes , ... this . _events , ] ; } addModifier ( modifier ) { this . _modifiers . push ( modifier ) ; } addOn ( on ) { this . _events . push ( on ) ; } addSlash ( slash ) { this . _slashes . push ( slash ) ; } addOption ( option ) { this . _options . push ( option ) ; } addGroup ( group ) { this . _groups . push ( group ) ; } addSubGroup ( subGroup ) { this . _subGroups . push ( subGroup ) ; } addGuard ( guard ) { this . _guards . push ( guard ) ; DIService . instance . addService ( guard . classRef ) ; } addDiscord ( discord ) { this . _discords . push ( discord ) ; DIService . instance . addService ( discord . classRef ) ; } async build ( ) { this . discordMembers . filter ( ( member ) => { const discord = this . _discords . find ( ( instance ) => { return instance . from === member . from ; } ) ; member . discord = discord ; if ( member instanceof DSlash ) { discord . slashes . push ( member ) ; } if ( member instanceof DOn ) { discord . events . push ( member ) ; } } ) ; await Modifier . applyFromModifierListToList ( this . _modifiers , this . _discords ) ; await Modifier . applyFromModifierListToList ( this . _modifiers , this . _events ) ; await Modifier . applyFromModifierListToList ( this . _modifiers , this . _slashes ) ; await Modifier . applyFromModifierListToList ( this . _modifiers , this . _options ) ; this . _groups . map ( ( group ) => { this . _slashes . map ( ( slash ) => { if ( group . from !== slash . from ) { return ; } slash . group = group . name ; } ) ; } ) ; this . _allSlashes = this . _slashes ; this . _slashes = this . groupSlashes ( ) ; } private groupSlashes ( ) { const groupedSlashes = new Map ( ) ; this . _groups . map ( ( group ) => { const slashParent = DSlash . create ( group . name , group . infos . description ) . decorate ( group . classRef , group . key , group . method ) ; slashParent . discord = this . _discords . find ( ( instance ) => { return instance . from === slashParent . from ; } ) ; slashParent . guilds = [ ... Client . slashGuilds , ... slashParent . discord . guilds ] ; slashParent . permissions = slashParent . discord . permissions ; groupedSlashes . set ( group . name , slashParent ) ; const slashes = this . _slashes . filter ( ( slash ) => { return slash . group === slashParent . name && ! slash . subgroup ; } ) ; slashes . map ( ( slash ) => { slashParent . options . push ( slash . toSubCommand ( ) ) ; } ) ; } ) ; this . _subGroups . map ( ( subGroup ) => { const option = DOption . create ( subGroup . name , "SUB_COMMAND_GROUP" , subGroup . infos . description ) . decorate ( subGroup . classRef , subGroup . key , subGroup . method ) ; const slashes = this . _slashes . filter ( ( slash ) => { return slash . subgroup === option . name ; } ) ; slashes . map ( ( slash ) => { option . options . push ( slash . toSubCommand ( ) ) ; } ) ; const groupSlash = groupedSlashes . get ( slashes [ 0 ] . group ) ; if ( groupSlash ) { groupSlash . options . push ( option ) ; } } ) ; return [ ... this . _slashes . filter ( ( s ) => ! s . group && ! s . subgroup ) , ... Array . from ( groupedSlashes . values ( ) ) ] ; } param event param client param once trigger < Event extends DiscordEvents > ( event , client , once = false ) { const responses = [ ] ; const eventsToExecute = this . _events . filter ( ( on ) => { return ( on . event === event && on . once === once ) ; } ) ; return async ( ... params ) => { for ( const on of eventsToExecute ) { const res = await on . execute ( params , client ) ; responses . push ( res ) ; } return responses ; } ; } }