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.js
CHANGED
|
@@ -1,3 +1,654 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
14
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
// node_modules/ltx/lib/escape.js
|
|
34
|
+
var require_escape = __commonJS({
|
|
35
|
+
"node_modules/ltx/lib/escape.js"(exports) {
|
|
36
|
+
"use strict";
|
|
37
|
+
var escapeXMLTable = {
|
|
38
|
+
"&": "&",
|
|
39
|
+
"<": "<",
|
|
40
|
+
">": ">",
|
|
41
|
+
'"': """,
|
|
42
|
+
"'": "'"
|
|
43
|
+
};
|
|
44
|
+
function escapeXMLReplace(match) {
|
|
45
|
+
return escapeXMLTable[match];
|
|
46
|
+
}
|
|
47
|
+
var unescapeXMLTable = {
|
|
48
|
+
"&": "&",
|
|
49
|
+
"<": "<",
|
|
50
|
+
">": ">",
|
|
51
|
+
""": '"',
|
|
52
|
+
"'": "'"
|
|
53
|
+
};
|
|
54
|
+
function unescapeXMLReplace(match) {
|
|
55
|
+
if (match[1] === "#") {
|
|
56
|
+
const num = match[2] === "x" ? parseInt(match.slice(3), 16) : parseInt(match.slice(2), 10);
|
|
57
|
+
if (num === 9 || num === 10 || num === 13 || num >= 32 && num <= 55295 || num >= 57344 && num <= 65533 || num >= 65536 && num <= 1114111) {
|
|
58
|
+
return String.fromCodePoint(num);
|
|
59
|
+
}
|
|
60
|
+
throw new Error("Illegal XML character 0x" + num.toString(16));
|
|
61
|
+
}
|
|
62
|
+
if (unescapeXMLTable[match]) {
|
|
63
|
+
return unescapeXMLTable[match] || match;
|
|
64
|
+
}
|
|
65
|
+
throw new Error("Illegal XML entity " + match);
|
|
66
|
+
}
|
|
67
|
+
function escapeXML2(s) {
|
|
68
|
+
return s.replace(/["&'<>]/g, escapeXMLReplace);
|
|
69
|
+
}
|
|
70
|
+
function unescapeXML2(s) {
|
|
71
|
+
let result = "";
|
|
72
|
+
let start = -1;
|
|
73
|
+
let end = -1;
|
|
74
|
+
let previous = 0;
|
|
75
|
+
while ((start = s.indexOf("&", previous)) !== -1 && (end = s.indexOf(";", start + 1)) !== -1) {
|
|
76
|
+
result = result + s.slice(previous, start) + unescapeXMLReplace(s.slice(start, end + 1));
|
|
77
|
+
previous = end + 1;
|
|
78
|
+
}
|
|
79
|
+
if (previous === 0) return s;
|
|
80
|
+
result = result + s.substring(previous);
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
function escapeXMLText2(s) {
|
|
84
|
+
return s.replace(/[&<>]/g, escapeXMLReplace);
|
|
85
|
+
}
|
|
86
|
+
function unescapeXMLText2(s) {
|
|
87
|
+
return s.replace(/&(amp|#38|lt|#60|gt|#62);/g, unescapeXMLReplace);
|
|
88
|
+
}
|
|
89
|
+
exports.escapeXML = escapeXML2;
|
|
90
|
+
exports.escapeXMLText = escapeXMLText2;
|
|
91
|
+
exports.unescapeXML = unescapeXML2;
|
|
92
|
+
exports.unescapeXMLText = unescapeXMLText2;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// node_modules/ltx/lib/Element.js
|
|
97
|
+
var require_Element = __commonJS({
|
|
98
|
+
"node_modules/ltx/lib/Element.js"(exports, module) {
|
|
99
|
+
"use strict";
|
|
100
|
+
var escape = require_escape();
|
|
101
|
+
var Element5 = class _Element {
|
|
102
|
+
constructor(name, attrs) {
|
|
103
|
+
this.name = name;
|
|
104
|
+
this.parent = null;
|
|
105
|
+
this.children = [];
|
|
106
|
+
this.attrs = {};
|
|
107
|
+
this.setAttrs(attrs);
|
|
108
|
+
}
|
|
109
|
+
/* Accessors */
|
|
110
|
+
/**
|
|
111
|
+
* if (element.is('message', 'jabber:client')) ...
|
|
112
|
+
**/
|
|
113
|
+
is(name, xmlns) {
|
|
114
|
+
return this.getName() === name && (!xmlns || this.getNS() === xmlns);
|
|
115
|
+
}
|
|
116
|
+
/* without prefix */
|
|
117
|
+
getName() {
|
|
118
|
+
const idx = this.name.indexOf(":");
|
|
119
|
+
return idx >= 0 ? this.name.slice(idx + 1) : this.name;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* retrieves the namespace of the current element, upwards recursively
|
|
123
|
+
**/
|
|
124
|
+
getNS() {
|
|
125
|
+
const idx = this.name.indexOf(":");
|
|
126
|
+
if (idx >= 0) {
|
|
127
|
+
const prefix = this.name.slice(0, idx);
|
|
128
|
+
return this.findNS(prefix);
|
|
129
|
+
}
|
|
130
|
+
return this.findNS();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* find the namespace to the given prefix, upwards recursively
|
|
134
|
+
**/
|
|
135
|
+
findNS(prefix) {
|
|
136
|
+
if (!prefix) {
|
|
137
|
+
if (this.attrs.xmlns) {
|
|
138
|
+
return this.attrs.xmlns;
|
|
139
|
+
} else if (this.parent) {
|
|
140
|
+
return this.parent.findNS();
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
const attr = "xmlns:" + prefix;
|
|
144
|
+
if (this.attrs[attr]) {
|
|
145
|
+
return this.attrs[attr];
|
|
146
|
+
} else if (this.parent) {
|
|
147
|
+
return this.parent.findNS(prefix);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Recursiverly gets all xmlns defined, in the form of {url:prefix}
|
|
153
|
+
**/
|
|
154
|
+
getXmlns() {
|
|
155
|
+
let namespaces = {};
|
|
156
|
+
if (this.parent) {
|
|
157
|
+
namespaces = this.parent.getXmlns();
|
|
158
|
+
}
|
|
159
|
+
for (const attr in this.attrs) {
|
|
160
|
+
const m = attr.match("xmlns:?(.*)");
|
|
161
|
+
if (this.attrs.hasOwnProperty(attr) && m) {
|
|
162
|
+
namespaces[this.attrs[attr]] = m[1];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return namespaces;
|
|
166
|
+
}
|
|
167
|
+
setAttrs(attrs) {
|
|
168
|
+
if (typeof attrs === "string") {
|
|
169
|
+
this.attrs.xmlns = attrs;
|
|
170
|
+
} else if (attrs) {
|
|
171
|
+
Object.assign(this.attrs, attrs);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* xmlns can be null, returns the matching attribute.
|
|
176
|
+
**/
|
|
177
|
+
getAttr(name, xmlns) {
|
|
178
|
+
if (!xmlns) {
|
|
179
|
+
return this.attrs[name];
|
|
180
|
+
}
|
|
181
|
+
const namespaces = this.getXmlns();
|
|
182
|
+
if (!namespaces[xmlns]) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
return this.attrs[[namespaces[xmlns], name].join(":")];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* xmlns can be null
|
|
189
|
+
**/
|
|
190
|
+
getChild(name, xmlns) {
|
|
191
|
+
return this.getChildren(name, xmlns)[0];
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* xmlns can be null
|
|
195
|
+
**/
|
|
196
|
+
getChildren(name, xmlns) {
|
|
197
|
+
const result = [];
|
|
198
|
+
for (const child of this.children) {
|
|
199
|
+
if (child.getName && child.getName() === name && (!xmlns || child.getNS() === xmlns)) {
|
|
200
|
+
result.push(child);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* xmlns and recursive can be null
|
|
207
|
+
**/
|
|
208
|
+
getChildByAttr(attr, val, xmlns, recursive) {
|
|
209
|
+
return this.getChildrenByAttr(attr, val, xmlns, recursive)[0];
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* xmlns and recursive can be null
|
|
213
|
+
**/
|
|
214
|
+
getChildrenByAttr(attr, val, xmlns, recursive) {
|
|
215
|
+
let result = [];
|
|
216
|
+
for (const child of this.children) {
|
|
217
|
+
if (child.attrs && child.attrs[attr] === val && (!xmlns || child.getNS() === xmlns)) {
|
|
218
|
+
result.push(child);
|
|
219
|
+
}
|
|
220
|
+
if (recursive && child.getChildrenByAttr) {
|
|
221
|
+
result.push(child.getChildrenByAttr(attr, val, xmlns, true));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (recursive) {
|
|
225
|
+
result = result.flat();
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
getChildrenByFilter(filter, recursive) {
|
|
230
|
+
let result = [];
|
|
231
|
+
for (const child of this.children) {
|
|
232
|
+
if (filter(child)) {
|
|
233
|
+
result.push(child);
|
|
234
|
+
}
|
|
235
|
+
if (recursive && child.getChildrenByFilter) {
|
|
236
|
+
result.push(child.getChildrenByFilter(filter, true));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (recursive) {
|
|
240
|
+
result = result.flat();
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
getText() {
|
|
245
|
+
let text = "";
|
|
246
|
+
for (const child of this.children) {
|
|
247
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
248
|
+
text += child;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return text;
|
|
252
|
+
}
|
|
253
|
+
getChildText(name, xmlns) {
|
|
254
|
+
const child = this.getChild(name, xmlns);
|
|
255
|
+
return child ? child.getText() : null;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Return all direct descendents that are Elements.
|
|
259
|
+
* This differs from `getChildren` in that it will exclude text nodes,
|
|
260
|
+
* processing instructions, etc.
|
|
261
|
+
*/
|
|
262
|
+
getChildElements() {
|
|
263
|
+
return this.getChildrenByFilter((child) => {
|
|
264
|
+
return child instanceof _Element;
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
/* Builder */
|
|
268
|
+
/** returns uppermost parent */
|
|
269
|
+
root() {
|
|
270
|
+
if (this.parent) {
|
|
271
|
+
return this.parent.root();
|
|
272
|
+
}
|
|
273
|
+
return this;
|
|
274
|
+
}
|
|
275
|
+
/** just parent or itself */
|
|
276
|
+
up() {
|
|
277
|
+
if (this.parent) {
|
|
278
|
+
return this.parent;
|
|
279
|
+
}
|
|
280
|
+
return this;
|
|
281
|
+
}
|
|
282
|
+
/** create child node and return it */
|
|
283
|
+
c(name, attrs) {
|
|
284
|
+
return this.cnode(new _Element(name, attrs));
|
|
285
|
+
}
|
|
286
|
+
cnode(child) {
|
|
287
|
+
this.children.push(child);
|
|
288
|
+
if (typeof child === "object") {
|
|
289
|
+
child.parent = this;
|
|
290
|
+
}
|
|
291
|
+
return child;
|
|
292
|
+
}
|
|
293
|
+
append(...nodes) {
|
|
294
|
+
for (const node of nodes) {
|
|
295
|
+
this.children.push(node);
|
|
296
|
+
if (typeof node === "object") {
|
|
297
|
+
node.parent = this;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
prepend(...nodes) {
|
|
302
|
+
for (const node of nodes) {
|
|
303
|
+
this.children.unshift(node);
|
|
304
|
+
if (typeof node === "object") {
|
|
305
|
+
node.parent = this;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** add text node and return element */
|
|
310
|
+
t(text) {
|
|
311
|
+
this.children.push(text);
|
|
312
|
+
return this;
|
|
313
|
+
}
|
|
314
|
+
/* Manipulation */
|
|
315
|
+
/**
|
|
316
|
+
* Either:
|
|
317
|
+
* el.remove(childEl)
|
|
318
|
+
* el.remove('author', 'urn:...')
|
|
319
|
+
*/
|
|
320
|
+
remove(el, xmlns) {
|
|
321
|
+
const filter = typeof el === "string" ? (child) => {
|
|
322
|
+
return !(child.is && child.is(el, xmlns));
|
|
323
|
+
} : (child) => {
|
|
324
|
+
return child !== el;
|
|
325
|
+
};
|
|
326
|
+
this.children = this.children.filter(filter);
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
text(val) {
|
|
330
|
+
if (val && this.children.length === 1) {
|
|
331
|
+
this.children[0] = val;
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
return this.getText();
|
|
335
|
+
}
|
|
336
|
+
attr(attr, val) {
|
|
337
|
+
if (typeof val !== "undefined" || val === null) {
|
|
338
|
+
if (!this.attrs) {
|
|
339
|
+
this.attrs = {};
|
|
340
|
+
}
|
|
341
|
+
this.attrs[attr] = val;
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
return this.attrs[attr];
|
|
345
|
+
}
|
|
346
|
+
/* Serialization */
|
|
347
|
+
toString() {
|
|
348
|
+
let s = "";
|
|
349
|
+
this.write((c) => {
|
|
350
|
+
s += c;
|
|
351
|
+
});
|
|
352
|
+
return s;
|
|
353
|
+
}
|
|
354
|
+
_addChildren(writer) {
|
|
355
|
+
writer(">");
|
|
356
|
+
for (const child of this.children) {
|
|
357
|
+
if (child != null) {
|
|
358
|
+
if (child.write) {
|
|
359
|
+
child.write(writer);
|
|
360
|
+
} else if (typeof child === "string") {
|
|
361
|
+
writer(escape.escapeXMLText(child));
|
|
362
|
+
} else if (child.toString) {
|
|
363
|
+
writer(escape.escapeXMLText(child.toString(10)));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
writer("</");
|
|
368
|
+
writer(this.name);
|
|
369
|
+
writer(">");
|
|
370
|
+
}
|
|
371
|
+
write(writer) {
|
|
372
|
+
writer("<");
|
|
373
|
+
writer(this.name);
|
|
374
|
+
for (const k in this.attrs) {
|
|
375
|
+
const v = this.attrs[k];
|
|
376
|
+
if (v != null) {
|
|
377
|
+
writer(" ");
|
|
378
|
+
writer(k);
|
|
379
|
+
writer('="');
|
|
380
|
+
writer(escape.escapeXML(typeof v === "string" ? v : v.toString(10)));
|
|
381
|
+
writer('"');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (this.children.length === 0) {
|
|
385
|
+
writer("/>");
|
|
386
|
+
} else {
|
|
387
|
+
this._addChildren(writer);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
Element5.prototype.tree = Element5.prototype.root;
|
|
392
|
+
module.exports = Element5;
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// node_modules/ltx/lib/createElement.js
|
|
397
|
+
var require_createElement = __commonJS({
|
|
398
|
+
"node_modules/ltx/lib/createElement.js"(exports, module) {
|
|
399
|
+
"use strict";
|
|
400
|
+
var Element5 = require_Element();
|
|
401
|
+
function append(el, child) {
|
|
402
|
+
if (Array.isArray(child)) {
|
|
403
|
+
for (const c of child) append(el, c);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (child === "" || child == null || child === true || child === false) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
el.cnode(child);
|
|
410
|
+
}
|
|
411
|
+
function createElement2(name, attrs, ...children) {
|
|
412
|
+
if (typeof attrs === "object" && attrs !== null) {
|
|
413
|
+
delete attrs.__source;
|
|
414
|
+
delete attrs.__self;
|
|
415
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
416
|
+
if (value == null) delete attrs[key];
|
|
417
|
+
else attrs[key] = value.toString(10);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const el = new Element5(name, attrs);
|
|
421
|
+
for (const child of children) {
|
|
422
|
+
append(el, child);
|
|
423
|
+
}
|
|
424
|
+
return el;
|
|
425
|
+
}
|
|
426
|
+
module.exports = createElement2;
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// node_modules/ltx/lib/parsers/ltx.js
|
|
431
|
+
var require_ltx = __commonJS({
|
|
432
|
+
"node_modules/ltx/lib/parsers/ltx.js"(exports, module) {
|
|
433
|
+
"use strict";
|
|
434
|
+
var events = __require("events");
|
|
435
|
+
var escape = require_escape();
|
|
436
|
+
var STATE_TEXT = 0;
|
|
437
|
+
var STATE_IGNORE_COMMENT = 1;
|
|
438
|
+
var STATE_IGNORE_INSTRUCTION = 2;
|
|
439
|
+
var STATE_TAG_NAME = 3;
|
|
440
|
+
var STATE_TAG = 4;
|
|
441
|
+
var STATE_ATTR_NAME = 5;
|
|
442
|
+
var STATE_ATTR_EQ = 6;
|
|
443
|
+
var STATE_ATTR_QUOT = 7;
|
|
444
|
+
var STATE_ATTR_VALUE = 8;
|
|
445
|
+
var STATE_CDATA = 9;
|
|
446
|
+
var STATE_IGNORE_CDATA = 10;
|
|
447
|
+
var SaxLtx = class extends events.EventEmitter {
|
|
448
|
+
constructor() {
|
|
449
|
+
super();
|
|
450
|
+
let state = STATE_TEXT;
|
|
451
|
+
let remainder;
|
|
452
|
+
let parseRemainder;
|
|
453
|
+
let tagName;
|
|
454
|
+
let attrs;
|
|
455
|
+
let endTag;
|
|
456
|
+
let selfClosing;
|
|
457
|
+
let attrQuote;
|
|
458
|
+
let attrQuoteChar;
|
|
459
|
+
let recordStart = 0;
|
|
460
|
+
let attrName;
|
|
461
|
+
this._handleTagOpening = function _handleTagOpening(endTag2, tagName2, attrs2) {
|
|
462
|
+
if (!endTag2) {
|
|
463
|
+
this.emit("startElement", tagName2, attrs2);
|
|
464
|
+
if (selfClosing) {
|
|
465
|
+
this.emit("endElement", tagName2, true);
|
|
466
|
+
}
|
|
467
|
+
} else {
|
|
468
|
+
this.emit("endElement", tagName2, false);
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
this.write = function write(data) {
|
|
472
|
+
if (typeof data !== "string") {
|
|
473
|
+
data = data.toString();
|
|
474
|
+
}
|
|
475
|
+
let pos = 0;
|
|
476
|
+
if (remainder) {
|
|
477
|
+
data = remainder + data;
|
|
478
|
+
pos += !parseRemainder ? remainder.length : 0;
|
|
479
|
+
parseRemainder = false;
|
|
480
|
+
remainder = null;
|
|
481
|
+
}
|
|
482
|
+
function endRecording() {
|
|
483
|
+
if (typeof recordStart === "number") {
|
|
484
|
+
const recorded = data.slice(recordStart, pos);
|
|
485
|
+
recordStart = void 0;
|
|
486
|
+
return recorded;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
for (; pos < data.length; pos++) {
|
|
490
|
+
switch (state) {
|
|
491
|
+
case STATE_TEXT: {
|
|
492
|
+
const lt = data.indexOf("<", pos);
|
|
493
|
+
if (lt !== -1 && pos !== lt) {
|
|
494
|
+
pos = lt;
|
|
495
|
+
}
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
case STATE_ATTR_VALUE: {
|
|
499
|
+
const quot = data.indexOf(attrQuoteChar, pos);
|
|
500
|
+
if (quot !== -1) {
|
|
501
|
+
pos = quot;
|
|
502
|
+
}
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
case STATE_IGNORE_COMMENT: {
|
|
506
|
+
const endcomment = data.indexOf("-->", pos);
|
|
507
|
+
if (endcomment !== -1) {
|
|
508
|
+
pos = endcomment + 2;
|
|
509
|
+
}
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
case STATE_IGNORE_CDATA: {
|
|
513
|
+
const endCDATA = data.indexOf("]]>", pos);
|
|
514
|
+
if (endCDATA !== -1) {
|
|
515
|
+
pos = endCDATA + 2;
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const c = data.charCodeAt(pos);
|
|
521
|
+
switch (state) {
|
|
522
|
+
case STATE_TEXT:
|
|
523
|
+
if (c === 60) {
|
|
524
|
+
const text = endRecording();
|
|
525
|
+
if (text) {
|
|
526
|
+
this.emit("text", escape.unescapeXML(text));
|
|
527
|
+
}
|
|
528
|
+
state = STATE_TAG_NAME;
|
|
529
|
+
recordStart = pos + 1;
|
|
530
|
+
attrs = {};
|
|
531
|
+
}
|
|
532
|
+
break;
|
|
533
|
+
case STATE_CDATA:
|
|
534
|
+
if (c === 93) {
|
|
535
|
+
if (data.substr(pos + 1, 2) === "]>") {
|
|
536
|
+
const cData = endRecording();
|
|
537
|
+
if (cData) {
|
|
538
|
+
this.emit("text", cData);
|
|
539
|
+
}
|
|
540
|
+
state = STATE_TEXT;
|
|
541
|
+
} else if (data.length < pos + 2) {
|
|
542
|
+
parseRemainder = true;
|
|
543
|
+
pos = data.length;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
break;
|
|
547
|
+
case STATE_TAG_NAME:
|
|
548
|
+
if (c === 47 && recordStart === pos) {
|
|
549
|
+
recordStart = pos + 1;
|
|
550
|
+
endTag = true;
|
|
551
|
+
} else if (c === 33) {
|
|
552
|
+
if (data.substr(pos + 1, 7) === "[CDATA[") {
|
|
553
|
+
recordStart = pos + 8;
|
|
554
|
+
state = STATE_CDATA;
|
|
555
|
+
} else if (data.length < pos + 8 && "[CDATA[".startsWith(data.slice(pos + 1))) {
|
|
556
|
+
parseRemainder = true;
|
|
557
|
+
pos = data.length;
|
|
558
|
+
} else {
|
|
559
|
+
recordStart = void 0;
|
|
560
|
+
state = STATE_IGNORE_COMMENT;
|
|
561
|
+
}
|
|
562
|
+
} else if (c === 63) {
|
|
563
|
+
recordStart = void 0;
|
|
564
|
+
state = STATE_IGNORE_INSTRUCTION;
|
|
565
|
+
} else if (c <= 32 || c === 47 || c === 62) {
|
|
566
|
+
tagName = endRecording();
|
|
567
|
+
pos--;
|
|
568
|
+
state = STATE_TAG;
|
|
569
|
+
}
|
|
570
|
+
break;
|
|
571
|
+
case STATE_IGNORE_COMMENT:
|
|
572
|
+
if (c === 62) {
|
|
573
|
+
const prevFirst = data.charCodeAt(pos - 1);
|
|
574
|
+
const prevSecond = data.charCodeAt(pos - 2);
|
|
575
|
+
if (prevFirst === 45 && prevSecond === 45 || prevFirst === 93 && prevSecond === 93) {
|
|
576
|
+
state = STATE_TEXT;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
break;
|
|
580
|
+
case STATE_IGNORE_INSTRUCTION:
|
|
581
|
+
if (c === 62) {
|
|
582
|
+
const prev = data.charCodeAt(pos - 1);
|
|
583
|
+
if (prev === 63) {
|
|
584
|
+
state = STATE_TEXT;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
break;
|
|
588
|
+
case STATE_TAG:
|
|
589
|
+
if (c === 62) {
|
|
590
|
+
this._handleTagOpening(endTag, tagName, attrs);
|
|
591
|
+
tagName = void 0;
|
|
592
|
+
attrs = void 0;
|
|
593
|
+
endTag = void 0;
|
|
594
|
+
selfClosing = void 0;
|
|
595
|
+
state = STATE_TEXT;
|
|
596
|
+
recordStart = pos + 1;
|
|
597
|
+
} else if (c === 47) {
|
|
598
|
+
selfClosing = true;
|
|
599
|
+
} else if (c > 32) {
|
|
600
|
+
recordStart = pos;
|
|
601
|
+
state = STATE_ATTR_NAME;
|
|
602
|
+
}
|
|
603
|
+
break;
|
|
604
|
+
case STATE_ATTR_NAME:
|
|
605
|
+
if (c <= 32 || c === 61) {
|
|
606
|
+
attrName = endRecording();
|
|
607
|
+
pos--;
|
|
608
|
+
state = STATE_ATTR_EQ;
|
|
609
|
+
}
|
|
610
|
+
break;
|
|
611
|
+
case STATE_ATTR_EQ:
|
|
612
|
+
if (c === 61) {
|
|
613
|
+
state = STATE_ATTR_QUOT;
|
|
614
|
+
}
|
|
615
|
+
break;
|
|
616
|
+
case STATE_ATTR_QUOT:
|
|
617
|
+
if (c === 34 || c === 39) {
|
|
618
|
+
attrQuote = c;
|
|
619
|
+
attrQuoteChar = c === 34 ? '"' : "'";
|
|
620
|
+
state = STATE_ATTR_VALUE;
|
|
621
|
+
recordStart = pos + 1;
|
|
622
|
+
}
|
|
623
|
+
break;
|
|
624
|
+
case STATE_ATTR_VALUE:
|
|
625
|
+
if (c === attrQuote) {
|
|
626
|
+
const value = escape.unescapeXML(endRecording());
|
|
627
|
+
attrs[attrName] = value;
|
|
628
|
+
attrName = void 0;
|
|
629
|
+
state = STATE_TAG;
|
|
630
|
+
}
|
|
631
|
+
break;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (typeof recordStart === "number" && recordStart <= data.length) {
|
|
635
|
+
remainder = data.slice(recordStart);
|
|
636
|
+
recordStart = 0;
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
end(data) {
|
|
641
|
+
if (data) {
|
|
642
|
+
this.write(data);
|
|
643
|
+
}
|
|
644
|
+
this.write = function write() {
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
module.exports = SaxLtx;
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
|
|
1
652
|
// src/types/smule-requests.ts
|
|
2
653
|
import { randomUUID } from "crypto";
|
|
3
654
|
var Device = class {
|
|
@@ -664,7 +1315,7 @@ var SmuleUtil;
|
|
|
664
1315
|
import axios from "axios";
|
|
665
1316
|
|
|
666
1317
|
// src/smule-live-chat.ts
|
|
667
|
-
import { client, xml } from "@xmpp/client";
|
|
1318
|
+
import { client, xml as xml2 } from "@xmpp/client";
|
|
668
1319
|
|
|
669
1320
|
// src/smule-urls.ts
|
|
670
1321
|
var SmuleUrls;
|
|
@@ -1297,22 +1948,117 @@ var SmuleUrls;
|
|
|
1297
1948
|
]);
|
|
1298
1949
|
})(SmuleUrls || (SmuleUrls = {}));
|
|
1299
1950
|
|
|
1951
|
+
// node_modules/@xmpp/xml/index.js
|
|
1952
|
+
var import_Element2 = __toESM(require_Element(), 1);
|
|
1953
|
+
var import_createElement = __toESM(require_createElement(), 1);
|
|
1954
|
+
var import_escape = __toESM(require_escape(), 1);
|
|
1955
|
+
|
|
1956
|
+
// node_modules/@xmpp/xml/lib/Parser.js
|
|
1957
|
+
var import_ltx = __toESM(require_ltx(), 1);
|
|
1958
|
+
var import_Element = __toESM(require_Element(), 1);
|
|
1959
|
+
|
|
1960
|
+
// node_modules/@xmpp/events/index.js
|
|
1961
|
+
import { EventEmitter } from "events";
|
|
1962
|
+
|
|
1963
|
+
// node_modules/@xmpp/xml/lib/XMLError.js
|
|
1964
|
+
var XMLError = class extends Error {
|
|
1965
|
+
constructor(...args) {
|
|
1966
|
+
super(...args);
|
|
1967
|
+
this.name = "XMLError";
|
|
1968
|
+
}
|
|
1969
|
+
};
|
|
1970
|
+
|
|
1971
|
+
// node_modules/@xmpp/xml/lib/Parser.js
|
|
1972
|
+
var Parser = class extends EventEmitter {
|
|
1973
|
+
constructor() {
|
|
1974
|
+
super();
|
|
1975
|
+
const parser = new import_ltx.default();
|
|
1976
|
+
this.root = null;
|
|
1977
|
+
this.cursor = null;
|
|
1978
|
+
parser.on("startElement", this.onStartElement.bind(this));
|
|
1979
|
+
parser.on("endElement", this.onEndElement.bind(this));
|
|
1980
|
+
parser.on("text", this.onText.bind(this));
|
|
1981
|
+
this.parser = parser;
|
|
1982
|
+
}
|
|
1983
|
+
onStartElement(name, attrs) {
|
|
1984
|
+
const element = new import_Element.default(name, attrs);
|
|
1985
|
+
const { root, cursor } = this;
|
|
1986
|
+
if (!root) {
|
|
1987
|
+
this.root = element;
|
|
1988
|
+
this.emit("start", element);
|
|
1989
|
+
} else if (cursor !== root) {
|
|
1990
|
+
cursor.append(element);
|
|
1991
|
+
}
|
|
1992
|
+
this.cursor = element;
|
|
1993
|
+
}
|
|
1994
|
+
onEndElement(name) {
|
|
1995
|
+
const { root, cursor } = this;
|
|
1996
|
+
if (name !== cursor.name) {
|
|
1997
|
+
this.emit("error", new XMLError(`${cursor.name} must be closed.`));
|
|
1998
|
+
return;
|
|
1999
|
+
}
|
|
2000
|
+
if (cursor === root) {
|
|
2001
|
+
this.emit("end", root);
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
if (!cursor.parent) {
|
|
2005
|
+
cursor.parent = root;
|
|
2006
|
+
this.emit("element", cursor);
|
|
2007
|
+
this.cursor = root;
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
2010
|
+
this.cursor = cursor.parent;
|
|
2011
|
+
}
|
|
2012
|
+
onText(str) {
|
|
2013
|
+
const { cursor } = this;
|
|
2014
|
+
if (!cursor) {
|
|
2015
|
+
this.emit("error", new XMLError(`${str} must be a child.`));
|
|
2016
|
+
return;
|
|
2017
|
+
}
|
|
2018
|
+
cursor.t(str);
|
|
2019
|
+
}
|
|
2020
|
+
write(data) {
|
|
2021
|
+
this.parser.write(data);
|
|
2022
|
+
}
|
|
2023
|
+
end(data) {
|
|
2024
|
+
if (data) {
|
|
2025
|
+
this.parser.write(data);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
};
|
|
2029
|
+
Parser.XMLError = XMLError;
|
|
2030
|
+
var Parser_default = Parser;
|
|
2031
|
+
|
|
2032
|
+
// node_modules/@xmpp/xml/index.js
|
|
2033
|
+
function xml(...args) {
|
|
2034
|
+
return (0, import_createElement.default)(...args);
|
|
2035
|
+
}
|
|
2036
|
+
Object.assign(xml, {
|
|
2037
|
+
Element: import_Element2.default,
|
|
2038
|
+
createElement: import_createElement.default,
|
|
2039
|
+
Parser: Parser_default,
|
|
2040
|
+
escapeXML: import_escape.escapeXML,
|
|
2041
|
+
unescapeXML: import_escape.unescapeXML,
|
|
2042
|
+
escapeXMLText: import_escape.escapeXMLText,
|
|
2043
|
+
unescapeXMLText: import_escape.unescapeXMLText,
|
|
2044
|
+
XMLError,
|
|
2045
|
+
xml
|
|
2046
|
+
});
|
|
2047
|
+
|
|
1300
2048
|
// src/smule-live-chat.ts
|
|
1301
|
-
import "
|
|
1302
|
-
import EventEmitter from "events";
|
|
2049
|
+
import EventEmitter2 from "events";
|
|
1303
2050
|
import "@xmpp/jid";
|
|
2051
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1304
2052
|
var SmuleLiveChat = class {
|
|
1305
|
-
events = new
|
|
2053
|
+
events = new EventEmitter2();
|
|
1306
2054
|
state = "closed";
|
|
1307
2055
|
client;
|
|
1308
2056
|
jid;
|
|
1309
|
-
|
|
1310
|
-
iqHasMore = false;
|
|
1311
|
-
lastIqId = "0";
|
|
2057
|
+
iqs = {};
|
|
1312
2058
|
roomJID = null;
|
|
1313
2059
|
roomUsers = [];
|
|
1314
2060
|
chat = { messages: [] };
|
|
1315
|
-
constructor(userId, session, host = SmuleUrls.
|
|
2061
|
+
constructor(userId, session, host = SmuleUrls.cfireChat, roomJID) {
|
|
1316
2062
|
this.client = client({
|
|
1317
2063
|
service: "xmpp://" + host,
|
|
1318
2064
|
domain: host,
|
|
@@ -1344,22 +2090,25 @@ var SmuleLiveChat = class {
|
|
|
1344
2090
|
this.jid = await this.client.start();
|
|
1345
2091
|
this._log("Connected as:", this.jid.getLocal() + "@" + this.jid.getDomain());
|
|
1346
2092
|
this.client.send(
|
|
1347
|
-
|
|
2093
|
+
xml2(
|
|
1348
2094
|
"presence",
|
|
1349
2095
|
{ to: this.roomJID + "/" + this.jid.getLocal() },
|
|
1350
|
-
|
|
2096
|
+
xml2(
|
|
1351
2097
|
"x",
|
|
1352
2098
|
{ xmlns: "http://jabber.org/protocol/muc" },
|
|
1353
|
-
|
|
2099
|
+
xml2(
|
|
1354
2100
|
"password"
|
|
1355
2101
|
),
|
|
1356
|
-
|
|
2102
|
+
xml2(
|
|
1357
2103
|
"history",
|
|
1358
2104
|
{ maxstanzas: "1" }
|
|
1359
2105
|
)
|
|
1360
2106
|
)
|
|
1361
2107
|
)
|
|
1362
2108
|
);
|
|
2109
|
+
this.sendIqQuery("http://jabber.org/protocol/disco#info", (el) => {
|
|
2110
|
+
console.log("reply from disco", el);
|
|
2111
|
+
});
|
|
1363
2112
|
}
|
|
1364
2113
|
/**
|
|
1365
2114
|
* Disconnects the client from the XMPP server.
|
|
@@ -1371,83 +2120,41 @@ var SmuleLiveChat = class {
|
|
|
1371
2120
|
*/
|
|
1372
2121
|
async disconnect() {
|
|
1373
2122
|
try {
|
|
2123
|
+
await this.client.send(xml2("presence", { type: "unavailable" }));
|
|
1374
2124
|
await this.client.stop();
|
|
1375
2125
|
} catch {
|
|
1376
2126
|
}
|
|
1377
2127
|
}
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
* paused -> Just stopped typing
|
|
1387
|
-
*
|
|
1388
|
-
* inactive -> You're inactive
|
|
1389
|
-
*
|
|
1390
|
-
* gone -> You're hidden / disconnected / You've left the chat
|
|
1391
|
-
*
|
|
1392
|
-
* @param state One of `active`, `composing`, `paused`, `inactive`, or `gone`.
|
|
1393
|
-
* Default is `active`
|
|
1394
|
-
*/
|
|
1395
|
-
async sendChatState(to, state = "active") {
|
|
1396
|
-
if (typeof to != "string" && "accountId" in to) to = this.getJIDFromUserId(to.accountId);
|
|
1397
|
-
await this.client.send(
|
|
1398
|
-
xml(
|
|
1399
|
-
"message",
|
|
1400
|
-
{ to: to.toString(), type: "chat" },
|
|
1401
|
-
xml(
|
|
1402
|
-
"chatstate",
|
|
1403
|
-
{ xmlns: "http://jabber.org/protocol/chatstates" },
|
|
1404
|
-
state
|
|
1405
|
-
)
|
|
2128
|
+
sendIq(data, callback, iqType = "get") {
|
|
2129
|
+
const id = randomUUID2();
|
|
2130
|
+
this.iqs[id] = callback;
|
|
2131
|
+
this.client.send(
|
|
2132
|
+
xml2(
|
|
2133
|
+
"iq",
|
|
2134
|
+
{ from: this.jid.toString(), to: this.roomJID, type: iqType, id },
|
|
2135
|
+
data
|
|
1406
2136
|
)
|
|
1407
2137
|
);
|
|
1408
2138
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
* @remarks Filtering by a specific JID may not work yet
|
|
1415
|
-
*/
|
|
1416
|
-
async loadMessageHistory(limit = 50, before = null, after = null, jid) {
|
|
1417
|
-
this._log("Loading live chat history...");
|
|
1418
|
-
this.ongoingIq = true;
|
|
1419
|
-
await this.client.send(
|
|
1420
|
-
xml(
|
|
1421
|
-
"iq",
|
|
1422
|
-
{ from: this.jid.toString(), to: this.roomJID, type: "get", id: "meow" },
|
|
1423
|
-
xml(
|
|
1424
|
-
"query",
|
|
1425
|
-
{ xmlns: "http://jabber.org/protocol/muc#history" }
|
|
1426
|
-
)
|
|
1427
|
-
)
|
|
2139
|
+
sendIqQuery(xmlns, callback, iqType = "get") {
|
|
2140
|
+
this.sendIq(
|
|
2141
|
+
xml2("query", { xmlns }),
|
|
2142
|
+
callback,
|
|
2143
|
+
iqType
|
|
1428
2144
|
);
|
|
1429
|
-
while (this.ongoingIq) await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1430
2145
|
}
|
|
1431
2146
|
/**
|
|
1432
|
-
* Send a text message
|
|
1433
|
-
* @param jid The JID to send the message to
|
|
2147
|
+
* Send a text message to the livestream
|
|
1434
2148
|
* @param message The message body
|
|
1435
2149
|
*/
|
|
1436
|
-
async sendTextMessage(
|
|
1437
|
-
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2150
|
+
async sendTextMessage(message) {
|
|
1438
2151
|
await this.client.send(
|
|
1439
|
-
|
|
2152
|
+
xml2(
|
|
1440
2153
|
"message",
|
|
1441
|
-
{ to:
|
|
1442
|
-
|
|
2154
|
+
{ to: this.roomJID, type: "groupchat" },
|
|
2155
|
+
xml2("body", {}, message)
|
|
1443
2156
|
)
|
|
1444
2157
|
);
|
|
1445
|
-
const data = {
|
|
1446
|
-
sender: parseInt(this.jid.getLocal()),
|
|
1447
|
-
content: message
|
|
1448
|
-
};
|
|
1449
|
-
this.chat[this.getUserIdFromJID(jid.toString())].messages.push(data);
|
|
1450
|
-
this.events.emit("message", data);
|
|
1451
2158
|
}
|
|
1452
2159
|
/**
|
|
1453
2160
|
* Read-only jid to prevent any bugs
|
|
@@ -1560,6 +2267,23 @@ var SmuleLiveChat = class {
|
|
|
1560
2267
|
this._log("Got host left!", data2);
|
|
1561
2268
|
this.events.emit("host-left", data2);
|
|
1562
2269
|
}
|
|
2270
|
+
child = el.getChild("song-listen");
|
|
2271
|
+
if (child) {
|
|
2272
|
+
const data2 = {
|
|
2273
|
+
arrKey: child.getChild("arrangement-key").getText(),
|
|
2274
|
+
hostSessionId: child.getChild("host-session-id").getText()
|
|
2275
|
+
};
|
|
2276
|
+
this._log("Got song listen!", data2);
|
|
2277
|
+
this.events.emit("song-listen", data2);
|
|
2278
|
+
}
|
|
2279
|
+
child = el.getChild("campfire-ended");
|
|
2280
|
+
if (child) {
|
|
2281
|
+
const data2 = {
|
|
2282
|
+
reason: child.getChild("reason").getText()
|
|
2283
|
+
};
|
|
2284
|
+
this._log("Got stop livestream!", data2);
|
|
2285
|
+
this.events.emit("stop-livestream", data2);
|
|
2286
|
+
}
|
|
1563
2287
|
child = el.getChild("result");
|
|
1564
2288
|
if (!child) return;
|
|
1565
2289
|
child = child.getChild("forwarded");
|
|
@@ -1583,15 +2307,17 @@ var SmuleLiveChat = class {
|
|
|
1583
2307
|
if (child) {
|
|
1584
2308
|
child = child.getChild("item");
|
|
1585
2309
|
if (child) {
|
|
1586
|
-
if (!el.getAttr("jid"))
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
2310
|
+
if (!el.getAttr("jid")) {
|
|
2311
|
+
} else {
|
|
2312
|
+
const data = {
|
|
2313
|
+
user: this.getUserIdFromJID(el.getAttr("jid")),
|
|
2314
|
+
role: child.getAttr("role"),
|
|
2315
|
+
affiliation: child.getAttr("affiliation")
|
|
2316
|
+
};
|
|
2317
|
+
this._log("Got presence!", data);
|
|
2318
|
+
this.roomUsers.push(data);
|
|
2319
|
+
this.events.emit("presence", data);
|
|
2320
|
+
}
|
|
1595
2321
|
}
|
|
1596
2322
|
}
|
|
1597
2323
|
}
|
|
@@ -1688,22 +2414,11 @@ var SmuleLiveChat = class {
|
|
|
1688
2414
|
this.parsePresence(el);
|
|
1689
2415
|
} else {
|
|
1690
2416
|
if (el.is("iq")) {
|
|
1691
|
-
|
|
1692
|
-
if (
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
child = child.getChild("set");
|
|
1696
|
-
if (child) {
|
|
1697
|
-
child = child.getChild("last");
|
|
1698
|
-
if (child) {
|
|
1699
|
-
this.lastIqId = child.getText();
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
} else {
|
|
1703
|
-
this.iqHasMore = false;
|
|
1704
|
-
}
|
|
2417
|
+
const id = el.getAttr("id");
|
|
2418
|
+
if (id) {
|
|
2419
|
+
this.iqs[id](el);
|
|
2420
|
+
delete this.iqs[id];
|
|
1705
2421
|
}
|
|
1706
|
-
this.ongoingIq = false;
|
|
1707
2422
|
}
|
|
1708
2423
|
this._log("Stanza!", el.toString());
|
|
1709
2424
|
}
|
|
@@ -2136,21 +2851,17 @@ var SmuleMIDI;
|
|
|
2136
2851
|
})(SmuleMIDI || (SmuleMIDI = {}));
|
|
2137
2852
|
|
|
2138
2853
|
// src/smule-chat.ts
|
|
2139
|
-
import { client as client2, xml as
|
|
2140
|
-
import "
|
|
2141
|
-
import EventEmitter2 from "events";
|
|
2854
|
+
import { client as client2, xml as xml3 } from "@xmpp/client";
|
|
2855
|
+
import EventEmitter3 from "events";
|
|
2142
2856
|
import "@xmpp/jid";
|
|
2857
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
2143
2858
|
var SmuleChat = class {
|
|
2144
|
-
events = new
|
|
2859
|
+
events = new EventEmitter3();
|
|
2145
2860
|
state = "closed";
|
|
2146
2861
|
client;
|
|
2147
2862
|
jid;
|
|
2148
|
-
|
|
2149
|
-
iqHasMore = false;
|
|
2150
|
-
lastIqId = "0";
|
|
2151
|
-
isLive = false;
|
|
2863
|
+
iqs = {};
|
|
2152
2864
|
roomJID = null;
|
|
2153
|
-
roomUsers = [];
|
|
2154
2865
|
chats = {};
|
|
2155
2866
|
constructor(userId, session, host = SmuleUrls.userChat, roomJID) {
|
|
2156
2867
|
this.client = client2({
|
|
@@ -2161,7 +2872,6 @@ var SmuleChat = class {
|
|
|
2161
2872
|
username: userId + "",
|
|
2162
2873
|
password: session
|
|
2163
2874
|
});
|
|
2164
|
-
this.isLive = host != SmuleUrls.userChat || !!roomJID;
|
|
2165
2875
|
this.roomJID = roomJID;
|
|
2166
2876
|
this.client.on("close", (el) => this.onClose(el));
|
|
2167
2877
|
this.client.on("closing", () => this.onClosing());
|
|
@@ -2184,27 +2894,7 @@ var SmuleChat = class {
|
|
|
2184
2894
|
async connect() {
|
|
2185
2895
|
this.jid = await this.client.start();
|
|
2186
2896
|
this._log("Connected as:", this.jid.getLocal() + "@" + this.jid.getDomain());
|
|
2187
|
-
|
|
2188
|
-
this.client.send(xml2("presence", {}));
|
|
2189
|
-
} else {
|
|
2190
|
-
this.client.send(
|
|
2191
|
-
xml2(
|
|
2192
|
-
"presence",
|
|
2193
|
-
{ to: this.roomJID + "/" + this.jid.getLocal() },
|
|
2194
|
-
xml2(
|
|
2195
|
-
"x",
|
|
2196
|
-
{ xmlns: "http://jabber.org/protocol/muc" },
|
|
2197
|
-
xml2(
|
|
2198
|
-
"password"
|
|
2199
|
-
),
|
|
2200
|
-
xml2(
|
|
2201
|
-
"history",
|
|
2202
|
-
{ maxstanzas: "1" }
|
|
2203
|
-
)
|
|
2204
|
-
)
|
|
2205
|
-
)
|
|
2206
|
-
);
|
|
2207
|
-
}
|
|
2897
|
+
this.client.send(xml3("presence", {}));
|
|
2208
2898
|
}
|
|
2209
2899
|
/**
|
|
2210
2900
|
* Disconnects the client from the XMPP server.
|
|
@@ -2216,10 +2906,29 @@ var SmuleChat = class {
|
|
|
2216
2906
|
*/
|
|
2217
2907
|
async disconnect() {
|
|
2218
2908
|
try {
|
|
2909
|
+
await this.client.send(xml3("presence", { type: "unavailable" }));
|
|
2219
2910
|
await this.client.stop();
|
|
2220
2911
|
} catch {
|
|
2221
2912
|
}
|
|
2222
2913
|
}
|
|
2914
|
+
sendIq(data, callback, iqType = "get") {
|
|
2915
|
+
const id = randomUUID3();
|
|
2916
|
+
this.iqs[id] = callback;
|
|
2917
|
+
this.client.send(
|
|
2918
|
+
xml3(
|
|
2919
|
+
"iq",
|
|
2920
|
+
{ from: this.jid.toString(), to: this.roomJID, type: iqType, id },
|
|
2921
|
+
data
|
|
2922
|
+
)
|
|
2923
|
+
);
|
|
2924
|
+
}
|
|
2925
|
+
sendIqQuery(xmlns, callback, iqType = "get") {
|
|
2926
|
+
this.sendIq(
|
|
2927
|
+
xml3("query", { xmlns }),
|
|
2928
|
+
callback,
|
|
2929
|
+
iqType
|
|
2930
|
+
);
|
|
2931
|
+
}
|
|
2223
2932
|
/**
|
|
2224
2933
|
* Send a chat state to the server. This is used to
|
|
2225
2934
|
* signal whether you are currently active or not.
|
|
@@ -2240,10 +2949,10 @@ var SmuleChat = class {
|
|
|
2240
2949
|
async sendChatState(to, state = "active") {
|
|
2241
2950
|
if (typeof to != "string" && "accountId" in to) to = this.getJIDFromUserId(to.accountId);
|
|
2242
2951
|
await this.client.send(
|
|
2243
|
-
|
|
2952
|
+
xml3(
|
|
2244
2953
|
"message",
|
|
2245
2954
|
{ to: to.toString(), type: "chat" },
|
|
2246
|
-
|
|
2955
|
+
xml3(
|
|
2247
2956
|
"chatstate",
|
|
2248
2957
|
{ xmlns: "http://jabber.org/protocol/chatstates" },
|
|
2249
2958
|
state
|
|
@@ -2259,50 +2968,29 @@ var SmuleChat = class {
|
|
|
2259
2968
|
* @remarks Filtering by a specific JID may not work yet
|
|
2260
2969
|
*/
|
|
2261
2970
|
async loadMessageHistory(limit = 50, before = null, after = null, jid) {
|
|
2262
|
-
if (
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
"
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
jid ? xml2("with", {}, jid.toString()) : null
|
|
2286
|
-
)
|
|
2287
|
-
)
|
|
2288
|
-
);
|
|
2289
|
-
while (this.ongoingIq) await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2290
|
-
if (this.iqHasMore) await this.loadMessageHistory(limit, null, this.lastIqId, jid);
|
|
2291
|
-
} else {
|
|
2292
|
-
this._log("Loading live chat history...");
|
|
2293
|
-
this.ongoingIq = true;
|
|
2294
|
-
await this.client.send(
|
|
2295
|
-
xml2(
|
|
2296
|
-
"iq",
|
|
2297
|
-
{ from: this.jid.toString(), to: this.roomJID, type: "get", id: "meow" },
|
|
2298
|
-
xml2(
|
|
2299
|
-
"query",
|
|
2300
|
-
{ xmlns: "http://jabber.org/protocol/muc#history" }
|
|
2301
|
-
)
|
|
2302
|
-
)
|
|
2303
|
-
);
|
|
2304
|
-
while (this.ongoingIq) await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2305
|
-
}
|
|
2971
|
+
if (jid)
|
|
2972
|
+
this._log(`Loading ${limit} messages with ${jid}...`);
|
|
2973
|
+
else
|
|
2974
|
+
this._log(`Loading ${limit} messages from history...`);
|
|
2975
|
+
if (!before && !after && !jid) this.chats = {};
|
|
2976
|
+
this.sendIq(
|
|
2977
|
+
xml3(
|
|
2978
|
+
"query",
|
|
2979
|
+
{ xmlns: "urn:xmpp:mam:2" },
|
|
2980
|
+
xml3(
|
|
2981
|
+
"set",
|
|
2982
|
+
{ xmlns: "http://jabber.org/protocol/rsm" },
|
|
2983
|
+
xml3("max", {}, limit.toString()),
|
|
2984
|
+
before ? xml3("before", {}, before.toString()) : null,
|
|
2985
|
+
after ? xml3("after", {}, after.toString()) : null
|
|
2986
|
+
),
|
|
2987
|
+
jid ? xml3("with", {}, jid.toString()) : null
|
|
2988
|
+
),
|
|
2989
|
+
(el) => {
|
|
2990
|
+
this._log("Finished loading history!", el.toString());
|
|
2991
|
+
},
|
|
2992
|
+
"set"
|
|
2993
|
+
);
|
|
2306
2994
|
}
|
|
2307
2995
|
/**
|
|
2308
2996
|
* Send a text message
|
|
@@ -2312,18 +3000,12 @@ var SmuleChat = class {
|
|
|
2312
3000
|
async sendTextMessage(jid, message) {
|
|
2313
3001
|
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2314
3002
|
await this.client.send(
|
|
2315
|
-
|
|
3003
|
+
xml3(
|
|
2316
3004
|
"message",
|
|
2317
|
-
{ to: jid.toString(), type:
|
|
2318
|
-
|
|
3005
|
+
{ to: jid.toString(), type: "chat" },
|
|
3006
|
+
xml3("body", {}, message)
|
|
2319
3007
|
)
|
|
2320
3008
|
);
|
|
2321
|
-
let data = {
|
|
2322
|
-
sender: parseInt(this.jid.getLocal()),
|
|
2323
|
-
content: message
|
|
2324
|
-
};
|
|
2325
|
-
this.chats[this.getUserIdFromJID(jid.toString())].messages.push(data);
|
|
2326
|
-
this.events.emit("message", data);
|
|
2327
3009
|
}
|
|
2328
3010
|
/**
|
|
2329
3011
|
* Send a performance / recording
|
|
@@ -2333,19 +3015,19 @@ var SmuleChat = class {
|
|
|
2333
3015
|
async sendPerformanceMessage(jid, performanceKey) {
|
|
2334
3016
|
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2335
3017
|
await this.client.send(
|
|
2336
|
-
|
|
3018
|
+
xml3(
|
|
2337
3019
|
"message",
|
|
2338
3020
|
{ to: jid.toString(), type: "chat" },
|
|
2339
|
-
|
|
3021
|
+
xml3(
|
|
2340
3022
|
"performance",
|
|
2341
3023
|
{ xmlns: "urn:x-smule:xmpp" },
|
|
2342
|
-
|
|
3024
|
+
xml3(
|
|
2343
3025
|
"key",
|
|
2344
3026
|
{},
|
|
2345
3027
|
performanceKey
|
|
2346
3028
|
)
|
|
2347
3029
|
),
|
|
2348
|
-
|
|
3030
|
+
xml3("body", {}, "")
|
|
2349
3031
|
)
|
|
2350
3032
|
);
|
|
2351
3033
|
}
|
|
@@ -2356,29 +3038,10 @@ var SmuleChat = class {
|
|
|
2356
3038
|
async sendReadReceipt(jid) {
|
|
2357
3039
|
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2358
3040
|
await this.client.send(
|
|
2359
|
-
|
|
3041
|
+
xml3(
|
|
2360
3042
|
"message",
|
|
2361
3043
|
{ to: jid.toString(), type: "chat" },
|
|
2362
|
-
|
|
2363
|
-
)
|
|
2364
|
-
);
|
|
2365
|
-
}
|
|
2366
|
-
//TODO - Most definitely not required
|
|
2367
|
-
async archiveMessage(jid, message) {
|
|
2368
|
-
if (typeof jid != "string" && "accountId" in jid) jid = this.getJIDFromUserId(jid.accountId);
|
|
2369
|
-
await this.client.send(
|
|
2370
|
-
xml2(
|
|
2371
|
-
"iq",
|
|
2372
|
-
{ type: "set" },
|
|
2373
|
-
xml2(
|
|
2374
|
-
"archive",
|
|
2375
|
-
{ xmlns: "urn:xmpp:mam:2" },
|
|
2376
|
-
xml2(
|
|
2377
|
-
"item",
|
|
2378
|
-
{ with: jid, id: Math.random().toString(16).substring(2, 8) },
|
|
2379
|
-
xml2("body", {}, message)
|
|
2380
|
-
)
|
|
2381
|
-
)
|
|
3044
|
+
xml3("received", { xmlns: "urn:xmpp:receipts" })
|
|
2382
3045
|
)
|
|
2383
3046
|
);
|
|
2384
3047
|
}
|
|
@@ -2396,7 +3059,6 @@ var SmuleChat = class {
|
|
|
2396
3059
|
*/
|
|
2397
3060
|
getUserIdFromJID(jid) {
|
|
2398
3061
|
if (!(typeof jid == "string")) return parseInt(jid.getLocal());
|
|
2399
|
-
if (jid.includes("/")) return parseInt(jid.split("/")[1]);
|
|
2400
3062
|
return parseInt(jid.split("@")[0]);
|
|
2401
3063
|
}
|
|
2402
3064
|
/**
|
|
@@ -2406,7 +3068,6 @@ var SmuleChat = class {
|
|
|
2406
3068
|
*/
|
|
2407
3069
|
getJIDFromUserId(userId) {
|
|
2408
3070
|
if (typeof userId != "string" && typeof userId != "number" && "accountId" in userId) userId = userId.accountId;
|
|
2409
|
-
if (this.isLive) return this.roomJID + "/" + userId;
|
|
2410
3071
|
return userId + "@" + this.jid.getDomain();
|
|
2411
3072
|
}
|
|
2412
3073
|
//* Processes all message-like elements
|
|
@@ -2431,7 +3092,6 @@ var SmuleChat = class {
|
|
|
2431
3092
|
}
|
|
2432
3093
|
child = el.getChild("body");
|
|
2433
3094
|
const perfChild = el.getChild("performance");
|
|
2434
|
-
const perfStartChild = el.getChild("performance-start");
|
|
2435
3095
|
if (child && (child.getText().trim().length > 0 || perfChild)) {
|
|
2436
3096
|
this._log("Got message!", child.getText());
|
|
2437
3097
|
let performanceKey2 = void 0;
|
|
@@ -2462,7 +3122,8 @@ var SmuleChat = class {
|
|
|
2462
3122
|
content: child.getText(),
|
|
2463
3123
|
sender: this.getUserIdFromJID(child.parent.getAttr("from")),
|
|
2464
3124
|
id: child.parent.getAttr("id"),
|
|
2465
|
-
performanceKey
|
|
3125
|
+
performanceKey,
|
|
3126
|
+
systemMessage: !!child.parent.getChild("smule-system-msg")
|
|
2466
3127
|
};
|
|
2467
3128
|
let chat = this.jid.getLocal().includes(data.sender + "") ? this.getUserIdFromJID(child.parent.getAttr("to")) : data.sender;
|
|
2468
3129
|
this.events.emit("history", data);
|
|
@@ -2471,25 +3132,6 @@ var SmuleChat = class {
|
|
|
2471
3132
|
}
|
|
2472
3133
|
parsePresence(el) {
|
|
2473
3134
|
if (el.children.length < 1) return;
|
|
2474
|
-
if (this.isLive) {
|
|
2475
|
-
let child = el.getChildByAttr("xmlns", "http://jabber.org/protocol/muc#user");
|
|
2476
|
-
if (child) {
|
|
2477
|
-
child = child.getChild("item");
|
|
2478
|
-
if (child) {
|
|
2479
|
-
if (!el.getAttr("jid")) return;
|
|
2480
|
-
let user = this.getUserIdFromJID(el.getAttr("jid"));
|
|
2481
|
-
let role = child.getAttr("role");
|
|
2482
|
-
let affiliation = child.getAttr("affiliation");
|
|
2483
|
-
let data = {
|
|
2484
|
-
user,
|
|
2485
|
-
role,
|
|
2486
|
-
affiliation
|
|
2487
|
-
};
|
|
2488
|
-
this.roomUsers.push(data);
|
|
2489
|
-
this.events.emit("presence", data);
|
|
2490
|
-
}
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
3135
|
}
|
|
2494
3136
|
/**
|
|
2495
3137
|
* Fetches the chats currently loaded
|
|
@@ -2507,9 +3149,6 @@ var SmuleChat = class {
|
|
|
2507
3149
|
if (!(user in this.chats)) this.chats[user] = { messages: [] };
|
|
2508
3150
|
return this.chats[user];
|
|
2509
3151
|
}
|
|
2510
|
-
fetchUsers() {
|
|
2511
|
-
return this.roomUsers;
|
|
2512
|
-
}
|
|
2513
3152
|
//#region Internal events
|
|
2514
3153
|
onClose(el) {
|
|
2515
3154
|
this._log("Closed!:", el);
|
|
@@ -2593,22 +3232,11 @@ var SmuleChat = class {
|
|
|
2593
3232
|
this.parsePresence(el);
|
|
2594
3233
|
} else {
|
|
2595
3234
|
if (el.is("iq")) {
|
|
2596
|
-
|
|
2597
|
-
if (
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
child = child.getChild("set");
|
|
2601
|
-
if (child) {
|
|
2602
|
-
child = child.getChild("last");
|
|
2603
|
-
if (child) {
|
|
2604
|
-
this.lastIqId = child.getText();
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
} else {
|
|
2608
|
-
this.iqHasMore = false;
|
|
2609
|
-
}
|
|
3235
|
+
const id = el.getAttr("id");
|
|
3236
|
+
if (id) {
|
|
3237
|
+
this.iqs[id](el);
|
|
3238
|
+
delete this.iqs[id];
|
|
2610
3239
|
}
|
|
2611
|
-
this.ongoingIq = false;
|
|
2612
3240
|
}
|
|
2613
3241
|
this._log("Stanza!", el.toString());
|
|
2614
3242
|
}
|
|
@@ -2616,13 +3244,13 @@ var SmuleChat = class {
|
|
|
2616
3244
|
//#endregion Internal events
|
|
2617
3245
|
//#region Logging
|
|
2618
3246
|
_log(...args) {
|
|
2619
|
-
console.log(
|
|
3247
|
+
console.log("[SmuleChat]", ...args);
|
|
2620
3248
|
}
|
|
2621
3249
|
_warn(...args) {
|
|
2622
|
-
console.warn(
|
|
3250
|
+
console.warn("[SmuleChat]", ...args);
|
|
2623
3251
|
}
|
|
2624
3252
|
_error(...args) {
|
|
2625
|
-
console.error(
|
|
3253
|
+
console.error("[SmuleChat]", ...args);
|
|
2626
3254
|
}
|
|
2627
3255
|
//#endregion Logging
|
|
2628
3256
|
};
|
|
@@ -2631,7 +3259,7 @@ var SmuleChat = class {
|
|
|
2631
3259
|
import { readFileSync } from "fs";
|
|
2632
3260
|
import * as crypto from "crypto";
|
|
2633
3261
|
import "@xmpp/jid";
|
|
2634
|
-
var APP_VERSION = "12.
|
|
3262
|
+
var APP_VERSION = "12.6.9";
|
|
2635
3263
|
var SmuleDigest;
|
|
2636
3264
|
((SmuleDigest2) => {
|
|
2637
3265
|
const SALT = `c2250918de500e32c37842f2d25d4d8210992a0ae96a7f36c4c9703cc675d02b92968bc4fa7feada`;
|
|
@@ -3175,13 +3803,37 @@ var Smule = class {
|
|
|
3175
3803
|
* Creates a new spark chat
|
|
3176
3804
|
* @param address The JID address of the chat partner
|
|
3177
3805
|
* @param type Whether the JID address is an individual or a group
|
|
3178
|
-
* @returns idk
|
|
3179
3806
|
*/
|
|
3180
3807
|
create: async (address, type = "ACCT") => {
|
|
3181
3808
|
const req = await this.internal._createRequest(SmuleUrls.SparkChatUpdate, { add: [{ name: address, type }], remove: [] });
|
|
3809
|
+
this.internal._handleNon200(req);
|
|
3810
|
+
},
|
|
3811
|
+
/**
|
|
3812
|
+
* Deletes an existing spark chat
|
|
3813
|
+
* @param address The JID address of the chat partner
|
|
3814
|
+
* @param type Whether the JID address is an individual or a group
|
|
3815
|
+
*/
|
|
3816
|
+
delete: async (address, type = "ACCT") => {
|
|
3817
|
+
const req = await this.internal._createRequest(SmuleUrls.SparkChatUpdate, { remove: [{ name: address, type }], add: [] });
|
|
3818
|
+
this.internal._handleNon200(req);
|
|
3819
|
+
},
|
|
3820
|
+
/**
|
|
3821
|
+
* Fetches your existing chats
|
|
3822
|
+
* @param type Whether an individual or a group
|
|
3823
|
+
* @returns Your inbox and your message requests
|
|
3824
|
+
*/
|
|
3825
|
+
fetchInboxes: async (type = "ACCT") => {
|
|
3826
|
+
const req = await this.internal._createRequest(SmuleUrls.SparkChatList, { type, limit: 200 });
|
|
3182
3827
|
if (!this.internal._handleNon200(req)) return;
|
|
3183
3828
|
return this.internal._getResponseData(req);
|
|
3184
3829
|
},
|
|
3830
|
+
/**
|
|
3831
|
+
* Marks you as offline to your chats
|
|
3832
|
+
*/
|
|
3833
|
+
markOffline: async () => {
|
|
3834
|
+
const req = await this.internal._createRequest(SmuleUrls.SparkChatOffline, {});
|
|
3835
|
+
this.internal._handleNon200(req);
|
|
3836
|
+
},
|
|
3185
3837
|
/**
|
|
3186
3838
|
* Creates a connection to the XMPP chat server
|
|
3187
3839
|
*/
|
|
@@ -4352,9 +5004,9 @@ var Smule = class {
|
|
|
4352
5004
|
* @param to The user to send the message to
|
|
4353
5005
|
* @param message The message body
|
|
4354
5006
|
*/
|
|
4355
|
-
sendTextMessage: async (
|
|
5007
|
+
sendTextMessage: async (message) => {
|
|
4356
5008
|
if (!this.liveChatSession) return;
|
|
4357
|
-
await this.liveChatSession.sendTextMessage(
|
|
5009
|
+
await this.liveChatSession.sendTextMessage(message);
|
|
4358
5010
|
},
|
|
4359
5011
|
/**
|
|
4360
5012
|
* Fetch all loaded chats
|
|
@@ -4367,27 +5019,47 @@ var Smule = class {
|
|
|
4367
5019
|
fetchUsers: () => {
|
|
4368
5020
|
if (!this.liveChatSession) return;
|
|
4369
5021
|
return this.liveChatSession.fetchUsers();
|
|
4370
|
-
},
|
|
4371
|
-
/**
|
|
4372
|
-
* Loads the entire message history
|
|
4373
|
-
* @param limit How many messages
|
|
4374
|
-
* @param before Messages before this
|
|
4375
|
-
* @param after Messages after this
|
|
4376
|
-
* @param user The chat partner
|
|
4377
|
-
*
|
|
4378
|
-
* @remarks This currently recurses until it loads ALL archived messages.
|
|
4379
|
-
* This means that it will take a long time to load all messages.
|
|
4380
|
-
* @remarks Filtering by a specific user may not work yet
|
|
4381
|
-
*/
|
|
4382
|
-
loadMessageHistory: async (limit = 50, before = null, after = null, user) => {
|
|
4383
|
-
if (!this.liveChatSession) return;
|
|
4384
|
-
await this.liveChatSession.loadMessageHistory(limit, before, after, user);
|
|
4385
5022
|
}
|
|
4386
5023
|
},
|
|
5024
|
+
/**
|
|
5025
|
+
* Fetches ("syncs") a livestream (campfire) so you can connect to it
|
|
5026
|
+
*
|
|
5027
|
+
* @param campfireId The campfire's id
|
|
5028
|
+
* @returns Data regarding the campfire and the streaming details
|
|
5029
|
+
*/
|
|
4387
5030
|
fetch: async (campfireId) => {
|
|
4388
5031
|
const req = await this.internal._createRequest(SmuleUrls.CfireSync, { campfireId });
|
|
4389
5032
|
if (!this.internal._handleNon200(req)) return;
|
|
4390
5033
|
return this.internal._getResponseData(req);
|
|
5034
|
+
},
|
|
5035
|
+
/**
|
|
5036
|
+
* Fetches gifts that have been sent to a live
|
|
5037
|
+
*
|
|
5038
|
+
* @param campfireId The campfire's id
|
|
5039
|
+
* @param cursor The starting point
|
|
5040
|
+
* @param limit How many results
|
|
5041
|
+
* @returns A list of gifts data
|
|
5042
|
+
*/
|
|
5043
|
+
fetchRecentGifts: async (campfireId, cursor = "start", limit = 10) => {
|
|
5044
|
+
const req = await this.internal._createRequest(SmuleUrls.GiftRecentTransactions, { campfireId, cursor, limit, animationVersion: "V2", extraGiftTypes: ["SYSTEM"], previewVersion: "PNG", type: "CFIRE" });
|
|
5045
|
+
if (!this.internal._handleNon200(req)) return;
|
|
5046
|
+
return this.internal._getResponseData(req);
|
|
5047
|
+
},
|
|
5048
|
+
/**
|
|
5049
|
+
* Sign up as available to sing
|
|
5050
|
+
* @param campfireId The livestream's id
|
|
5051
|
+
*/
|
|
5052
|
+
joinToSing: async (campfireId) => {
|
|
5053
|
+
const req = await this.internal._createRequest(SmuleUrls.CfireSignupAdd, { campfireId, message: "I'm available to sing" });
|
|
5054
|
+
this.internal._handleNon200(req);
|
|
5055
|
+
},
|
|
5056
|
+
/**
|
|
5057
|
+
* Revoke your availability to sing
|
|
5058
|
+
* @param campfireId The livestream's id
|
|
5059
|
+
*/
|
|
5060
|
+
revokeJoinToSing: async (campfireId) => {
|
|
5061
|
+
const req = await this.internal._createRequest(SmuleUrls.CfireSignupRemove, { campfireId });
|
|
5062
|
+
this.internal._handleNon200(req);
|
|
4391
5063
|
}
|
|
4392
5064
|
};
|
|
4393
5065
|
groups = {
|