import camel from 'camelcase' ; import winston from 'winston' ; import { DiscordPayload , Embed } from '../model/DiscordApi' ; import { LoggerUtil } from '../util/LoggerUtil' ; /**
 * Base provider, which all other providers will subclass. You can then
 * use the provided methods to format the data to Discord
 */ export abstract class BaseProvider { protected payload : DiscordPayload ; protected logger : winston . Logger ; protected headers : any ; protected body : any ; protected query : any ; protected embedColor : number | null ; constructor ( ) { this . payload = { } ; this . embedColor = null ; this . logger = LoggerUtil . logger ( ) ; } /**
     * Override this and provide the name of the provider
     */ public abstract getName ( ) ; /**
     * By default, the path is always just the same as the name, all lower case. Override if that is not the case
     */ public getPath ( ) { return this . getName ( ) . toLowerCase ( ) ; } param body param headers param query public async parse ( body , headers = null , query = null ) { this . body = body ; this . headers = headers ; this . query = query ; this . preParse ( ) ; this . parseImpl ( ) ; this . postParse ( ) ; return this . payload ; } /**
     * Nullify the payload. This will effectively cancel the operation and sent nothing to discord.
     */ protected nullifyPayload ( ) { this . payload = null ! ; } /**
     * Open method to do certain things pre parse.
     */ protected preParse ( ) { } /**
     * Parse implementation. The parse strategy is up to the implementation.
     */ protected abstract parseImpl ( ) ; /**
     * Open method to do certain things post parse and before the payload is returned.
     */ protected postParse ( ) { } protected addEmbed ( embed ) { embed . footer = { text : 'Powered by Skyhook' } ; if ( this . embedColor != null ) { embed . color = this . embedColor ; } if ( this . payload . embeds == null ) { this . payload . embeds = [ ] ; } this . payload . embeds . push ( embed ) ; } protected setEmbedColor ( color ) { this . embedColor = color ; } } /**
 * BaseProvider implementation that uses a direct parse strategy.
 * Subclasses should implement parse logic in the parseData method.
 */ export abstract class DirectParseProvider extends BaseProvider { public abstract parseData ( ) ; protected async parseImpl ( ) { await this . parseData ( ) ; } } /**
 * BaseProvider implementation that uses a type based parse strategy.
 * Sublasses must implement a getType method. This method will look at
 * the payload data and determine its type. A function matching the returned
 * type name will be executed. If none function matching the type name
 * is found, nothing will be executed.
 */ export abstract class TypeParseProvder extends BaseProvider { public abstract getType ( ) ; public abstract knownTypes ( ) ; param type public static formatType ( type ) { if ( type == null ) { return null ; } type = type . replace ( /:/g , '_' ) ; return camel ( type ) ; } protected async parseImpl ( ) { const type = TypeParseProvder . formatType ( this . getType ( ) ) ; if ( type != null ) { if ( this . knownTypes ( ) . includes ( type ) ) { const method = ( this as any ) [ type ] ; if ( method != null && typeof method === 'function' ) { this . logger . info ( `Calling ${ type }() in ${ this . constructor . name } provider.` ) ; await method . bind ( this ) ( ) ; return ; } } } this . nullifyPayload ( ) ; } }