You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

chat.service.js 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import PubNub from 'pubnub'
  2. // custom services
  3. import {fetchMembershipsByProfileId} from '../services/grouping.service'
  4. /**
  5. * Provider method holder
  6. * We always reference this object so
  7. * we don't have to hardcode provider specific
  8. * methods for doing chat things.
  9. *
  10. * This gets overloaded later in the program
  11. */
  12. const providerMethods = {
  13. publish: () => console.error('no provider publish method set'),
  14. subscribe: () => console.error('no provider subscribe method set'),
  15. listen: () => console.error('no provider listen method set'),
  16. }
  17. /**
  18. * Breaking out as much pubnub specific flavor
  19. */
  20. const setupPubnub = async uuid => {
  21. const publishKey = 'pub-c-73f35484-396f-47ff-b4b6-45bed079fd3b'
  22. const subscribeKey = 'sub-c-6cb7f5d0-94e2-11ec-b249-a68c05a281ab'
  23. if (!uuid) return console.error('no pubnub uuid set')
  24. const pubnubClient = await new PubNub({
  25. publishKey: publishKey,
  26. subscribeKey: subscribeKey,
  27. logVerbosity: false,
  28. uuid,
  29. })
  30. // Pass pubnub specific methods to our placeholder obj
  31. providerMethods['publish'] = pubnubClient.publish
  32. providerMethods['subscribe'] = pubnubClient.subscribe
  33. providerMethods['listen'] = pubnubClient.addListener
  34. return pubnubClient
  35. }
  36. class ChatMessage {
  37. constructor({ title, description }) {
  38. ;(this.title = title), (this.description = description)
  39. }
  40. }
  41. const testMessage = new ChatMessage({
  42. title: 'testing',
  43. description: 'hello world!',
  44. })
  45. const MAIN_CHANNEL = 'Channel-Barcelona'
  46. /** Singleton that holds all our chat information */
  47. class Chatter {
  48. /**
  49. * Create our chatter instance
  50. * @return {Chatter} our chatter instance object
  51. */
  52. constructor() {
  53. // Map of each active chat
  54. // * this is where we will store all of our groupings on from the backend on user login...
  55. this.groupings = {}
  56. // Our pubnub instance
  57. this.provider = null
  58. // UUID used to identify unique users
  59. this.uuid = null
  60. // Setup the main channel
  61. // subscriptions array will be built dynamically from the "this.groupings" object
  62. this.subscriptions = [MAIN_CHANNEL, 'Channel-LosAngeles']
  63. this.listeners = {
  64. status: async e => {
  65. await this.publish(this.subscriptions[2], testMessage)
  66. if (e.category !== 'PNConnectedCategory') return
  67. },
  68. message: this._onMessage,
  69. presence: this._onPresence,
  70. }
  71. }
  72. /**
  73. * Callback that fires on every message
  74. * @param {event} e
  75. */
  76. async _onMessage(e) {
  77. if (e.message) {
  78. console.log(
  79. `received message: ${e.message.title} - ${e.message.description}`,
  80. e,
  81. )
  82. }
  83. }
  84. async _onPresence(e) {
  85. return
  86. }
  87. async setup(uuid) {
  88. this.uuid = `${uuid}`
  89. this.provider = await setupPubnub(this.uuid)
  90. // step 1: build the this.groupings object from the backend
  91. // ? .then() to wait for the groupings to be fetched before subscribing to channels
  92. this.getGroupingsByProfileId(this.uuid).then(() => {
  93. this._listenFor({ listeners: this.listeners })
  94. this._subscribe(this.subscriptions)
  95. })
  96. console.log('this.subscriptions', this.subscriptions)
  97. }
  98. /**
  99. * Send a message to a channel
  100. * example = new ChatMessage({ title: 'example', description: 'ni' })
  101. * Facade so we can hide provider specific methods
  102. * @param {string} channel
  103. * @param {ChatMessage} message
  104. * @return {object} timestamp
  105. */
  106. async publish(channel, message) {
  107. console.log('publishing message to channel:', channel)
  108. return await providerMethods['publish']({ channel, message })
  109. }
  110. /**
  111. * Subscribe to a channels
  112. * Facade so we can hide provider specific methods
  113. * @param {array} channels
  114. */
  115. _subscribe(channels) {
  116. providerMethods['subscribe']({ channels })
  117. }
  118. /**
  119. * Listen to events and set callbacks
  120. * Facade so we can hide provider specific methods
  121. */
  122. _listenFor({ listeners }) {
  123. providerMethods['listen'](listeners)
  124. }
  125. // step 2: build the this.subscriptions array from the this.groupings object
  126. // fetch all groupings for this profile and then store them in the chatter groupings object for reference
  127. async getGroupingsByProfileId(profileId) {
  128. console.log('fetching groupings for profileId:', profileId)
  129. const groupings = await fetchMembershipsByProfileId(profileId)
  130. this.groupings = groupings
  131. this.createChannelNamesByGroupings(this.groupings)
  132. }
  133. // building a list of channel names from the groupings object.grouping_name
  134. createChannelNamesByGroupings(groupings) {
  135. groupings.forEach(item => {
  136. this.subscriptions.push(item.grouping_name)
  137. });
  138. }
  139. }
  140. export { Chatter }