wingbot 3.59.1 → 3.60.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.59.1",
3
+ "version": "3.60.0",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,54 @@
1
+ const Router = require('../../src/Router');
2
+
3
+ /**
4
+ *
5
+ * @param {object} params
6
+ * @param {'any'|'image'|'audio'|'video'|'file'} params.type
7
+ * @param {string} params.variable
8
+ * @param {'array'|'string'} params.datatype
9
+ * @returns {import('../../src/Router').Middleware}
10
+ */
11
+ module.exports = (params) => {
12
+
13
+ /**
14
+ * @param {import('../../src/Request')} req
15
+ * @param {import('../../src/Responder')} res
16
+ */
17
+ const uploadPlugin = async (req, res) => {
18
+ if (req.isAttachment()) {
19
+
20
+ const typeOk = (!params.type || params.type === 'any')
21
+ || req.attachments.every((a) => a.type === params.type);
22
+
23
+ if (!typeOk) {
24
+ await res.run('badType');
25
+ return Router.NEXT;
26
+ }
27
+
28
+ const varName = `${params.variable || 'uploadUrl'}`.trim();
29
+
30
+ if (params.datatype === 'array') {
31
+ const curr = req.state[varName] || [];
32
+ const urls = req.attachments.map((a) => a.payload.url)
33
+ .filter((u) => !!u);
34
+
35
+ res.setState({
36
+ [varName]: [...curr, ...urls]
37
+ });
38
+ } else {
39
+ const [first] = req.attachments;
40
+
41
+ res.setState({
42
+ [varName]: first.payload.url || null
43
+ });
44
+ }
45
+ await res.run('success');
46
+
47
+ } else {
48
+ await res.run('noAttachment');
49
+ }
50
+ return Router.NEXT;
51
+ };
52
+
53
+ return uploadPlugin;
54
+ };
@@ -609,6 +609,57 @@
609
609
  ],
610
610
  "items": [
611
611
  ]
612
+ },
613
+ {
614
+ "id": "ai.wingbot.upload",
615
+ "name": "Process upload",
616
+ "description": "Plugin is intended to be used in an interaction plugin",
617
+ "availableSince": 3.60,
618
+ "editable": false,
619
+ "isFactory": true,
620
+ "category": "detectors",
621
+ "inputs": [
622
+ {
623
+ "name": "type",
624
+ "label": "Allowed attachment type",
625
+ "type": "select",
626
+ "options": [
627
+ { "value": "any", "label": "any attachment type" },
628
+ { "value": "image", "label": "image" },
629
+ { "value": "audio", "label": "audio" },
630
+ { "value": "video", "label": "video" },
631
+ { "value": "file", "label": "file" }
632
+ ]
633
+ },
634
+ {
635
+ "name": "variable",
636
+ "label": "Variable name to set attachment URL(s)",
637
+ "type": "text"
638
+ },
639
+ {
640
+ "name": "datatype",
641
+ "label": "Allowed attachment type",
642
+ "type": "select",
643
+ "options": [
644
+ { "value": "string", "label": "string" },
645
+ { "value": "array", "label": "array of strings" }
646
+ ]
647
+ }
648
+ ],
649
+ "items": [
650
+ {
651
+ "id": "noAttachment",
652
+ "description": "No attachment uploaded"
653
+ },
654
+ {
655
+ "id": "badType",
656
+ "description": "Disallowed attachment type"
657
+ },
658
+ {
659
+ "id": "success",
660
+ "description": "Successfully uploaded"
661
+ }
662
+ ]
612
663
  }
613
664
  ],
614
665
  "categories": [
package/src/Processor.js CHANGED
@@ -527,7 +527,14 @@ class Processor extends EventEmitter {
527
527
  }
528
528
  }
529
529
 
