Amazebot / bbot

An adaptable conversation engine for building bespoke bots.
MIT License
55 stars 2 forks source link

Ability to send JSON response as is #100

Closed ubarsaiyan closed 5 years ago

ubarsaiyan commented 5 years ago

I wish to send a JSON object as a message in Rocket.Chat without any processing via bbot. This can be useful in cases where a user wants to send some custom fields or when bbot does not support some new fields.

An example JSON:

{
  "attachments": [
    {
      "title": "button with compact webview",
      "actions": [
        {
          "type": "button",
          "text": "Book flights",
          "url": "http://www.kayak.com",
          "is_webview": true,
          "webview_height_ratio": "compact"
        }
      ]
    }
  ]
}

As of bbot v1.3.1 the bot does not pass on the field webview_height_ratio. If there is an option to send the raw JSON then these types of problems can be avoided and the user won't need to wait for bbot supporting all the fields. I think you can include an option like b.json similar to b.respond and directly link it to lower level API calls. :)

timkinnane commented 5 years ago

@ubarsaiyan have you tried passing the object to b.respond. Seems to work for me, e.g.

b.respond({
  "title": "button with compact webview",
  "actions": [{
    "type": "button",
    "text": "Book flights",
    "url": "http://www.kayak.com",
    "is_webview": true,
    "webview_height_ratio": "compact"
  }]
})

What is webview_height_ratio meant to do? Is it implemented?

ubarsaiyan commented 5 years ago

@timkinnane webview_height_ratio does nothing on the web client but it specifies the size of the webpage in the mobile browser. I think it is implemented in the android client. Anyways, there should be an option to pass any custom field/JSON. I had earlier tried the method you have mentioned. But the JSON sent did not include the height ratio field.

timkinnane commented 5 years ago

Yeah, so I'm using the exact code I just posted and the SDK logs the data sent to Rocket.Chat as follows:

info:   [sendMessage] Calling (async): [{"rid":"Rz7CSTyvZfJB3drETukDCjot64oTZfD4uh","attachments":[{"title":"button with compact webview","actions":[{"type":"button","text":"Book flights","url":"http://www.kayak.com","is_webview":true,"webview_height_ratio":"compact"}]}],"bot":{"i":"js.SDK"}}]

So the custom data is being passed. Can you link to the code your using that isn't passing the right attributes, or if it's private can you create a demo for just this issue (e.g. clone the boilerplate and replace examples with your callback).

timkinnane commented 5 years ago

So apart from the noted options, I've added another .custom method to payload helpers, also loosening type checking, to allow any object to be given and become the payload which goes through to the message adapter, without requiring it to fit the internal attachment/action interfaces. The adapter still needs to recognise the payload attributes, or it will not be able to convert them to the platform's required message object.

This is so far unreleased and undocumented, but if you need it before the next release, you can pull the master branch from npm instead of the published version.

It would be used in a callback as follows:

(b) => {
  b.envelope.payload.custom({ 'custom-attribute': 'value' }) // prepare the outgoing envelope custom payload
  return b.respond() // dispatch the envelope
}
ubarsaiyan commented 5 years ago

@timkinnane Thank you very much for these modifications to bbot. Now everything works fine :) Just one thing...

  b.envelope.write('text button with msg in chat window')
  b.envelope.payload.quickReply({ 
    msg: 'hello (message sent via RichMessageBot) :D',
    text: 'hello in chat window',
  })

The above code does not pass the msg field. bbot assumes that what is written on the button is sent as the chat message. But this may not be the case. Hence, please allow passing a msg field like above and if no such field is passed then msg=text. This thing works by sending the JSON like:

return b.respond({
      "title": "text button with msg in chat window",
      "actions": [{
          "type": "button",
          "text": "Say hello in chat window?",
          "msg": "hello (message sent via RichMessageBot) :D",
          "msg_in_chat_window": true
      }]
  }).catch((err) => console.error(err))
timkinnane commented 5 years ago

@ubarsaiyan Can you try using content as the field for what is sent to the channel. That's the internal schema attribute equivalent to Rocket.Chat's action msg field.

See the internal schema here and how it gets parsed to the Rocket.Chat schema here.

Or, as previous, you can send the whole attachment object as you need it in Rocket.Chat with the custom method.

The internal model for quick replies is not intended to align exactly with Rocket.Chat's schema, because the framework is platform agnostic and payloads will be parsed from the internal schema into a variety of platforms. So I'm not going to implement every attribute following Rocket.Chat. I also decided that msg is too generic an attribute name for this purpose.

ubarsaiyan commented 5 years ago

@timkinnane Thank you for your help! I didn't know about the content field and I understand that the platform is not Rocket.Chat specific. Thanks!