@shoru/kitten 0.0.6 → 0.1.1
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/README.md +7 -2
- package/internal-test/index.js +4 -0
- package/internal-test/kittenwa.config.js +33 -0
- package/internal-test/plugins/exp.js +7 -0
- package/package.json +10 -10
- package/src/auth/init-session.js +18 -5
- package/src/auth/lmdb-auth-state.js +270 -176
- package/src/client/auth-handler.js +97 -0
- package/src/client/client.js +552 -603
- package/src/client/constants.js +41 -0
- package/src/client/errors.js +47 -0
- package/src/client/event-bus.js +69 -0
- package/src/client/index.js +9 -2
- package/src/client/registry.js +63 -0
- package/src/client/socket-proxy.js +57 -0
- package/src/client/sync-manager.js +79 -0
- package/src/config/default.js +39 -39
- package/src/formatter/format-message.js +189 -144
- package/src/index.js +2 -1
- package/src/internals/config.js +15 -3
- package/src/internals/lmdb-manager.js +79 -54
- package/src/plugins/config.js +1 -1
- package/src/plugins/handlers.js +121 -84
- package/src/plugins/loader.js +19 -13
- package/src/plugins/matcher.js +77 -58
- package/src/plugins/registry.js +184 -94
- package/src/plugins/watcher.js +13 -11
- package/src/utils/time-string.js +31 -19
- package/src/utils/type-conversions.js +11 -5
package/README.md
CHANGED
|
@@ -141,14 +141,19 @@ export default {
|
|
|
141
141
|
browser: Browsers.ubuntu('Chrome'),
|
|
142
142
|
markOnlineOnConnect: false,
|
|
143
143
|
syncFullHistory: false,
|
|
144
|
-
generateHighQualityLinkPreview:
|
|
144
|
+
generateHighQualityLinkPreview: false,
|
|
145
|
+
shouldIgnoreJid: () => false,
|
|
146
|
+
shouldSyncHistoryMessage: () => false,
|
|
145
147
|
logger: pino({ level: 'silent' })
|
|
146
148
|
},
|
|
147
149
|
|
|
148
150
|
db: {
|
|
149
151
|
path: './db',
|
|
150
152
|
compression: true,
|
|
151
|
-
mapSize: 2 * 1024 * 1024 * 1024
|
|
153
|
+
mapSize: 2 * 1024 * 1024 * 1024, // 2 GB
|
|
154
|
+
maxReaders: 126,
|
|
155
|
+
noSync: true,
|
|
156
|
+
noMetaSync: true
|
|
152
157
|
},
|
|
153
158
|
|
|
154
159
|
plugins: {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
6
|
+
|
|
7
|
+
const pluginsDir = path.resolve(__dirname, 'plugins');
|
|
8
|
+
|
|
9
|
+
const db = {
|
|
10
|
+
path: path.resolve(__dirname, '../db'),
|
|
11
|
+
compression: true,
|
|
12
|
+
mapSize: 2 * 1024 * 1024 * 1024, // 2 GB
|
|
13
|
+
maxReaders: 126,
|
|
14
|
+
noSync: false,
|
|
15
|
+
noMetaSync: false,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const plugins = {
|
|
19
|
+
dir: pluginsDir,
|
|
20
|
+
prefixes: ['.', '\\', '!'],
|
|
21
|
+
defaultEvent: 'messages.upsert',
|
|
22
|
+
hmr: {
|
|
23
|
+
enable: true,
|
|
24
|
+
debounce: 200,
|
|
25
|
+
debug: true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
db,
|
|
31
|
+
plugins,
|
|
32
|
+
timeZone: 'Africa/Casablanca'
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shoru/kitten",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"description": "A powerful Node.js framework to simplify making WhatsApp Bots",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"repository": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"start": "node --no-warnings src/index.js",
|
|
12
|
-
"test": "
|
|
12
|
+
"test": "node --no-warnings internal-test/index.js"
|
|
13
13
|
},
|
|
14
14
|
"imports": {
|
|
15
15
|
"#utils.js": "./src/utils/index.js",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@hapi/boom": "^10.0.1",
|
|
29
|
-
"@inquirer/prompts": "^8.
|
|
30
|
-
"@shoru/spindle": "^1.0.
|
|
29
|
+
"@inquirer/prompts": "^8.7.0",
|
|
30
|
+
"@shoru/spindle": "^1.0.7",
|
|
31
31
|
"async-mutex": "^0.5.0",
|
|
32
|
-
"baileys": "
|
|
33
|
-
"chalk": "^
|
|
32
|
+
"baileys": "github:WhiskeySockets/Baileys",
|
|
33
|
+
"chalk": "^6.0.0",
|
|
34
34
|
"chokidar": "^5.0.0",
|
|
35
|
-
"cosmiconfig": "^
|
|
36
|
-
"defu": "^6.1.
|
|
37
|
-
"lmdb": "^3.
|
|
38
|
-
"pino": "^10.1
|
|
35
|
+
"cosmiconfig": "^10.0.0",
|
|
36
|
+
"defu": "^6.1.7",
|
|
37
|
+
"lmdb": "^3.5.6",
|
|
38
|
+
"pino": "^10.3.1",
|
|
39
39
|
"pino-pretty": "^13.1.3",
|
|
40
40
|
"qrcode-terminal": "^0.12.0"
|
|
41
41
|
}
|
package/src/auth/init-session.js
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
|
-
import { makeWASocket } from "baileys";
|
|
1
|
+
import { makeWASocket, fetchLatestWaWebVersion } from "baileys";
|
|
2
2
|
import { useLMDBAuthState } from "./lmdb-auth-state.js";
|
|
3
3
|
import { getConfig } from "#internals.js";
|
|
4
4
|
|
|
5
5
|
const config = await getConfig();
|
|
6
|
+
let cachedWaVersion = null;
|
|
7
|
+
|
|
8
|
+
const getWaVersion = async () => {
|
|
9
|
+
if (!cachedWaVersion) {
|
|
10
|
+
try {
|
|
11
|
+
const { version } = await fetchLatestWaWebVersion();
|
|
12
|
+
cachedWaVersion = version;
|
|
13
|
+
} catch {/* noop */}
|
|
14
|
+
}
|
|
15
|
+
return cachedWaVersion;
|
|
16
|
+
};
|
|
6
17
|
|
|
7
18
|
export const initSession = async ({ socketConfig, id } = {}) => {
|
|
8
19
|
try {
|
|
9
20
|
const { state, saveCreds, session } = await useLMDBAuthState(id);
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
const version = (await getWaVersion()) || config.socket?.version;
|
|
22
|
+
|
|
23
|
+
const sock = makeWASocket({
|
|
24
|
+
version: version || undefined,
|
|
12
25
|
auth: state,
|
|
13
|
-
...config.socket,
|
|
26
|
+
...config.socket,
|
|
14
27
|
...socketConfig
|
|
15
28
|
});
|
|
16
|
-
|
|
29
|
+
|
|
17
30
|
sock.ev.on("creds.update", saveCreds);
|
|
18
31
|
|
|
19
32
|
return { sock, session };
|
|
@@ -1,177 +1,271 @@
|
|
|
1
|
-
import { proto, initAuthCreds } from "baileys";
|
|
2
|
-
import { LMDBManager, logger } from "#internals.js";
|
|
3
|
-
import { serialize, deserialize } from "#utils.js";
|
|
4
|
-
|
|
5
|
-
const KEY_PREFIX = "baileys";
|
|
6
|
-
const COUNTER_KEY = `${KEY_PREFIX}:__meta__:counter`;
|
|
7
|
-
const SESSION_PREFIX = `${KEY_PREFIX}:__sessions__:`;
|
|
8
|
-
|
|
9
|
-
const keyBuilder = (sessionId) => {
|
|
10
|
-
const prefix = `${KEY_PREFIX}:${sessionId}:`;
|
|
11
|
-
return {
|
|
12
|
-
sessionId,
|
|
13
|
-
sessionPrefix: prefix,
|
|
14
|
-
creds: `${prefix}creds`,
|
|
15
|
-
forKey: (type, id) => `${prefix}${type}:${id}`,
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const genID = async (db) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
1
|
+
import { proto, initAuthCreds } from "baileys";
|
|
2
|
+
import { LMDBManager, logger } from "#internals.js";
|
|
3
|
+
import { serialize, deserialize } from "#utils.js";
|
|
4
|
+
|
|
5
|
+
const KEY_PREFIX = "baileys";
|
|
6
|
+
const COUNTER_KEY = `${KEY_PREFIX}:__meta__:counter`;
|
|
7
|
+
const SESSION_PREFIX = `${KEY_PREFIX}:__sessions__:`;
|
|
8
|
+
|
|
9
|
+
const keyBuilder = (sessionId) => {
|
|
10
|
+
const prefix = `${KEY_PREFIX}:${sessionId}:`;
|
|
11
|
+
return {
|
|
12
|
+
sessionId,
|
|
13
|
+
sessionPrefix: prefix,
|
|
14
|
+
creds: `${prefix}creds`,
|
|
15
|
+
forKey: (type, id) => `${prefix}${type}:${id}`,
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const genID = async (db) => {
|
|
20
|
+
const current = db.get(COUNTER_KEY);
|
|
21
|
+
let id;
|
|
22
|
+
if (current == null) {
|
|
23
|
+
const existing = listSessions();
|
|
24
|
+
id = existing.length > 0 ? Math.max(...existing) + 1 : 0;
|
|
25
|
+
} else {
|
|
26
|
+
id = current + 1;
|
|
27
|
+
}
|
|
28
|
+
await db.put(COUNTER_KEY, id);
|
|
29
|
+
return id;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getSessionId = async (db, input) => {
|
|
33
|
+
if (input == null) {
|
|
34
|
+
const existing = listSessions();
|
|
35
|
+
if (existing.length > 0) {
|
|
36
|
+
return existing[0];
|
|
37
|
+
}
|
|
38
|
+
return genID(db);
|
|
39
|
+
}
|
|
40
|
+
if (Number.isInteger(input) && input >= 0) return input;
|
|
41
|
+
throw new TypeError(
|
|
42
|
+
'Invalid sessionId: expected null/undefined or non-negative integer'
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export async function useLMDBAuthState(inputSessionId) {
|
|
47
|
+
const { db } = LMDBManager;
|
|
48
|
+
const sessionId = await getSessionId(db, inputSessionId);
|
|
49
|
+
const keys = keyBuilder(sessionId);
|
|
50
|
+
|
|
51
|
+
const existingCreds = db.get(keys.creds);
|
|
52
|
+
let creds = null;
|
|
53
|
+
let isNew = false;
|
|
54
|
+
|
|
55
|
+
if (existingCreds != null) {
|
|
56
|
+
try {
|
|
57
|
+
creds = deserialize(existingCreds);
|
|
58
|
+
} catch {
|
|
59
|
+
logger.warn(`[LMDBAuthState] Corrupted credentials for session ${sessionId}, purging session`);
|
|
60
|
+
creds = null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (creds && (creds.registered || creds.me)) {
|
|
64
|
+
await db.put(`${SESSION_PREFIX}${sessionId}`, true);
|
|
65
|
+
} else {
|
|
66
|
+
// Credentials not registered or corrupted: clean up old session keys and start fresh
|
|
67
|
+
for (const { key } of db.getRange({
|
|
68
|
+
start: keys.sessionPrefix,
|
|
69
|
+
end: `${keys.sessionPrefix}\xFF`,
|
|
70
|
+
})) {
|
|
71
|
+
await db.remove(key);
|
|
72
|
+
}
|
|
73
|
+
await db.remove(`${SESSION_PREFIX}${sessionId}`);
|
|
74
|
+
creds = initAuthCreds();
|
|
75
|
+
await db.put(keys.creds, serialize(creds));
|
|
76
|
+
isNew = true;
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
creds = initAuthCreds();
|
|
80
|
+
await db.put(keys.creds, serialize(creds));
|
|
81
|
+
isNew = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const writeCreds = async (credsData) => {
|
|
85
|
+
await db.put(keys.creds, serialize(credsData));
|
|
86
|
+
if (credsData?.registered || credsData?.me) {
|
|
87
|
+
await db.put(`${SESSION_PREFIX}${sessionId}`, true);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const getKeys = (type, ids) => {
|
|
92
|
+
if (!ids.length) return {};
|
|
93
|
+
|
|
94
|
+
const result = {};
|
|
95
|
+
for (const id of ids) {
|
|
96
|
+
const dbKey = keys.forKey(type, id);
|
|
97
|
+
const rawValue = db.get(dbKey);
|
|
98
|
+
|
|
99
|
+
if (rawValue != null) {
|
|
100
|
+
try {
|
|
101
|
+
let parsed = deserialize(rawValue);
|
|
102
|
+
if (type === "app-state-sync-key" && parsed) {
|
|
103
|
+
parsed = proto.Message.AppStateSyncKeyData.fromObject(parsed);
|
|
104
|
+
}
|
|
105
|
+
result[id] = parsed;
|
|
106
|
+
} catch (err) {
|
|
107
|
+
logger.error(
|
|
108
|
+
err,
|
|
109
|
+
`[LMDBAuthState] Deserialize error: ${type}:${id}`
|
|
110
|
+
);
|
|
111
|
+
result[id] = null;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
result[id] = null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const setKeys = async (data) => {
|
|
121
|
+
const writes = [];
|
|
122
|
+
|
|
123
|
+
for (const [category, categoryData] of Object.entries(data)) {
|
|
124
|
+
if (!categoryData) continue;
|
|
125
|
+
for (const [id, value] of Object.entries(categoryData)) {
|
|
126
|
+
const key = keys.forKey(category, id);
|
|
127
|
+
if (value != null) {
|
|
128
|
+
writes.push(db.put(key, serialize(value)));
|
|
129
|
+
} else {
|
|
130
|
+
writes.push(db.remove(key));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (writes.length > 0) {
|
|
136
|
+
await Promise.all(writes);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const clearKeys = async () => {
|
|
141
|
+
let count = 0;
|
|
142
|
+
const writes = [];
|
|
143
|
+
|
|
144
|
+
for (const { key } of db.getRange({
|
|
145
|
+
start: keys.sessionPrefix,
|
|
146
|
+
end: `${keys.sessionPrefix}\xFF`,
|
|
147
|
+
})) {
|
|
148
|
+
if (key !== keys.creds) {
|
|
149
|
+
writes.push(db.remove(key));
|
|
150
|
+
count++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (writes.length > 0) {
|
|
155
|
+
await Promise.all(writes);
|
|
156
|
+
}
|
|
157
|
+
logger.debug(`[LMDBAuthState] Cleared ${count} keys`);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const deleteSession = async () => {
|
|
161
|
+
const writes = [];
|
|
162
|
+
|
|
163
|
+
for (const { key } of db.getRange({
|
|
164
|
+
start: keys.sessionPrefix,
|
|
165
|
+
end: `${keys.sessionPrefix}\xFF`,
|
|
166
|
+
})) {
|
|
167
|
+
writes.push(db.remove(key));
|
|
168
|
+
}
|
|
169
|
+
writes.push(db.remove(`${SESSION_PREFIX}${sessionId}`));
|
|
170
|
+
|
|
171
|
+
await Promise.all(writes);
|
|
172
|
+
logger.debug(`[LMDBAuthState] Deleted session ${sessionId}`);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
state: {
|
|
177
|
+
creds,
|
|
178
|
+
keys: {
|
|
179
|
+
get: getKeys,
|
|
180
|
+
set: setKeys,
|
|
181
|
+
clear: clearKeys,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
saveCreds: () => writeCreds(creds),
|
|
185
|
+
session: {
|
|
186
|
+
delete: deleteSession,
|
|
187
|
+
clear: clearKeys,
|
|
188
|
+
id: sessionId,
|
|
189
|
+
isNew,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function listSessions() {
|
|
195
|
+
const { db } = LMDBManager;
|
|
196
|
+
if (!db) return [];
|
|
197
|
+
|
|
198
|
+
const sessions = new Set();
|
|
199
|
+
|
|
200
|
+
for (const { key } of db.getRange({
|
|
201
|
+
start: SESSION_PREFIX,
|
|
202
|
+
end: `${SESSION_PREFIX}\xFF`,
|
|
203
|
+
})) {
|
|
204
|
+
const id = parseInt(key.slice(SESSION_PREFIX.length), 10);
|
|
205
|
+
if (!isNaN(id)) {
|
|
206
|
+
const rawCreds = db.get(`${KEY_PREFIX}:${id}:creds`);
|
|
207
|
+
if (rawCreds != null) {
|
|
208
|
+
try {
|
|
209
|
+
const creds = deserialize(rawCreds);
|
|
210
|
+
if (creds?.registered || creds?.me) {
|
|
211
|
+
sessions.add(id);
|
|
212
|
+
} else {
|
|
213
|
+
db.remove(key);
|
|
214
|
+
}
|
|
215
|
+
} catch {
|
|
216
|
+
db.remove(key);
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
db.remove(key);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Also check for existing credentials as fallback
|
|
225
|
+
for (const { key, value } of db.getRange({
|
|
226
|
+
start: `${KEY_PREFIX}:`,
|
|
227
|
+
end: `${KEY_PREFIX}:\xFF`,
|
|
228
|
+
})) {
|
|
229
|
+
if (key.endsWith(':creds')) {
|
|
230
|
+
const parts = key.split(':');
|
|
231
|
+
if (parts.length === 3 && parts[0] === KEY_PREFIX && parts[2] === 'creds') {
|
|
232
|
+
const id = parseInt(parts[1], 10);
|
|
233
|
+
if (!isNaN(id) && !sessions.has(id)) {
|
|
234
|
+
try {
|
|
235
|
+
const creds = deserialize(value);
|
|
236
|
+
if (creds?.registered || creds?.me) {
|
|
237
|
+
sessions.add(id);
|
|
238
|
+
db.put(`${SESSION_PREFIX}${id}`, true);
|
|
239
|
+
}
|
|
240
|
+
} catch {
|
|
241
|
+
/* ignore corrupted creds */
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return [...sessions].sort((a, b) => a - b);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function sessionExists(sessionId) {
|
|
252
|
+
if (!Number.isInteger(sessionId) || sessionId < 0) return false;
|
|
253
|
+
const { db } = LMDBManager;
|
|
254
|
+
if (!db) return false;
|
|
255
|
+
|
|
256
|
+
const rawCreds = db.get(`${KEY_PREFIX}:${sessionId}:creds`);
|
|
257
|
+
if (rawCreds != null) {
|
|
258
|
+
try {
|
|
259
|
+
const creds = deserialize(rawCreds);
|
|
260
|
+
if (creds?.registered || creds?.me) {
|
|
261
|
+
db.put(`${SESSION_PREFIX}${sessionId}`, true);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
} catch {
|
|
265
|
+
db.remove(`${SESSION_PREFIX}${sessionId}`);
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
db.remove(`${SESSION_PREFIX}${sessionId}`);
|
|
270
|
+
return false;
|
|
177
271
|
}
|