smule.js 1.3.1 → 1.4.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/LICENSE +0 -0
- package/README.md +0 -0
- package/dist/index.cjs +894 -251
- package/dist/index.d.cts +73 -56
- package/dist/index.d.ts +73 -56
- package/dist/index.js +943 -271
- package/package.json +15 -17
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
+
};
|
|
7
10
|
var __export = (target, all) => {
|
|
8
11
|
for (var name in all)
|
|
9
12
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -26,6 +29,625 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
29
|
));
|
|
27
30
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
31
|
|
|
32
|
+
// node_modules/ltx/lib/escape.js
|
|
33
|
+
var require_escape = __commonJS({
|
|
34
|
+
"node_modules/ltx/lib/escape.js"(exports2) {
|
|
35
|
+
"use strict";
|
|
36
|
+
var escapeXMLTable = {
|
|
37
|
+
"&": "&",
|
|
38
|
+
"<": "<",
|
|
39
|
+
">": ">",
|
|
40
|
+
'"': """,
|
|
41
|
+
"'": "'"
|
|
42
|
+
};
|
|
43
|
+
function escapeXMLReplace(match) {
|
|
44
|
+
return escapeXMLTable[match];
|
|
45
|
+
}
|
|
46
|
+
var unescapeXMLTable = {
|
|
47
|
+
"&": "&",
|
|
48
|
+
"<": "<",
|
|
49
|
+
">": ">",
|
|
50
|
+
""": '"',
|
|
51
|
+
"'": "'"
|
|
52
|
+
};
|
|
53
|
+
function unescapeXMLReplace(match) {
|
|
54
|
+
if (match[1] === "#") {
|
|
55
|
+
const num = match[2] === "x" ? parseInt(match.slice(3), 16) : parseInt(match.slice(2), 10);
|
|
56
|
+
if (num === 9 || num === 10 || num === 13 || num >= 32 && num <= 55295 || num >= 57344 && num <= 65533 || num >= 65536 && num <= 1114111) {
|
|
57
|
+
return String.fromCodePoint(num);
|
|
58
|
+
}
|
|
59
|
+
throw new Error("Illegal XML character 0x" + num.toString(16));
|
|
60
|
+
}
|
|
61
|
+
if (unescapeXMLTable[match]) {
|
|
62
|
+
return unescapeXMLTable[match] || match;
|
|
63
|
+
}
|
|
64
|
+
throw new Error("Illegal XML entity " + match);
|
|
65
|
+
}
|
|
66
|
+
function escapeXML2(s) {
|
|
67
|
+
return s.replace(/["&'<>]/g, escapeXMLReplace);
|
|
68
|
+
}
|
|
69
|
+
function unescapeXML2(s) {
|
|
70
|
+
let result = "";
|
|
71
|
+
let start = -1;
|
|
72
|
+
let end = -1;
|
|
73
|
+
let previous = 0;
|
|
74
|
+
while ((start = s.indexOf("&", previous)) !== -1 && (end = s.indexOf(";", start + 1)) !== -1) {
|
|
75
|
+
result = result + s.slice(previous, start) + unescapeXMLReplace(s.slice(start, end + 1));
|
|
76
|
+
previous = end + 1;
|
|
77
|
+
}
|
|
78
|
+
if (previous === 0) return s;
|
|
79
|
+
result = result + s.substring(previous);
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
function escapeXMLText2(s) {
|
|
83
|
+
return s.replace(/[&<>]/g, escapeXMLReplace);
|
|
84
|
+
}
|
|
85
|
+
function unescapeXMLText2(s) {
|
|
86
|
+
return s.replace(/&(amp|#38|lt|#60|gt|#62);/g, unescapeXMLReplace);
|
|
87
|
+
}
|
|
88
|
+
exports2.escapeXML = escapeXML2;
|
|
89
|
+
exports2.escapeXMLText = escapeXMLText2;
|
|
90
|
+
exports2.unescapeXML = unescapeXML2;
|
|
91
|
+
exports2.unescapeXMLText = unescapeXMLText2;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// node_modules/ltx/lib/Element.js
|
|
96
|
+
var require_Element = __commonJS({
|
|
97
|
+
"node_modules/ltx/lib/Element.js"(exports2, module2) {
|
|
98
|
+
"use strict";
|
|
99
|
+
var escape = require_escape();
|
|
100
|
+
var Element5 = class _Element {
|
|
101
|
+
constructor(name, attrs) {
|
|
102
|
+
this.name = name;
|
|
103
|
+
this.parent = null;
|
|
104
|
+
this.children = [];
|
|
105
|
+
this.attrs = {};
|
|
106
|
+
this.setAttrs(attrs);
|
|
107
|
+
}
|
|
108
|
+
/* Accessors */
|
|
109
|
+
/**
|
|
110
|
+
* if (element.is('message', 'jabber:client')) ...
|
|
111
|
+
**/
|
|
112
|
+
is(name, xmlns) {
|
|
113
|
+
return this.getName() === name && (!xmlns || this.getNS() === xmlns);
|
|
114
|
+
}
|
|
115
|
+
/* without prefix */
|
|
116
|
+
getName() {
|
|
117
|
+
const idx = this.name.indexOf(":");
|
|
118
|
+
return idx >= 0 ? this.name.slice(idx + 1) : this.name;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* retrieves the namespace of the current element, upwards recursively
|
|
122
|
+
**/
|
|
123
|
+
getNS() {
|
|
124
|
+
const idx = this.name.indexOf(":");
|
|
125
|
+
if (idx >= 0) {
|
|
126
|
+
const prefix = this.name.slice(0, idx);
|
|
127
|
+
return this.findNS(prefix);
|
|
128
|
+
}
|
|
129
|
+
return this.findNS();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* find the namespace to the given prefix, upwards recursively
|
|
133
|
+
**/
|
|
134
|
+
findNS(prefix) {
|
|
135
|
+
if (!prefix) {
|
|
136
|
+
if (this.attrs.xmlns) {
|
|
137
|
+
return this.attrs.xmlns;
|
|
138
|
+
} else if (this.parent) {
|
|
139
|
+
return this.parent.findNS();
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
const attr = "xmlns:" + prefix;
|
|
143
|
+
if (this.attrs[attr]) {
|
|
144
|
+
return this.attrs[attr];
|
|
145
|
+
} else if (this.parent) {
|
|
146
|
+
return this.parent.findNS(prefix);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Recursiverly gets all xmlns defined, in the form of {url:prefix}
|
|
152
|
+
**/
|
|
153
|
+
getXmlns() {
|
|
154
|
+
let namespaces = {};
|
|
155
|
+
if (this.parent) {
|
|
156
|
+
namespaces = this.parent.getXmlns();
|
|
157
|
+
}
|
|
158
|
+
for (const attr in this.attrs) {
|
|
159
|
+
const m = attr.match("xmlns:?(.*)");
|
|
160
|
+
if (this.attrs.hasOwnProperty(attr) && m) {
|
|
161
|
+
namespaces[this.attrs[attr]] = m[1];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return namespaces;
|
|
165
|
+
}
|
|
166
|
+
setAttrs(attrs) {
|
|
167
|
+
if (typeof attrs === "string") {
|
|
168
|
+
this.attrs.xmlns = attrs;
|
|
169
|
+
} else if (attrs) {
|
|
170
|
+
Object.assign(this.attrs, attrs);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* xmlns can be null, returns the matching attribute.
|
|
175
|
+
**/
|
|
176
|
+
getAttr(name, xmlns) {
|
|
177
|
+
if (!xmlns) {
|
|
178
|
+
return this.attrs[name];
|
|
179
|
+
}
|
|
180
|
+
const namespaces = this.getXmlns();
|
|
181
|
+
if (!namespaces[xmlns]) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
return this.attrs[[namespaces[xmlns], name].join(":")];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* xmlns can be null
|
|
188
|
+
**/
|
|
189
|
+
getChild(name, xmlns) {
|
|
190
|
+
return this.getChildren(name, xmlns)[0];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* xmlns can be null
|
|
194
|
+
**/
|
|
195
|
+
getChildren(name, xmlns) {
|
|
196
|
+
const result = [];
|
|
197
|
+
for (const child of this.children) {
|
|
198
|
+
if (child.getName && child.getName() === name && (!xmlns || child.getNS() === xmlns)) {
|
|
199
|
+
result.push(child);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* xmlns and recursive can be null
|
|
206
|
+
**/
|
|
207
|
+
getChildByAttr(attr, val, xmlns, recursive) {
|
|
208
|
+
return this.getChildrenByAttr(attr, val, xmlns, recursive)[0];
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* xmlns and recursive can be null
|
|
212
|
+
**/
|
|
213
|
+
getChildrenByAttr(attr, val, xmlns, recursive) {
|
|
214
|
+
let result = [];
|
|
215
|
+
for (const child of this.children) {
|
|
216
|
+
if (child.attrs && child.attrs[attr] === val && (!xmlns || child.getNS() === xmlns)) {
|
|
217
|
+
result.push(child);
|
|
218
|
+
}
|
|
219
|
+
if (recursive && child.getChildrenByAttr) {
|
|
220
|
+
result.push(child.getChildrenByAttr(attr, val, xmlns, true));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (recursive) {
|
|
224
|
+
result = result.flat();
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
getChildrenByFilter(filter, recursive) {
|
|
229
|
+
let result = [];
|
|
230
|
+
for (const child of this.children) {
|
|
231
|
+
if (filter(child)) {
|
|
232
|
+
result.push(child);
|
|
233
|
+
}
|
|
234
|
+
if (recursive && child.getChildrenByFilter) {
|
|
235
|
+
result.push(child.getChildrenByFilter(filter, true));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (recursive) {
|
|
239
|
+
result = result.flat();
|
|
240
|
+
}
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
getText() {
|
|
244
|
+
let text = "";
|
|
245
|
+
for (const child of this.children) {
|
|
246
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
247
|
+
text += child;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return text;
|
|
251
|
+
}
|
|
252
|
+
getChildText(name, xmlns) {
|
|
253
|
+
const child = this.getChild(name, xmlns);
|
|
254
|
+
return child ? child.getText() : null;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Return all direct descendents that are Elements.
|
|
258
|
+
* This differs from `getChildren` in that it will exclude text nodes,
|
|
259
|
+
* processing instructions, etc.
|
|
260
|
+
*/
|
|
261
|
+
getChildElements() {
|
|
262
|
+
return this.getChildrenByFilter((child) => {
|
|
263
|
+
return child instanceof _Element;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
/* Builder */
|
|
267
|
+
/** returns uppermost parent */
|
|
268
|
+
root() {
|
|
269
|
+
if (this.parent) {
|
|
270
|
+
return this.parent.root();
|
|
271
|
+
}
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
/** just parent or itself */
|
|
275
|
+
up() {
|
|
276
|
+
if (this.parent) {
|
|
277
|
+
return this.parent;
|
|
278
|
+
}
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
281
|
+
/** create child node and return it */
|
|
282
|
+
c(name, attrs) {
|
|
283
|
+
return this.cnode(new _Element(name, attrs));
|
|
284
|
+
}
|
|
285
|
+
cnode(child) {
|
|
286
|
+
this.children.push(child);
|
|
287
|
+
if (typeof child === "object") {
|
|
288
|
+
child.parent = this;
|
|
289
|
+
}
|
|
290
|
+
return child;
|
|
291
|
+
}
|
|
292
|
+
append(...nodes) {
|
|
293
|
+
for (const node of nodes) {
|
|
294
|
+
this.children.push(node);
|
|
295
|
+
if (typeof node === "object") {
|
|
296
|
+
node.parent = this;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
prepend(...nodes) {
|
|
301
|
+
for (const node of nodes) {
|
|
302
|
+
this.children.unshift(node);
|
|
303
|
+
if (typeof node === "object") {
|
|
304
|
+
node.parent = this;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/** add text node and return element */
|
|
309
|
+
t(text) {
|
|
310
|
+
this.children.push(text);
|
|
311
|
+
return this;
|
|
312
|
+
}
|
|
313
|
+
/* Manipulation */
|
|
314
|
+
/**
|
|
315
|
+
* Either:
|
|
316
|
+
* el.remove(childEl)
|
|
317
|
+
* el.remove('author', 'urn:...')
|
|
318
|
+
*/
|
|
319
|
+
remove(el, xmlns) {
|
|
320
|
+
const filter = typeof el === "string" ? (child) => {
|
|
321
|
+
return !(child.is && child.is(el, xmlns));
|
|
322
|
+
} : (child) => {
|
|
323
|
+
return child !== el;
|
|
324
|
+
};
|
|
325
|
+
this.children = this.children.filter(filter);
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
text(val) {
|
|
329
|
+
if (val && this.children.length === 1) {
|
|
330
|
+
this.children[0] = val;
|
|
331
|
+
return this;
|
|
332
|
+
}
|
|
333
|
+
return this.getText();
|
|
334
|
+
}
|
|
335
|
+
attr(attr, val) {
|
|
336
|
+
if (typeof val !== "undefined" || val === null) {
|
|
337
|
+
if (!this.attrs) {
|
|
338
|
+
this.attrs = {};
|
|
339
|
+
}
|
|
340
|
+
this.attrs[attr] = val;
|
|
341
|
+
return this;
|
|
342
|
+
}
|
|
343
|
+
return this.attrs[attr];
|
|
344
|
+
}
|
|
345
|
+
/* Serialization */
|
|
346
|
+
toString() {
|
|
347
|
+
let s = "";
|
|
348
|
+
this.write((c) => {
|
|
349
|
+
s += c;
|
|
350
|
+
});
|
|
351
|
+
return s;
|
|
352
|
+
}
|
|
353
|
+
_addChildren(writer) {
|
|
354
|
+
writer(">");
|
|
355
|
+
for (const child of this.children) {
|
|
356
|
+
if (child != null) {
|
|
357
|
+
if (child.write) {
|
|
358
|
+
child.write(writer);
|
|
359
|
+
} else if (typeof child === "string") {
|
|
360
|
+
writer(escape.escapeXMLText(child));
|
|
361
|
+
} else if (child.toString) {
|
|
362
|
+
writer(escape.escapeXMLText(child.toString(10)));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
writer("</");
|
|
367
|
+
writer(this.name);
|
|
368
|
+
writer(">");
|
|
369
|
+
}
|
|
370
|
+
write(writer) {
|
|
371
|
+
writer("<");
|
|
372
|
+
writer(this.name);
|
|
373
|
+
for (const k in this.attrs) {
|
|
374
|
+
const v = this.attrs[k];
|
|
375
|
+
if (v != null) {
|
|
376
|
+
writer(" ");
|
|
377
|
+
writer(k);
|
|
378
|
+
writer('="');
|
|
379
|
+
writer(escape.escapeXML(typeof v === "string" ? v : v.toString(10)));
|
|
380
|
+
writer('"');
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (this.children.length === 0) {
|
|
384
|
+
writer("/>");
|
|
385
|
+
} else {
|
|
386
|
+
this._addChildren(writer);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
Element5.prototype.tree = Element5.prototype.root;
|
|
391
|
+
module2.exports = Element5;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// node_modules/ltx/lib/createElement.js
|
|
396
|
+
var require_createElement = __commonJS({
|
|
397
|
+
"node_modules/ltx/lib/createElement.js"(exports2, module2) {
|
|
398
|
+
"use strict";
|
|
399
|
+
var Element5 = require_Element();
|
|
400
|
+
function append(el, child) {
|
|
401
|
+
if (Array.isArray(child)) {
|
|
402
|
+
for (const c of child) append(el, c);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (child === "" || child == null || child === true || child === false) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
el.cnode(child);
|
|
409
|
+
}
|
|
410
|
+
function createElement2(name, attrs, ...children) {
|
|
411
|
+
if (typeof attrs === "object" && attrs !== null) {
|
|
412
|
+
delete attrs.__source;
|
|
413
|
+
delete attrs.__self;
|
|
414
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
415
|
+
if (value == null) delete attrs[key];
|
|
416
|
+
else attrs[key] = value.toString(10);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const el = new Element5(name, attrs);
|
|
420
|
+
for (const child of children) {
|
|
421
|
+
append(el, child);
|
|
422
|
+
}
|
|
423
|
+
return el;
|
|
424
|
+
}
|
|
425
|
+
module2.exports = createElement2;
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// node_modules/ltx/lib/parsers/ltx.js
|
|
430
|
+
var require_ltx = __commonJS({
|
|
431
|
+
"node_modules/ltx/lib/parsers/ltx.js"(exports2, module2) {
|
|
432
|
+
"use strict";
|
|
433
|
+
var events = require("events");
|
|
434
|
+
var escape = require_escape();
|
|
435
|
+
var STATE_TEXT = 0;
|
|
436
|
+
var STATE_IGNORE_COMMENT = 1;
|
|
437
|
+
var STATE_IGNORE_INSTRUCTION = 2;
|
|
438
|
+
var STATE_TAG_NAME = 3;
|
|
439
|
+
var STATE_TAG = 4;
|
|
440
|
+
var STATE_ATTR_NAME = 5;
|
|
441
|
+
var STATE_ATTR_EQ = 6;
|
|
442
|
+
var STATE_ATTR_QUOT = 7;
|
|
443
|
+
var STATE_ATTR_VALUE = 8;
|
|
444
|
+
var STATE_CDATA = 9;
|
|
445
|
+
var STATE_IGNORE_CDATA = 10;
|
|
446
|
+
var SaxLtx = class extends events.EventEmitter {
|
|
447
|
+
constructor() {
|
|
448
|
+
super();
|
|
449
|
+
let state = STATE_TEXT;
|
|
450
|
+
let remainder;
|
|
451
|
+
let parseRemainder;
|
|
452
|
+
let tagName;
|
|
453
|
+
let attrs;
|
|
454
|
+
let endTag;
|
|
455
|
+
let selfClosing;
|
|
456
|
+
let attrQuote;
|
|
457
|
+
let attrQuoteChar;
|
|
458
|
+
let recordStart = 0;
|
|
459
|
+
let attrName;
|
|
460
|
+
this._handleTagOpening = function _handleTagOpening(endTag2, tagName2, attrs2) {
|
|
461
|
+
if (!endTag2) {
|
|
462
|
+
this.emit("startElement", tagName2, attrs2);
|
|
463
|
+
if (selfClosing) {
|
|
464
|
+
this.emit("endElement", tagName2, true);
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
this.emit("endElement", tagName2, false);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
this.write = function write(data) {
|
|
471
|
+
if (typeof data !== "string") {
|
|
472
|
+
data = data.toString();
|
|
473
|
+
}
|
|
474
|
+
let pos = 0;
|
|
475
|
+
if (remainder) {
|
|
476
|
+
data = remainder + data;
|
|
477
|
+
pos += !parseRemainder ? remainder.length : 0;
|
|
478
|
+
parseRemainder = false;
|
|
479
|
+
remainder = null;
|
|
480
|
+
}
|
|
481
|
+
function endRecording() {
|
|
482
|
+
if (typeof recordStart === "number") {
|
|
483
|
+
const recorded = data.slice(recordStart, pos);
|
|
484
|
+
recordStart = void 0;
|
|
485
|
+
return recorded;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
for (; pos < data.length; pos++) {
|
|
489
|
+
switch (state) {
|
|
490
|
+
case STATE_TEXT: {
|
|
491
|
+
const lt = data.indexOf("<", pos);
|
|
492
|
+
if (lt !== -1 && pos !== lt) {
|
|
493
|
+
pos = lt;
|
|
494
|
+
}
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
case STATE_ATTR_VALUE: {
|
|
498
|
+
const quot = data.indexOf(attrQuoteChar, pos);
|
|
499
|
+
if (quot !== -1) {
|
|
500
|
+
pos = quot;
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
}
|
|
504
|
+
case STATE_IGNORE_COMMENT: {
|
|
505
|
+
const endcomment = data.indexOf("-->", pos);
|
|
506
|
+
if (endcomment !== -1) {
|
|
507
|
+
pos = endcomment + 2;
|
|
508
|
+
}
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case STATE_IGNORE_CDATA: {
|
|
512
|
+
const endCDATA = data.indexOf("]]>", pos);
|
|
513
|
+
if (endCDATA !== -1) {
|
|
514
|
+
pos = endCDATA + 2;
|
|
515
|
+
}
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
const c = data.charCodeAt(pos);
|
|
520
|
+
switch (state) {
|
|
521
|
+
case STATE_TEXT:
|
|
522
|
+
if (c === 60) {
|
|
523
|
+
const text = endRecording();
|
|
524
|
+
if (text) {
|
|
525
|
+
this.emit("text", escape.unescapeXML(text));
|
|
526
|
+
}
|
|
527
|
+
state = STATE_TAG_NAME;
|
|
528
|
+
recordStart = pos + 1;
|
|
529
|
+
attrs = {};
|
|
530
|
+
}
|
|
531
|
+
break;
|
|
532
|
+
case STATE_CDATA:
|
|
533
|
+
if (c === 93) {
|
|
534
|
+
if (data.substr(pos + 1, 2) === "]>") {
|
|
535
|
+
const cData = endRecording();
|
|
536
|
+
if (cData) {
|
|
537
|
+
this.emit("text", cData);
|
|
538
|
+
}
|
|
539
|
+
state = STATE_TEXT;
|
|
540
|
+
} else if (data.length < pos + 2) {
|
|
541
|
+
parseRemainder = true;
|
|
542
|
+
pos = data.length;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
break;
|
|
546
|
+
case STATE_TAG_NAME:
|
|
547
|
+
if (c === 47 && recordStart === pos) {
|
|
548
|
+
recordStart = pos + 1;
|
|
549
|
+
endTag = true;
|
|
550
|
+
} else if (c === 33) {
|
|
551
|
+
if (data.substr(pos + 1, 7) === "[CDATA[") {
|
|
552
|
+
recordStart = pos + 8;
|
|
553
|
+
state = STATE_CDATA;
|
|
554
|
+
} else if (data.length < pos + 8 && "[CDATA[".startsWith(data.slice(pos + 1))) {
|
|
555
|
+
parseRemainder = true;
|
|
556
|
+
pos = data.length;
|
|
557
|
+
} else {
|
|
558
|
+
recordStart = void 0;
|
|
559
|
+
state = STATE_IGNORE_COMMENT;
|
|
560
|
+
}
|
|
561
|
+
} else if (c === 63) {
|
|
562
|
+
recordStart = void 0;
|
|
563
|
+
state = STATE_IGNORE_INSTRUCTION;
|
|
564
|
+
} else if (c <= 32 || c === 47 || c === 62) {
|
|
565
|
+
tagName = endRecording();
|
|
566
|
+
pos--;
|
|
567
|
+
state = STATE_TAG;
|
|
568
|
+
}
|
|
569
|
+
break;
|
|
570
|
+
case STATE_IGNORE_COMMENT:
|
|
571
|
+
if (c === 62) {
|
|
572
|
+
const prevFirst = data.charCodeAt(pos - 1);
|
|
573
|
+
const prevSecond = data.charCodeAt(pos - 2);
|
|
574
|
+
if (prevFirst === 45 && prevSecond === 45 || prevFirst === 93 && prevSecond === 93) {
|
|
575
|
+
state = STATE_TEXT;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
break;
|
|
579
|
+
case STATE_IGNORE_INSTRUCTION:
|
|
580
|
+
if (c === 62) {
|
|
581
|
+
const prev = data.charCodeAt(pos - 1);
|
|
582
|
+
if (prev === 63) {
|
|
583
|
+
state = STATE_TEXT;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
break;
|
|
587
|
+
case STATE_TAG:
|
|
588
|
+
if (c === 62) {
|
|
589
|
+
this._handleTagOpening(endTag, tagName, attrs);
|
|
590
|
+
tagName = void 0;
|
|
591
|
+
attrs = void 0;
|
|
592
|
+
endTag = void 0;
|
|
593
|
+
selfClosing = void 0;
|
|
594
|
+
state = STATE_TEXT;
|
|
595
|
+
recordStart = pos + 1;
|
|
596
|
+
} else if (c === 47) {
|
|
597
|
+
selfClosing = true;
|
|
598
|
+
} else if (c > 32) {
|
|
599
|
+
recordStart = pos;
|
|
600
|
+
state = STATE_ATTR_NAME;
|
|
601
|
+
}
|
|
602
|
+
break;
|
|
603
|
+
case STATE_ATTR_NAME:
|
|
604
|
+
if (c <= 32 || c === 61) {
|
|
605
|
+
attrName = endRecording();
|
|
606
|
+
pos--;
|
|
607
|
+
state = STATE_ATTR_EQ;
|
|
608
|
+
}
|
|
609
|
+
break;
|
|
610
|
+
case STATE_ATTR_EQ:
|
|
611
|
+
if (c === 61) {
|
|
612
|
+
state = STATE_ATTR_QUOT;
|
|
613
|
+
}
|
|
614
|
+
break;
|
|
615
|
+
case STATE_ATTR_QUOT:
|
|
616
|
+
if (c === 34 || c === 39) {
|
|
617
|
+
attrQuote = c;
|
|
618
|
+
attrQuoteChar = c === 34 ? '"' : "'";
|
|
619
|
+
state = STATE_ATTR_VALUE;
|
|
620
|
+
recordStart = pos + 1;
|
|
621
|
+
}
|
|
622
|
+
break;
|
|
623
|
+
case STATE_ATTR_VALUE:
|
|
624
|
+
if (c === attrQuote) {
|
|
625
|
+
const value = escape.unescapeXML(endRecording());
|
|
626
|
+
attrs[attrName] = value;
|
|
627
|
+
attrName = void 0;
|
|
628
|
+
state = STATE_TAG;
|
|
629
|
+
}
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (typeof recordStart === "number" && recordStart <= data.length) {
|
|
634
|
+
remainder = data.slice(recordStart);
|
|
635
|
+
recordStart = 0;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
end(data) {
|
|
640
|
+
if (data) {
|
|
641
|
+
this.write(data);
|
|
642
|
+
}
|
|
643
|
+
this.write = function write() {
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
module2.exports = SaxLtx;
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
|
|
29
651
|
// src/index.ts
|
|
30
652
|
var index_exports = {};
|
|
31
653
|
__export(index_exports, {
|
|
@@ -1360,22 +1982,117 @@ var SmuleUrls;
|
|
|
1360
1982
|
]);
|
|
1361
1983
|
})(SmuleUrls || (SmuleUrls = {}));
|
|
1362
1984
|
|
|
1985
|
+
// node_modules/@xmpp/xml/index.js
|
|
1986
|
+
var import_Element2 = __toESM(require_Element(), 1);
|
|
1987
|
+
var import_createElement = __toESM(require_createElement(), 1);
|
|
1988
|
+
var import_escape = __toESM(require_escape(), 1);
|
|
1989
|
+
|
|
1990
|
+
// node_modules/@xmpp/xml/lib/Parser.js
|
|
1991
|
+
var import_ltx = __toESM(require_ltx(), 1);
|
|
1992
|
+
var import_Element = __toESM(require_Element(), 1);
|
|
1993
|
+
|
|
1994
|
+
// node_modules/@xmpp/events/index.js
|
|
1995
|
+
var import_events = require("events");
|
|
1996
|
+
|
|
1997
|
+
// node_modules/@xmpp/xml/lib/XMLError.js
|
|
1998
|
+
var XMLError = class extends Error {
|
|
1999
|
+
constructor(...args) {
|
|
2000
|
+
super(...args);
|
|
2001
|
+
this.name = "XMLError";
|
|
2002
|
+
}
|
|
2003
|
+
};
|
|
2004
|
+
|
|
2005
|
+
// node_modules/@xmpp/xml/lib/Parser.js
|
|
2006
|
+
var Parser = class extends import_events.EventEmitter {
|
|
2007
|
+
constructor() {
|
|
2008
|
+
super();
|
|
2009
|
+
const parser = new import_ltx.default();
|
|
2010
|
+
this.root = null;
|
|
2011
|
+
this.cursor = null;
|
|
2012
|
+
parser.on("startElement", this.onStartElement.bind(this));
|
|
2013
|
+
parser.on("endElement", this.onEndElement.bind(this));
|
|
2014
|
+
parser.on("text", this.onText.bind(this));
|
|
2015
|
+
this.parser = parser;
|
|
2016
|
+
}
|
|
2017
|
+
onStartElement(name, attrs) {
|
|
2018
|
+
const element = new import_Element.default(name, attrs);
|
|
2019
|
+
const { root, cursor } = this;
|
|
2020
|
+
if (!root) {
|
|
2021
|
+
this.root = element;
|
|
2022
|
+
this.emit("start", element);
|
|
2023
|
+
} else if (cursor !== root) {
|
|
2024
|
+
cursor.append(element);
|
|
2025
|
+
}
|
|
2026
|
+
this.cursor = element;
|
|
2027
|
+
}
|
|
2028
|
+
onEndElement(name) {
|
|
2029
|
+
const { root, cursor } = this;
|
|
2030
|
+
if (name !== cursor.name) {
|
|
2031
|
+
this.emit("error", new XMLError(`${cursor.name} must be closed.`));
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
if (cursor === root) {
|
|
2035
|
+
this.emit("end", root);
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
if (!cursor.parent) {
|
|
2039
|
+
cursor.parent = root;
|
|
2040
|
+
this.emit("element", cursor);
|
|
2041
|
+
this.cursor = root;
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
this.cursor = cursor.parent;
|
|
2045
|
+
}
|
|
2046
|
+
onText(str) {
|
|
2047
|
+
const { cursor } = this;
|
|
2048
|
+
if (!cursor) {
|
|
2049
|
+
this.emit("error", new XMLError(`${str} must be a child.`));
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
cursor.t(str);
|
|
2053
|
+
}
|
|
2054
|
+
write(data) {
|
|
2055
|
+
this.parser.write(data);
|
|
2056
|
+
}
|
|
2057
|
+
end(data) {
|
|
2058
|
+
if (data) {
|
|
2059
|
+
this.parser.write(data);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
Parser.XMLError = XMLError;
|
|
2064
|
+
var Parser_default = Parser;
|
|
2065
|
+
|
|
2066
|
+
// node_modules/@xmpp/xml/index.js
|
|
2067
|
+
function xml(...args) {
|
|
2068
|
+
return (0, import_createElement.default)(...args);
|
|
2069
|
+
}
|
|
2070
|
+
Object.assign(xml, {
|
|
2071
|
+
Element: import_Element2.default,
|
|
2072
|
+
createElement: import_createElement.default,
|
|
2073
|
+
Parser: Parser_default,
|
|
2074
|
+
escapeXML: import_escape.escapeXML,
|
|
2075
|
+
unescapeXML: import_escape.unescapeXML,
|
|
2076
|
+
escapeXMLText: import_escape.escapeXMLText,
|
|
2077
|
+
unescapeXMLText: import_escape.unescapeXMLText,
|
|
2078
|
+
XMLError,
|
|
2079
|
+
xml
|
|
2080
|
+
});
|
|
2081
|
+
|
|
1363
2082
|
// src/smule-live-chat.ts
|
|
1364
|
-
var
|
|
1365
|
-
var import_events = __toESM(require("events"), 1);
|
|
2083
|
+
var import_events3 = __toESM(require("events"), 1);
|
|
1366
2084
|
var import_jid = require("@xmpp/jid");
|
|
2085
|
+
var import_crypto2 = require("crypto");
|
|
1367
2086
|
var SmuleLiveChat = class {
|
|
1368
|
-
events = new
|
|
2087
|
+
events = new import_events3.default();
|
|
1369
2088
|
state = "closed";
|
|
1370
2089
|
client;
|
|
1371
2090
|
jid;
|
|
1372
|
-
|
|
1373
|
-
iqHasMore = false;
|
|
1374
|
-
lastIqId = "0";
|
|
2091
|
+
iqs = {};
|
|
1375
2092
|
roomJID = null;
|
|
1376
2093
|
roomUsers = [];
|
|
1377
2094
|
chat = { messages: [] };
|
|
1378
|
-
constructor(userId, session, host = SmuleUrls.
|
|
2095
|
+
constructor(userId, session, host = SmuleUrls.cfireChat, roomJID) {
|
|
1379
2096
|
this.client = (0, import_client.client)({
|
|
1380
2097
|
service: "xmpp://" + host,
|
|
1381
2098
|
domain: host,
|
|
@@ -1423,6 +2140,9 @@ var SmuleLiveChat = class {
|
|
|
1423
2140
|
)
|
|
1424
2141
|
)
|
|
1425
2142
|
);
|
|
2143
|
+
this.sendIqQuery("http://jabber.org/protocol/disco#info", (el) => {
|
|
2144
|
+
console.log("reply from disco", el);
|
|
2145
|
+
});
|
|
1426
2146
|
}
|
|
1427
2147
|
/**
|
|
1428
2148
|
* Disconnects the client from the XMPP server.
|
|
@@ -1434,83 +2154,41 @@ var SmuleLiveChat = class {
|
|
|
1434
2154
|
*/
|
|
1435
2155
|
async disconnect() {
|
|
1436
2156
|
try {
|
|
2157
|
+
await this.client.send((0, import_client.xml)("presence", { type: "unavailable" }));
|
|
1437
2158
|
await this.client.stop();
|
|
1438
2159
|
} catch {
|
|
1439
2160
|
}
|
|
1440
2161
|
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
* active -> You're active
|
|
1446
|
-
*
|
|
1447
|
-
* composing -> Typing
|
|
1448
|
-
*
|
|
1449
|
-
* paused -> Just stopped typing
|
|
1450
|
-
*
|
|
1451
|
-
* inactive -> You're inactive
|
|
1452
|
-
*
|
|
1453
|
-
* gone -> You're hidden / disconnected / You've left the chat
|
|
1454
|
-
*
|
|
1455
|
-
* @param state One of `active`, `composing`, `paused`, `inactive`, or `gone`.
|
|
1456
|
-
* Default is `active`
|
|
1457
|
-
*/
|
|
1458
|
-
async sendChatState(to, state = "active") {
|
|
1459
|
-
if (typeof to != "string" && "accountId" in to) to = this.getJIDFromUserId(to.accountId);
|
|
1460
|
-
await this.client.send(
|
|
2162
|
+
sendIq(data, callback, iqType = "get") {
|
|
2163
|
+
const id = (0, import_crypto2.randomUUID)();
|
|
2164
|
+
this.iqs[id] = callback;
|
|
2165
|
+
this.client.send(
|
|
1461
2166
|
(0, import_client.xml)(
|
|
1462
|
-
"
|
|
1463
|
-
{
|
|
1464
|
-
|
|
1465
|
-
"chatstate",
|
|
1466
|
-
{ xmlns: "http://jabber.org/protocol/chatstates" },
|
|
1467
|
-
state
|
|
1468
|
-
)
|
|
2167
|
+
"iq",
|
|
2168
|
+
{ from: this.jid.toString(), to: this.roomJID, type: iqType, id },
|
|
2169
|
+
data
|
|
1469
2170
|
)
|
|
1470
2171
|
);
|
|
1471
2172
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
* @remarks Filtering by a specific JID may not work yet
|
|
1478
|
-
*/
|
|
1479
|
-
async loadMessageHistory(limit = 50, before = null, after = null, jid) {
|
|
1480
|
-
this._log("Loading live chat history...");
|
|
1481
|
-
this.ongoingIq = true;
|
|
1482
|
-
await this.client.send(
|
|
1483
|
-
(0, import_client.xml)(
|
|
1484
|
-
"iq",
|
|
1485
|
-
{ from: this.jid.toString(), to: this.roomJID, type: "get", id: "meow" },
|
|
1486
|
-
(0, import_client.xml)(
|
|
1487
|
-
"query",
|
|
1488
|
-
{ xmlns: "http://jabber.org/protocol/muc#history" }
|
|
1489
|
-
)
|
|
1490
|
-
)
|
|
2173
|
+
sendIqQuery(xmlns, callback, iqType = "get") {
|
|
2174
|
+
this.sendIq(
|
|
2175
|
+
(0, import_client.xml)("query", { xmlns }),
|
|
2176
|
+
callback,
|
|
2177
|
+
iqType
|
|
1491
2178
|
);
|
|
1492
|
-
while (this.ongoingIq) await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1493
2179
|
}
|
|
1494
2180
|
/**
|
|
1495
|
-
* Send a text message
|
|
1496
|
-
* @param jid The JID to send the message to
|
|
2181
|
+
* Send a text message to the livestream
|
|
1497
2182
|
* @param message The message body
|
|
1498
2183
|
*/
|
|
1499
|
-
async sendTextMessage(
|
|
1500
|
-
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2184
|
+
async sendTextMessage(message) {
|
|
1501
2185
|
await this.client.send(
|
|
1502
2186
|
(0, import_client.xml)(
|
|
1503
2187
|
"message",
|
|
1504
|
-
{ to:
|
|
2188
|
+
{ to: this.roomJID, type: "groupchat" },
|
|
1505
2189
|
(0, import_client.xml)("body", {}, message)
|
|
1506
2190
|
)
|
|
1507
2191
|
);
|
|
1508
|
-
const data = {
|
|
1509
|
-
sender: parseInt(this.jid.getLocal()),
|
|
1510
|
-
content: message
|
|
1511
|
-
};
|
|
1512
|
-
this.chat[this.getUserIdFromJID(jid.toString())].messages.push(data);
|
|
1513
|
-
this.events.emit("message", data);
|
|
1514
2192
|
}
|
|
1515
2193
|
/**
|
|
1516
2194
|
* Read-only jid to prevent any bugs
|
|
@@ -1623,6 +2301,23 @@ var SmuleLiveChat = class {
|
|
|
1623
2301
|
this._log("Got host left!", data2);
|
|
1624
2302
|
this.events.emit("host-left", data2);
|
|
1625
2303
|
}
|
|
2304
|
+
child = el.getChild("song-listen");
|
|
2305
|
+
if (child) {
|
|
2306
|
+
const data2 = {
|
|
2307
|
+
arrKey: child.getChild("arrangement-key").getText(),
|
|
2308
|
+
hostSessionId: child.getChild("host-session-id").getText()
|
|
2309
|
+
};
|
|
2310
|
+
this._log("Got song listen!", data2);
|
|
2311
|
+
this.events.emit("song-listen", data2);
|
|
2312
|
+
}
|
|
2313
|
+
child = el.getChild("campfire-ended");
|
|
2314
|
+
if (child) {
|
|
2315
|
+
const data2 = {
|
|
2316
|
+
reason: child.getChild("reason").getText()
|
|
2317
|
+
};
|
|
2318
|
+
this._log("Got stop livestream!", data2);
|
|
2319
|
+
this.events.emit("stop-livestream", data2);
|
|
2320
|
+
}
|
|
1626
2321
|
child = el.getChild("result");
|
|
1627
2322
|
if (!child) return;
|
|
1628
2323
|
child = child.getChild("forwarded");
|
|
@@ -1646,15 +2341,17 @@ var SmuleLiveChat = class {
|
|
|
1646
2341
|
if (child) {
|
|
1647
2342
|
child = child.getChild("item");
|
|
1648
2343
|
if (child) {
|
|
1649
|
-
if (!el.getAttr("jid"))
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
2344
|
+
if (!el.getAttr("jid")) {
|
|
2345
|
+
} else {
|
|
2346
|
+
const data = {
|
|
2347
|
+
user: this.getUserIdFromJID(el.getAttr("jid")),
|
|
2348
|
+
role: child.getAttr("role"),
|
|
2349
|
+
affiliation: child.getAttr("affiliation")
|
|
2350
|
+
};
|
|
2351
|
+
this._log("Got presence!", data);
|
|
2352
|
+
this.roomUsers.push(data);
|
|
2353
|
+
this.events.emit("presence", data);
|
|
2354
|
+
}
|
|
1658
2355
|
}
|
|
1659
2356
|
}
|
|
1660
2357
|
}
|
|
@@ -1751,22 +2448,11 @@ var SmuleLiveChat = class {
|
|
|
1751
2448
|
this.parsePresence(el);
|
|
1752
2449
|
} else {
|
|
1753
2450
|
if (el.is("iq")) {
|
|
1754
|
-
|
|
1755
|
-
if (
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
child = child.getChild("set");
|
|
1759
|
-
if (child) {
|
|
1760
|
-
child = child.getChild("last");
|
|
1761
|
-
if (child) {
|
|
1762
|
-
this.lastIqId = child.getText();
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1765
|
-
} else {
|
|
1766
|
-
this.iqHasMore = false;
|
|
1767
|
-
}
|
|
2451
|
+
const id = el.getAttr("id");
|
|
2452
|
+
if (id) {
|
|
2453
|
+
this.iqs[id](el);
|
|
2454
|
+
delete this.iqs[id];
|
|
1768
2455
|
}
|
|
1769
|
-
this.ongoingIq = false;
|
|
1770
2456
|
}
|
|
1771
2457
|
this._log("Stanza!", el.toString());
|
|
1772
2458
|
}
|
|
@@ -2200,20 +2886,16 @@ var SmuleMIDI;
|
|
|
2200
2886
|
|
|
2201
2887
|
// src/smule-chat.ts
|
|
2202
2888
|
var import_client2 = require("@xmpp/client");
|
|
2203
|
-
var
|
|
2204
|
-
var import_events2 = __toESM(require("events"), 1);
|
|
2889
|
+
var import_events4 = __toESM(require("events"), 1);
|
|
2205
2890
|
var import_jid2 = require("@xmpp/jid");
|
|
2891
|
+
var import_crypto3 = require("crypto");
|
|
2206
2892
|
var SmuleChat = class {
|
|
2207
|
-
events = new
|
|
2893
|
+
events = new import_events4.default();
|
|
2208
2894
|
state = "closed";
|
|
2209
2895
|
client;
|
|
2210
2896
|
jid;
|
|
2211
|
-
|
|
2212
|
-
iqHasMore = false;
|
|
2213
|
-
lastIqId = "0";
|
|
2214
|
-
isLive = false;
|
|
2897
|
+
iqs = {};
|
|
2215
2898
|
roomJID = null;
|
|
2216
|
-
roomUsers = [];
|
|
2217
2899
|
chats = {};
|
|
2218
2900
|
constructor(userId, session, host = SmuleUrls.userChat, roomJID) {
|
|
2219
2901
|
this.client = (0, import_client2.client)({
|
|
@@ -2224,7 +2906,6 @@ var SmuleChat = class {
|
|
|
2224
2906
|
username: userId + "",
|
|
2225
2907
|
password: session
|
|
2226
2908
|
});
|
|
2227
|
-
this.isLive = host != SmuleUrls.userChat || !!roomJID;
|
|
2228
2909
|
this.roomJID = roomJID;
|
|
2229
2910
|
this.client.on("close", (el) => this.onClose(el));
|
|
2230
2911
|
this.client.on("closing", () => this.onClosing());
|
|
@@ -2247,27 +2928,7 @@ var SmuleChat = class {
|
|
|
2247
2928
|
async connect() {
|
|
2248
2929
|
this.jid = await this.client.start();
|
|
2249
2930
|
this._log("Connected as:", this.jid.getLocal() + "@" + this.jid.getDomain());
|
|
2250
|
-
|
|
2251
|
-
this.client.send((0, import_client2.xml)("presence", {}));
|
|
2252
|
-
} else {
|
|
2253
|
-
this.client.send(
|
|
2254
|
-
(0, import_client2.xml)(
|
|
2255
|
-
"presence",
|
|
2256
|
-
{ to: this.roomJID + "/" + this.jid.getLocal() },
|
|
2257
|
-
(0, import_client2.xml)(
|
|
2258
|
-
"x",
|
|
2259
|
-
{ xmlns: "http://jabber.org/protocol/muc" },
|
|
2260
|
-
(0, import_client2.xml)(
|
|
2261
|
-
"password"
|
|
2262
|
-
),
|
|
2263
|
-
(0, import_client2.xml)(
|
|
2264
|
-
"history",
|
|
2265
|
-
{ maxstanzas: "1" }
|
|
2266
|
-
)
|
|
2267
|
-
)
|
|
2268
|
-
)
|
|
2269
|
-
);
|
|
2270
|
-
}
|
|
2931
|
+
this.client.send((0, import_client2.xml)("presence", {}));
|
|
2271
2932
|
}
|
|
2272
2933
|
/**
|
|
2273
2934
|
* Disconnects the client from the XMPP server.
|
|
@@ -2279,10 +2940,29 @@ var SmuleChat = class {
|
|
|
2279
2940
|
*/
|
|
2280
2941
|
async disconnect() {
|
|
2281
2942
|
try {
|
|
2943
|
+
await this.client.send((0, import_client2.xml)("presence", { type: "unavailable" }));
|
|
2282
2944
|
await this.client.stop();
|
|
2283
2945
|
} catch {
|
|
2284
2946
|
}
|
|
2285
2947
|
}
|
|
2948
|
+
sendIq(data, callback, iqType = "get") {
|
|
2949
|
+
const id = (0, import_crypto3.randomUUID)();
|
|
2950
|
+
this.iqs[id] = callback;
|
|
2951
|
+
this.client.send(
|
|
2952
|
+
(0, import_client2.xml)(
|
|
2953
|
+
"iq",
|
|
2954
|
+
{ from: this.jid.toString(), to: this.roomJID, type: iqType, id },
|
|
2955
|
+
data
|
|
2956
|
+
)
|
|
2957
|
+
);
|
|
2958
|
+
}
|
|
2959
|
+
sendIqQuery(xmlns, callback, iqType = "get") {
|
|
2960
|
+
this.sendIq(
|
|
2961
|
+
(0, import_client2.xml)("query", { xmlns }),
|
|
2962
|
+
callback,
|
|
2963
|
+
iqType
|
|
2964
|
+
);
|
|
2965
|
+
}
|
|
2286
2966
|
/**
|
|
2287
2967
|
* Send a chat state to the server. This is used to
|
|
2288
2968
|
* signal whether you are currently active or not.
|
|
@@ -2322,50 +3002,29 @@ var SmuleChat = class {
|
|
|
2322
3002
|
* @remarks Filtering by a specific JID may not work yet
|
|
2323
3003
|
*/
|
|
2324
3004
|
async loadMessageHistory(limit = 50, before = null, after = null, jid) {
|
|
2325
|
-
if (
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
await this.client.send(
|
|
2335
|
-
(0, import_client2.xml)(
|
|
2336
|
-
"iq",
|
|
2337
|
-
{ type: "set", id: "mam-query" },
|
|
2338
|
-
(0, import_client2.xml)(
|
|
2339
|
-
"query",
|
|
2340
|
-
{ xmlns: "urn:xmpp:mam:2" },
|
|
2341
|
-
(0, import_client2.xml)(
|
|
2342
|
-
"set",
|
|
2343
|
-
{ xmlns: "http://jabber.org/protocol/rsm" },
|
|
2344
|
-
(0, import_client2.xml)("max", {}, limit.toString()),
|
|
2345
|
-
before ? (0, import_client2.xml)("before", {}, before.toString()) : null,
|
|
2346
|
-
after ? (0, import_client2.xml)("after", {}, after.toString()) : null
|
|
2347
|
-
),
|
|
2348
|
-
jid ? (0, import_client2.xml)("with", {}, jid.toString()) : null
|
|
2349
|
-
)
|
|
2350
|
-
)
|
|
2351
|
-
);
|
|
2352
|
-
while (this.ongoingIq) await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2353
|
-
if (this.iqHasMore) await this.loadMessageHistory(limit, null, this.lastIqId, jid);
|
|
2354
|
-
} else {
|
|
2355
|
-
this._log("Loading live chat history...");
|
|
2356
|
-
this.ongoingIq = true;
|
|
2357
|
-
await this.client.send(
|
|
3005
|
+
if (jid)
|
|
3006
|
+
this._log(`Loading ${limit} messages with ${jid}...`);
|
|
3007
|
+
else
|
|
3008
|
+
this._log(`Loading ${limit} messages from history...`);
|
|
3009
|
+
if (!before && !after && !jid) this.chats = {};
|
|
3010
|
+
this.sendIq(
|
|
3011
|
+
(0, import_client2.xml)(
|
|
3012
|
+
"query",
|
|
3013
|
+
{ xmlns: "urn:xmpp:mam:2" },
|
|
2358
3014
|
(0, import_client2.xml)(
|
|
2359
|
-
"
|
|
2360
|
-
{
|
|
2361
|
-
(0, import_client2.xml)(
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
)
|
|
2366
|
-
)
|
|
2367
|
-
|
|
2368
|
-
|
|
3015
|
+
"set",
|
|
3016
|
+
{ xmlns: "http://jabber.org/protocol/rsm" },
|
|
3017
|
+
(0, import_client2.xml)("max", {}, limit.toString()),
|
|
3018
|
+
before ? (0, import_client2.xml)("before", {}, before.toString()) : null,
|
|
3019
|
+
after ? (0, import_client2.xml)("after", {}, after.toString()) : null
|
|
3020
|
+
),
|
|
3021
|
+
jid ? (0, import_client2.xml)("with", {}, jid.toString()) : null
|
|
3022
|
+
),
|
|
3023
|
+
(el) => {
|
|
3024
|
+
this._log("Finished loading history!", el.toString());
|
|
3025
|
+
},
|
|
3026
|
+
"set"
|
|
3027
|
+
);
|
|
2369
3028
|
}
|
|
2370
3029
|
/**
|
|
2371
3030
|
* Send a text message
|
|
@@ -2377,16 +3036,10 @@ var SmuleChat = class {
|
|
|
2377
3036
|
await this.client.send(
|
|
2378
3037
|
(0, import_client2.xml)(
|
|
2379
3038
|
"message",
|
|
2380
|
-
{ to: jid.toString(), type:
|
|
3039
|
+
{ to: jid.toString(), type: "chat" },
|
|
2381
3040
|
(0, import_client2.xml)("body", {}, message)
|
|
2382
3041
|
)
|
|
2383
3042
|
);
|
|
2384
|
-
let data = {
|
|
2385
|
-
sender: parseInt(this.jid.getLocal()),
|
|
2386
|
-
content: message
|
|
2387
|
-
};
|
|
2388
|
-
this.chats[this.getUserIdFromJID(jid.toString())].messages.push(data);
|
|
2389
|
-
this.events.emit("message", data);
|
|
2390
3043
|
}
|
|
2391
3044
|
/**
|
|
2392
3045
|
* Send a performance / recording
|
|
@@ -2426,25 +3079,6 @@ var SmuleChat = class {
|
|
|
2426
3079
|
)
|
|
2427
3080
|
);
|
|
2428
3081
|
}
|
|
2429
|
-
//TODO - Most definitely not required
|
|
2430
|
-
async archiveMessage(jid, message) {
|
|
2431
|
-
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2432
|
-
await this.client.send(
|
|
2433
|
-
(0, import_client2.xml)(
|
|
2434
|
-
"iq",
|
|
2435
|
-
{ type: "set" },
|
|
2436
|
-
(0, import_client2.xml)(
|
|
2437
|
-
"archive",
|
|
2438
|
-
{ xmlns: "urn:xmpp:mam:2" },
|
|
2439
|
-
(0, import_client2.xml)(
|
|
2440
|
-
"item",
|
|
2441
|
-
{ with: jid, id: Math.random().toString(16).substring(2, 8) },
|
|
2442
|
-
(0, import_client2.xml)("body", {}, message)
|
|
2443
|
-
)
|
|
2444
|
-
)
|
|
2445
|
-
)
|
|
2446
|
-
);
|
|
2447
|
-
}
|
|
2448
3082
|
/**
|
|
2449
3083
|
* Read-only jid to prevent any bugs
|
|
2450
3084
|
* @returns user's JID
|
|
@@ -2459,7 +3093,6 @@ var SmuleChat = class {
|
|
|
2459
3093
|
*/
|
|
2460
3094
|
getUserIdFromJID(jid) {
|
|
2461
3095
|
if (!(typeof jid == "string")) return parseInt(jid.getLocal());
|
|
2462
|
-
if (jid.includes("/")) return parseInt(jid.split("/")[1]);
|
|
2463
3096
|
return parseInt(jid.split("@")[0]);
|
|
2464
3097
|
}
|
|
2465
3098
|
/**
|
|
@@ -2469,7 +3102,6 @@ var SmuleChat = class {
|
|
|
2469
3102
|
*/
|
|
2470
3103
|
getJIDFromUserId(userId) {
|
|
2471
3104
|
if (typeof userId != "string" && typeof userId != "number" && "accountId" in userId) userId = userId.accountId;
|
|
2472
|
-
if (this.isLive) return this.roomJID + "/" + userId;
|
|
2473
3105
|
return userId + "@" + this.jid.getDomain();
|
|
2474
3106
|
}
|
|
2475
3107
|
//* Processes all message-like elements
|
|
@@ -2494,7 +3126,6 @@ var SmuleChat = class {
|
|
|
2494
3126
|
}
|
|
2495
3127
|
child = el.getChild("body");
|
|
2496
3128
|
const perfChild = el.getChild("performance");
|
|
2497
|
-
const perfStartChild = el.getChild("performance-start");
|
|
2498
3129
|
if (child && (child.getText().trim().length > 0 || perfChild)) {
|
|
2499
3130
|
this._log("Got message!", child.getText());
|
|
2500
3131
|
let performanceKey2 = void 0;
|
|
@@ -2525,7 +3156,8 @@ var SmuleChat = class {
|
|
|
2525
3156
|
content: child.getText(),
|
|
2526
3157
|
sender: this.getUserIdFromJID(child.parent.getAttr("from")),
|
|
2527
3158
|
id: child.parent.getAttr("id"),
|
|
2528
|
-
performanceKey
|
|
3159
|
+
performanceKey,
|
|
3160
|
+
systemMessage: !!child.parent.getChild("smule-system-msg")
|
|
2529
3161
|
};
|
|
2530
3162
|
let chat = this.jid.getLocal().includes(data.sender + "") ? this.getUserIdFromJID(child.parent.getAttr("to")) : data.sender;
|
|
2531
3163
|
this.events.emit("history", data);
|
|
@@ -2534,25 +3166,6 @@ var SmuleChat = class {
|
|
|
2534
3166
|
}
|
|
2535
3167
|
parsePresence(el) {
|
|
2536
3168
|
if (el.children.length < 1) return;
|
|
2537
|
-
if (this.isLive) {
|
|
2538
|
-
let child = el.getChildByAttr("xmlns", "http://jabber.org/protocol/muc#user");
|
|
2539
|
-
if (child) {
|
|
2540
|
-
child = child.getChild("item");
|
|
2541
|
-
if (child) {
|
|
2542
|
-
if (!el.getAttr("jid")) return;
|
|
2543
|
-
let user = this.getUserIdFromJID(el.getAttr("jid"));
|
|
2544
|
-
let role = child.getAttr("role");
|
|
2545
|
-
let affiliation = child.getAttr("affiliation");
|
|
2546
|
-
let data = {
|
|
2547
|
-
user,
|
|
2548
|
-
role,
|
|
2549
|
-
affiliation
|
|
2550
|
-
};
|
|
2551
|
-
this.roomUsers.push(data);
|
|
2552
|
-
this.events.emit("presence", data);
|
|
2553
|
-
}
|
|
2554
|
-
}
|
|
2555
|
-
}
|
|
2556
3169
|
}
|
|
2557
3170
|
/**
|
|
2558
3171
|
* Fetches the chats currently loaded
|
|
@@ -2570,9 +3183,6 @@ var SmuleChat = class {
|
|
|
2570
3183
|
if (!(user in this.chats)) this.chats[user] = { messages: [] };
|
|
2571
3184
|
return this.chats[user];
|
|
2572
3185
|
}
|
|
2573
|
-
fetchUsers() {
|
|
2574
|
-
return this.roomUsers;
|
|
2575
|
-
}
|
|
2576
3186
|
//#region Internal events
|
|
2577
3187
|
onClose(el) {
|
|
2578
3188
|
this._log("Closed!:", el);
|
|
@@ -2656,22 +3266,11 @@ var SmuleChat = class {
|
|
|
2656
3266
|
this.parsePresence(el);
|
|
2657
3267
|
} else {
|
|
2658
3268
|
if (el.is("iq")) {
|
|
2659
|
-
|
|
2660
|
-
if (
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
child = child.getChild("set");
|
|
2664
|
-
if (child) {
|
|
2665
|
-
child = child.getChild("last");
|
|
2666
|
-
if (child) {
|
|
2667
|
-
this.lastIqId = child.getText();
|
|
2668
|
-
}
|
|
2669
|
-
}
|
|
2670
|
-
} else {
|
|
2671
|
-
this.iqHasMore = false;
|
|
2672
|
-
}
|
|
3269
|
+
const id = el.getAttr("id");
|
|
3270
|
+
if (id) {
|
|
3271
|
+
this.iqs[id](el);
|
|
3272
|
+
delete this.iqs[id];
|
|
2673
3273
|
}
|
|
2674
|
-
this.ongoingIq = false;
|
|
2675
3274
|
}
|
|
2676
3275
|
this._log("Stanza!", el.toString());
|
|
2677
3276
|
}
|
|
@@ -2679,13 +3278,13 @@ var SmuleChat = class {
|
|
|
2679
3278
|
//#endregion Internal events
|
|
2680
3279
|
//#region Logging
|
|
2681
3280
|
_log(...args) {
|
|
2682
|
-
console.log(
|
|
3281
|
+
console.log("[SmuleChat]", ...args);
|
|
2683
3282
|
}
|
|
2684
3283
|
_warn(...args) {
|
|
2685
|
-
console.warn(
|
|
3284
|
+
console.warn("[SmuleChat]", ...args);
|
|
2686
3285
|
}
|
|
2687
3286
|
_error(...args) {
|
|
2688
|
-
console.error(
|
|
3287
|
+
console.error("[SmuleChat]", ...args);
|
|
2689
3288
|
}
|
|
2690
3289
|
//#endregion Logging
|
|
2691
3290
|
};
|
|
@@ -2694,7 +3293,7 @@ var SmuleChat = class {
|
|
|
2694
3293
|
var import_fs = require("fs");
|
|
2695
3294
|
var crypto = __toESM(require("crypto"), 1);
|
|
2696
3295
|
var import_jid3 = require("@xmpp/jid");
|
|
2697
|
-
var APP_VERSION = "12.
|
|
3296
|
+
var APP_VERSION = "12.6.9";
|
|
2698
3297
|
var SmuleDigest;
|
|
2699
3298
|
((SmuleDigest2) => {
|
|
2700
3299
|
const SALT = `c2250918de500e32c37842f2d25d4d8210992a0ae96a7f36c4c9703cc675d02b92968bc4fa7feada`;
|
|
@@ -3238,13 +3837,37 @@ var Smule = class {
|
|
|
3238
3837
|
* Creates a new spark chat
|
|
3239
3838
|
* @param address The JID address of the chat partner
|
|
3240
3839
|
* @param type Whether the JID address is an individual or a group
|
|
3241
|
-
* @returns idk
|
|
3242
3840
|
*/
|
|
3243
3841
|
create: async (address, type = "ACCT") => {
|
|
3244
3842
|
const req = await this.internal._createRequest(SmuleUrls.SparkChatUpdate, { add: [{ name: address, type }], remove: [] });
|
|
3843
|
+
this.internal._handleNon200(req);
|
|
3844
|
+
},
|
|
3845
|
+
/**
|
|
3846
|
+
* Deletes an existing spark chat
|
|
3847
|
+
* @param address The JID address of the chat partner
|
|
3848
|
+
* @param type Whether the JID address is an individual or a group
|
|
3849
|
+
*/
|
|
3850
|
+
delete: async (address, type = "ACCT") => {
|
|
3851
|
+
const req = await this.internal._createRequest(SmuleUrls.SparkChatUpdate, { remove: [{ name: address, type }], add: [] });
|
|
3852
|
+
this.internal._handleNon200(req);
|
|
3853
|
+
},
|
|
3854
|
+
/**
|
|
3855
|
+
* Fetches your existing chats
|
|
3856
|
+
* @param type Whether an individual or a group
|
|
3857
|
+
* @returns Your inbox and your message requests
|
|
3858
|
+
*/
|
|
3859
|
+
fetchInboxes: async (type = "ACCT") => {
|
|
3860
|
+
const req = await this.internal._createRequest(SmuleUrls.SparkChatList, { type, limit: 200 });
|
|
3245
3861
|
if (!this.internal._handleNon200(req)) return;
|
|
3246
3862
|
return this.internal._getResponseData(req);
|
|
3247
3863
|
},
|
|
3864
|
+
/**
|
|
3865
|
+
* Marks you as offline to your chats
|
|
3866
|
+
*/
|
|
3867
|
+
markOffline: async () => {
|
|
3868
|
+
const req = await this.internal._createRequest(SmuleUrls.SparkChatOffline, {});
|
|
3869
|
+
this.internal._handleNon200(req);
|
|
3870
|
+
},
|
|
3248
3871
|
/**
|
|
3249
3872
|
* Creates a connection to the XMPP chat server
|
|
3250
3873
|
*/
|
|
@@ -4415,9 +5038,9 @@ var Smule = class {
|
|
|
4415
5038
|
* @param to The user to send the message to
|
|
4416
5039
|
* @param message The message body
|
|
4417
5040
|
*/
|
|
4418
|
-
sendTextMessage: async (
|
|
5041
|
+
sendTextMessage: async (message) => {
|
|
4419
5042
|
if (!this.liveChatSession) return;
|
|
4420
|
-
await this.liveChatSession.sendTextMessage(
|
|
5043
|
+
await this.liveChatSession.sendTextMessage(message);
|
|
4421
5044
|
},
|
|
4422
5045
|
/**
|
|
4423
5046
|
* Fetch all loaded chats
|
|
@@ -4430,27 +5053,47 @@ var Smule = class {
|
|
|
4430
5053
|
fetchUsers: () => {
|
|
4431
5054
|
if (!this.liveChatSession) return;
|
|
4432
5055
|
return this.liveChatSession.fetchUsers();
|
|
4433
|
-
},
|
|
4434
|
-
/**
|
|
4435
|
-
* Loads the entire message history
|
|
4436
|
-
* @param limit How many messages
|
|
4437
|
-
* @param before Messages before this
|
|
4438
|
-
* @param after Messages after this
|
|
4439
|
-
* @param user The chat partner
|
|
4440
|
-
*
|
|
4441
|
-
* @remarks This currently recurses until it loads ALL archived messages.
|
|
4442
|
-
* This means that it will take a long time to load all messages.
|
|
4443
|
-
* @remarks Filtering by a specific user may not work yet
|
|
4444
|
-
*/
|
|
4445
|
-
loadMessageHistory: async (limit = 50, before = null, after = null, user) => {
|
|
4446
|
-
if (!this.liveChatSession) return;
|
|
4447
|
-
await this.liveChatSession.loadMessageHistory(limit, before, after, user);
|
|
4448
5056
|
}
|
|
4449
5057
|
},
|
|
5058
|
+
/**
|
|
5059
|
+
* Fetches ("syncs") a livestream (campfire) so you can connect to it
|
|
5060
|
+
*
|
|
5061
|
+
* @param campfireId The campfire's id
|
|
5062
|
+
* @returns Data regarding the campfire and the streaming details
|
|
5063
|
+
*/
|
|
4450
5064
|
fetch: async (campfireId) => {
|
|
4451
5065
|
const req = await this.internal._createRequest(SmuleUrls.CfireSync, { campfireId });
|
|
4452
5066
|
if (!this.internal._handleNon200(req)) return;
|
|
4453
5067
|
return this.internal._getResponseData(req);
|
|
5068
|
+
},
|
|
5069
|
+
/**
|
|
5070
|
+
* Fetches gifts that have been sent to a live
|
|
5071
|
+
*
|
|
5072
|
+
* @param campfireId The campfire's id
|
|
5073
|
+
* @param cursor The starting point
|
|
5074
|
+
* @param limit How many results
|
|
5075
|
+
* @returns A list of gifts data
|
|
5076
|
+
*/
|
|
5077
|
+
fetchRecentGifts: async (campfireId, cursor = "start", limit = 10) => {
|
|
5078
|
+
const req = await this.internal._createRequest(SmuleUrls.GiftRecentTransactions, { campfireId, cursor, limit, animationVersion: "V2", extraGiftTypes: ["SYSTEM"], previewVersion: "PNG", type: "CFIRE" });
|
|
5079
|
+
if (!this.internal._handleNon200(req)) return;
|
|
5080
|
+
return this.internal._getResponseData(req);
|
|
5081
|
+
},
|
|
5082
|
+
/**
|
|
5083
|
+
* Sign up as available to sing
|
|
5084
|
+
* @param campfireId The livestream's id
|
|
5085
|
+
*/
|
|
5086
|
+
joinToSing: async (campfireId) => {
|
|
5087
|
+
const req = await this.internal._createRequest(SmuleUrls.CfireSignupAdd, { campfireId, message: "I'm available to sing" });
|
|
5088
|
+
this.internal._handleNon200(req);
|
|
5089
|
+
},
|
|
5090
|
+
/**
|
|
5091
|
+
* Revoke your availability to sing
|
|
5092
|
+
* @param campfireId The livestream's id
|
|
5093
|
+
*/
|
|
5094
|
+
revokeJoinToSing: async (campfireId) => {
|
|
5095
|
+
const req = await this.internal._createRequest(SmuleUrls.CfireSignupRemove, { campfireId });
|
|
5096
|
+
this.internal._handleNon200(req);
|
|
4454
5097
|
}
|
|
4455
5098
|
};
|
|
4456
5099
|
groups = {
|