Source: message-sdk.js

import _ from 'lodash'
import gaManager from '../libs/ga-manager'
import MessagingClient from '../libs/messaging-client'

/**
 * MessageManager is a browser-side and server-side SDK, please
 * use global function createMessageManager to get instance
 */
class MessageManager extends MessagingClient {
  /**
   * Please use global function createMessageManager to instead of new a MessageManager instance
   * @constructor
   */
  constructor(sdkConfig) {
    super(sdkConfig.accountId, sdkConfig.memberToken)
    const optConfig = {
      straasSupport: true,
      ...sdkConfig,
    }
    gaManager.init(optConfig)
  }

  /**
   * To call Init function is required, after getting MessageManager instance
   * from function createMessageManager
   * @return {Promise} a promise
   */
  init() {
    return super.init()
  }

  /**
   * Connect to a specific chat room, by chatroomName, which is defined by developers
   * @param  {string} chatroomName chat room name
   * @param  {object} options
   * @param  {object} options.events
   * @param  {function} options.events.user_meta:(self) triggers when user meta are arrived
   * @param  {function} options.events.user_update:(users) triggers when users are updated
   * @param  {function} options.events.user_add:(users) triggers when new users are arrived
   * @param  {function} options.events.user_remove:(users) triggers when users left the chat room
   * @param  {function} options.events.chat_meta:(meta) triggers when chat room meta are arrived
   * @param  {function} options.events.chat_write_mode:(chatWriteMode) triggers when chat_write_mode
   *                    is changed
   * @param  {function} options.events.message_input_interval:(inputInterval) triggers when
   *                    message_input_interval is changed,
   *                    usually happen when message number is too large
   * @param  {function} options.events.user_count:(userCount) triggers when server automatically
   *                    broadcasting user count
   * @param  {function} options.events.messages:(msg) triggers when new messages are arrived
   * @param  {function} options.events.message_flush triggers when admin clean up all the messages
   * @param  {function} options.events.message_remove:(mid) triggers when single message is removed
   * @param  {function} options.events.aggregated_data_add:(msg) triggers when new aggregated
   *                    messages are arrived
   * @param  {function} options.events.raw_data_add:(msg) triggers when new raw messages are arrived
   * @param  {function} options.meta:(msg) triggers when meta are arrived
   * @param  {function} options.events.connection_status:(status) triggers chat room status
   *                    is changed
   * @return  {Promise} a promise
   */
  connect(chatroomName, options = {}) {
    const opt = {
      ...options,
      isLoadOldMsgs: false,
    }
    return super.connect(chatroomName, opt)
  }

  /**
   * Disconnect from a specific chat room
   * @param  {string} chatroomName chat room name
   * @return  {Promise} a promise
   */
  disconnect(chatroomName) {
    return super.disconnect(chatroomName)
  }

  /**
   * Send message to a specific chat room
   * This method can't be call more than once within one second
   * @param  {string} chatroomName chat room name
   * @param  {string} message a simple string, e.g. "abc", should within 300 characters
   * @return  {Promise} a promise
   */
  sendMessage(chatroomName, message) {
    return super.sendMessage(chatroomName, message)
  }

  /**
   * Send a string to a specific chat room which is aggregated in aggregated_data_add
   * @param  {string} chatroomName chat room name
   * @param  {string} message a simple string, e.g. "like", "cry", should within 100 characters
   * @return  {Promise} a promise
   */
  sendAggregatedDataTypeMessage(chatroomName, message) {
    return super.sendAggregatedDataTypeMessage(chatroomName, message)
  }

  /**
   * Send the raw data to a specific chat room, this type of message is not aggregated
   * @param  {string} chatroomName chat room name
   * @param  {string} message a json or array type of message, e.g. "{ id: 1 } or [{ id: 1 }]",
   *                  should within 2048 characters
   * @return  {Promise} a promise
   */
  sendRawData(chatroomName, message) {
    return super.sendRawData(chatroomName, message)
  }

  /**
   * Update the current user's nickname
   * @param  {string} chatroomName chat room name
   * @param  {string} nickname a nickname to update
   * @return  {Promise} a promise
   */
  updateNickName(chatroomName, nickname) {
    return super.updateNickName(chatroomName, nickname)
  }

  /**
   * Update the role by user object for a specific user
   * @param  {string} chatroomName chat room name
   * @param  {object} user the user object of a specific user
   * @param  {string} role MODERATOR|NORMAL
   * @return  {Promise} a promise
   */
  updateUserRole(chatroomName, user, role) {
    return super.updateUserRole(chatroomName, user, role)
  }

