import PubNub from 'pubnub' // custom services import {fetchMembershipsByProfileId} from '../services/grouping.service' /** * Provider method holder * We always reference this object so * we don't have to hardcode provider specific * methods for doing chat things. * * This gets overloaded later in the program */ const providerMethods = { publish: () => console.error('no provider publish method set'), subscribe: () => console.error('no provider subscribe method set'), listen: () => console.error('no provider listen method set'), } /** * Breaking out as much pubnub specific flavor */ const setupPubnub = async uuid => { const publishKey = 'pub-c-73f35484-396f-47ff-b4b6-45bed079fd3b' const subscribeKey = 'sub-c-6cb7f5d0-94e2-11ec-b249-a68c05a281ab' if (!uuid) return console.error('no pubnub uuid set') const pubnubClient = await new PubNub({ publishKey: publishKey, subscribeKey: subscribeKey, logVerbosity: false, uuid, }) // Pass pubnub specific methods to our placeholder obj providerMethods['publish'] = pubnubClient.publish providerMethods['subscribe'] = pubnubClient.subscribe providerMethods['listen'] = pubnubClient.addListener return pubnubClient } class ChatMessage { constructor({ title, description }) { ;(this.title = title), (this.description = description) } } const testMessage = new ChatMessage({ title: 'testing', description: 'hello world!', }) const MAIN_CHANNEL = 'Channel-Barcelona' /** Singleton that holds all our chat information */ class Chatter { /** * Create our chatter instance * @return {Chatter} our chatter instance object */ constructor() { // Map of each active chat // * this is where we will store all of our groupings on from the backend on user login... this.groupings = {} // Our pubnub instance this.provider = null // UUID used to identify unique users this.uuid = null // Setup the main channel // subscriptions array will be built dynamically from the "this.groupings" object this.subscriptions = [MAIN_CHANNEL, 'Channel-LosAngeles'] this.listeners = { status: async e => { await this.publish(this.subscriptions[2], testMessage) if (e.category !== 'PNConnectedCategory') return }, message: this._onMessage, presence: this._onPresence, } } /** * Callback that fires on every message * @param {event} e */ async _onMessage(e) { if (e.message) { console.log( `received message: ${e.message.title} - ${e.message.description}`, e, ) } } async _onPresence(e) { return } async setup(uuid) { this.uuid = `${uuid}` this.provider = await setupPubnub(this.uuid) // step 1: build the this.groupings object from the backend // ? .then() to wait for the groupings to be fetched before subscribing to channels this.getGroupingsByProfileId(this.uuid).then(() => { this._listenFor({ listeners: this.listeners }) this._subscribe(this.subscriptions) }) console.log('this.subscriptions', this.subscriptions) } /** * Send a message to a channel * example = new ChatMessage({ title: 'example', description: 'ni' }) * Facade so we can hide provider specific methods * @param {string} channel * @param {ChatMessage} message * @return {object} timestamp */ async publish(channel, message) { console.log('publishing message to channel:', channel) return await providerMethods['publish']({ channel, message }) } /** * Subscribe to a channels * Facade so we can hide provider specific methods * @param {array} channels */ _subscribe(channels) { providerMethods['subscribe']({ channels }) } /** * Listen to events and set callbacks * Facade so we can hide provider specific methods */ _listenFor({ listeners }) { providerMethods['listen'](listeners) } // step 2: build the this.subscriptions array from the this.groupings object // fetch all groupings for this profile and then store them in the chatter groupings object for reference async getGroupingsByProfileId(profileId) { console.log('fetching groupings for profileId:', profileId) const groupings = await fetchMembershipsByProfileId(profileId) this.groupings = groupings this.createChannelNamesByGroupings(this.groupings) } // building a list of channel names from the groupings object.grouping_name createChannelNamesByGroupings(groupings) { groupings.forEach(item => { this.subscriptions.push(item.grouping_name) }); } } export { Chatter }