lib/makeHumaniseWare.js
function makeHumaniseWare ({
  apiKey,
  incomingWebhookUrl,
  logger,
  getHandoffFromUpdate
}) {
  if (!apiKey || !incomingWebhookUrl) {
    throw new Error('botmaster-humanise-ware requires at least both of apiKey and incomingWebhookUrl parameters to be defined')
  }
  const HUMANISE_URL = incomingWebhookUrl
  if (!logger) {
    logger = {
      log: debug,
      debug: debug,
      info: debug,
      verbose: debug,
      warn: debug,
      error: debug
    }
  }
  logger.info(`sending updates to humanise on: ${HUMANISE_URL}`)
  const incoming = {
    type: 'incoming',
    name: 'humanise-wrapped-incoming-ware',
    controller: async (bot, update) => {
      bot.sendIsTypingMessageTo(update.sender.id, {ignoreMiddleware: true}).catch(err => logger.error(err))

      // a few refinements for messenger specific messages before sending to humanise
      // will be deprecated in the future
      if (bot.type === 'messenger') {
        convertPostbacks(bot, update)
        convertRefs(bot, update)
        convertMessengerThumbsup(bot, update)
      }

      // updates with no messages are currently not supported. Also,
      // not sending back messages that come from a potential humanise bot
      // as would just be re-sending to platform that just sent it
      if (!update.message || bot.type === 'humanise') {
        const debugMessage = !update.message
        ? 'Got an update with no message, not sending it to humanise'
        : 'Got a user update from humanise, not sending it back to them'
        logger.verbose(debugMessage)
        return
      }

      // humanise takes in only objects that would be accepted on the various platforms
      const userInfo = await bot.getUserInfo(update.sender.id)
      if (getHandoffFromUpdate) {
        const handoffReason = await getHandoffFromUpdate(update)
        if (handoffReason) {
          const handoffTag = `<handoff>${handoffReason}</handoff>`
          update.message.text
            ? update.message.text += handoffTag
            : update.message.text = handoffTag
        }
      }
      const objectToSend = {
        apiKey,
        update,
        senderType: 'user',
        userInfo
      }

      const requestOptions = {
        method: 'POST',
        uri: HUMANISE_URL,
        json: objectToSend
      }

      const debugMessage = 'About to send update to humanise'
      logger.debug(debugMessage)
      await request(requestOptions)
      update.senderUserInfo = userInfo
    }
  }

  const outgoing = {
    type: 'outgoing',
    name: 'humanise-wrapped-outgoing-ware',
    controller: async (bot, update, message) => {
      // skip if there is no message
      if (!message.message) {
        return
      }

      let userInfo
      if (update.sender.id === message.recipient.id) {
        userInfo = update.senderUserInfo
      } else {
        // this should never be the case if it is something like an
        // an automated answer from an AI
        userInfo = bot.getUserInfo(message.recipient.id)
      }

      const objectToSend = {
        apiKey,
        update: message,
        senderType: 'bot',
        userInfo
      }

      const requestOptions = {
        method: 'POST',
        uri: HUMANISE_URL,
        json: objectToSend
      }

      await request(requestOptions)

      // don't send anything. Your webhook should now be doing that
      return 'cancel'
    }
  }

  const humaniseWare = {
    incoming,
    outgoing
  }

  return humaniseWare
}
function makeHumaniseWare ({
  apiKey,
  incomingWebhookUrl,
  logger,
  getHandoffFromUpdate
}) {
  if (!apiKey || !incomingWebhookUrl) {
    throw new Error('botmaster-humanise-ware requires at least both of apiKey and incomingWebhookUrl parameters to be defined')
  }
  const HUMANISE_URL = incomingWebhookUrl
  if (!logger) {
    logger = {
      log: debug,
      debug: debug,
      info: debug,
      verbose: debug,
      warn: debug,
      error: debug
    }
  }
  logger.info(`sending updates to humanise on: ${HUMANISE_URL}`)
  const incoming = {
    type: 'incoming',
    name: 'humanise-wrapped-incoming-ware',
    controller: async (bot, update) => {
      bot.sendIsTypingMessageTo(update.sender.id, {ignoreMiddleware: true}).catch(err => logger.error(err))

      // a few refinements for messenger specific messages before sending to humanise
      // will be deprecated in the future
      if (bot.type === 'messenger') {
        convertPostbacks(bot, update)
        convertRefs(bot, update)
        convertMessengerThumbsup(bot, update)
      }

      // updates with no messages are currently not supported. Also,
      // not sending back messages that come from a potential humanise bot
      // as would just be re-sending to platform that just sent it
      if (!update.message || bot.type === 'humanise') {
        const debugMessage = !update.message
        ? 'Got an update with no message, not sending it to humanise'
        : 'Got a user update from humanise, not sending it back to them'
        logger.verbose(debugMessage)
        return
      }

      // humanise takes in only objects that would be accepted on the various platforms
      const userInfo = await bot.getUserInfo(update.sender.id)
      if (getHandoffFromUpdate) {
        const handoffReason = await getHandoffFromUpdate(update)
        if (handoffReason) {
          const handoffTag = `<handoff>${handoffReason}</handoff>`
          update.message.text
            ? update.message.text += handoffTag
            : update.message.text = handoffTag
        }
      }
      const objectToSend = {
        apiKey,
        update,
        senderType: 'user',
        userInfo
      }

      const requestOptions = {
        method: 'POST',
        uri: HUMANISE_URL,
        json: objectToSend
      }

      const debugMessage = 'About to send update to humanise'
      logger.debug(debugMessage)
      await request(requestOptions)
      update.senderUserInfo = userInfo
    }
  }

  const outgoing = {
    type: 'outgoing',
    name: 'humanise-wrapped-outgoing-ware',
    controller: async (bot, update, message) => {
      // skip if there is no message
      if (!message.message) {
        return
      }

      let userInfo
      if (update.sender.id === message.recipient.id) {
        userInfo = update.senderUserInfo
      } else {
        // this should never be the case if it is something like an
        // an automated answer from an AI
        userInfo = bot.getUserInfo(message.recipient.id)
      }

      const objectToSend = {
        apiKey,
        update: message,
        senderType: 'bot',
        userInfo
      }

      const requestOptions = {
        method: 'POST',
        uri: HUMANISE_URL,
        json: objectToSend
      }

      await request(requestOptions)

      // don't send anything. Your webhook should now be doing that
      return 'cancel'
    }
  }

  const humaniseWare = {
    incoming,
    outgoing
  }

  return humaniseWare
}
function makeHumaniseWare ( { apiKey , incomingWebhookUrl , logger , getHandoffFromUpdate } ) { if ( ! apiKey || ! incomingWebhookUrl ) { throw new Error ( 'botmaster-humanise-ware requires at least both of apiKey and incomingWebhookUrl parameters to be defined' ) } const HUMANISE_URL = incomingWebhookUrl if ( ! logger ) { logger = { log : debug , debug : debug , info : debug , verbose : debug , warn : debug , error : debug } } logger . info ( ` ${ HUMANISE_URL } ` ) const incoming = { type : 'incoming' , name : 'humanise-wrapped-incoming-ware' , controller : async ( bot , update ) => { bot . sendIsTypingMessageTo ( update . sender . id , { ignoreMiddleware : true } ) . catch ( err => logger . error ( err ) ) // a few refinements for messenger specific messages before sending to humanise // will be deprecated in the future if ( bot . type === 'messenger' ) { convertPostbacks ( bot , update ) convertRefs ( bot , update ) convertMessengerThumbsup ( bot , update ) } // updates with no messages are currently not supported. Also, // not sending back messages that come from a potential humanise bot // as would just be re-sending to platform that just sent it if ( ! update . message || bot . type === 'humanise' ) { const debugMessage = ! update . message ? 'Got an update with no message, not sending it to humanise' : 'Got a user update from humanise, not sending it back to them' logger . verbose ( debugMessage ) return } // humanise takes in only objects that would be accepted on the various platforms const userInfo = await bot . getUserInfo ( update . sender . id ) if ( getHandoffFromUpdate ) { const handoffReason = await getHandoffFromUpdate ( update ) if ( handoffReason ) { const handoffTag = ` ${ handoffReason } ` update . message . text ? update . message . text += handoffTag : update . message . text = handoffTag } } const objectToSend = { apiKey , update , senderType : 'user' , userInfo } const requestOptions = { method : 'POST' , uri : HUMANISE_URL , json : objectToSend } const debugMessage = 'About to send update to humanise' logger . debug ( debugMessage ) await request ( requestOptions ) update . senderUserInfo = userInfo } } const outgoing = { type : 'outgoing' , name : 'humanise-wrapped-outgoing-ware' , controller : async ( bot , update , message ) => { // skip if there is no message if ( ! message . message ) { return } let userInfo if ( update . sender . id === message . recipient . id ) { userInfo = update . senderUserInfo } else { // this should never be the case if it is something like an // an automated answer from an AI userInfo = bot . getUserInfo ( message . recipient . id ) } const objectToSend = { apiKey , update : message , senderType : 'bot' , userInfo } const requestOptions = { method : 'POST' , uri : HUMANISE_URL , json : objectToSend } await request ( requestOptions ) // don't send anything. Your webhook should now be doing that return 'cancel' } } const humaniseWare = { incoming , outgoing } return humaniseWare }
Make botmaster middleware
@param {$0.apiKey} ApiKey Humanise.AI API Key
@param {$0.incomingWebhookUrl} incomingWebhookUrl Humanise.AI full webhook url that identifies your channel. It ends with your Webhook Id
to humanise should go to. This package will then make calls to: https://alpha.humanise.ai/webhooks/{WebhookId}
@param {$0.logger} [Logger] optional logger with .verbose, .debug, .error, .info, .warning methods
@param {$0.getHandoffFromUpdate} [getHandoffFromUpdate] optional async function that takes a botmaster update and returns 'lowSentiment', 'handoff', 'lowConfidence' or null.
Use this param to dynamically set whether you want to handoff a conversation based on a certain user input message. Sentiment of the
user's message is a good example of how to use this.
@exports
Make botmaster middleware