  /**
   * Update the role by member id for a specific user
   * @param  {string} chatroomName chat room name
   * @param  {string} memberId the member id of a specific user
   * @param  {string} role MODERATOR|NORMAL
   * @return  {Promise} a promise
   */
  updateUserRoleByMemberId(chatroomName, memberId, role) {
    return super.updateUserRoleByMemberId(chatroomName, memberId, role)
  }

  /**
   * Show all the connected chat room
   * @return {array} names of all connected chat rooms
   */
  getConnectedRooms() {
    return super.getConnectedRooms()
  }

  /**
   * Show related meta for a specific chat room
   * @param  {string} chatroomName chat room name
   * @return {object} meta object of chat room
   */
  getChatroomMeta(chatroomName) {
    return super.getChatroomMeta(chatroomName)
  }

  /**
   * Returns send message interval of current chatroom.
   * @param  {string} chatroomName chat room name
   * @return {int} Interval in second
   */
  getSendMessageInterval(chatroomName) {
    return this
      .getRoom(chatroomName)
      .then(room => room.getSendMessageInterval())
  }

  /**
   * Return all a specific type of users in a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {string} userType onlineUser|blocked|supervisor,
   *                           onlineUser=[GLOBAL_MANAGER, LOCAL_MANAGER,
   *                           MASTER, MODERATOR, NORMAL] ;
   *                           blocked=[BLOCKED] ;
   *                           supervisor=[GLOBAL_MANAGER, LOCAL_MANAGER, MODERATOR]
   * @return {object} users - array of users
   */
  getUsers(chatroomName, userType) {
    return super.getUsers(chatroomName, userType)
  }

  /**
   * Return all messages in a specific chat room
   * If there are over 5000 people in the chat room, it responds empty array
   * @param  {string} chatroomName chat room name
   * @param  {object} options
   * @param  {number} options.page undefined or null imply no shift, default is 1
   * @param  {number} options.perPage default is 10 and MAX is 100
   * @param  {number} options.oldestDate unix time in millisecond,
   *                  ex: 1406183498018, undefined or null imply no constraint
   * @param  {number} options.latestDate unix time in millisecond,
   *                  ex: 1406183498018, undefined or null imply no constraint
   * @param  {string} options.order asc|desc, order by created_date with asc or desc ordering,
   *                  default is desc
   * @return {object} messages - array of messages
   */
  getMessages(chatroomName, options) {
    return super.getMessages(chatroomName, options)
  }

  /**
   * Return aggregate data in a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {object} options
   * @param  {number} options.page undefined or null imply no shift, default is 1
   * @param  {number} options.perPage default is 10 and MAX is 100
   * @param  {number} options.oldestDate unix time in millisecond,
   *                  ex: 1406183498018, undefined or null imply no constraint
   * @param  {number} options.latestDate unix time in millisecond,
   *                  ex: 1406183498018, undefined or null imply no constraint
   * @param  {string} options.order asc|desc, order by created_date with asc or desc ordering,
   *                  default is desc
   * @return {object} messages - array of messages
   */
  getAggregatedData(chatroomName, options) {
    return super.getAggregatedData(chatroomName, options)
  }

  /**
   * Return raw data in a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {object} options
   * @param  {number} options.page undefined or null imply no shift, default is 1
   * @param  {number} options.perPage default is 10 and MAX is 100
   * @param  {number} options.oldestDate unix time in millisecond,
   *                  ex: 1406183498018, undefined or null imply no constraint
   * @param  {number} options.latestDate unix time in millisecond,
   *                  ex: 1406183498018, undefined or null imply no constraint
   * @param  {string} options.order asc|desc, order by created_date with asc or desc ordering,
   *                  default is desc
   * @return {object} messages - array of messages
   */
  getRawData(chatroomName, options) {
    return super.getRawData(chatroomName, options)
  }

  /**
   * Set meta in a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {string} key indicate the meta key, shouldn't start with _
   * @param  {object} value indicate the meta value
   * @param  {bool} broadcast indicate meta is broadcast or not
   * @return {Promise} a promise
   */
  setMeta(chatroomName, key, value, broadcast) {
    return super.setMeta(chatroomName, key, value, broadcast)
  }

