From be914a71925284df4bd86d8d96bedd77a71f952c Mon Sep 17 00:00:00 2001 From: Samuel Gaus Date: Wed, 9 Jan 2019 16:25:18 +0000 Subject: [PATCH 1/5] Automatically send message to existing session on page load if instructed --- src/components/Widget/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/Widget/index.js b/src/components/Widget/index.js index dea5412d..d00d9d26 100644 --- a/src/components/Widget/index.js +++ b/src/components/Widget/index.js @@ -71,6 +71,16 @@ class Widget extends Component { storeLocalSession(storage, SESSION_NAME, remote_id); this.props.dispatch(pullSession()); this.trySendInitPayload() + } else { + // If this is an existing session, it's possible we changed pages and want to send a + // user message when we land. + const params = (new URL(document.location)).searchParams; + const send = params.get('send'); + + if (send) { + this.props.dispatch(addUserMessage(send)); + this.props.dispatch(emitUserMessage(send)); + } } }); From 245ac7fa4b761979e9d8a743a84236e3f3a17206 Mon Sep 17 00:00:00 2001 From: Samuel Gaus Date: Wed, 9 Jan 2019 16:35:10 +0000 Subject: [PATCH 2/5] Add URL query message sending feature to CHANGELOG and README --- CHANGELOG.md | 3 +++ README.md | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ff32ec1..8d1e766f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.5.4 +- When reconnecting to an existing chat session, the bot will send any message contained in the `?send=` URL parameter once it has restored the socket.io connection + ## 0.5.3 - Added the parameter hideWhenNotConnected to not display the widget when the server is not connected (defaults to true) - Fixed issue where the 'connected' property was being loaded from previous session instead of being triggered on actual connection diff --git a/README.md b/README.md index 3cf00368..d599f69b 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,10 @@ emit('bot_uttered', message, room=socket_id) `storage: "local"` defines the state to be stored in the local stoage. The local storage persists after the the browser is closed, and is cleared when the cookies of the browser are cleared, or when `localStorage.clear()`is called. +## Sending a message on page load + +When reconnecting to an existing chat session, the bot will send any message contained in the `?send=` URL parameter once it has restored the socket.io connection. This is useful if you would like your bot to be able to offer your user to navigate around the site. + ## API From 0682002930673a910e352318e8c2dab642c1786b Mon Sep 17 00:00:00 2001 From: Samuel Gaus Date: Wed, 9 Jan 2019 16:37:35 +0000 Subject: [PATCH 3/5] Fix typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d599f69b..b5f9def4 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ emit('bot_uttered', message, room=socket_id) `storage: "local"` defines the state to be stored in the local stoage. The local storage persists after the the browser is closed, and is cleared when the cookies of the browser are cleared, or when `localStorage.clear()`is called. -## Sending a message on page load +### Sending a message on page load When reconnecting to an existing chat session, the bot will send any message contained in the `?send=` URL parameter once it has restored the socket.io connection. This is useful if you would like your bot to be able to offer your user to navigate around the site. From be4ef10bf7844e31a753da11d75c36d8fd902e9e Mon Sep 17 00:00:00 2001 From: Samuel Gaus Date: Mon, 14 Jan 2019 17:56:42 +0000 Subject: [PATCH 4/5] Change next message functionality to use localStorage to eliminate possibility of XSS vulnerability --- CHANGELOG.md | 2 +- README.md | 2 +- src/components/Widget/index.js | 16 ++++++++++------ src/constants.js | 2 ++ 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1e766f..c12a745a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ ## 0.5.4 -- When reconnecting to an existing chat session, the bot will send any message contained in the `?send=` URL parameter once it has restored the socket.io connection +- When reconnecting to an existing chat session, the bot will send a message contained in the localStorage key specified by the `NEXT_MESSAGE` constant. The message should be stringified JSON with a `message` property describing the message and an `expiry` property set to a UNIX timestamp in milliseconds after which this message should not be sent. ## 0.5.3 - Added the parameter hideWhenNotConnected to not display the widget when the server is not connected (defaults to true) diff --git a/README.md b/README.md index d599f69b..e4a7a3ef 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ emit('bot_uttered', message, room=socket_id) ## Sending a message on page load -When reconnecting to an existing chat session, the bot will send any message contained in the `?send=` URL parameter once it has restored the socket.io connection. This is useful if you would like your bot to be able to offer your user to navigate around the site. +When reconnecting to an existing chat session, the bot will send a message contained in the localStorage key specified by the `NEXT_MESSAGE` constant. The message should be stringified JSON with a `message` property describing the message and an `expiry` property set to a UNIX timestamp in milliseconds after which this message should not be sent. This is useful if you would like your bot to be able to offer your user to navigate around the site. ## API diff --git a/src/components/Widget/index.js b/src/components/Widget/index.js index d00d9d26..5f0e3bdd 100644 --- a/src/components/Widget/index.js +++ b/src/components/Widget/index.js @@ -22,7 +22,7 @@ import { import { isSnippet, isVideo, isImage, isQR, isText } from './msgProcessor'; import WidgetLayout from './layout'; import { storeLocalSession, getLocalSession } from '../../store/reducers/helper'; -import { SESSION_NAME } from 'constants'; +import { SESSION_NAME, NEXT_MESSAGE } from 'constants'; class Widget extends Component { @@ -74,12 +74,16 @@ class Widget extends Component { } else { // If this is an existing session, it's possible we changed pages and want to send a // user message when we land. - const params = (new URL(document.location)).searchParams; - const send = params.get('send'); + const nextMessage = window.localStorage.getItem(NEXT_MESSAGE); - if (send) { - this.props.dispatch(addUserMessage(send)); - this.props.dispatch(emitUserMessage(send)); + if (nextMessage !== null) { + const { message, expiry } = JSON.parse(nextMessage); + window.localStorage.removeItem(NEXT_MESSAGE); + + if (expiry === 0 || expiry > Date.now()) { + this.props.dispatch(addUserMessage(message)); + this.props.dispatch(emitUserMessage(message)); + } } } }); diff --git a/src/constants.js b/src/constants.js index 4f93a0ca..4ea8973a 100644 --- a/src/constants.js +++ b/src/constants.js @@ -23,6 +23,8 @@ export const MESSAGES_TYPES = { CUSTOM_COMPONENT: 'component' }; +export const NEXT_MESSAGE = 'mrbot_next_message'; + export const PROP_TYPES = { MESSAGE: ImmutablePropTypes.contains({ From c0c2749dbe98f78a5baa90d27b41cffc9d7bdda2 Mon Sep 17 00:00:00 2001 From: Samuel Gaus Date: Wed, 16 Jan 2019 10:22:08 +0000 Subject: [PATCH 5/5] Allow JavaScript in links from bot --- .../components/Messages/components/Message/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Widget/components/Conversation/components/Messages/components/Message/index.js b/src/components/Widget/components/Conversation/components/Messages/components/Message/index.js index e549673f..734c43ae 100644 --- a/src/components/Widget/components/Conversation/components/Messages/components/Message/index.js +++ b/src/components/Widget/components/Conversation/components/Messages/components/Message/index.js @@ -12,7 +12,7 @@ class Message extends PureComponent {
{sender === 'response' ? ( - { if (!url.startsWith('mailto')) return '_blank'; }} /> + { if (!url.startsWith('mailto') && !url.startsWith('javascript')) return '_blank'; }} transformLinkUri={null} /> ) : ( text )}