@sockethub/platform-xmpp 5.0.0-alpha.3 → 5.0.0-alpha.6

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.
@@ -1,309 +1,348 @@
1
1
  function getMessageBody(stanza) {
2
- for (let elem of stanza.children) {
3
- if (elem.name === 'body') {
4
- return elem.children.join(' ');
2
+ for (const elem of stanza.children) {
3
+ if (elem.name === "body") {
4
+ return elem.children.join(" ");
5
+ }
5
6
  }
6
- }
7
7
  }
8
8
 
9
9
  function getMessageTimestamp(stanza) {
10
- try {
11
- const delay = stanza.children.find(c => c.name === 'delay');
12
- return delay.attrs.stamp;
13
- } catch (e) {
14
- // no timestamp
15
- return null;
16
- }
10
+ try {
11
+ const delay = stanza.children.find((c) => c.name === "delay");
12
+ return delay.attrs.stamp;
13
+ } catch (e) {
14
+ // no timestamp
15
+ return null;
16
+ }
17
17
  }
18
18
 
19
19
  function getMessageId(stanza) {
20
- try {
21
- return stanza.attrs.id;
22
- } catch (e) {
23
- // no message id
24
- return null;
25
- }
20
+ try {
21
+ return stanza.attrs.id;
22
+ } catch (e) {
23
+ // no message id
24
+ return null;
25
+ }
26
26
  }
27
27
 
28
28
  function getMessageStanzaId(stanza) {
29
- try {
30
- const stanzaId = stanza.children.find(c => c.name === 'stanza-id');
31
- return stanzaId.attrs.id;
32
- } catch (e) {
33
- // no stanza id
34
- return null;
35
- }
29
+ try {
30
+ const stanzaId = stanza.children.find((c) => c.name === "stanza-id");
31
+ return stanzaId.attrs.id;
32
+ } catch (e) {
33
+ // no stanza id
34
+ return null;
35
+ }
36
36
  }
37
37
 
38
38
  function getMessageReplaceId(stanza) {
39
- try {
40
- const replaceEl = stanza.children.find(c => c.name === 'replace');
41
- return replaceEl.attrs.id;
42
- } catch (e) {
43
- // no origin id
44
- return null;
45
- }
46
- }
47
-
48
- class IncomingHandlers {
49
- constructor(session) {
50
- this.session = session;
51
- }
52
-
53
- close() {
54
- this.session.debug('received close event with no handler specified');
55
- this.session.sendToClient({
56
- context: 'xmpp',
57
- type: 'close',
58
- actor: this.session.actor,
59
- target: this.session.actor
60
- });
61
- this.session.debug('**** xmpp this.session.for ' + this.session.actor['id'] + ' closed');
62
- this.session.connection.disconnect();
63
- }
64
-
65
- error(err) {
66
39
  try {
67
- this.session.sendToClient({
68
- context: 'xmpp',
69
- type: 'error',
70
- error: err.text || err.toString(),
71
- object: {
72
- type: 'message',
73
- condition: err.condition || 'unknown'
74
- }
75
- });
40
+ const replaceEl = stanza.children.find((c) => c.name === "replace");
41
+ return replaceEl.attrs.id;
76
42
  } catch (e) {
77
- this.session.debug('*** XMPP ERROR (rl catch): ', e);
43
+ // no origin id
44
+ return null;
78
45
  }
79
- }
46
+ }
80
47
 
81
- presence(stanza) {
82
- const obj = {
83
- context: 'xmpp',
84
- type: 'update',
85
- actor: {
86
- type: 'person',
87
- id: stanza.attrs.from,
88
- },
89
- object: {
90
- type: 'presence'
91
- }
92
- };
93
- if (stanza.getChildText('status')) {
94
- obj.object.content = stanza.getChildText('status');
95
- }
96
- if (stanza.getChild('show')) {
97
- obj.object.presence = stanza.getChild('show').getText();
98
- } else {
99
- obj.object.presence = stanza.attrs.type === "unavailable" ? "offline" : "online";
100
- }
101
- if (stanza.attrs.to) {
102
- obj.target = {id: stanza.attrs.to, type: 'person'};
103
- } else {
104
- obj.actor.name = stanza.attrs.from.split('/')[1];
48
+ function getPresence(stanza) {
49
+ if (stanza.getChild("show")) {
50
+ return stanza.getChild("show").getText();
105
51
  }
106
- this.session.debug('received contact presence update from ' + stanza.attrs.from);
107
- this.session.sendToClient(obj);
108
- }
52
+ return stanza.attrs.type === "unavailable" ? "offline" : "online";
53
+ }
109
54
 
110
- subscribe(to, from, name) {
111
- this.session.debug('received subscribe request from ' + from);
112
- const actor = { id: from, type: 'person' };
113
- if (name) {
114
- actor.name = name;
55
+ export class IncomingHandlers {
56
+ constructor(session) {
57
+ this.session = session;
115
58
  }
116
- this.session.sendToClient({
117
- context: 'xmpp',
118
- type: "request-friend",
119
- actor: actor,
120
- target: to
121
- });
122
- }
123
-
124
- // unsubscribe(from) {
125
- // this.session.debug('received unsubscribe request from ' + from);
126
- // this.session.sendToClient({
127
- // type: "remove-friend",
128
- // actor: { id: from },
129
- // target: this.session.actor
130
- // });
131
- // }
132
59
 
133
- notifyChatMessage(stanza) {
134
- const message = getMessageBody(stanza);
135
- if (!message) { return; }
136
- const from = stanza.attrs.from;
137
- const timestamp = getMessageTimestamp(stanza);
138
- const messageId = getMessageId(stanza);
139
- const type = stanza.attrs.type === 'groupchat' ? 'room' : 'person';
60
+ close() {
61
+ if (!this.session) {
62
+ console.debug("close event received but session is undefined");
63
+ return;
64
+ }
140
65
 
141
- const activity = {
142
- context: 'xmpp',
143
- type: 'send',
144
- actor: {
145
- type: 'person',
146
- id: from,
147
- },
148
- target: {
149
- type: type,
150
- id: stanza.attrs.to,
151
- },
152
- object: {
153
- type: 'message',
154
- id: messageId,
155
- content: message,
156
- }
157
- };
66
+ this.session.debug("received close event with no handler specified");
67
+ if (this.session.actor && this.session.sendToClient) {
68
+ this.session.sendToClient({
69
+ context: "xmpp",
70
+ type: "close",
71
+ actor: this.session.actor,
72
+ target: this.session.actor,
73
+ });
74
+ this.session.debug(
75
+ `**** xmpp this.session.for ${this.session.actor.id} closed`,
76
+ );
77
+ }
78
+ if (
79
+ this.session.connection &&
80
+ typeof this.session.connection.disconnect === "function"
81
+ ) {
82
+ this.session.connection.disconnect();
83
+ }
84
+ }
158
85
 
159
- const messageStanzaId = getMessageStanzaId(stanza);
160
- if (messageStanzaId) { activity.object['xmpp:stanza-id'] = messageStanzaId; }
86
+ error(err) {
87
+ try {
88
+ this.session.sendToClient({
89
+ context: "xmpp",
90
+ type: "error",
91
+ error: err.text || err.toString(),
92
+ object: {
93
+ type: "message",
94
+ condition: err.condition || "unknown",
95
+ },
96
+ });
97
+ } catch (e) {
98
+ this.session.debug("*** XMPP ERROR (rl catch): ", e);
99
+ }
100
+ }
161
101
 
162
- const messageReplaceId = getMessageReplaceId(stanza);
163
- if (messageReplaceId) {
164
- activity.object['xmpp:replace'] = { id: messageReplaceId };
102
+ presence(stanza) {
103
+ const obj = {
104
+ context: "xmpp",
105
+ type: "update",
106
+ actor: {
107
+ type: "person",
108
+ id: stanza.attrs.from,
109
+ },
110
+ object: {
111
+ type: "presence",
112
+ },
113
+ };
114
+ if (stanza.getChildText("status")) {
115
+ obj.object.content = stanza.getChildText("status");
116
+ }
117
+ obj.object.presence = getPresence(stanza);
118
+ if (stanza.attrs.to) {
119
+ obj.target = { id: stanza.attrs.to, type: "person" };
120
+ } else {
121
+ obj.actor.name = stanza.attrs.from.split("/")[1];
122
+ }
123
+ this.session.debug(
124
+ `received contact presence update from ${stanza.attrs.from}`,
125
+ );
126
+ this.session.sendToClient(obj);
165
127
  }
166
128
 
167
- if (type === 'room') {
168
- [activity.target['id'], activity.actor.name] = from.split('/');
129
+ subscribe(to, from, name) {
130
+ this.session.debug(`received subscribe request from ${from}`);
131
+ const actor = { id: from, type: "person" };
132
+ if (name) {
133
+ actor.name = name;
134
+ }
135
+ this.session.sendToClient({
136
+ context: "xmpp",
137
+ type: "request-friend",
138
+ actor: actor,
139
+ target: to,
140
+ });
169
141
  }
170
142
 
171
- if (timestamp) { activity.published = timestamp; }
143
+ // unsubscribe(from) {
144
+ // this.session.debug('received unsubscribe request from ' + from);
145
+ // this.session.sendToClient({
146
+ // type: "remove-friend",
147
+ // actor: { id: from },
148
+ // target: this.session.actor
149
+ // });
150
+ // }
172
151
 
173
- this.session.sendToClient(activity);
174
- }
152
+ notifyChatMessage(stanza) {
153
+ const message = getMessageBody(stanza);
154
+ if (!message) {
155
+ return;
156
+ }
157
+ const from = stanza.attrs.from;
158
+ const timestamp = getMessageTimestamp(stanza);
159
+ const messageId = getMessageId(stanza);
160
+ const type = stanza.attrs.type === "groupchat" ? "room" : "person";
175
161
 
176
- notifyError(stanza) {
177
- const error = stanza.getChild('error');
178
- let message = stanza.toString();
179
- let type = 'message';
180
- if (stanza.is('presence')) {
181
- type = 'update';
182
- }
162
+ const activity = {
163
+ context: "xmpp",
164
+ type: "send",
165
+ actor: {
166
+ type: "person",
167
+ id: from,
168
+ },
169
+ target: {
170
+ type: type,
171
+ id: stanza.attrs.to,
172
+ },
173
+ object: {
174
+ type: "message",
175
+ id: messageId,
176
+ content: message,
177
+ },
178
+ };
183
179
 
184
- if (error) {
185
- message = error.toString();
186
- if (error.getChild('remote-server-not-found')) {
187
- // when we get this.session.type of return message, we know it was a response from a join
188
- type = 'join';
189
- message = 'remote server not found ' + stanza.attrs.from;
190
- }
191
- }
180
+ const messageStanzaId = getMessageStanzaId(stanza);
181
+ if (messageStanzaId) {
182
+ activity.object["xmpp:stanza-id"] = messageStanzaId;
183
+ }
192
184
 
193
- this.session.sendToClient({
194
- context: 'xmpp',
195
- type: type,
196
- actor: {
197
- id: stanza.attrs.from,
198
- type: 'room'
199
- },
200
- error: message,
201
- target: {
202
- id: stanza.attrs.to,
203
- type: 'person'
204
- }
205
- });
206
- }
185
+ const messageReplaceId = getMessageReplaceId(stanza);
186
+ if (messageReplaceId) {
187
+ activity.object["xmpp:replace"] = { id: messageReplaceId };
188
+ }
207
189
 
208
- notifyRoomAttendance(stanza) {
209
- const query = stanza.getChild('query');
210
- if (query) {
211
- let members = [];
212
- const entries = query.getChildren('item');
213
- for (let e in entries) {
214
- if (!entries.hasOwnProperty(e)) {
215
- continue;
190
+ if (type === "room") {
191
+ [activity.target.id, activity.actor.name] = from.split("/");
216
192
  }
217
- members.push(entries[e].attrs.name);
218
- }
219
193
 
220
- this.session.sendToClient({
221
- context: 'xmpp',
222
- type: 'query',
223
- actor: {
224
- id: stanza.attrs.from,
225
- type: 'room'
226
- },
227
- target: {
228
- id: stanza.attrs.to,
229
- type: 'person'
230
- },
231
- object: {
232
- type: 'attendance',
233
- members: members
194
+ if (timestamp) {
195
+ activity.published = new Date(timestamp).toISOString();
234
196
  }
235
- });
197
+
198
+ this.session.sendToClient(activity);
236
199
  }
237
- }
238
200
 
239
- online() {
240
- this.session.debug('online');
241
- }
201
+ notifyError(stanza) {
202
+ const error = stanza.getChild("error");
203
+ let message = stanza.toString();
204
+ let type = "message";
205
+ if (stanza.is("presence")) {
206
+ type = "update";
207
+ }
208
+
209
+ if (error) {
210
+ message = error.toString();
211
+ if (error.getChild("remote-server-not-found")) {
212
+ // when we get this.session.type of return message, we know it was a response from a join
213
+ type = "join";
214
+ message = `remote server not found ${stanza.attrs.from}`;
215
+ }
216
+ }
242
217
 
243
- /**
244
- * Handles all unknown conditions that we don't have an explicit handler for
245
- **/
246
- stanza(stanza) {
247
- // console.log("incoming stanza ", stanza);
248
- if ((stanza.attrs.type === 'error')) {
249
- this.notifyError(stanza);
250
- } else if (stanza.is('message')) {
251
- this.notifyChatMessage(stanza);
252
- } else if (stanza.is('presence')) {
253
- this.presence(stanza);
254
- } else if (stanza.is('iq')) {
255
- if (stanza.attrs.id === 'muc_id' && stanza.attrs.type === 'result') {
256
- this.session.debug('got room attendance list');
257
- return this.notifyRoomAttendance(stanza);
258
- }
218
+ this.session.sendToClient({
219
+ context: "xmpp",
220
+ type: type,
221
+ actor: {
222
+ id: stanza.attrs.from,
223
+ type: "room",
224
+ },
225
+ error: message,
226
+ target: {
227
+ id: stanza.attrs.to,
228
+ type: "person",
229
+ },
230
+ });
231
+ }
232
+
233
+ notifyRoomAttendance(stanza) {
234
+ const query = stanza.getChild("query");
235
+ if (query) {
236
+ const members = [];
237
+ const entries = query.getChildren("item");
238
+ for (const e in entries) {
239
+ if (!Object.hasOwnProperty.call(entries, e)) {
240
+ continue;
241
+ }
242
+ members.push(entries[e].attrs.name);
243
+ }
259
244
 
260
- // todo: clean up this area, unsure of what these are
261
- const query = stanza.getChild('query');
262
- if (query) {
263
- const entries = query.getChildren('item');
264
- for (let e in entries) {
265
- if (! entries.hasOwnProperty(e)) {
266
- continue;
267
- }
268
- this.session.debug('STANZA ATTRS: ', entries[e].attrs);
269
- if (entries[e].attrs.subscription === 'both') {
270
- this.session.sendToClient({
271
- context: 'xmpp',
272
- type: 'update',
273
- actor: { id: entries[e].attrs.jid, name: entries[e].attrs.name },
274
- target: this.session.actor,
275
- object: {
276
- type: 'presence',
277
- status: '',
278
- presence: state
279
- }
280
- });
281
- } else if ((entries[e].attrs.subscription === 'from') &&
282
- (entries[e].attrs.ask) && (entries[e].attrs.ask === 'subscribe')) {
283
245
  this.session.sendToClient({
284
- context: 'xmpp',
285
- type: 'update',
286
- actor: { id: entries[e].attrs.jid, name: entries[e].attrs.name },
287
- target: this.session.actor,
288
- object: {
289
- type: 'presence',
290
- statusText: '',
291
- presence: 'notauthorized'
292
- }
246
+ context: "xmpp",
247
+ type: "query",
248
+ actor: {
249
+ id: stanza.attrs.from,
250
+ type: "room",
251
+ },
252
+ target: {
253
+ id: stanza.attrs.to,
254
+ type: "person",
255
+ },
256
+ object: {
257
+ type: "attendance",
258
+ members: members,
259
+ },
293
260
  });
294
- } else {
295
- /**
296
- * can't figure out how to know if one of these query stanzas are from
297
- * added contacts or pending requests
298
- */
299
- this.subscribe(this.session.actor, entries[e].attrs.jid, entries[e].attrs.name);
300
- }
301
261
  }
302
- }
303
- } else {
304
- this.session.debug("got XMPP unknown stanza... " + stanza);
305
262
  }
306
- }
307
- }
308
263
 
309
- module.exports = IncomingHandlers;
264
+ online() {
265
+ this.session.debug("online");
266
+ }
267
+
268
+ /**
269
+ * Handles all unknown conditions that we don't have an explicit handler for
270
+ **/
271
+ stanza(stanza) {
272
+ // console.log("incoming stanza ", stanza);
273
+ if (stanza.attrs.type === "error") {
274
+ this.notifyError(stanza);
275
+ } else if (stanza.is("message")) {
276
+ this.notifyChatMessage(stanza);
277
+ } else if (stanza.is("presence")) {
278
+ this.presence(stanza);
279
+ } else if (stanza.is("iq")) {
280
+ if (
281
+ stanza.attrs.id === "muc_id" &&
282
+ stanza.attrs.type === "result"
283
+ ) {
284
+ this.session.debug("got room attendance list");
285
+ return this.notifyRoomAttendance(stanza);
286
+ }
287
+
288
+ // todo: clean up this area, unsure of what these are
289
+ const query = stanza.getChild("query");
290
+ if (query) {
291
+ const entries = query.getChildren("item");
292
+ for (const e in entries) {
293
+ if (!entries.hasOwn(e)) {
294
+ continue;
295
+ }
296
+ this.session.debug("STANZA ATTRS: ", entries[e].attrs);
297
+ if (entries[e].attrs.subscription === "both") {
298
+ this.session.sendToClient({
299
+ context: "xmpp",
300
+ type: "update",
301
+ actor: {
302
+ id: entries[e].attrs.jid,
303
+ name: entries[e].attrs.name,
304
+ },
305
+ target: this.session.actor,
306
+ object: {
307
+ type: "presence",
308
+ status: "",
309
+ presence: getPresence(entries[e]),
310
+ },
311
+ });
312
+ } else if (
313
+ entries[e].attrs.subscription === "from" &&
314
+ entries[e].attrs.ask &&
315
+ entries[e].attrs.ask === "subscribe"
316
+ ) {
317
+ this.session.sendToClient({
318
+ context: "xmpp",
319
+ type: "update",
320
+ actor: {
321
+ id: entries[e].attrs.jid,
322
+ name: entries[e].attrs.name,
323
+ },
324
+ target: this.session.actor,
325
+ object: {
326
+ type: "presence",
327
+ statusText: "",
328
+ presence: "notauthorized",
329
+ },
330
+ });
331
+ } else {
332
+ /**
333
+ * can't figure out how to know if one of these query stanzas are from
334
+ * added contacts or pending requests
335
+ */
336
+ this.subscribe(
337
+ this.session.actor,
338
+ entries[e].attrs.jid,
339
+ entries[e].attrs.name,
340
+ );
341
+ }
342
+ }
343
+ }
344
+ } else {
345
+ this.session.debug(`got XMPP unknown stanza... ${stanza}`);
346
+ }
347
+ }
348
+ }