  /**
   * Get meta from a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {array}  keys to get, return all if not specified
   * @return {object} meta - array of metas
   */
  getMeta(chatroomName, keys) {
    return super.getMeta(chatroomName, keys)
  }

  /**
   * Remove a message by message id from a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {string} messageId message id to remove
   * @return  {Promise} a promise
   */
  removeMessage(chatroomName, messageId) {
    return super.removeMessage(chatroomName, messageId)
  }

  /**
   * Flush all messages from a specific chat room
   * @param  {string} chatroomName chat room name
   * @return  {Promise} a promise
   */
  flushMessage(chatroomName) {
    return super.flushMessage(chatroomName)
  }

  /**
   * Change a chat write mode from a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {string} mode ALL|LOGIN|ANCHOR
   * @return  {Promise} a promise
   */
  changeChatWriteMode(chatroomName, mode) {
    return super.changeChatWriteMode(chatroomName, mode)
  }

  /**
   * Return the current user related meta in a specific chat room
   * @param  {string} chatroomName chat room name
   * @return {object} user meta object
   */
  getCurrentUserInChatroom(chatroomName) {
    return super.getCurrentUserInChatroom(chatroomName)
  }

  /**
   * Block the user/users to BLOCKED role from a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {object|array} user a single user object or an array of user objects,
   *                        user object should include label (int type).
   *                        You can get user object from registerd events which is
   *                        started with `user_` or from `getUsers` API
   * @return  {Promise} a promise
   */
  blockUser(chatroomName, user) {
    return super.blockUser(chatroomName, user)
  }

  /**
   * Revive the user/users to NORMAL role from a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {object|array} user a single user object or an array of user objects,
   *                        user object should include label (int type).
   *                        You can get user object from registerd events which is
   *                        started with `user_` or from `getUsers` API
   * @return  {Promise} a promise
   */
  reviveUser(chatroomName, user) {
    return super.reviveUser(chatroomName, user)
  }

  /**
   * Get status from a specific chat room
   * @param  {string} chatroomName chat room name
   * @return  {string} DISCONNECTING|CONNECTING|CONNECTED|IDLE|NOT_USE
   */
  getRoomStatus(chatroomName) {
    return super.getRoomStatus(chatroomName)
  }

  /**
   * Get all aggregated data from a specific chat room
   * @param  {string} chatroomName chat room name
   * @return  {array} an array of aggregated data key and n
   */
  getTotalAggregatedData(chatroomName) {
    return super.getTotalAggregatedData(chatroomName)
  }

  /**
   * Pin a message by message id from a specific chat room
   * @param  {string} chatroomName chat room name
   * @param  {string} messageId message id to pin
   * @return  {Promise} a promise
   */
  pinMessage(chatroomName, messageId) {
    return super.pinMessage(chatroomName, messageId)
  }

  /**
   * Unpin a pinned message from a specific chat room
   * @param  {string} chatroomName chat room name
   * @return  {Promise} a promise
   */
  unpinMessage(chatroomName) {
    return super.unpinMessage(chatroomName)
  }

  /**
   * Get pinned message from a specific chat room
   * @param  {string} chatroomName chat room name
   * @return  {Promise} a promise
   */
  getPinnedMessage(chatroomName) {
    return super.getPinnedMessage(chatroomName)
  }
}

/**
 * Create message manager sdk
 * Synchronously initiate a messaging manager with a cms account id and an user access token
 * Note you should use promise style to handle the callback
 * @param {object} sdkConfig
 * @param {string} sdkConfig.accountId required, a cms account id
 * @param {string} sdkConfig.memberJWT optional, a jwt token to identify an user
 * @return {object} a MessageManager instance
 */
export function createMessageManager(sdkConfig) {
  _.forEach(['accountId'], (v) => {
    if (_.isUndefined(sdkConfig[v])) {
      throw new Error(`config ${v} is required`)
    }
  })
  return new MessageManager(sdkConfig)
}

if (typeof window !== 'undefined') {
  if (_.isNil(window.StraaSChatroom)) {
    window.StraaSChatroom = {}
  }
  window.StraaSChatroom.createMessageManager = createMessageManager

  if (_.isNil(window.StraaS)) {
    window.StraaS = window.StraaSChatroom
  }
}

if (typeof window !== 'undefined' && _.isFunction(window.onStraaSMessageManagerSdkReady)) {
  window.onStraaSMessageManagerSdkReady(createMessageManager)
}

export default createMessageManager