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