papercups-io / papercups

Open-source live customer chat
https://app.papercups.io/demo
MIT License
5.75k stars 516 forks source link

Starting conversations programatically #822

Open lucasavila00 opened 3 years ago

lucasavila00 commented 3 years ago

Problem I want to be able to send an user a message when my server decides it. It shouldn't matter if the user has started a conversation yet or not. It is expected that the user has a webpage loaded with the widget in it, though.

Solution There are two approaches:

A server to server solution would be the best one, but it would require a lot of work on Papercups to support it. As it is, the client won't register itself until a message has been sent. Also, it has the issue of needing to set up unique matching user ids between two systems.

A client-based solution might do it, as it would require just a special type of user message to flow through the same paths, however this would be unsafe for "trusted" data, since at the end my server message will flow through the client machine before reaching Papercups. These messages could be signed in my server beforehand, making it safe.

The client-side approach seems the best one in relation to not having to sync what my system has as user_id to a unique Papercups customer_id.

In the end, the client-side approach would expose a JS API like

Papercups.sendMessageAsServer("blablabla"); Papercups.sendSignedMessageAsServer("blablabla", "signature");

which is my responsibility to call at the right time. This message would then be sent to the chat as usual and be shown to the person answering and the user in the chat.

As I see it, the only downside of the client-based approach is that Papercups can't be used to reach the user if the conversation is closed, but it also doesn't require an unique user to be set up in agreement between Papercups and my server.


A good example of how this could be used is an "I need help" button.

When this button is clicked, an automated message could be sent to the user is if it were the server, but it actually started in the client.

This message could contain a couple of common answers and callout to have to user say something else if he's in doubt so that the chat flow continues.

Only if we would like to have trust in the data being communicated between the user and the person answering the chat the signature part is needed.

In the same philosophy of #803, there would a a opt-in feature that only allows these "clientServer" messages if they're signed. I believe this is important, as the person answering the chat doesn't need to be aware of signed/unsgined data.

On the other hand, it seems dangerous having sendMessageAsServer enabled by default, as it would allow someone to fake a message as if it had been sent from the server.

The signature part of it could work well and provide an easy to use UI where you can set pre-defined messages and the UI will sign it for you, and you can sign them on-demand yourself if desired.


TLDR: expose a Papercups.sendSignedMessageAsBot("blablabla", "signature"); which the clients will show as a message sent from the server, identified as a bot, and the person answering the chat would see the message identified as a bot. The signature should contain a timestamp to expire the message, too. This timestamp can't be more than 1 minute in the future.

lucasavila00 commented 3 years ago

I have made this draft of what are the needed changes, and they're not that much.

The signature handling part on Elixir was left vague as many technologies could work there.