import Constants from '../../common/constants' ; import { Plugin } from '../../common/plugin' ; import { IContainer , IMessage , ChannelType , Maybe } from '../../common/types' ; import { MessageEmbed , Message } from 'discord.js' ; export default class MarketPlacePlugin extends Plugin { public commandName : string = 'marketplace' ; public name : string = 'MarketPlace' ; public description : string = 'Stores and Lists Everything On MarketPlace.' ; public usage : string = 'Market <add/list>' ; public override pluginAlias = [ 'market' ] ; public permission : ChannelType = ChannelType . Public ; public override pluginChannelName : string = Constants . Channels . Public . BuySellTrade ; public override commandPattern : RegExp = /(add\s.*|list)/ ; private _LISTING_PREFIX = '!marketplace add' ; private _ALIAS_PREFIX = '!market add' ; private _SOLD_EMOJI = '💰' ; private _MAX_CHAR_LENGTH = 2000 ; private _LINK_PREFIX : Maybe < string > = null ; private _lastListingPost : Maybe < IMessage > = null ; constructor ( public container ) { super ( ) ; } public async execute ( message , args ) { const [ sub_command ] = args ; if ( sub_command === 'add' ) { await this . _handleAddMarket ( message ) ; return ; } if ( sub_command === 'list' ) { await this . _handleListMarket ( message ) ; } } private async _handleAddMarket ( message ) { return this . container . messageService . attemptDMUser ( message , new MessageEmbed ( ) . setDescription ( `Your item has been added! Please react to your message with ${ this . _SOLD_EMOJI } once it is sold.` ) ) ; } private async _handleListMarket ( message ) { const oldMessages = await this . _fetchMessages ( message , 300 ) ; const itemsForSale = this . _fetchListings ( oldMessages ) ; if ( ! itemsForSale . length ) { await message . reply ( 'Sorry, I could not find any listings' ) ; return ; } const chunks = [ ] ; while ( itemsForSale . length > 0 ) { let curLength = 0 ; const temp = [ ] ; while ( itemsForSale . length && curLength + itemsForSale [ itemsForSale . length - 1 ] . length < this . _MAX_CHAR_LENGTH ) { temp . push ( itemsForSale . pop ( ) as string ) ; curLength = temp . join ( '' ) . length ; } chunks . push ( temp . reverse ( ) ) ; } const pages = this . _createListingEmbed ( chunks ) ; return Promise . all ( [ this . container . messageService . sendPagedEmbed ( message , pages ) . then ( async ( sentMsg ) => this . _deleteOldListingPost ( message , sentMsg ) ) , message . delete ( ) , ] ) ; } private _createListingEmbed ( chunks ) { return chunks . map ( ( items ) => { const embed = new MessageEmbed ( ) ; embed . setTitle ( 'Items For Sale' ) ; embed . setColor ( '#7289da' ) ; embed . setDescription ( items . reverse ( ) . join ( '\n\n' ) ) ; return embed ; } ) ; } private async _deleteOldListingPost ( listCall , newPosting ) { if ( this . _lastListingPost && listCall . channel . messages . cache . get ( this . _lastListingPost . id ) ) { await this . _lastListingPost . delete ( ) ; this . _lastListingPost = newPosting ; return ; } await this . _fetchMessages ( listCall , 100 ) . then ( ( messages ) => { const botMsgs = messages . filter ( ( msg ) => msg . author . bot && msg . embeds . length && newPosting . id !== msg . id ) ; if ( botMsgs . length === 0 ) { return ; } this . _lastListingPost = botMsgs [ 0 ] ; } ) ; if ( ! this . _lastListingPost ) { this . _lastListingPost = newPosting ; return ; } await this . _lastListingPost . delete ( ) ; this . _lastListingPost = newPosting ; } private async _fetchMessages ( message , limitParam ) { let i ; let last_id = message . id ; const buffer = [ ] ; for ( i = 0 ; i < limitParam / 100 ; i ++ ) { const config = { limit : 100 , before : last_id } ; const batch = await message . channel . messages . fetch ( config ) ; if ( ! batch . size ) { continue ; } const last = batch . last ( ) ; if ( last ) { last_id = last . id ; } buffer . push ( ... [ ... batch . values ( ) ] ) ; } return buffer ; } private _fetchListings ( messages ) { const calls = messages . filter ( ( msg ) => ( msg . content . startsWith ( this . _LISTING_PREFIX ) || msg . content . startsWith ( this . _ALIAS_PREFIX ) ) && ! Boolean ( msg . reactions . cache . find ( ( r ) => r . emoji . name === this . _SOLD_EMOJI ) ) ) ; return calls . reduce ( ( acc , msg ) => { const parsed = this . _resolveToListing ( msg ) ; if ( parsed ) { acc . push ( parsed ) ; } return acc ; } , [ ] ) ; } private _resolveToListing ( msg ) { const item = this . _parseItemFromMessage ( msg ) ; if ( ! item ?. length ) { return '' ; } const user = msg . author ; return `${ item }\n ${ user . toString ( ) } [Link](${ this . _createMessageLink ( msg . id ) })` ; } private _parseItemFromMessage ( msg ) { const [ , ... temp ] = msg . content . split ( 'add' ) ; return temp . join ( 'add' ) ; } private _createMessageLink ( id ) { if ( ! this . _LINK_PREFIX ) { const guildID = this . container . guildService . get ( ) . id ; const chanID = this . container . guildService . getChannel ( Constants . Channels . Public . BuySellTrade ) . id ; this . _LINK_PREFIX = `https://discord.com/channels/${ guildID }/${ chanID }/` ; } return `${ this . _LINK_PREFIX }${ id }` ; } }