530
- async _processMessage (message, pageId, messageSender, responderData, preloadPromise = null) {
530
+ async _processMessage (
531
+ message,
532
+ pageId,
533
+ messageSender,
534
+ responderData,
535
+ preloadPromise = null,
536
+ senderMeta = null
537
+ ) {
531
538
  let senderId = message.sender && message.sender.id;
532
539
  const fromEvent = !!preloadPromise;
533
540
 
@@ -663,7 +670,8 @@ class Processor extends EventEmitter {
663
670
  token,
664
671
  options,
665
672
  responderData,
666
- configuration
673
+ configuration,
674
+ senderMeta
667
675
  );
668
676
  const postBack = this._createPostBack(postbackAcumulator, req, res, features);
669
677
 
@@ -815,7 +823,8 @@ class Processor extends EventEmitter {
815
823
  senderId,
816
824
  pageId,
817
825
  messageSender,
818
- responderData
826
+ responderData,
827
+ res.senderMeta
819
828
  );
820
829
 
821
830
  await emitPromise; // probably has been resolved this time
@@ -906,7 +915,14 @@ class Processor extends EventEmitter {
906
915
  });
907
916
  }
908
917
 
909
- _processPostbacks (postbackAcumulator, senderId, pageId, messageSender, responderData) {
918
+ _processPostbacks (
919
+ postbackAcumulator,
920
+ senderId,
921
+ pageId,
922
+ messageSender,
923
+ responderData,
924
+ senderMeta
925
+ ) {
910
926
  return postbackAcumulator.reduce((promise, postback) => promise
911
927
  .then(() => postback)
912
928
  .then(({ action, data = {}, features }) => {
@@ -917,7 +933,14 @@ class Processor extends EventEmitter {
917
933
  request = Request.postBack(senderId, action, data);
918
934
  }
919
935
  Object.assign(request, { features });
920
- return this._processMessage(request, pageId, messageSender, responderData);
936
+ return this._processMessage(
937
+ request,
938
+ pageId,
939
+ messageSender,
940
+ responderData,
941
+ null,
942
+ senderMeta
943
+ );
921
944
  }), Promise.resolve({}));
922
945
  }
923
946
 
package/src/Request.js CHANGED
@@ -109,6 +109,13 @@ function makeTimestamp () {
109
109
  * @prop {number} score
110
110
  */
111
111
 
112
+ /**
113
+ * @typedef {object} Attachment
114
+ * @prop {'file'|'audio'|'video'|'image'} type
115
+ * @prop {object} payload
116
+ * @prop {string} payload.url
117
+ */
118
+
112
119
  /**
113
120
  * @typedef {number} AiSetStateOption
114
121
  */
@@ -175,6 +182,7 @@ class Request {
175
182
 
176
183
  this._optin = event.optin || null;
177
184
 
185
+ /** @type {Attachment[]} */
178
186
  this.attachments = (event.message
179
187
  && (event.message.attachment
180
188
  ? [event.message.attachment]
package/src/Responder.js CHANGED
@@ -102,7 +102,8 @@ class Responder {
102
102
  token = null,
103
103
  options = {},
104
104
  data = {},
105
- configuration = {}
105
+ configuration = {},
106
+ senderMeta = null
106
107
  ) {
107
108
  this._messageSender = messageSender;
108
109
  this._senderId = senderId;
@@ -190,7 +191,7 @@ class Responder {
190
191
  this._trackAsAction = null;
191
192
 
192
193
  // both vars are package protected
193
- this._senderMeta = { flag: null };
194
+ this._senderMeta = senderMeta || { flag: null };
194
195
 
195
196
  this._persona = null;
196
197
 
package/src/Tester.js CHANGED
@@ -143,6 +143,11 @@ class Tester {
143
143
  * @prop {string[]}
144
144
  */
145
145
  this.features = null;
146
+
147
+ /**
148
+ * @prop {string}
149
+ */
150
+ this.ATTACHMENT_MOCK_URL = 'http://mock.url/file.txt';
146
151
  }
147
152
 
148
153
  _actionHasGlobalIntent (action) {
@@ -415,6 +420,18 @@ class Tester {
415
420
  return this.processMessage(Request.text(this.senderId, text));
416
421
  }
417
422
 
423
+ /**
424
+ * Sends attachment
425
+ *
426
+ * @param {'image'|'audio'|'video'|'file'} type
427
+ * @param {string} [url]
428
+ * @returns {Promise}
429
+ * @memberOf Tester
430
+ */
431
+ attachment (type = 'file', url = this.ATTACHMENT_MOCK_URL) {
432
+ return this.processMessage(Request.fileAttachment(this.senderId, url, type));
433
+ }
434
+
418
435
  /**
419
436
  * Makes recognised AI intent request
420
437
  *