@chainlesschain/personal-data-hub 0.4.7 → 0.4.23

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.
Files changed (45) hide show
  1. package/__tests__/adapters/biz-tianyancha.test.js +159 -0
  2. package/__tests__/adapters/doc-baidu-netdisk.test.js +102 -0
  3. package/__tests__/adapters/doc-camscanner.test.js +147 -0
  4. package/__tests__/adapters/doc-platforms.test.js +177 -0
  5. package/__tests__/adapters/gov-ixiamen.test.js +150 -0
  6. package/__tests__/adapters/gov-tax.test.js +135 -0
  7. package/__tests__/adapters/health-meiyou.test.js +125 -0
  8. package/__tests__/adapters/music-kugou.test.js +187 -0
  9. package/__tests__/adapters/recruit-boss.test.js +180 -0
  10. package/__tests__/adapters/shopping-dianping.test.js +239 -0
  11. package/__tests__/adapters/social-csdn.test.js +175 -0
  12. package/__tests__/adapters/social-dongchedi.test.js +165 -0
  13. package/__tests__/adapters/social-zhihu.test.js +246 -0
  14. package/__tests__/adapters/travel-ctrip.test.js +175 -1
  15. package/__tests__/adapters/travel-didi.test.js +204 -0
  16. package/__tests__/adapters/travel-tongcheng.test.js +289 -0
  17. package/__tests__/adapters/video-platforms.test.js +152 -0
  18. package/__tests__/adapters/video-xigua.test.js +106 -0
  19. package/__tests__/adapters/wework-pc.test.js +124 -0
  20. package/lib/adapter-guide.js +25 -3
  21. package/lib/adapters/_document-base.js +370 -0
  22. package/lib/adapters/_video-base.js +331 -0
  23. package/lib/adapters/biz-tianyancha/index.js +348 -0
  24. package/lib/adapters/doc-baidu-netdisk/index.js +91 -0
  25. package/lib/adapters/doc-camscanner/index.js +102 -0
  26. package/lib/adapters/doc-tencent-docs/index.js +94 -0
  27. package/lib/adapters/doc-wps/index.js +77 -0
  28. package/lib/adapters/gov-ixiamen/index.js +380 -0
  29. package/lib/adapters/gov-tax/index.js +451 -0
  30. package/lib/adapters/health-meiyou/index.js +393 -0
  31. package/lib/adapters/music-kugou/index.js +418 -0
  32. package/lib/adapters/recruit-boss/index.js +442 -0
  33. package/lib/adapters/shopping-dianping/index.js +473 -0
  34. package/lib/adapters/social-csdn/index.js +444 -0
  35. package/lib/adapters/social-dongchedi/index.js +360 -0
  36. package/lib/adapters/social-zhihu/index.js +488 -0
  37. package/lib/adapters/travel-ctrip/index.js +255 -40
  38. package/lib/adapters/travel-didi/index.js +327 -0
  39. package/lib/adapters/travel-tongcheng/index.js +393 -0
  40. package/lib/adapters/video-iqiyi/index.js +75 -0
  41. package/lib/adapters/video-tencent/index.js +78 -0
  42. package/lib/adapters/video-xigua/index.js +68 -0
  43. package/lib/adapters/wework-pc/index.js +31 -0
  44. package/lib/index.js +40 -0
  45. package/package.json +1 -1
