jsir 3.0.5 → 3.0.7
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/cmd/oaa.js +78 -35
- package/deps/room.js +24 -12
- package/deps/server.js +2 -2
- package/deps/util.js +36 -19
- package/package.json +1 -1
package/cmd/oaa.js
CHANGED
|
@@ -56,12 +56,21 @@ const _dealOnLazyGet = (key, onLazyTempCode) => {
|
|
|
56
56
|
return _data[key]
|
|
57
57
|
}
|
|
58
58
|
return new Promise(async (resolve, reject) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
if (typeof _onLazyTempCode === 'function') {
|
|
60
|
+
if (!await _onLazyTempCode()) {
|
|
61
|
+
reject("tempCode check failed")
|
|
62
|
+
} else {
|
|
63
|
+
_onLazyGetMap[key] = Date.now() + _lazyTime
|
|
64
|
+
resolve(_data[key])
|
|
65
|
+
}
|
|
62
66
|
} else {
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
let inputCode = onLazyTempCode || await nextLine(i => i, "TEMP_CODE: ", true)
|
|
68
|
+
if (inputCode !== _onLazyTempCode) {
|
|
69
|
+
reject("tempCode check failed")
|
|
70
|
+
} else {
|
|
71
|
+
_onLazyGetMap[key] = Date.now() + _lazyTime
|
|
72
|
+
resolve(_data[key])
|
|
73
|
+
}
|
|
65
74
|
}
|
|
66
75
|
})
|
|
67
76
|
}
|
|
@@ -75,6 +84,11 @@ const _dataSet = (key, val, onLazyTempCode) => {
|
|
|
75
84
|
}
|
|
76
85
|
} else if (true === onLazyTempCode) {
|
|
77
86
|
useOnLazy = true
|
|
87
|
+
} else if (typeof onLazyTempCode === "function") {
|
|
88
|
+
useOnLazy = true
|
|
89
|
+
if (!vl(_onLazyTempCode)) {
|
|
90
|
+
_onLazyTempCode = onLazyTempCode;
|
|
91
|
+
}
|
|
78
92
|
} else if (onLazyTempCode !== undefined) {
|
|
79
93
|
throw "invalid tempCode defined"
|
|
80
94
|
}
|
|
@@ -178,7 +192,10 @@ function checkWorkspaces() {
|
|
|
178
192
|
continue
|
|
179
193
|
}
|
|
180
194
|
if (fs.existsSync(workspace)) {
|
|
181
|
-
|
|
195
|
+
let stat = fs.lstatSync(workspace)
|
|
196
|
+
if (stat.isDirectory()) {
|
|
197
|
+
setting.workspaceMap[space] = workspace;
|
|
198
|
+
}
|
|
182
199
|
}
|
|
183
200
|
}
|
|
184
201
|
arrayDataFile(_workspaceConfigFile, () => Object.values(setting.workspaceMap))
|
|
@@ -635,7 +652,13 @@ async function wrapperInput(str, packOutput = false) {
|
|
|
635
652
|
await _wrapperInput(str);
|
|
636
653
|
} catch (e) {
|
|
637
654
|
if (promptId === setting.promptId) {
|
|
638
|
-
|
|
655
|
+
let msg = (e.message || e);
|
|
656
|
+
if (msg === 'Terminal Interrupt') {
|
|
657
|
+
console.warn(msg)
|
|
658
|
+
console.$warn(e)
|
|
659
|
+
} else {
|
|
660
|
+
console.error(e)
|
|
661
|
+
}
|
|
639
662
|
} else {
|
|
640
663
|
console.$error(e)
|
|
641
664
|
}
|
|
@@ -647,13 +670,21 @@ async function wrapperInput(str, packOutput = false) {
|
|
|
647
670
|
}
|
|
648
671
|
}
|
|
649
672
|
|
|
650
|
-
function wrapperAlias(
|
|
673
|
+
function wrapperAlias(items) {
|
|
651
674
|
let aliasMap = getConfig("alias");
|
|
652
675
|
if (!aliasMap || Object.keys(aliasMap).length <= 0) {
|
|
653
|
-
return
|
|
676
|
+
return items;
|
|
654
677
|
}
|
|
655
|
-
let
|
|
656
|
-
|
|
678
|
+
let result = []
|
|
679
|
+
for (let i = 0; i < items.length; i++) {
|
|
680
|
+
let item = items[i]
|
|
681
|
+
if (!item.endsWith(" ") && item.startsWith(".")) {
|
|
682
|
+
result.push(...enrichArgs(getAlias(aliasMap, item)))
|
|
683
|
+
} else {
|
|
684
|
+
result.push(item)
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return result;
|
|
657
688
|
}
|
|
658
689
|
|
|
659
690
|
async function _wrapperInput(str) {
|
|
@@ -663,7 +694,6 @@ async function _wrapperInput(str) {
|
|
|
663
694
|
return;
|
|
664
695
|
}
|
|
665
696
|
setting.newError = false;
|
|
666
|
-
str = wrapperAlias(str);
|
|
667
697
|
|
|
668
698
|
if (/^[`'"]/.test(str)) {
|
|
669
699
|
let fstr = str.substring(0, 1);
|
|
@@ -694,7 +724,7 @@ async function _wrapperInput(str) {
|
|
|
694
724
|
await evalText(text)
|
|
695
725
|
}
|
|
696
726
|
} else if (str.match(/^\./)) {
|
|
697
|
-
await dealKeyword(enrichArgs(str))
|
|
727
|
+
await dealKeyword(wrapperAlias(enrichArgs(str)))
|
|
698
728
|
} else if (!str.split(/\s+/)[0].match(/^\d+$/)) {
|
|
699
729
|
filterCmdAndList(str);
|
|
700
730
|
} else {
|
|
@@ -1515,6 +1545,13 @@ const keywordDef = {
|
|
|
1515
1545
|
let workspaces = Object.values(setting.workspaceMap)
|
|
1516
1546
|
workspaces.push(newWorkspace)
|
|
1517
1547
|
arrayDataFile(_workspaceConfigFile, () => workspaces)
|
|
1548
|
+
} else if (newWorkspace.startsWith("+")) {
|
|
1549
|
+
let name = newWorkspace.replace(/^\+\s*/, '');
|
|
1550
|
+
let path = setting.workspaceMap[name]
|
|
1551
|
+
if (path && name !== setting.defaultSpace) {
|
|
1552
|
+
let target = setting.workspaceMap[setting.defaultSpace] + '/' + name
|
|
1553
|
+
recreateSymlink(path, target)
|
|
1554
|
+
}
|
|
1518
1555
|
} else {
|
|
1519
1556
|
console.warn('invalid args')
|
|
1520
1557
|
}
|
|
@@ -1590,7 +1627,7 @@ const keywordDef = {
|
|
|
1590
1627
|
}
|
|
1591
1628
|
}
|
|
1592
1629
|
} else {
|
|
1593
|
-
console.warn(`require "${keyword}" not unique`)
|
|
1630
|
+
console.warn(`require "${keyword}" not exist&unique`)
|
|
1594
1631
|
}
|
|
1595
1632
|
},
|
|
1596
1633
|
args: {
|
|
@@ -1720,21 +1757,13 @@ const keywordDef = {
|
|
|
1720
1757
|
short: 'T'
|
|
1721
1758
|
},
|
|
1722
1759
|
room: {
|
|
1723
|
-
comment: 'manage room ([node])',
|
|
1760
|
+
comment: 'manage room ([node/pid][cmdStr])',
|
|
1724
1761
|
exeFn: async (args) => {
|
|
1725
1762
|
await Room.syncSetting();
|
|
1726
1763
|
if (args.length > 0) {
|
|
1727
|
-
let have = false;
|
|
1728
1764
|
let tasks = []
|
|
1729
|
-
let
|
|
1730
|
-
let
|
|
1731
|
-
for (let arg of args) {
|
|
1732
|
-
if (inputArgs.length > 0 || !/^\d/.test(arg)) {
|
|
1733
|
-
inputArgs.push(arg)
|
|
1734
|
-
} else {
|
|
1735
|
-
targets.push(arg)
|
|
1736
|
-
}
|
|
1737
|
-
}
|
|
1765
|
+
let taskPids = []
|
|
1766
|
+
let targets = [args[0]]
|
|
1738
1767
|
for (let room of setting.rooms) {
|
|
1739
1768
|
for (let pid of Object.keys(room.jsirs || {})) {
|
|
1740
1769
|
if (targets.indexOf(room.selfNode) === -1 && targets.indexOf(pid) === -1) {
|
|
@@ -1743,21 +1772,26 @@ const keywordDef = {
|
|
|
1743
1772
|
if (setting.selfRoom.selfNode === room.selfNode && String(process.pid) === pid) {
|
|
1744
1773
|
continue;
|
|
1745
1774
|
}
|
|
1746
|
-
if (setting.selfRoom.selfNode !== room.selfNode && targets.includes(room.selfNode) && !targets.includes(pid)
|
|
1747
|
-
&& room.jsirs[pid].port === setting.defaultPort) {
|
|
1748
|
-
continue;
|
|
1749
|
-
}
|
|
1750
|
-
have = true;
|
|
1751
1775
|
tasks.push(async (input) => {
|
|
1776
|
+
let pidKey = `[${room.name} ${pid}]`
|
|
1777
|
+
if (taskPids.includes(pid)) {
|
|
1778
|
+
console.log(warnStr(`Skip ${pidKey} Cause Duplicate Pid`))
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
console.log(infoStr(pidKey))
|
|
1782
|
+
taskPids.push(pid);
|
|
1752
1783
|
let jsir = room.jsirs[pid];
|
|
1753
|
-
console.log(infoStr(`[${pid}]`))
|
|
1754
1784
|
let resp = await Room.reqNode(room.selfNode, "post", "/enter", jsir.port, JSON.stringify({input}))
|
|
1755
1785
|
console.log(JSON.parse(resp).output)
|
|
1756
1786
|
})
|
|
1757
1787
|
}
|
|
1758
1788
|
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1789
|
+
if (tasks.length === 0) {
|
|
1790
|
+
console.warn('no items')
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
let inputStr = args.slice(1).join(' ')
|
|
1794
|
+
let input = inputStr || await nextLine(i => i)
|
|
1761
1795
|
if (vl(input)) {
|
|
1762
1796
|
for (let task of tasks) {
|
|
1763
1797
|
try {
|
|
@@ -2006,6 +2040,15 @@ function initWorkspace(space) {
|
|
|
2006
2040
|
setting.defaultSpace = workspace;
|
|
2007
2041
|
}
|
|
2008
2042
|
|
|
2043
|
+
function recreateSymlink(src, dest) {
|
|
2044
|
+
// 如果存在则删除(无论是文件还是软链)
|
|
2045
|
+
if (fs.existsSync(dest)) {
|
|
2046
|
+
fs.unlinkSync(dest);
|
|
2047
|
+
}
|
|
2048
|
+
// 重新创建软链
|
|
2049
|
+
fs.symlinkSync(src, dest, 'dir'); // dir/file 根据实际类型
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2009
2052
|
function filterCmdAndList(arg) {
|
|
2010
2053
|
arg = trim(arg) || lastFilterArg;
|
|
2011
2054
|
if (arg) {
|
|
@@ -2378,7 +2421,7 @@ function filterRequire(currSpace, cmdMatchStr) {
|
|
|
2378
2421
|
}
|
|
2379
2422
|
}
|
|
2380
2423
|
if (cmds.length !== 1) {
|
|
2381
|
-
throw `require "${cmdMatchStr}" not unique`
|
|
2424
|
+
throw `require "${cmdMatchStr}" not exist&unique`
|
|
2382
2425
|
}
|
|
2383
2426
|
return cmds[0];
|
|
2384
2427
|
}
|
|
@@ -2410,7 +2453,7 @@ async function _requireSource(currSpace, cmdMatchStr, force = false, $args) {
|
|
|
2410
2453
|
throw `service function ${serviceKey}/${prop} not found`;
|
|
2411
2454
|
}
|
|
2412
2455
|
return async (...args) => {
|
|
2413
|
-
return await Room.reqFn(`${serviceKey}/${prop}`, args);
|
|
2456
|
+
return await Room.reqFn(`${serviceKey}/${prop}`, args, $args);
|
|
2414
2457
|
}
|
|
2415
2458
|
}
|
|
2416
2459
|
})
|
package/deps/room.js
CHANGED
|
@@ -44,17 +44,17 @@ function onRoom() {
|
|
|
44
44
|
res.output = warnStr("Disable Remote")
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
+
if (!isRunningInBackground()) {
|
|
48
|
+
res.output = warnStr("Disable Remote")
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
47
51
|
if (vl(req.input)) {
|
|
48
|
-
if (!isRunningInBackground() && ['.nsir', '.N'].indexOf(req.input.trim()) === -1) {
|
|
49
|
-
res.output = warnStr("Disable Remote")
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
52
|
res.output = await setting.wrapperInput(req.input, true)
|
|
53
53
|
setting.promptId = Date.now()
|
|
54
54
|
}
|
|
55
55
|
})
|
|
56
56
|
} catch (e) {
|
|
57
|
-
console.$
|
|
57
|
+
console.$error("initRoute failed", e)
|
|
58
58
|
}
|
|
59
59
|
_onRoom();
|
|
60
60
|
}
|
|
@@ -79,7 +79,7 @@ function offRoom() {
|
|
|
79
79
|
setting.roomTid[0] = null
|
|
80
80
|
if (setting.server) {
|
|
81
81
|
setting.server.close(() => {
|
|
82
|
-
console.$
|
|
82
|
+
console.$log('Existing server shut down.');
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -112,15 +112,17 @@ async function initNodes() {
|
|
|
112
112
|
} catch (e) {
|
|
113
113
|
console.$debug("initNodes", e)
|
|
114
114
|
}
|
|
115
|
+
let isFirst = true
|
|
115
116
|
for (let line of resp.split("\n").map(trim)) {
|
|
116
|
-
let offline = line.indexOf('offline') !== -1
|
|
117
117
|
let ss = line.split(/\s+/);
|
|
118
118
|
if (/^\d+\.\d+\.\d+\.\d+$/.test(ss[0])) {
|
|
119
|
+
let offline = line.indexOf('offline') !== -1 || line.indexOf('active') === -1
|
|
119
120
|
nodes[ss[0]] = {
|
|
120
121
|
name: ss[1],
|
|
121
|
-
offline,
|
|
122
|
+
offline: !isFirst && offline,
|
|
122
123
|
account: ss[2]
|
|
123
124
|
}
|
|
125
|
+
isFirst = false
|
|
124
126
|
}
|
|
125
127
|
}
|
|
126
128
|
}
|
|
@@ -581,14 +583,24 @@ function busyPick(busyItems) {
|
|
|
581
583
|
}
|
|
582
584
|
}
|
|
583
585
|
|
|
584
|
-
|
|
586
|
+
function isMatchTarget(target, node, port) {
|
|
587
|
+
if (!target) {
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
target = String(target).trim()
|
|
591
|
+
if (target.includes(":")) {
|
|
592
|
+
return target === `${node}:${port}`
|
|
593
|
+
} else {
|
|
594
|
+
return target === node;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
async function reqFn(fnKey, args = [], reqTarget) {
|
|
585
599
|
let targets = setting.serviceFns[fnKey]
|
|
586
600
|
if (!targets) {
|
|
587
601
|
throw `service function ${fnKey} instance not found`;
|
|
588
602
|
}
|
|
589
|
-
targets = targets
|
|
590
|
-
.filter(i => i.active)
|
|
591
|
-
.filter(i => !isDisableConnect(i.node, i.port));
|
|
603
|
+
targets = targets.filter(i => isMatchTarget(reqTarget, i.node, i.port) && i.active && !isDisableConnect(i.node, i.port));
|
|
592
604
|
let target = null;
|
|
593
605
|
if (targets.length > 0) {
|
|
594
606
|
target = busyPick(targets);
|
package/deps/server.js
CHANGED
|
@@ -103,7 +103,7 @@ async function createServer(port) {
|
|
|
103
103
|
return await new Promise((resolve, reject) => {
|
|
104
104
|
server.listen(port, () => {
|
|
105
105
|
const address = server.address();
|
|
106
|
-
console.$
|
|
106
|
+
console.$log(`Server listening on port ${address.port}`);
|
|
107
107
|
resolve(server)
|
|
108
108
|
});
|
|
109
109
|
server.on('error', (err) => {
|
|
@@ -149,7 +149,7 @@ function setRoute(method, url, fn, isApi = false, handler = jsonHandle) {
|
|
|
149
149
|
isApi
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
|
-
console.$
|
|
152
|
+
console.$log(`setRoute: ${method.toUpperCase()} ${url} ${handler ? handler.name:''}`);
|
|
153
153
|
return setting.server;
|
|
154
154
|
}
|
|
155
155
|
|
package/deps/util.js
CHANGED
|
@@ -136,10 +136,10 @@ const $error = createLimitLogger(`${setting.name}.error`, {
|
|
|
136
136
|
error: true,
|
|
137
137
|
syncLogs: [$log]
|
|
138
138
|
});
|
|
139
|
-
const $errorOnly = createLimitLogger(`${setting.name}.error`, {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
139
|
+
// const $errorOnly = createLimitLogger(`${setting.name}.error`, {
|
|
140
|
+
// logInfo: false,
|
|
141
|
+
// error: true
|
|
142
|
+
// });
|
|
143
143
|
|
|
144
144
|
const roomLog = createLimitLogger(`room.log`, {
|
|
145
145
|
logInfo: false
|
|
@@ -285,17 +285,17 @@ function createConsole(uniqueName, _logToFile, _errorToFile) {
|
|
|
285
285
|
result.$draft = draftLog;
|
|
286
286
|
result.$abort = () => false;
|
|
287
287
|
if (uniqueName) {
|
|
288
|
-
let pair = parseUniqueName(uniqueName)
|
|
289
|
-
let fileName = pair[0] + '/' + pair[1].split(".")[0]
|
|
290
|
-
logToFile = createLimitLogger(fileName + '.log', {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
});
|
|
294
|
-
errorToFile = createLimitLogger(fileName + '.error', {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
});
|
|
288
|
+
// let pair = parseUniqueName(uniqueName)
|
|
289
|
+
// let fileName = pair[0] + '/' + pair[1].split(".")[0]
|
|
290
|
+
// logToFile = createLimitLogger(fileName + '.log', {
|
|
291
|
+
// logInfo: false,
|
|
292
|
+
// syncLogs: [$log]
|
|
293
|
+
// });
|
|
294
|
+
// errorToFile = createLimitLogger(fileName + '.error', {
|
|
295
|
+
// logInfo: false,
|
|
296
|
+
// error: true,
|
|
297
|
+
// syncLogs: [logToFile, $errorOnly]
|
|
298
|
+
// });
|
|
299
299
|
const promptId = setting.promptId;
|
|
300
300
|
result.$abort = () => promptId !== setting.promptId;
|
|
301
301
|
}
|
|
@@ -333,6 +333,10 @@ function createConsole(uniqueName, _logToFile, _errorToFile) {
|
|
|
333
333
|
}
|
|
334
334
|
setting.lastChangeFlag = flag
|
|
335
335
|
}
|
|
336
|
+
if (!is$ && uniqueName && quite && hasFlag) {
|
|
337
|
+
// ignore
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
336
340
|
if (is$ || (uniqueName && quite) || (setting.lastOutput && !hasFlag && 'debug' === key)) {
|
|
337
341
|
if ((key === 'table' || key === 'nable') && typeof args[0] === "object") {
|
|
338
342
|
args = ['', ...args]
|
|
@@ -629,6 +633,7 @@ async function draftModify(fLine) {
|
|
|
629
633
|
fs.writeFileSync(tempPath, results[0].split(/\n/).slice(1).join('\n'))
|
|
630
634
|
await eia(getEditor(), [`"${tempPath}"`], true)
|
|
631
635
|
let tempText = String(fs.readFileSync(tempPath))
|
|
636
|
+
fs.writeFileSync(tempPath, '')
|
|
632
637
|
let lineRange = lineRanges.get(results[0]);
|
|
633
638
|
let before = allLines.filter((_, index) => {
|
|
634
639
|
return index < lineRange.start;
|
|
@@ -844,7 +849,7 @@ function createLimitLogger(fileName, {
|
|
|
844
849
|
setting.newError = true;
|
|
845
850
|
}
|
|
846
851
|
if (time) {
|
|
847
|
-
let prefix = debugStr(`${timeStr('YYYY-MM-DD HH:mm:ss.SSS')} ${String(process.pid%
|
|
852
|
+
let prefix = debugStr(`${timeStr('YYYY-MM-DD HH:mm:ss.SSS')} ${String(process.pid%100000).padStart(5, '0')}>`)
|
|
848
853
|
text = `${prefix} ${text}`
|
|
849
854
|
}
|
|
850
855
|
fp.appendFile(logPath, text + '\n')
|
|
@@ -2065,11 +2070,17 @@ function getTextComments(text) {
|
|
|
2065
2070
|
function wrapperJsirText(text) {
|
|
2066
2071
|
return text
|
|
2067
2072
|
.replace(/^require\s*\(\s*(["'`][ei][^a-zA-Z]+)/mg, 'await $require($1')
|
|
2068
|
-
// .replace(/([\s=;]require\s*\(\s*["'`])\.\/([ei][^a-zA-Z]+)/g, '$1$2')
|
|
2069
2073
|
.replace(/([\s=;])require\s*\(\s*(["'`][ei][^a-zA-Z]+)/g, '$1await $require($2')
|
|
2074
|
+
|
|
2075
|
+
.replace(/^require\s*\(\s*(["'`][^/.]+\/[ei][^a-zA-Z]+)/mg, 'await $require($1')
|
|
2076
|
+
.replace(/([\s=;])require\s*\(\s*(["'`][^/.]+\/[ei][^a-zA-Z]+)/g, '$1await $require($2')
|
|
2077
|
+
|
|
2078
|
+
.replace(/^require\s*\(\s*(["'`])\.\//mg, 'await $require($1')
|
|
2070
2079
|
.replace(/([\s=;])require\s*\(\s*(["'`])\.\//g, '$1await $require($2')
|
|
2071
|
-
|
|
2080
|
+
|
|
2072
2081
|
.replace(/^import\s*\(/mg, '$import(')
|
|
2082
|
+
.replace(/([\s=;])import\s*\(/g, '$1$import(')
|
|
2083
|
+
|
|
2073
2084
|
.replace(/^module\.exports\s*=\s*/m, 'return ')
|
|
2074
2085
|
;
|
|
2075
2086
|
}
|
|
@@ -2249,6 +2260,10 @@ function currentRooms() {
|
|
|
2249
2260
|
return JSON.parse(JSON.stringify(setting.rooms));
|
|
2250
2261
|
}
|
|
2251
2262
|
|
|
2263
|
+
function uid() {
|
|
2264
|
+
return Date.now().toString(36) + Math.random().toString(36).slice(2, 10).padEnd(8, '0');
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2252
2267
|
module.exports = {
|
|
2253
2268
|
formatSec,
|
|
2254
2269
|
wrapperJsirText,
|
|
@@ -2369,5 +2384,7 @@ module.exports = {
|
|
|
2369
2384
|
formatMb,
|
|
2370
2385
|
currentJsir,
|
|
2371
2386
|
currentRoom,
|
|
2372
|
-
currentRooms
|
|
2387
|
+
currentRooms,
|
|
2388
|
+
uid,
|
|
2389
|
+
consoleStrs
|
|
2373
2390
|
}
|