@subiz/widget-v4 4.1.155 → 4.1.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/compiled_src/bot.js +9 -0
  2. package/compiled_src/chatbox/AgentsAvatar.js +7 -6
  3. package/compiled_src/chatbox/ChatButton.js +25 -14
  4. package/compiled_src/chatbox/Widget.js +41 -0
  5. package/compiled_src/store/store.js +101 -13
  6. package/dist/1986e37f014.app.js +1 -0
  7. package/dist/{19816b2e8ca.chat.html → 1986e37f014.chat.html} +1 -1
  8. package/dist/1986e37f014.chat.js +1 -0
  9. package/dist/{19816b2e8ca.form.html → 1986e37f014.form.html} +1 -1
  10. package/dist/1986e37f014.form.js +1 -0
  11. package/dist/{19816b2e8ca.index.html → 1986e37f014.index.html} +1 -1
  12. package/dist/{19816b2e8ca.library.html → 1986e37f014.library.html} +1 -1
  13. package/dist/1986e37f014.library.js +1 -0
  14. package/dist/{19816b2e8ca.preview.html → 1986e37f014.preview.html} +1 -1
  15. package/dist/1986e37f014.preview.js +1 -0
  16. package/dist/1986e37f014.webview.js +1 -0
  17. package/dist/HASH +1 -1
  18. package/dist/screenshoot.js +52 -1
  19. package/package.json +3 -3
  20. package/src/bot.js +8 -1
  21. package/src/chatbox/AgentsAvatar.js +30 -12
  22. package/src/chatbox/ChatButton.js +30 -17
  23. package/src/chatbox/Widget.js +27 -0
  24. package/src/store/store.js +92 -17
  25. package/dist/19816b2e8ca.app.js +0 -1
  26. package/dist/19816b2e8ca.chat.js +0 -1
  27. package/dist/19816b2e8ca.form.js +0 -1
  28. package/dist/19816b2e8ca.library.js +0 -1
  29. package/dist/19816b2e8ca.preview.js +0 -1
  30. package/dist/19816b2e8ca.webview.js +0 -1
  31. /package/dist/{19816b2e8ca.127.js → 1986e37f014.127.js} +0 -0
  32. /package/dist/{19816b2e8ca.132.js → 1986e37f014.132.js} +0 -0
  33. /package/dist/{19816b2e8ca.185.js → 1986e37f014.185.js} +0 -0
  34. /package/dist/{19816b2e8ca.27.js → 1986e37f014.27.js} +0 -0
  35. /package/dist/{19816b2e8ca.278.js → 1986e37f014.278.js} +0 -0
  36. /package/dist/{19816b2e8ca.339.js → 1986e37f014.339.js} +0 -0
  37. /package/dist/{19816b2e8ca.459.js → 1986e37f014.459.js} +0 -0
  38. /package/dist/{19816b2e8ca.490.js → 1986e37f014.490.js} +0 -0
  39. /package/dist/{19816b2e8ca.74.js → 1986e37f014.74.js} +0 -0
  40. /package/dist/{19816b2e8ca.997.js → 1986e37f014.997.js} +0 -0
