@chainlesschain/personal-data-hub 0.3.0 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/adapters/email-adapter-snapshot.test.js +237 -0
- package/__tests__/adapters/email-adapter.test.js +1 -1
- package/__tests__/adapters/email-pdf-extractor.test.js +1 -1
- package/__tests__/adapters/email-retry-progress.test.js +1 -1
- package/__tests__/adapters/email-templates.test.js +1 -1
- package/__tests__/adapters/social-bilibili-adb-api-client.test.js +721 -0
- package/__tests__/adapters/social-bilibili-adb-chromium-cookies-reader.test.js +346 -0
- package/__tests__/adapters/social-bilibili-adb-collector.test.js +284 -0
- package/__tests__/adapters/social-bilibili-adb-cookies-extension.test.js +343 -0
- package/__tests__/adapters/social-bilibili-adb-snapshot-builder.test.js +296 -0
- package/__tests__/adapters/social-douyin-adb-collector.test.js +254 -0
- package/__tests__/adapters/social-douyin-adb-im-db-parser.test.js +304 -0
- package/__tests__/adapters/social-douyin-adb-snapshot-builder.test.js +216 -0
- package/__tests__/adapters/social-weibo-adb-api-client.test.js +362 -0
- package/__tests__/adapters/social-weibo-adb-collector.test.js +201 -0
- package/__tests__/adapters/social-weibo-adb-snapshot-builder.test.js +189 -0
- package/__tests__/adapters/social-xiaohongshu-adb-collector.test.js +207 -0
- package/__tests__/adapters/social-xiaohongshu-adb-sign.test.js +130 -0
- package/__tests__/adapters/system-data-android.test.js +32 -1
- package/__tests__/longtail-adapters.test.js +15 -2
- package/__tests__/shopping-adapters.test.js +96 -0
- package/__tests__/sign-providers.test.js +62 -0
- package/__tests__/travel-adapters.test.js +163 -5
- package/__tests__/whatsapp-adapter.test.js +5 -2
- package/lib/adapters/browser-history-chrome/chrome-db-reader.js +11 -1
- package/lib/adapters/email-imap/email-adapter.js +224 -17
- package/lib/adapters/messaging-telegram/index.js +15 -12
- package/lib/adapters/messaging-whatsapp/index.js +15 -12
- package/lib/adapters/shopping-taobao/index.js +161 -21
- package/lib/adapters/social-bilibili-adb/api-client.js +555 -0
- package/lib/adapters/social-bilibili-adb/chromium-cookies-reader.js +296 -0
- package/lib/adapters/social-bilibili-adb/collector.js +190 -0
- package/lib/adapters/social-bilibili-adb/cookies-extension.js +250 -0
- package/lib/adapters/social-bilibili-adb/index.js +51 -0
- package/lib/adapters/social-bilibili-adb/snapshot-builder.js +197 -0
- package/lib/adapters/social-douyin/index.js +4 -0
- package/lib/adapters/social-douyin-adb/collector.js +165 -0
- package/lib/adapters/social-douyin-adb/db-extension.js +281 -0
- package/lib/adapters/social-douyin-adb/im-db-parser.js +287 -0
- package/lib/adapters/social-douyin-adb/index.js +57 -0
- package/lib/adapters/social-douyin-adb/snapshot-builder.js +174 -0
- package/lib/adapters/social-weibo-adb/api-client.js +281 -0
- package/lib/adapters/social-weibo-adb/collector.js +169 -0
- package/lib/adapters/social-weibo-adb/cookies-extension.js +251 -0
- package/lib/adapters/social-weibo-adb/index.js +55 -0
- package/lib/adapters/social-weibo-adb/snapshot-builder.js +145 -0
- package/lib/adapters/social-xiaohongshu-adb/api-client.js +278 -0
- package/lib/adapters/social-xiaohongshu-adb/collector.js +158 -0
- package/lib/adapters/social-xiaohongshu-adb/cookies-extension.js +211 -0
- package/lib/adapters/social-xiaohongshu-adb/index.js +50 -0
- package/lib/adapters/social-xiaohongshu-adb/sign.js +90 -0
- package/lib/adapters/social-xiaohongshu-adb/snapshot-builder.js +126 -0
- package/lib/adapters/system-data-android/adapter.js +77 -3
- package/lib/adapters/travel-12306/index.js +215 -29
- package/lib/adapters/travel-amap/index.js +16 -10
- package/lib/adapters/travel-ctrip/index.js +25 -9
- package/lib/adapters/vscode/vscode-reader.js +7 -1
- package/lib/sign-providers/index.js +20 -0
- package/lib/sign-providers/interface.js +82 -0
- package/lib/sign-providers/null-sign-provider.js +30 -0
- package/package.json +6 -1
|
@@ -19,20 +19,22 @@ const fs = require("node:fs");
|
|
|
19
19
|
const { normalizeTravelRecord, parseChineseDateTime } = require("../travel-base");
|
|
20
20
|
|
|
21
21
|
const NAME = "travel-amap";
|
|
22
|
-
const VERSION = "0.
|
|
22
|
+
const VERSION = "0.6.0"; // 2026-05-25 — account.deviceId OPTIONAL + inputPath alias
|
|
23
23
|
|
|
24
24
|
class AmapAdapter {
|
|
25
25
|
constructor(opts = {}) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
// 2026-05-25 — account.deviceId OPTIONAL (mirror Taobao/Ctrip/Telegram).
|
|
27
|
+
// sqlite-mode adapter still requires user to provide a pulled amap.db
|
|
28
|
+
// (`/data/data/com.autonavi.minimap/databases/amap.db`). Earlier strict
|
|
29
|
+
// ctor blocked auto-register at boot → silent "no adapter travel-amap"
|
|
30
|
+
// when Android collector ships extracted db.
|
|
31
|
+
this.account = opts.account || null;
|
|
32
|
+
this._dbPath = opts.dbPath || opts.inputPath || null;
|
|
31
33
|
this._dbDriverFactory = opts.dbDriverFactory || null;
|
|
32
34
|
|
|
33
35
|
this.name = NAME;
|
|
34
36
|
this.version = VERSION;
|
|
35
|
-
this.capabilities = ["sync:sqlite", "parse:amap-history"];
|
|
37
|
+
this.capabilities = ["sync:sqlite", "sync:snapshot", "parse:amap-history"];
|
|
36
38
|
this.extractMode = "device-pull";
|
|
37
39
|
this.rateLimits = {};
|
|
38
40
|
this.dataDisclosure = {
|
|
@@ -46,8 +48,12 @@ class AmapAdapter {
|
|
|
46
48
|
};
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
async authenticate() {
|
|
50
|
-
|
|
51
|
+
async authenticate(ctx = {}) {
|
|
52
|
+
const dbPath = (ctx && (ctx.inputPath || ctx.dbPath)) || this._dbPath;
|
|
53
|
+
if (!dbPath || !fs.existsSync(dbPath)) {
|
|
54
|
+
return { ok: true, account: this.account ? this.account.deviceId : null, mode: "ready" };
|
|
55
|
+
}
|
|
56
|
+
return { ok: true, account: this.account ? this.account.deviceId : null, mode: "snapshot-file" };
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
async healthCheck() {
|
|
@@ -55,7 +61,7 @@ class AmapAdapter {
|
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
async *sync(opts = {}) {
|
|
58
|
-
const dbPath = opts.dbPath || this._dbPath;
|
|
64
|
+
const dbPath = opts.inputPath || opts.dbPath || this._dbPath;
|
|
59
65
|
if (!dbPath || !fs.existsSync(dbPath)) return;
|
|
60
66
|
const Database = this._dbDriverFactory || (() => require("better-sqlite3-multiple-ciphers"));
|
|
61
67
|
const Driver = typeof Database === "function" ? Database() : Database;
|
|
@@ -16,19 +16,21 @@ const fs = require("node:fs");
|
|
|
16
16
|
const { normalizeTravelRecord, parseChineseDateTime } = require("../travel-base");
|
|
17
17
|
|
|
18
18
|
const NAME = "travel-ctrip";
|
|
19
|
-
const VERSION = "0.
|
|
19
|
+
const VERSION = "0.6.0"; // §9.3b — account.email OPTIONAL + inputPath snapshot alias
|
|
20
20
|
|
|
21
21
|
class CtripAdapter {
|
|
22
22
|
constructor(opts = {}) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
// §9.3b 2026-05-25 — account.email OPTIONAL (mirror shopping-jd/taobao
|
|
24
|
+
// dual-mode). file-import mode is stateless; bookkeeping account.email
|
|
25
|
+
// is informational, not gating. Earlier strict ctor blocked
|
|
26
|
+
// auto-register at boot → Android collector ship JSON staging path
|
|
27
|
+
// failed with silent "no adapter travel-ctrip".
|
|
28
|
+
this.account = opts.account || null;
|
|
27
29
|
this._dataPath = opts.dataPath || null;
|
|
28
30
|
|
|
29
31
|
this.name = NAME;
|
|
30
32
|
this.version = VERSION;
|
|
31
|
-
this.capabilities = ["import:json", "parse:ctrip-orders"];
|
|
33
|
+
this.capabilities = ["import:json", "sync:snapshot", "parse:ctrip-orders"];
|
|
32
34
|
this.extractMode = "file-import";
|
|
33
35
|
this.rateLimits = {};
|
|
34
36
|
this.dataDisclosure = {
|
|
@@ -40,8 +42,19 @@ class CtripAdapter {
|
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
async authenticate() {
|
|
44
|
-
|
|
45
|
+
async authenticate(ctx = {}) {
|
|
46
|
+
// Snapshot / file-import path: validate file readable when an inputPath
|
|
47
|
+
// / dataPath is provided. Otherwise return ok with whatever account
|
|
48
|
+
// bookkeeping we have (file path can be supplied later via sync(opts)).
|
|
49
|
+
const filePath = (ctx && ctx.inputPath) || ctx.dataPath || this._dataPath;
|
|
50
|
+
if (filePath) {
|
|
51
|
+
try { fs.accessSync(filePath, fs.constants.R_OK); }
|
|
52
|
+
catch (err) {
|
|
53
|
+
return { ok: false, reason: "INPUT_PATH_UNREADABLE", message: `not readable at ${filePath}: ${err.message}` };
|
|
54
|
+
}
|
|
55
|
+
return { ok: true, mode: "snapshot-file" };
|
|
56
|
+
}
|
|
57
|
+
return { ok: true, account: this.account ? this.account.email : null, mode: "ready" };
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
async healthCheck() {
|
|
@@ -49,7 +62,10 @@ class CtripAdapter {
|
|
|
49
62
|
}
|
|
50
63
|
|
|
51
64
|
async *sync(opts = {}) {
|
|
52
|
-
|
|
65
|
+
// Snapshot mode aliases dataPath → inputPath so Android in-APK cc can
|
|
66
|
+
// call syncAdapter("travel-ctrip", path) with the same shape it uses
|
|
67
|
+
// for the other snapshot-mode adapters (shopping-jd / travel-12306).
|
|
68
|
+
const dataPath = opts.inputPath || opts.dataPath || this._dataPath;
|
|
53
69
|
if (!dataPath || !fs.existsSync(dataPath)) return;
|
|
54
70
|
const text = fs.readFileSync(dataPath, "utf-8");
|
|
55
71
|
let records;
|
|
@@ -23,7 +23,12 @@ const os = require("node:os");
|
|
|
23
23
|
// Dual-load: bs3mc tracks Electron's ABI 140 (runtime path), plain
|
|
24
24
|
// better-sqlite3 tracks Node's ABI 127 (test path). Whichever loads
|
|
25
25
|
// wins. See chrome-db-reader.js for the same pattern + rationale.
|
|
26
|
+
//
|
|
27
|
+
// CRITICAL: must be lazy. Top-level invocation kills main process when
|
|
28
|
+
// both modules absent/ABI-mismatched (v5.0.3.87 startup crash).
|
|
29
|
+
let _cachedDatabaseClass = null;
|
|
26
30
|
function loadDatabase() {
|
|
31
|
+
if (_cachedDatabaseClass) return _cachedDatabaseClass;
|
|
27
32
|
for (const mod of ["better-sqlite3-multiple-ciphers", "better-sqlite3"]) {
|
|
28
33
|
let cls;
|
|
29
34
|
try {
|
|
@@ -35,6 +40,7 @@ function loadDatabase() {
|
|
|
35
40
|
try {
|
|
36
41
|
const probe = new cls(":memory:");
|
|
37
42
|
probe.close();
|
|
43
|
+
_cachedDatabaseClass = cls;
|
|
38
44
|
return cls;
|
|
39
45
|
} catch (_e) {
|
|
40
46
|
/* ABI mismatch, try next */
|
|
@@ -44,7 +50,6 @@ function loadDatabase() {
|
|
|
44
50
|
"vscode-reader: neither better-sqlite3-multiple-ciphers nor better-sqlite3 loaded — both ABI-mismatched",
|
|
45
51
|
);
|
|
46
52
|
}
|
|
47
|
-
const Database = loadDatabase();
|
|
48
53
|
|
|
49
54
|
function defaultVscodeRoot() {
|
|
50
55
|
if (process.platform === "win32") {
|
|
@@ -136,6 +141,7 @@ function readTerminalHistory(vscodeRoot, opts = {}) {
|
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
try {
|
|
144
|
+
const Database = loadDatabase();
|
|
139
145
|
const db = new Database(tmp, { readonly: true });
|
|
140
146
|
const get = (k) => {
|
|
141
147
|
try {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Phase 6a (2026-05-25) — sign-providers entry point.
|
|
5
|
+
*
|
|
6
|
+
* Re-exports the abstract `SignProvider` contract + the default
|
|
7
|
+
* `NullSignProvider` impl. Real implementations live in the desktop
|
|
8
|
+
* Electron main process (`desktop-app-vue/src/main/sign-bridge/`)
|
|
9
|
+
* because they need a WebContentsView. CLI / web-shell / test code
|
|
10
|
+
* uses NullSignProvider unless desktop-side wiring injects a real one.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { SignProvider } = require("./interface");
|
|
14
|
+
const { NullSignProvider, NULL_SIGN_PROVIDER } = require("./null-sign-provider");
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
SignProvider,
|
|
18
|
+
NullSignProvider,
|
|
19
|
+
NULL_SIGN_PROVIDER,
|
|
20
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Phase 6a (2026-05-25) — SignProvider abstract contract for platforms
|
|
5
|
+
* that require per-request signatures (Toutiao `_signature` / Kuaishou
|
|
6
|
+
* `NS_sig3` / Xhs `X-S` / Douyin `X-Bogus`).
|
|
7
|
+
*
|
|
8
|
+
* Mirror of Android-side `pdh/social/SignProvider.kt`. Same 3-method
|
|
9
|
+
* interface so Node API clients can swap impl without changes:
|
|
10
|
+
*
|
|
11
|
+
* - `signUrl(rawUrl, purpose)` — Some platforms (Toutiao, Kuaishou)
|
|
12
|
+
* append `_signature=...` / `NS_sig3=...` to the URL itself; this
|
|
13
|
+
* returns a NEW URL with sig appended, OR `null` if signing failed.
|
|
14
|
+
*
|
|
15
|
+
* - `signedHeaders(rawUrl, purpose)` — Other platforms (Xhs) leave
|
|
16
|
+
* the URL alone and put `X-S` / `X-T` / `X-S-Common` in HTTP
|
|
17
|
+
* headers; this returns an object of header name → value, possibly
|
|
18
|
+
* empty when signing failed.
|
|
19
|
+
*
|
|
20
|
+
* - `shutdown()` — Release the WebContentsView / WebView held by the
|
|
21
|
+
* bridge implementation. Idempotent.
|
|
22
|
+
*
|
|
23
|
+
* **The two methods are independent** — a bridge for Toutiao implements
|
|
24
|
+
* signUrl (URL mutation), Xhs implements signedHeaders (header set).
|
|
25
|
+
* The base abstract returns null/empty for both so subclasses only
|
|
26
|
+
* implement what they need.
|
|
27
|
+
*
|
|
28
|
+
* **`purpose` string** is platform-defined opaque context the JS in the
|
|
29
|
+
* WebContentsView needs to discriminate which signing function to call.
|
|
30
|
+
* For Xhs we encode as `"<pathWithQuery>|<bodyJsonOrEmpty>"`. For
|
|
31
|
+
* Toutiao we use a string like `"feed"` / `"collection"` to pick the
|
|
32
|
+
* acrawler.js entry point. Subclasses define the schema.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Abstract base — direct subclassing in JS uses prototypal extension;
|
|
37
|
+
* the methods here are stubs returning null/empty so subclasses can
|
|
38
|
+
* implement only what their platform needs.
|
|
39
|
+
*/
|
|
40
|
+
class SignProvider {
|
|
41
|
+
/**
|
|
42
|
+
* Sign a URL by appending platform-specific query params (e.g.
|
|
43
|
+
* Toutiao's `_signature`). Returns a new URL string with sig
|
|
44
|
+
* appended, or `null` if signing failed (bridge cold / JS rotated).
|
|
45
|
+
*
|
|
46
|
+
* The caller (api-client) MUST handle `null` by surfacing a
|
|
47
|
+
* lastErrorCode like -99 ("_signature unavailable") and returning
|
|
48
|
+
* empty result for that endpoint, NOT throwing.
|
|
49
|
+
*
|
|
50
|
+
* @param {URL|string} rawUrl the unsigned URL
|
|
51
|
+
* @param {string} purpose opaque context for the bridge's JS
|
|
52
|
+
* @returns {Promise<string|null>} signed URL or null
|
|
53
|
+
*/
|
|
54
|
+
async signUrl(_rawUrl, _purpose) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Sign by returning HTTP headers to merge into the request (e.g.
|
|
60
|
+
* Xhs `X-S` / `X-T` / `X-S-Common`). Returns an object — empty
|
|
61
|
+
* map `{}` when signing failed (NOT null) so callers can spread
|
|
62
|
+
* the result unconditionally.
|
|
63
|
+
*
|
|
64
|
+
* @param {URL|string} rawUrl
|
|
65
|
+
* @param {string} purpose
|
|
66
|
+
* @returns {Promise<{[name: string]: string}>}
|
|
67
|
+
*/
|
|
68
|
+
async signedHeaders(_rawUrl, _purpose) {
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Release WebContentsView and any background resources. Idempotent —
|
|
74
|
+
* the api-client calls this in a `finally` so racing shutdowns
|
|
75
|
+
* must not throw.
|
|
76
|
+
*/
|
|
77
|
+
async shutdown() {
|
|
78
|
+
// no-op default
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = { SignProvider };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Phase 6a (2026-05-25) — NullSignProvider: default no-op for callers
|
|
5
|
+
* that don't have a WebContentsView context (e.g. headless `cc serve`
|
|
6
|
+
* without Electron, or unit tests).
|
|
7
|
+
*
|
|
8
|
+
* Mirror of Android `pdh/social/NullSignProvider.kt`.
|
|
9
|
+
*
|
|
10
|
+
* API clients use this as the default — when wiring upgrades to
|
|
11
|
+
* Electron+WebContentsView, swap to `XhsSignBridge` / `ToutiaoSignBridge`
|
|
12
|
+
* etc. **without changing the api-client code**. The signing endpoints
|
|
13
|
+
* gracefully degrade to "best-effort" or "empty result" rather than
|
|
14
|
+
* throwing.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { SignProvider } = require("./interface");
|
|
18
|
+
|
|
19
|
+
class NullSignProvider extends SignProvider {
|
|
20
|
+
// Inherits all stubs from base — signUrl returns null,
|
|
21
|
+
// signedHeaders returns {}, shutdown is no-op.
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Frozen singleton — callers should not create multiple NullSignProviders. */
|
|
25
|
+
const NULL_SIGN_PROVIDER = Object.freeze(new NullSignProvider());
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
NullSignProvider,
|
|
29
|
+
NULL_SIGN_PROVIDER,
|
|
30
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainlesschain/personal-data-hub",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Personal Data Hub — UnifiedSchema + validators + KG ingest helpers for the data-back-to-the-individual middleware",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"./bridges/cc-llm-adapter": "./lib/bridges/cc-llm-adapter.js",
|
|
28
28
|
"./bridges/cc-kg-sink": "./lib/bridges/cc-kg-sink.js",
|
|
29
29
|
"./bridges/cc-rag-sink": "./lib/bridges/cc-rag-sink.js",
|
|
30
|
+
"./sign-providers": "./lib/sign-providers/index.js",
|
|
30
31
|
"./adapters/email-imap": "./lib/adapters/email-imap/index.js",
|
|
31
32
|
"./adapters/alipay-bill": "./lib/adapters/alipay-bill/index.js",
|
|
32
33
|
"./adapters/system-data": "./lib/adapters/system-data/index.js",
|
|
@@ -53,9 +54,13 @@
|
|
|
53
54
|
"./adapters/shopping-jd": "./lib/adapters/shopping-jd/index.js",
|
|
54
55
|
"./adapters/shopping-meituan": "./lib/adapters/shopping-meituan/index.js",
|
|
55
56
|
"./adapters/social-bilibili": "./lib/adapters/social-bilibili/index.js",
|
|
57
|
+
"./adapters/social-bilibili-adb": "./lib/adapters/social-bilibili-adb/index.js",
|
|
56
58
|
"./adapters/social-weibo": "./lib/adapters/social-weibo/index.js",
|
|
59
|
+
"./adapters/social-weibo-adb": "./lib/adapters/social-weibo-adb/index.js",
|
|
57
60
|
"./adapters/social-douyin": "./lib/adapters/social-douyin/index.js",
|
|
61
|
+
"./adapters/social-douyin-adb": "./lib/adapters/social-douyin-adb/index.js",
|
|
58
62
|
"./adapters/social-xiaohongshu": "./lib/adapters/social-xiaohongshu/index.js",
|
|
63
|
+
"./adapters/social-xiaohongshu-adb": "./lib/adapters/social-xiaohongshu-adb/index.js",
|
|
59
64
|
"./adapters/messaging-qq": "./lib/adapters/messaging-qq/index.js",
|
|
60
65
|
"./adapters/messaging-telegram": "./lib/adapters/messaging-telegram/index.js",
|
|
61
66
|
"./adapters/messaging-whatsapp": "./lib/adapters/messaging-whatsapp/index.js",
|