@@ -0,0 +1,91 @@
1
+ /**
2
+ * §13+ — 百度网盘 (Baidu Netdisk, com.baidu.netdisk) adapter. §12.1 ROI ⭐⭐⭐
3
+ * "文件 + 外链".
4
+ *
5
+ * Thin wrapper over _document-base — a cloud-drive file list is the same shape
6
+ * as the doc-wps / doc-tencent-docs "own-document list". Baidu Netdisk exposes
7
+ * the owner's files via pan.baidu.com/api/list (BDUSS cookie); this adapter
8
+ * supplies the endpoint + field mapping, the base handles snapshot + cookie-api
9
+ * orchestration + normalize (event POST + item DOCUMENT). Endpoint best-effort +
10
+ * overridable via opts.listUrl (not field-verified — FAMILY-23 playbook).
11
+ */
12
+
13
+ "use strict";
14
+
15
+ const { createDocumentAdapter, parseTime, SNAPSHOT_SCHEMA_VERSION } = require("../_document-base");
16
+
17
+ const NAME = "doc-baidu-netdisk";
18
+ const VERSION = "0.1.0";
19
+
20
+ // Best-effort Baidu Netdisk file-list endpoint. Overridable via opts.listUrl.
21
+ const NETDISK_LIST_URL = "https://pan.baidu.com/api/list";
22
+
23
+ // Baidu Netdisk `category` codes → normalized docType.
24
+ const CATEGORY_MAP = {
25
+ 1: "video",
26
+ 2: "audio",
27
+ 3: "image",
28
+ 4: "doc",
29
+ 5: "app",
30
+ 6: "other",
31
+ 7: "seed",
32
+ };
33
+
34
+ function mapNetdiskType(d) {
35
+ if (d.isdir === 1 || d.isdir === true) return "folder";
36
+ const cat = d.category != null ? d.category : d.file_category;
37
+ if (cat != null && CATEGORY_MAP[cat]) return CATEGORY_MAP[cat];
38
+ const name = String(d.server_filename || d.filename || "").toLowerCase();
39
+ if (/\.(mp4|mkv|avi|mov)$/.test(name)) return "video";
40
+ if (/\.(mp3|flac|wav|m4a)$/.test(name)) return "audio";
41
+ if (/\.(jpg|jpeg|png|gif|webp)$/.test(name)) return "image";
42
+ if (/\.(docx?|xlsx?|pptx?|pdf|txt)$/.test(name)) return "doc";
43
+ return "file";
44
+ }
45
+
46
+ function extractDocs(resp) {
47
+ if (!resp || typeof resp !== "object") return [];
48
+ if (Array.isArray(resp.list)) return resp.list;
49
+ if (Array.isArray(resp.data)) return resp.data;
50
+ if (resp.data && Array.isArray(resp.data.list)) return resp.data.list;
51
+ return [];
52
+ }
53
+
54
+ function mapDoc(d) {
55
+ if (!d || typeof d !== "object") return null;
56
+ const docId = d.fs_id || d.fsId || d.id || d.path;
57
+ if (!docId) return null;
58
+ return {
59
+ docId: String(docId),
60
+ title: d.server_filename || d.filename || d.title || "(未命名)",
61
+ docType: mapNetdiskType(d),
62
+ url: d.path || d.dlink || null,
63
+ createdMs: parseTime(d.server_ctime || d.local_ctime || d.ctime),
64
+ updatedMs: parseTime(d.server_mtime || d.local_mtime || d.mtime),
65
+ extra: {
66
+ size: d.size != null ? d.size : null,
67
+ isDir: d.isdir === 1 || d.isdir === true ? true : false,
68
+ path: d.path || null,
69
+ category: d.category != null ? d.category : null,
70
+ },
71
+ };
72
+ }
73
+
74
+ const BaiduNetdiskAdapter = createDocumentAdapter({
75
+ NAME,
76
+ VERSION,
77
+ platform: "baidu-netdisk",
78
+ defaultListUrl: NETDISK_LIST_URL,
79
+ extractDocs,
80
+ mapDoc,
81
+ });
82
+
83
+ module.exports = {
84
+ BaiduNetdiskAdapter,
85
+ extractDocs,
86
+ mapDoc,
87
+ CATEGORY_MAP,
88
+ NAME,
89
+ VERSION,
90
+ SNAPSHOT_SCHEMA_VERSION,
91
+ };
@@ -0,0 +1,102 @@
1
+ /**
2
+ * §13+ — 扫描全能王 (CamScanner, com.intsig.camscanner) adapter. §12.1 ROI ⭐⭐
3
+ * "扫描文档归档".
4
+ *
5
+ * Thin wrapper over _document-base — CamScanner's scanned-document archive is
6
+ * the same shape as the doc-wps / doc-tencent-docs / doc-baidu-netdisk
7
+ * "own-document list": each scanned doc has a title, page count, create/modify
8
+ * time, and a PDF/jump url. CamScanner syncs the owner's docs to its cloud
9
+ * (intsig sync API, session cookie / sync token); this adapter supplies the
10
+ * endpoint + field mapping, the base handles snapshot + cookie-api orchestration
11
+ * + normalize (event POST + item DOCUMENT). Endpoint best-effort + overridable
12
+ * via opts.listUrl (not field-verified — FAMILY-23 playbook). A signProvider
13
+ * seam covers intsig's request signature; best-effort unsigned when absent.
14
+ */
15
+
16
+ "use strict";
17
+
18
+ const { createDocumentAdapter, parseTime, SNAPSHOT_SCHEMA_VERSION } = require("../_document-base");
19
+
20
+ const NAME = "doc-camscanner";
21
+ const VERSION = "0.1.0";
22
+
23
+ // Best-effort CamScanner cloud doc-list endpoint. Overridable via opts.listUrl.
24
+ const CAMSCANNER_LIST_URL = "https://sync.intsig.net/sync/list_docs";
25
+
26
+ // CamScanner document type hints → normalized docType. A CamScanner "doc" is a
27
+ // scanned bundle of pages exportable as PDF; certificate/book/excel are OCR
28
+ // sub-modes the app offers.
29
+ const TYPE_MAP = {
30
+ 0: "scan",
31
+ 1: "scan",
32
+ 2: "certificate",
33
+ 3: "book",
34
+ 4: "excel",
35
+ 5: "ppt",
36
+ pdf: "pdf",
37
+ doc: "scan",
38
+ certificate: "certificate",
39
+ book: "book",
40
+ excel: "excel",
41
+ ppt: "ppt",
42
+ };
43
+
44
+ function mapCamScannerType(d) {
45
+ const t = d.doc_type != null ? d.doc_type : d.type;
46
+ if (t != null && TYPE_MAP[t] != null) return TYPE_MAP[t];
47
+ const title = String(d.title || d.doc_title || d.pdf_name || "").toLowerCase();
48
+ if (/\.pdf$/.test(title)) return "pdf";
49
+ if (/\.(xlsx?|csv)$/.test(title)) return "excel";
50
+ if (/\.(pptx?)$/.test(title)) return "ppt";
51
+ return "scan";
52
+ }
53
+
54
+ function extractDocs(resp) {
55
+ if (!resp || typeof resp !== "object") return [];
56
+ if (Array.isArray(resp.docs)) return resp.docs;
57
+ if (Array.isArray(resp.list)) return resp.list;
58
+ if (Array.isArray(resp.data)) return resp.data;
59
+ if (resp.data && Array.isArray(resp.data.docs)) return resp.data.docs;
60
+ if (resp.data && Array.isArray(resp.data.list)) return resp.data.list;
61
+ return [];
62
+ }
63
+
64
+ function mapDoc(d) {
65
+ if (!d || typeof d !== "object") return null;
66
+ const docId = d.sync_doc_id || d.doc_id || d.docId || d.id || d.sid;
67
+ if (!docId) return null;
68
+ const pages = d.page_num != null ? d.page_num : d.pages != null ? d.pages : d.page_count;
69
+ return {
70
+ docId: String(docId),
71
+ title: d.title || d.doc_title || d.pdf_name || "(未命名扫描件)",
72
+ docType: mapCamScannerType(d),
73
+ url: d.pdf_url || d.url || d.jump_url || null,
74
+ createdMs: parseTime(d.create_time || d.upload_time || d.ctime || d.created),
75
+ updatedMs: parseTime(d.modify_time || d.last_modify_time || d.update_time || d.mtime),
76
+ extra: {
77
+ pageNum: Number.isFinite(Number(pages)) ? Number(pages) : null,
78
+ tags: Array.isArray(d.tags) ? d.tags : d.tag != null ? [d.tag] : [],
79
+ folder: d.dir_title || d.folder || null,
80
+ },
81
+ };
82
+ }
83
+
84
+ const CamScannerDocAdapter = createDocumentAdapter({
85
+ NAME,
86
+ VERSION,
87
+ platform: "camscanner",
88
+ defaultListUrl: CAMSCANNER_LIST_URL,
89
+ extractDocs,
90
+ mapDoc,
91
+ });
92
+
93
+ module.exports = {
94
+ CamScannerDocAdapter,
95
+ extractDocs,
96
+ mapDoc,
97
+ mapCamScannerType,
98
+ TYPE_MAP,
99
+ NAME,
100
+ VERSION,
101
+ SNAPSHOT_SCHEMA_VERSION,
102
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * §13+ — 腾讯文档 (Tencent Docs) adapter. "自创文档列表" (§12.1, ROI ⭐⭐⭐).
3
+ *
4
+ * Thin wrapper over _document-base. 腾讯文档 exposes the owner's documents via
5
+ * docs.qq.com dop-api; this adapter supplies the endpoint + field mapping, the
6
+ * base handles snapshot + cookie-api orchestration + normalize. Endpoint is
7
+ * best-effort + overridable via opts.listUrl (docs.qq.com rotates its dop-api;
8
+ * some calls need a sign — opts.signProvider seam — FAMILY-23 playbook, not
9
+ * field-verified).
10
+ */
11
+
12
+ "use strict";
13
+
14
+ const { createDocumentAdapter, parseTime, SNAPSHOT_SCHEMA_VERSION } = require("../_document-base");
15
+
16
+ const NAME = "doc-tencent-docs";
17
+ const VERSION = "0.1.0";
18
+
19
+ // Best-effort Tencent Docs "my documents" list. Overridable via opts.listUrl.
20
+ const TENCENT_DOCS_LIST_URL = "https://docs.qq.com/dop-api/get/personal/files";
21
+
22
+ // Tencent Docs type codes → normalized docType.
23
+ const TYPE_MAP = {
24
+ doc: "doc",
25
+ document: "doc",
26
+ sheet: "sheet",
27
+ spreadsheet: "sheet",
28
+ slide: "slide",
29
+ presentation: "slide",
30
+ pdf: "pdf",
31
+ form: "form",
32
+ mind: "mind",
33
+ 1: "doc",
34
+ 2: "sheet",
35
+ 3: "slide",
36
+ };
37
+
38
+ function mapTencentType(d) {
39
+ const raw = d.type != null ? d.type : d.docType != null ? d.docType : d.fileType;
40
+ const key = String(raw == null ? "" : raw).toLowerCase();
41
+ return TYPE_MAP[key] || TYPE_MAP[raw] || "doc";
42
+ }
43
+
44
+ function extractDocs(resp) {
45
+ if (!resp || typeof resp !== "object") return [];
46
+ if (Array.isArray(resp.files)) return resp.files;
47
+ if (Array.isArray(resp.list)) return resp.list;
48
+ const data = resp.data && typeof resp.data === "object" ? resp.data : null;
49
+ if (data) {
50
+ if (Array.isArray(data.files)) return data.files;
51
+ if (Array.isArray(data.list)) return data.list;
52
+ if (Array.isArray(data.records)) return data.records;
53
+ }
54
+ return [];
55
+ }
56
+
57
+ function mapDoc(d) {
58
+ if (!d || typeof d !== "object") return null;
59
+ const docId = d.id || d.fileId || d.file_id || d.docId || d.url;
60
+ if (!docId) return null;
61
+ return {
62
+ docId: String(docId),
63
+ title: d.title || d.name || d.fileName || "(无标题)",
64
+ docType: mapTencentType(d),
65
+ url:
66
+ d.url ||
67
+ (d.id ? `https://docs.qq.com/doc/${d.id}` : null),
68
+ createdMs: parseTime(d.createTime || d.create_time || d.gmtCreate),
69
+ updatedMs: parseTime(d.lastModifyTime || d.modifyTime || d.updateTime || d.gmtModify),
70
+ extra: {
71
+ ownerName: d.ownerName || d.creatorName || null,
72
+ starred: d.isStar != null ? d.isStar : undefined,
73
+ },
74
+ };
75
+ }
76
+
77
+ const TencentDocsAdapter = createDocumentAdapter({
78
+ NAME,
79
+ VERSION,
80
+ platform: "tencent-docs",
81
+ defaultListUrl: TENCENT_DOCS_LIST_URL,
82
+ extractDocs,
83
+ mapDoc,
84
+ });
85
+
86
+ module.exports = {
87
+ TencentDocsAdapter,
88
+ extractDocs,
89
+ mapDoc,
90
+ TYPE_MAP,
91
+ NAME,
92
+ VERSION,
93
+ SNAPSHOT_SCHEMA_VERSION,
94
+ };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * §13+ — WPS 云文档 (Kingsoft Office) adapter. "自创文档列表" (§12.1, ROI ⭐⭐⭐).
3
+ *
4
+ * Thin wrapper over _document-base. WPS exposes the owner's cloud documents via
5
+ * drive.wps.cn; this adapter supplies the endpoint + field mapping, the base
6
+ * handles snapshot + cookie-api orchestration + normalize (event POST + item
7
+ * DOCUMENT). Endpoint is best-effort + overridable via opts.listUrl (WPS rotates
8
+ * its drive API — FAMILY-23 playbook, not field-verified).
9
+ */
10
+
11
+ "use strict";
12
+
13
+ const { createDocumentAdapter, parseTime, SNAPSHOT_SCHEMA_VERSION } = require("../_document-base");
14
+
15
+ const NAME = "doc-wps";
16
+ const VERSION = "0.1.0";
17
+
18
+ // Best-effort WPS cloud-drive file list. Overridable via opts.listUrl.
19
+ const WPS_LIST_URL = "https://drive.wps.cn/api/v5/groups/special/files";
20
+
21
+ // WPS doc-type codes/names → normalized docType.
22
+ function mapWpsType(d) {
23
+ const t = String(d.fname || d.name || "").toLowerCase();
24
+ if (d.ftype && typeof d.ftype === "string") return d.ftype;
25
+ if (/\.(xlsx?|et|csv)$/.test(t)) return "sheet";
26
+ if (/\.(pptx?|dps)$/.test(t)) return "slide";
27
+ if (/\.pdf$/.test(t)) return "pdf";
28
+ if (/\.(docx?|wps)$/.test(t)) return "doc";
29
+ return "doc";
30
+ }
31
+
32
+ function extractDocs(resp) {
33
+ if (!resp || typeof resp !== "object") return [];
34
+ if (Array.isArray(resp.files)) return resp.files;
35
+ if (Array.isArray(resp.data)) return resp.data;
36
+ if (resp.data && Array.isArray(resp.data.files)) return resp.data.files;
37
+ if (Array.isArray(resp.list)) return resp.list;
38
+ return [];
39
+ }
40
+
41
+ function mapDoc(d) {
42
+ if (!d || typeof d !== "object") return null;
43
+ const docId = d.id || d.fileid || d.file_id || d.fid;
44
+ if (!docId) return null;
45
+ return {
46
+ docId: String(docId),
47
+ title: d.fname || d.name || d.title || "(无标题)",
48
+ docType: mapWpsType(d),
49
+ url:
50
+ d.url ||
51
+ (d.id ? `https://www.kdocs.cn/p/${d.id}` : null),
52
+ createdMs: parseTime(d.ctime || d.create_time || d.created),
53
+ updatedMs: parseTime(d.mtime || d.modify_time || d.updated || d.utime),
54
+ extra: {
55
+ size: d.fsize || d.size || null,
56
+ groupId: d.group_id || d.groupid || null,
57
+ },
58
+ };
59
+ }
60
+
61
+ const WpsDocAdapter = createDocumentAdapter({
62
+ NAME,
63
+ VERSION,
64
+ platform: "wps",
65
+ defaultListUrl: WPS_LIST_URL,
66
+ extractDocs,
67
+ mapDoc,
68
+ });
69
+
70
+ module.exports = {
71
+ WpsDocAdapter,
72
+ extractDocs,
73
+ mapDoc,
74
+ NAME,
75
+ VERSION,
76
+ SNAPSHOT_SCHEMA_VERSION,
77
+ };