package/dist/HASH CHANGED
@@ -1 +1 @@
1
- 19816b2e8ca
1
+ 1986e37f014
@@ -3775,6 +3775,57 @@ function jsonifyTextPlain(param, done) {
3775
3775
  _defineProperty(this, "sendTyping", cid => this.apireq.post(`/accounts/${this.accid}/conversations/${cid}/typing`));
3776
3776
  _defineProperty(this, "sendLostFocus", () => this.apireq.post(`/accounts/${this.accid}/focuses/${this.uid}/delete`));
3777
3777
  _defineProperty(this, "uploadToS3", async file => {
3778
+ let name = file.name.replace(/\s+/g, '_');
3779
+ var {
3780
+ body,
3781
+ error
3782
+ } = await this.apireq.setBaseUrl('https://api5.subiz.com.vn/4.1').setQuery({
3783
+ 'account-id': this.accid,
3784
+ description: 'upload\n user-client: web-widget',
3785
+ name: name,
3786
+ presign: true,
3787
+ size: file.size,
3788
+ type: file.type
3789
+ }).post('/files');
3790
+ if (error) return {
3791
+ body,
3792
+ error
3793
+ };
3794
+ let signedurl = body.signed_url;
3795
+ let fileid = body.id;
3796
+ let err = await new Promise(resolve => {
3797
+ const xhr = new util/* default */.A.XMLHttpRequest();
3798
+ xhr.open('PUT', signedurl, true);
3799
+ xhr.setRequestHeader('Content-Type', file.mimetype);
3800
+ xhr.onload = function () {
3801
+ if (xhr.status === 200) {
3802
+ resolve();
3803
+ } else {
3804
+ resolve(new Error(`Upload failed: ${xhr.statusText}`));
3805
+ }
3806
+ };
3807
+ xhr.onerror = function () {
3808
+ resolve(new Error('Network error during upload.'));
3809
+ };
3810
+ xhr.send(file);
3811
+ });
3812
+ if (err) return {
3813
+ error: err
3814
+ };
3815
+ var {
3816
+ body,
3817
+ error
3818
+ } = await this.apireq.setBaseUrl('https://api5.subiz.com.vn/4.1').setQuery({
3819
+ 'account-id': this.accid
3820
+ }).post(`/files/${fileid}/uploaded`);
3821
+ if (error) return {
3822
+ error
3823
+ };
3824
+ return {
3825
+ url: util/* default */.A.get(body, 'file.url', '')
3826
+ };
3827
+ });
3828
+ _defineProperty(this, "uploadToS32", async file => {
3778
3829
  var {
3779
3830
  body,
3780
3831
  error
@@ -3830,7 +3881,7 @@ function jsonifyTextPlain(param, done) {
3830
3881
  this.refreshLock = new util/* default */.A.Mutex();
3831
3882
  this.FileURL = FileURL;
3832
3883
  this.ApiURL = ApiURL;
3833
- this.api41 = ajax.setBaseUrl('https://api5.subiz.com.vn/4.1').withCredentials(true).setContentType('text/plain').beforeHook(jsonifyTextPlain).setParser('json');
3884
+ this.api41 = ajax.setBaseUrl('https://api.sbz.vn/4.1').withCredentials(true).setContentType('text/plain').beforeHook(jsonifyTextPlain).setParser('json');
3834
3885
  this.apireq = ajax.setBaseUrl(ApiURL).withCredentials(true).addQuery('v', '6').setContentType('text/plain').beforeHook(jsonifyTextPlain).setParser('json').beforeHook((param, done) => {
3835
3886
  if (this.token_generator) {
3836
3887
  let user_id = this.profile_id;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.1.155",
3
+ "version": "4.1.156",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
@@ -13,7 +13,7 @@
13
13
  "@subiz/flow": "^1.1.0",
14
14
  "@subiz/wsclient": "^4.0.34",
15
15
  "cookie_js": "1.4.2",
16
- "core-js": "^3.44.0",
16
+ "core-js": "^3.45.0",
17
17
  "css-loader": "5.2.7",
18
18
  "file-loader": "^6.2.0",
19
19
  "less": "^4.4.0",
@@ -29,7 +29,7 @@
29
29
  "babel-loader": "^10.0.0",
30
30
  "babel-plugin-syntax-jsx": "^6.18.0",
31
31
  "html-webpack-plugin": "^5.6.3",
32
- "puppeteer": "^24.15.0",
32
+ "puppeteer": "^24.16.0",
33
33
  "webpack": "^5.101.0",
34
34
  "webpack-bundle-analyzer": "^4.10.2",
35
35
  "webpack-cli": "^6.0.1",
package/src/bot.js CHANGED
@@ -11,7 +11,14 @@ export default function (store) {
11
11
  run = () => true // dont run twice
12
12
  let match = sb.checkRunConditions(bot.initiative_frequency, bot.conditions, store.matchLastBotRun(bot.id), store)
13
13
  if (!match) return
14
-
14
+ if (bot.id.startsWith('at')) {
15
+ if (!bot.welcome_message) return
16
+ let {error} = await store.startLightConvo(bot.id, bot.welcome_message, common.getLocale(bot, sb.detectLang()))
17
+ if (error) return console.error(error)
18
+ store.logBotRun(bot.id)
19
+ return
20
+ }
21
+ // old bot, should deprecated
15
22
  let {error} = await store.startConvo({
16
23
  initial_by: bot.id,
17
24
  locale: common.getLocale(bot, sb.detectLang()),
@@ -59,6 +59,10 @@ export default function AgentsAvatar(props) {
59
59
  // 1 agent
60
60
  if (agents.length === 1) {
61
61
  var agent = agents[0]
62
+
63
+ let avatarurl =
64
+ agent.avatar_url || props.store.replaceFileUrl(acc.logo_url) || require('../../assets/img/image_default.png')
65
+
62
66
  var groupClass = mode === 'primary' ? 'group-avatar--agent-middle' : 'group-avatar--agent-left'
63
67
  return (
64
68
  <div class={`group-avatar group-avatar--${mode}`}>
@@ -67,13 +71,7 @@ export default function AgentsAvatar(props) {
67
71
  data-tooltip={agent.fullname || acc.name}
68
72
  data-tooltip-position={tooltippos}
69
73
  >
70
- <img
71
- width={35}
72
- height={35}
73
- class={`avatar ${groupClass}`}
74
- alt='agent avatar'
75
- src={props.store.replaceFileUrl(agent.avatar_url) || require('../../assets/img/default_avatar.png')}
76
- />
74
+ <img width={35} height={35} class={`avatar ${groupClass}`} alt='agent avatar' src={avatarurl} />
77
75
  </div>
78
76
  </div>
79
77
  )
@@ -95,7 +93,11 @@ export default function AgentsAvatar(props) {
95
93
  height={35}
96
94
  alt='agent avatar left'
97
95
  class='avatar group-avatar--agent-left'
98
- src={props.store.replaceFileUrl(leftAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
96
+ src={
97
+ props.store.replaceFileUrl(leftAgent.avatar_url) ||
98
+ props.store.replaceFileUrl(acc.logo_url) ||
99
+ require('../../assets/img/image_default.png')
100
+ }
99
101
  />
100
102
  </div>
101
103
  <div
@@ -108,7 +110,11 @@ export default function AgentsAvatar(props) {
108
110
  width={35}
109
111
  height={35}
110
112
  class='avatar group-avatar--agent-right'
111
- src={props.store.replaceFileUrl(rightAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
113
+ src={
114
+ props.store.replaceFileUrl(rightAgent.avatar_url) ||
115
+ props.store.replaceFileUrl(acc.logo_url) ||
116
+ require('../../assets/img/image_default.png')
117
+ }
112
118
  />
113
119
  </div>
114
120
  </div>
@@ -132,7 +138,11 @@ export default function AgentsAvatar(props) {
132
138
  height={35}
133
139
  alt='agent avatar left'
134
140
  class='avatar group-avatar--agent-left'
135
- src={props.store.replaceFileUrl(leftAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
141
+ src={
142
+ props.store.replaceFileUrl(leftAgent.avatar_url) ||
143
+ props.store.replaceFileUrl(acc.logo_url) ||
144
+ require('../../assets/img/image_default.png')
145
+ }
136
146
  />
137
147
  </div>
138
148
  <div
@@ -145,7 +155,11 @@ export default function AgentsAvatar(props) {
145
155
  width={35}
146
156
  height={35}
147
157
  class='avatar group-avatar--agent-middle'
148
- src={props.store.replaceFileUrl(middleAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
158
+ src={
159
+ props.store.replaceFileUrl(middleAgent.avatar_url) ||
160
+ props.store.replaceFileUrl(acc.logo_url) ||
161
+ require('../../assets/img/image_default.png')
162
+ }
149
163
  />
150
164
  </div>
151
165
  <div
@@ -158,7 +172,11 @@ export default function AgentsAvatar(props) {
158
172
  height={35}
159
173
  alt='agent avatar right'
160
174
  class='avatar group-avatar--agent-right'
161
- src={props.store.replaceFileUrl(rightAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
175
+ src={
176
+ props.store.replaceFileUrl(rightAgent.avatar_url) ||
177
+ props.store.replaceFileUrl(acc.logo_url) ||
178
+ require('../../assets/img/image_default.png')
179
+ }
162
180
  />
163
181
  </div>
164
182
  </div>
@@ -22,7 +22,7 @@ export default class ChatButton extends Com {
22
22
  if (sb.get(ev, 'type') !== 'message_sent') return
23
23
 
24
24
  let bytype = sb.get(ev, 'by.type')
25
- if (bytype !== 'system' && bytype !== 'agent') return
25
+ if (bytype !== 'system' && bytype !== 'agent' && bytype !== 'bot') return
26
26
 
27
27
  let isquickreplies = false
28
28
  sb.map(sb.get(ev, 'data.message.attachments', []), (att) => {
@@ -106,25 +106,38 @@ export default class ChatButton extends Com {
106
106
  this.setState({displayPreview: false})
107
107
  }
108
108
 
109
- // this method could be call from the parent
110
- ShowGreeting() {
111
- // workaround for bao chau elect dont want show greeting in mobile
112
- if (this.props.store.isMobile()) {
113
- let accid = sb.get(this.props.plugin, 'chatbox.account_id', {})
114
- if (accid === 'acqjeefqeaoiagyfprap') return
115
- }
116
- let greeting = sb.get(this.props.plugin, 'chatbox.greeting', {})
117
- let agentM = this.props.store.matchAgent('*')
118
- let byid = greeting.agent_id
119
- if (!byid) byid = randomAgent(agentM).id
120
-
121
- let text = this.props.t.i18n(sb.get(greeting, 'greeting', {})) || greeting.message
109
+ pickBestGreeting() {
110
+ let convoM = this.props.store.matchConvo('*')
111
+ let unseenConvo = sb
112
+ .filter(convoM, (convo) => {
113
+ let seen = sb.isConvoSeen(convo, this.props.store.matchUser().id)
114
+ return !seen
115
+ })
116
+ .sort((a, b) => sb.get(b, 'last_message_sent.created', 0) - sb.get(a, 'last_message_sent.created', 0))
117
+ if (sb.size(unseenConvo) == 0) {
118
+ // workaround for bao chau elect dont want show greeting in mobile
119
+ if (this.props.store.isMobile()) {
120
+ let accid = sb.get(this.props.plugin, 'chatbox.account_id', {})
121
+ if (accid === 'acqjeefqeaoiagyfprap') return
122
+ }
123
+ let greeting = sb.get(this.props.plugin, 'chatbox.greeting', {})
124
+ let agentM = this.props.store.matchAgent('*')
125
+ let byid = greeting.agent_id
126
+ if (!byid) byid = randomAgent(agentM).id
122
127
 
123
- this.setState({
124
- previewEvent: {
128
+ let text = this.props.t.i18n(sb.get(greeting, 'greeting', {})) || greeting.message
129
+ return {
125
130
  by: {id: byid, type: 'agent'},
126
131
  data: {message: {text, format: 'plaintext'}},
127
- },
132
+ }
133
+ }
134
+ return unseenConvo[0].last_message_sent
135
+ }
136
+
137
+ // this method could be call from the parent
138
+ ShowGreeting() {
139
+ this.setState({
140
+ previewEvent: this.pickBestGreeting(),
128
141
  displayPreview: true,
129
142
  })
130
143
  }
@@ -776,6 +776,33 @@ export default class Widget extends Com {
776
776
  }
777
777
 
778
778
  let text = message.text
779
+
780
+ if (this.props.cid && this.props.cid.startsWith('cslight')) {
781
+ let cid = this.props.cid
782
+ this._creating = (this._creating || 0) + 1
783
+ let _creating = this._creating
784
+ this.setState({creating: true})
785
+ let botid = cid.split('_')[0].slice(7) // 6 = len(cslight)
786
+ const {convo, error} = await this.props.store.startConvo({
787
+ locale: this.props.t.locale(),
788
+ message: text,
789
+ members: [{type: 'bot', id: botid}],
790
+ initial_by: this.props.store.matchUser().id,
791
+ })
792
+ if (_creating != this._creating) return // outdated
793
+ if (error) {
794
+ this.setState({creating: false})
795
+ return
796
+ // show error and try again
797
+ }
798
+ this.props.store.deleteLightConvo(cid)
799
+ await this.props.store.sendConvoEvent(convo.id, 'message_sent', {message})
800
+ if (_creating != this._creating) return // outdated
801
+ this.props.onGo({view: 'chat', cid: convo.id})
802
+ this.setState({creating: false})
803
+ return
804
+ }
805
+
779
806
  if (!this.props.cid) {
780
807
  this._creating = (this._creating || 0) + 1
781
808
  let _creating = this._creating
@@ -35,6 +35,7 @@ export default class Store {
35
35
  this.FileURL = FileURL
36
36
  this._track_page_view = true
37
37
  this.device_type = 'desktop'
38
+ this.lightConvos = {} // convo that have not been created, for faking bot conversation
38
39
  if (this.fake) this.api = new APIFake(ApiURL, FileURL)
39
40
  else this.api = new API(ApiURL, FileURL)
40
41
 
@@ -63,9 +64,9 @@ export default class Store {
63
64
 
64
65
  // dont dupplicate seen
65
66
  this.g_haveSentSeenM = {}
66
- this.last_focused = sb.Date.now() // 0 -> in focus, timestamp -> lost focus at
67
+ this.last_focused = this.now() // 0 -> in focus, timestamp -> lost focus at
67
68
  window.addEventListener('blur', () => {
68
- this.last_focused = sb.Date.now()
69
+ this.last_focused = this.now()
69
70
  this.sendPresence()
70
71
  })
71
72
  window.addEventListener('focus', () => {
@@ -93,7 +94,7 @@ export default class Store {
93
94
  this._presenceInterval2 = sb.setInterval(() => {
94
95
  if (this._die) return sb.clearInterval(this._presenceInterval2)
95
96
  if (this.browserVisibility === 'visible' && document.hasFocus()) return
96
- if (this.last_focused && sb.Date.now() - this.last_focused > 30 * 60000) {
97
+ if (this.last_focused && this.now() - this.last_focused > 30 * 60000) {
97
98
  // lost focus for more than 30 min
98
99
  return // dont send presence
99
100
  }
@@ -347,20 +348,23 @@ export default class Store {
347
348
  return agentM[id]
348
349
  }
349
350
 
350
- // must ensure only call this function after init is done
351
351
  matchConvo = (id) => {
352
352
  if (!id) return
353
353
 
354
354
  if (id === '*') {
355
355
  this._touchAcc()
356
- return sb.filter(this.cache.all(), (value, k) => k.startsWith('convo_'))
356
+ // combind with
357
+ return sb.filter(this.cache.all(), (value, k) => k.startsWith('convo_')).concat(sb.map(this.lightConvos))
357
358
  }
358
359
 
360
+ if (id.startsWith('cslight')) return this.lightConvos[id]
359
361
  if (!this.isInsync(id)) this.fetchConvo(id)
360
362
  return this.cache.match('convo_' + id)
361
363
  }
362
364
 
363
365
  fetchConvo = async (cid) => {
366
+ if (!cid) return
367
+ if (cid.startsWith('cslight')) return
364
368
  if (this._die) return dieErr
365
369
  await this.readyGate.entry()
366
370
  await this.reconnectGate.entry(undefined, true)
@@ -382,10 +386,13 @@ export default class Store {
382
386
 
383
387
  listEvents = (id) => {
384
388
  if (!id || id === '*' || typeof id !== 'string') return
389
+ if (id.startsWith('cslight')) return sb.get(this.lightConvos, [id, 'events'], [])
385
390
  return this.chain.listM(id)
386
391
  }
387
392
 
388
393
  fetchMoreEvents = async (convoid) => {
394
+ if (!convoid) return
395
+ if (convoid.startsWith('cslight')) return [[], '']
389
396
  if (!this.isInsync('events' + convoid)) {
390
397
  await this.readyGate.entry()
391
398
  await this.reconnectGate.entry(undefined, true)
@@ -535,6 +542,7 @@ export default class Store {
535
542
  this.reconnect()
536
543
  })
537
544
 
545
+ this.lightConvos = this.kv.match('light_convos') || {}
538
546
  this.seenLoop()
539
547
  await this.reconnect({user: user}) // already fetched
540
548
  this.readyGate.open()
@@ -603,26 +611,36 @@ export default class Store {
603
611
  // ignore sending message
604
612
  if (lastmsgsent.id === lastmsgsent.data.message.idempotency_key) return
605
613
 
606
- // send seen
607
- this.api.markAsSeen(id, lastmsgsent.id)
608
-
609
614
  // fire own event so guest code can update unread number
610
615
  this.pubsub.publish('events', {
611
- created: sb.Date.now(),
616
+ created: this.now(),
612
617
  type: 'message_pong',
613
618
  by: {type: 'user'},
614
619
  data: {
615
620
  message: {
616
621
  conversation_id: id,
617
622
  id: '*',
618
- pongs: [{type: 'seen', created: sb.Date.now()}],
623
+ pongs: [{type: 'seen', created: this.now()}],
619
624
  },
620
625
  },
621
626
  })
627
+ if (id.startsWith('cslight')) {
628
+ let old = this.lightConvos[id]
629
+ let user = this.matchUser()
630
+ if (!old) return
631
+ let mem = sb.find(old.members, (mem) => mem.type == 'user' && mem.id == user.id)
632
+ mem.seen_at = this.now()
633
+ this.kv.put('light_convos', this.lightConvos)
634
+ this.g_haveSentSeenM[lastmsgsent.id] = true
635
+ return
636
+ }
637
+
638
+ // send seen
639
+ this.api.markAsSeen(id, lastmsgsent.id)
622
640
 
623
641
  let convo = this.cache.match('convo_' + id) || {}
624
642
  let mem = sb.find(convo.members, (m) => m.id === user.id)
625
- if (mem) mem.seen_at = sb.Date.now()
643
+ if (mem) mem.seen_at = this.now()
626
644
  this._setConvo(convo)
627
645
  this.g_haveSentSeenM[lastmsgsent.id] = true
628
646
  })
@@ -838,7 +856,7 @@ export default class Store {
838
856
  let convo
839
857
 
840
858
  let alreadyFetched = false
841
- if (cid) {
859
+ if (cid && !cid.startsWith('cslight')) {
842
860
  convo = this.cache.match('convo_' + cid)
843
861
  if (!convo || !convo.id) {
844
862
  let {body: apiconvo, error} = await this.api.getConversation(cid)
@@ -849,6 +867,16 @@ export default class Store {
849
867
  }
850
868
  }
851
869
 
870
+ if (cid.startsWith('cslight')) {
871
+ convo = this.lightConvos[cid]
872
+ if (!convo) return
873
+ convo.events.push(ev)
874
+ convo.last_message_sent = ev
875
+ this.kv.put('light_convos', this.lightConvos)
876
+ this.pubsub.publish('events', ev)
877
+ return
878
+ }
879
+
852
880
  if (!convo) return
853
881
 
854
882
  // ignore wrong channel
@@ -962,11 +990,54 @@ export default class Store {
962
990
 
963
991
  typing(cid) {
964
992
  if (!cid) return
993
+ if (cid.startsWith('cslight')) return
965
994
  this._typing(cid)
966
995
  }
967
996
 
968
997
  _typing = sb.throttle((convoid) => this.api.sendTyping(convoid), 3000, {trailing: false})
969
998
 
999
+ deleteLightConvo(id) {
1000
+ delete this.lightConvos[id]
1001
+ this.kv.put('light_convos', this.lightConvos)
1002
+ }
1003
+
1004
+ startLightConvo(botid, message, locale) {
1005
+ let convoid = 'cslight' + botid + '_' + this.now()
1006
+ let user = this.cache.match('user') || {}
1007
+
1008
+ let old = this.lightConvos[convoid]
1009
+ if (old) return {convo: old}
1010
+ let now = this.now()
1011
+ let ev = {}
1012
+ ev.created = now
1013
+ ev.event_time = now
1014
+ ev.id = 'evfake' + now
1015
+ ev.type = 'message_sent'
1016
+ ev.by = {id: botid, type: 'bot'}
1017
+ ev.data = {message: message}
1018
+ ev.data.message.conversation_id = convoid
1019
+ let newconvo = {
1020
+ id: convoid,
1021
+ locale: locale,
1022
+ initial_by: botid,
1023
+ created: now,
1024
+ actived: now,
1025
+ last_message_sent: ev,
1026
+ members: [
1027
+ {type: 'user', id: user.id},
1028
+ {type: 'bot', id: botid, membership: 'active'},
1029
+ ],
1030
+ state: 'active',
1031
+ touchpoint: {id: convoid, channel: 'subiz', source: 'web'},
1032
+ traffic_source: 'direct',
1033
+ events: [ev],
1034
+ }
1035
+ this.pubsub.publish('events', ev)
1036
+ this.lightConvos[convoid] = newconvo
1037
+ this.kv.put('light_convos', this.lightConvos)
1038
+ return {convo: newconvo}
1039
+ }
1040
+
970
1041
  async startConvo(req) {
971
1042
  if (!req) req = {}
972
1043
  await this.readyGate.entry()
@@ -990,17 +1061,18 @@ export default class Store {
990
1061
  }
991
1062
 
992
1063
  createPostback(cid, postback) {
1064
+ if (cid && cid.startsWith('cslight')) return
993
1065
  return this.api.createPostback(cid, postback)
994
1066
  }
995
1067
 
996
1068
  sendReaction(cid, ev) {
1069
+ if (cid && cid.startsWith('cslight')) return
997
1070
  return this.api.sendConvoEvent(cid, ev)
998
1071
  }
999
1072
 
1000
1073
  async sendConvoEvent(cid, type, data) {
1001
1074
  await this.readyGate.entry()
1002
1075
  var idempotency = sb.randomString(36)
1003
-
1004
1076
  let user = this.cache.match('user') || {}
1005
1077
 
1006
1078
  var event = {
@@ -1044,6 +1116,8 @@ export default class Store {
1044
1116
  })
1045
1117
 
1046
1118
  if (event._error) return this.onWs(event) // dont send error msg
1119
+ if (cid && cid.startsWith('cslight')) return
1120
+
1047
1121
  let {body: ret, error} = await this.api.sendConvoEvent(cid, event)
1048
1122
  if (error) {
1049
1123
  event._error = error
@@ -1059,7 +1133,7 @@ export default class Store {
1059
1133
  dataLayer.push({event: 'SUBIZ Chat', event_action: 'Sent', event_label: 'User', first_interaction: 1})
1060
1134
  }
1061
1135
 
1062
- this.kv.put('last_msg_sent', sb.Date.now())
1136
+ this.kv.put('last_msg_sent', this.now())
1063
1137
  return ret
1064
1138
  }
1065
1139
 
@@ -1179,6 +1253,7 @@ export default class Store {
1179
1253
 
1180
1254
  async listmessageapi(type, anchor, limit) {
1181
1255
  let convoid = type
1256
+ if (convoid && convoid.startsWith('cslight')) return [fakeevents, '', undefined, true]
1182
1257
  let {body: events, code, error} = await this.api.listMessages(convoid, -limit, anchor)
1183
1258
  if (error || code !== 200) return [[], anchor, error]
1184
1259
  anchor = sb.get(sb.last(events), 'id')
@@ -1212,16 +1287,16 @@ export default class Store {
1212
1287
  timeDiff = 0
1213
1288
  async loopTime() {
1214
1289
  if (this._die) return
1215
- let startms = sb.Date.now()
1290
+ let startms = this.now()
1216
1291
 
1217
1292
  // store not init
1218
1293
  if (!sb.get(this.cache.match('user'), 'id')) return sb.setTimeout(() => this.loopTime(), 240000)
1219
1294
 
1220
1295
  let {body: t, error} = await this.api.time()
1221
1296
  if (error) return sb.setTimeout(() => this.loopTime(), 30000)
1222
- var latences = Math.abs(sb.Date.now() - startms) / 2
1297
+ var latences = Math.abs(this.now() - startms) / 2
1223
1298
  var serverMs = new sb.Date(t).getTime() + latences
1224
- var localMs = sb.Date.now()
1299
+ var localMs = this.now()
1225
1300
  this.timeDiff = Math.floor(serverMs - localMs)
1226
1301
  sb.setTimeout(() => this.loopTime(), 240000)
1227
1302
  }