multi-publisher 1.0.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.
Files changed (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +370 -0
  3. package/dist/adapters/baijiahao.d.ts +14 -0
  4. package/dist/adapters/baijiahao.js +77 -0
  5. package/dist/adapters/base-adapter.d.ts +41 -0
  6. package/dist/adapters/base-adapter.js +84 -0
  7. package/dist/adapters/bilibili.d.ts +14 -0
  8. package/dist/adapters/bilibili.js +86 -0
  9. package/dist/adapters/cnblogs.d.ts +14 -0
  10. package/dist/adapters/cnblogs.js +90 -0
  11. package/dist/adapters/csdn.d.ts +29 -0
  12. package/dist/adapters/csdn.js +174 -0
  13. package/dist/adapters/cto51.d.ts +14 -0
  14. package/dist/adapters/cto51.js +72 -0
  15. package/dist/adapters/douban.d.ts +14 -0
  16. package/dist/adapters/douban.js +49 -0
  17. package/dist/adapters/eastmoney.d.ts +14 -0
  18. package/dist/adapters/eastmoney.js +47 -0
  19. package/dist/adapters/imooc.d.ts +14 -0
  20. package/dist/adapters/imooc.js +78 -0
  21. package/dist/adapters/index.d.ts +26 -0
  22. package/dist/adapters/index.js +22 -0
  23. package/dist/adapters/interface.d.ts +44 -0
  24. package/dist/adapters/interface.js +1 -0
  25. package/dist/adapters/juejin.d.ts +23 -0
  26. package/dist/adapters/juejin.js +166 -0
  27. package/dist/adapters/oschina.d.ts +14 -0
  28. package/dist/adapters/oschina.js +77 -0
  29. package/dist/adapters/registry.d.ts +61 -0
  30. package/dist/adapters/registry.js +146 -0
  31. package/dist/adapters/segmentfault.d.ts +14 -0
  32. package/dist/adapters/segmentfault.js +73 -0
  33. package/dist/adapters/sohu.d.ts +14 -0
  34. package/dist/adapters/sohu.js +72 -0
  35. package/dist/adapters/toutiao.d.ts +9 -0
  36. package/dist/adapters/toutiao.js +199 -0
  37. package/dist/adapters/wechat-publisher.d.ts +55 -0
  38. package/dist/adapters/wechat-publisher.js +210 -0
  39. package/dist/adapters/weibo.d.ts +14 -0
  40. package/dist/adapters/weibo.js +99 -0
  41. package/dist/adapters/weixin.d.ts +14 -0
  42. package/dist/adapters/weixin.js +63 -0
  43. package/dist/adapters/woshipm.d.ts +14 -0
  44. package/dist/adapters/woshipm.js +72 -0
  45. package/dist/adapters/xiaohongshu.d.ts +9 -0
  46. package/dist/adapters/xiaohongshu.js +199 -0
  47. package/dist/adapters/xueqiu.d.ts +14 -0
  48. package/dist/adapters/xueqiu.js +74 -0
  49. package/dist/adapters/yuque.d.ts +13 -0
  50. package/dist/adapters/yuque.js +25 -0
  51. package/dist/adapters/zhihu.d.ts +23 -0
  52. package/dist/adapters/zhihu.js +142 -0
  53. package/dist/cli/cookie.d.ts +5 -0
  54. package/dist/cli/cookie.js +80 -0
  55. package/dist/cli/credential.d.ts +6 -0
  56. package/dist/cli/credential.js +32 -0
  57. package/dist/cli/index.d.ts +5 -0
  58. package/dist/cli/index.js +72 -0
  59. package/dist/cli/login.d.ts +3 -0
  60. package/dist/cli/login.js +101 -0
  61. package/dist/cli/platforms.d.ts +1 -0
  62. package/dist/cli/platforms.js +35 -0
  63. package/dist/cli/publish-all.d.ts +6 -0
  64. package/dist/cli/publish-all.js +101 -0
  65. package/dist/cli/publish.d.ts +7 -0
  66. package/dist/cli/publish.js +78 -0
  67. package/dist/cli/render.d.ts +9 -0
  68. package/dist/cli/render.js +40 -0
  69. package/dist/commands/login.d.ts +43 -0
  70. package/dist/commands/login.js +248 -0
  71. package/dist/commands/publish.d.ts +19 -0
  72. package/dist/commands/publish.js +275 -0
  73. package/dist/config.d.ts +177 -0
  74. package/dist/config.js +333 -0
  75. package/dist/core/mathjax.d.ts +4 -0
  76. package/dist/core/mathjax.js +33 -0
  77. package/dist/core/parser.d.ts +17 -0
  78. package/dist/core/parser.js +42 -0
  79. package/dist/core/renderer.d.ts +18 -0
  80. package/dist/core/renderer.js +30 -0
  81. package/dist/core/styler.d.ts +8 -0
  82. package/dist/core/styler.js +11 -0
  83. package/dist/core/theme.d.ts +9 -0
  84. package/dist/core/theme.js +420 -0
  85. package/dist/index.d.ts +8 -0
  86. package/dist/index.js +7 -0
  87. package/dist/runtime/browser-runtime.d.ts +79 -0
  88. package/dist/runtime/browser-runtime.js +501 -0
  89. package/dist/runtime/index.d.ts +12 -0
  90. package/dist/runtime/index.js +1 -0
  91. package/dist/runtime/node-runtime.d.ts +5 -0
  92. package/dist/runtime/node-runtime.js +25 -0
  93. package/dist/tools/xiaohongshu-sniffer.d.ts +1 -0
  94. package/dist/tools/xiaohongshu-sniffer.js +54 -0
  95. package/package.json +62 -0
  96. package/themes/all-themes-preview.html +522 -0
  97. package/themes/previews/cyberpunk.png +0 -0
  98. package/themes/previews/minimal.png +0 -0
  99. package/themes/previews/nord.png +0 -0
  100. package/themes/previews/wechat.png +0 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * 慕课网适配器
3
+ * 认证方式: Cookie
4
+ */
5
+ import { BaseAdapter } from './base-adapter.js';
6
+ export class ImoocAdapter extends BaseAdapter {
7
+ meta = {
8
+ id: 'imooc',
9
+ name: '慕课网',
10
+ icon: 'https://www.imooc.com/favicon.ico',
11
+ homepage: 'https://www.imooc.com/',
12
+ capabilities: ['article', 'draft'],
13
+ };
14
+ cookieData = null;
15
+ async init() {
16
+ this.cookieData = await this.loadCookies();
17
+ }
18
+ getCookieConfigKey() {
19
+ return 'imooc';
20
+ }
21
+ async checkAuth() {
22
+ if (!this.cookieData) {
23
+ return { isAuthenticated: false, error: '未配置慕课网 Cookie' };
24
+ }
25
+ try {
26
+ const cookieStr = this.buildCookieString(this.cookieData);
27
+ const res = await fetch('https://www.imooc.com/user/setinfo', {
28
+ headers: {
29
+ 'Cookie': cookieStr,
30
+ ...this.getCommonHeaders(),
31
+ },
32
+ });
33
+ const data = await res.json();
34
+ if (data.result?.userid) {
35
+ return {
36
+ isAuthenticated: true,
37
+ userId: String(data.result.userid),
38
+ username: data.result.username,
39
+ };
40
+ }
41
+ return { isAuthenticated: false, error: '未登录或登录已过期' };
42
+ }
43
+ catch (err) {
44
+ return { isAuthenticated: false, error: err.message };
45
+ }
46
+ }
47
+ async publish(article) {
48
+ const start = Date.now();
49
+ if (!this.cookieData) {
50
+ return this.createErrorResult('未配置慕课网 Cookie', start);
51
+ }
52
+ try {
53
+ const cookieStr = this.buildCookieString(this.cookieData);
54
+ // 慕课网文章发布
55
+ const res = await fetch('https://www.imooc.com/article/save_draft', {
56
+ method: 'POST',
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ 'Cookie': cookieStr,
60
+ ...this.getCommonHeaders(),
61
+ },
62
+ body: JSON.stringify({
63
+ title: article.title,
64
+ content: article.markdown || '',
65
+ draft: 1,
66
+ }),
67
+ });
68
+ const data = await res.json();
69
+ if (data.code === 0 && data.data?.id) {
70
+ return this.createSuccessResult(data.data.id, `https://www.imooc.com/article/edit?id=${data.data.id}`, true, start);
71
+ }
72
+ return this.createErrorResult('发布失败', start);
73
+ }
74
+ catch (err) {
75
+ return this.createErrorResult(err.message, start);
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 适配器统一导出
3
+ */
4
+ export type { IPlatformAdapter, PlatformMeta, Article, SyncResult, AuthResult, PlatformCapability } from './interface.js';
5
+ export { BaseAdapter } from './base-adapter.js';
6
+ export { WeixinAdapter } from './weixin.js';
7
+ export { ZhihuAdapter } from './zhihu.js';
8
+ export { JuejinAdapter } from './juejin.js';
9
+ export { CSDNAdapter } from './csdn.js';
10
+ export { WeiboAdapter } from './weibo.js';
11
+ export { BilibiliAdapter } from './bilibili.js';
12
+ export { BaijiahaoAdapter } from './baijiahao.js';
13
+ export { CnblogsAdapter } from './cnblogs.js';
14
+ export { DoubanAdapter } from './douban.js';
15
+ export { EastmoneyAdapter } from './eastmoney.js';
16
+ export { ImoocAdapter } from './imooc.js';
17
+ export { OschinaAdapter } from './oschina.js';
18
+ export { SegmentfaultAdapter } from './segmentfault.js';
19
+ export { SohuAdapter } from './sohu.js';
20
+ export { WoshipmAdapter } from './woshipm.js';
21
+ export { XueqiuAdapter } from './xueqiu.js';
22
+ export { YuqueAdapter } from './yuque.js';
23
+ export { Cto51Adapter } from './cto51.js';
24
+ export { ToutiaoAdapter } from './toutiao.js';
25
+ export { XiaohongshuAdapter } from './xiaohongshu.js';
26
+ export { adapterRegistry, initAdapterRegistry, getAdapter, getLoggedInPlatforms, publishToPlatforms } from './registry.js';
@@ -0,0 +1,22 @@
1
+ export { BaseAdapter } from './base-adapter.js';
2
+ export { WeixinAdapter } from './weixin.js';
3
+ export { ZhihuAdapter } from './zhihu.js';
4
+ export { JuejinAdapter } from './juejin.js';
5
+ export { CSDNAdapter } from './csdn.js';
6
+ export { WeiboAdapter } from './weibo.js';
7
+ export { BilibiliAdapter } from './bilibili.js';
8
+ export { BaijiahaoAdapter } from './baijiahao.js';
9
+ export { CnblogsAdapter } from './cnblogs.js';
10
+ export { DoubanAdapter } from './douban.js';
11
+ export { EastmoneyAdapter } from './eastmoney.js';
12
+ export { ImoocAdapter } from './imooc.js';
13
+ export { OschinaAdapter } from './oschina.js';
14
+ export { SegmentfaultAdapter } from './segmentfault.js';
15
+ export { SohuAdapter } from './sohu.js';
16
+ export { WoshipmAdapter } from './woshipm.js';
17
+ export { XueqiuAdapter } from './xueqiu.js';
18
+ export { YuqueAdapter } from './yuque.js';
19
+ export { Cto51Adapter } from './cto51.js';
20
+ export { ToutiaoAdapter } from './toutiao.js';
21
+ export { XiaohongshuAdapter } from './xiaohongshu.js';
22
+ export { adapterRegistry, initAdapterRegistry, getAdapter, getLoggedInPlatforms, publishToPlatforms } from './registry.js';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 平台适配器接口
3
+ */
4
+ import type { RuntimeInterface } from '../runtime/index.js';
5
+ export type PlatformCapability = 'article' | 'draft' | 'image_upload';
6
+ export interface PlatformMeta {
7
+ id: string;
8
+ name: string;
9
+ icon: string;
10
+ homepage: string;
11
+ capabilities: PlatformCapability[];
12
+ }
13
+ export interface Article {
14
+ title: string;
15
+ markdown: string;
16
+ html?: string;
17
+ author?: string;
18
+ cover?: string;
19
+ source_url?: string;
20
+ summary?: string;
21
+ tags?: string[];
22
+ }
23
+ export interface SyncResult {
24
+ platform: string;
25
+ success: boolean;
26
+ postId?: string;
27
+ postUrl?: string;
28
+ draftOnly?: boolean;
29
+ error?: string;
30
+ timestamp: number;
31
+ }
32
+ export interface AuthResult {
33
+ isAuthenticated: boolean;
34
+ username?: string;
35
+ userId?: string;
36
+ avatar?: string;
37
+ error?: string;
38
+ }
39
+ export interface IPlatformAdapter {
40
+ readonly meta: PlatformMeta;
41
+ init(runtime: RuntimeInterface): Promise<void>;
42
+ checkAuth(): Promise<AuthResult>;
43
+ publish(article: Article): Promise<SyncResult>;
44
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 掘金适配器
3
+ * 认证方式: Cookie
4
+ * 特殊: 需要 CSRF token 和 ImageX AWS4 图片上传
5
+ */
6
+ import type { IPlatformAdapter, Article, SyncResult, AuthResult, PlatformMeta } from './interface.js';
7
+ import type { RuntimeInterface } from '../runtime/index.js';
8
+ export declare class JuejinAdapter implements IPlatformAdapter {
9
+ readonly meta: PlatformMeta;
10
+ private runtime;
11
+ private cookieData;
12
+ private cachedCsrfToken;
13
+ init(runtime: RuntimeInterface): Promise<void>;
14
+ private loadCookie;
15
+ private buildCookieString;
16
+ private getCommonHeaders;
17
+ checkAuth(): Promise<AuthResult>;
18
+ /**
19
+ * 获取 CSRF Token
20
+ */
21
+ private getCsrfToken;
22
+ publish(article: Article): Promise<SyncResult>;
23
+ }
@@ -0,0 +1,166 @@
1
+ import { ConfigStore } from '../config.js';
2
+ // ImageX 服务常量
3
+ const IMAGEX_AID = '2608';
4
+ const IMAGEX_SERVICE_ID = '73owjymdk6';
5
+ function generateUUID() {
6
+ return 'xxxxxxxxxxxxxxxx'.replace(/x/g, () => Math.floor(Math.random() * 16).toString(16)) + Date.now().toString();
7
+ }
8
+ export class JuejinAdapter {
9
+ meta = {
10
+ id: 'juejin',
11
+ name: '掘金',
12
+ icon: 'https://lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/static/favicons/favicon-32x32.png',
13
+ homepage: 'https://juejin.cn',
14
+ capabilities: ['article', 'draft', 'image_upload'],
15
+ };
16
+ runtime;
17
+ cookieData = null;
18
+ cachedCsrfToken = null;
19
+ async init(runtime) {
20
+ this.runtime = runtime;
21
+ this.cookieData = await this.loadCookie();
22
+ }
23
+ async loadCookie() {
24
+ const cookies = await ConfigStore.getJuejinCookies();
25
+ if (!cookies)
26
+ return null;
27
+ return { cookies };
28
+ }
29
+ buildCookieString(cookieData) {
30
+ if (!cookieData.cookies)
31
+ return '';
32
+ return Object.entries(cookieData.cookies)
33
+ .map(([k, v]) => `${k}=${v}`)
34
+ .join('; ');
35
+ }
36
+ getCommonHeaders(cookieStr) {
37
+ return {
38
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
39
+ 'Cookie': cookieStr,
40
+ 'Origin': 'https://juejin.cn',
41
+ 'Referer': 'https://juejin.cn/',
42
+ };
43
+ }
44
+ async checkAuth() {
45
+ if (!this.cookieData?.cookies) {
46
+ return { isAuthenticated: false, error: '未配置掘金 Cookie,请运行: mpub cookie --platform juejin --set' };
47
+ }
48
+ try {
49
+ const cookieStr = this.buildCookieString(this.cookieData);
50
+ const res = await this.runtime.fetch('https://api.juejin.cn/user_api/v1/user/get', {
51
+ headers: this.getCommonHeaders(cookieStr),
52
+ });
53
+ const data = await res.json();
54
+ if (data.data?.user_id) {
55
+ return {
56
+ isAuthenticated: true,
57
+ userId: data.data.user_id,
58
+ username: data.data.user_name,
59
+ avatar: data.data.avatar_large,
60
+ };
61
+ }
62
+ return { isAuthenticated: false, error: '未获取到用户信息' };
63
+ }
64
+ catch (err) {
65
+ return { isAuthenticated: false, error: err.message };
66
+ }
67
+ }
68
+ /**
69
+ * 获取 CSRF Token
70
+ */
71
+ async getCsrfToken() {
72
+ if (this.cachedCsrfToken) {
73
+ return this.cachedCsrfToken;
74
+ }
75
+ if (!this.cookieData?.cookies) {
76
+ throw new Error('未配置掘金 Cookie');
77
+ }
78
+ const cookieStr = this.buildCookieString(this.cookieData);
79
+ const response = await this.runtime.fetch('https://api.juejin.cn/user_api/v1/sys/token', {
80
+ method: 'HEAD',
81
+ headers: {
82
+ ...this.getCommonHeaders(cookieStr),
83
+ 'x-secsdk-csrf-request': '1',
84
+ 'x-secsdk-csrf-version': '1.2.10',
85
+ },
86
+ });
87
+ const wareToken = response.headers.get('x-ware-csrf-token');
88
+ if (!wareToken) {
89
+ throw new Error('Failed to get CSRF token');
90
+ }
91
+ // Token 格式: "0,{actual_token},86370000,success,{session_id}"
92
+ const parts = wareToken.split(',');
93
+ if (parts.length < 2) {
94
+ throw new Error('Invalid CSRF token format');
95
+ }
96
+ this.cachedCsrfToken = parts[1];
97
+ return this.cachedCsrfToken;
98
+ }
99
+ async publish(article) {
100
+ const start = Date.now();
101
+ try {
102
+ if (!this.cookieData?.cookies) {
103
+ throw new Error('未配置掘金 Cookie,请运行: mpub cookie --platform juejin --set');
104
+ }
105
+ const cookieStr = this.buildCookieString(this.cookieData);
106
+ const csrfToken = await this.getCsrfToken();
107
+ // 使用 Markdown 格式
108
+ let markdown = article.markdown || '';
109
+ // 创建草稿
110
+ const createResponse = await this.runtime.fetch('https://api.juejin.cn/content_api/v1/article_draft/create', {
111
+ method: 'POST',
112
+ headers: {
113
+ 'Content-Type': 'application/json',
114
+ ...this.getCommonHeaders(cookieStr),
115
+ 'x-secsdk-csrf-token': csrfToken,
116
+ },
117
+ body: JSON.stringify({
118
+ brief_content: '',
119
+ category_id: '0',
120
+ cover_image: '',
121
+ edit_type: 10,
122
+ html_content: 'deprecated',
123
+ link_url: '',
124
+ mark_content: markdown,
125
+ tag_ids: [],
126
+ title: article.title,
127
+ }),
128
+ });
129
+ const responseText = await createResponse.text();
130
+ if (!createResponse.ok) {
131
+ throw new Error(`创建草稿失败: ${createResponse.status} - ${responseText}`);
132
+ }
133
+ let createData;
134
+ try {
135
+ createData = JSON.parse(responseText);
136
+ }
137
+ catch {
138
+ throw new Error(`创建草稿失败: 响应不是有效 JSON - ${responseText.substring(0, 100)}`);
139
+ }
140
+ if (createData.err_no && createData.err_no !== 0) {
141
+ throw new Error(createData.err_msg || `创建草稿失败: 错误码 ${createData.err_no}`);
142
+ }
143
+ if (!createData.data?.id) {
144
+ throw new Error(createData.err_msg || '创建草稿失败: 无效响应');
145
+ }
146
+ const draftId = createData.data.id;
147
+ const draftUrl = `https://juejin.cn/editor/drafts/${draftId}`;
148
+ return {
149
+ platform: this.meta.id,
150
+ success: true,
151
+ postId: draftId,
152
+ postUrl: draftUrl,
153
+ draftOnly: true,
154
+ timestamp: Date.now() - start,
155
+ };
156
+ }
157
+ catch (err) {
158
+ return {
159
+ platform: this.meta.id,
160
+ success: false,
161
+ error: err.message,
162
+ timestamp: Date.now() - start,
163
+ };
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 开源中国适配器
3
+ * 认证方式: Cookie
4
+ */
5
+ import { BaseAdapter } from './base-adapter.js';
6
+ import type { Article, AuthResult, PlatformMeta } from './interface.js';
7
+ export declare class OschinaAdapter extends BaseAdapter {
8
+ readonly meta: PlatformMeta;
9
+ private cookieData;
10
+ init(): Promise<void>;
11
+ protected getCookieConfigKey(): string;
12
+ checkAuth(): Promise<AuthResult>;
13
+ publish(article: Article): Promise<import('./interface.js').SyncResult>;
14
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 开源中国适配器
3
+ * 认证方式: Cookie
4
+ */
5
+ import { BaseAdapter } from './base-adapter.js';
6
+ export class OschinaAdapter extends BaseAdapter {
7
+ meta = {
8
+ id: 'oschina',
9
+ name: '开源中国',
10
+ icon: 'https://www.oschina.net/favicon.ico',
11
+ homepage: 'https://www.oschina.net/',
12
+ capabilities: ['article', 'draft', 'image_upload'],
13
+ };
14
+ cookieData = null;
15
+ async init() {
16
+ this.cookieData = await this.loadCookies();
17
+ }
18
+ getCookieConfigKey() {
19
+ return 'oschina';
20
+ }
21
+ async checkAuth() {
22
+ if (!this.cookieData) {
23
+ return { isAuthenticated: false, error: '未配置开源中国 Cookie' };
24
+ }
25
+ try {
26
+ const cookieStr = this.buildCookieString(this.cookieData);
27
+ const res = await fetch('https://www.oschina.net/home/user-info', {
28
+ headers: {
29
+ 'Cookie': cookieStr,
30
+ ...this.getCommonHeaders(),
31
+ },
32
+ });
33
+ const data = await res.json();
34
+ if (data.user?.id) {
35
+ return {
36
+ isAuthenticated: true,
37
+ userId: String(data.user.id),
38
+ username: data.user.name,
39
+ };
40
+ }
41
+ return { isAuthenticated: false, error: '未登录或登录已过期' };
42
+ }
43
+ catch (err) {
44
+ return { isAuthenticated: false, error: err.message };
45
+ }
46
+ }
47
+ async publish(article) {
48
+ const start = Date.now();
49
+ if (!this.cookieData) {
50
+ return this.createErrorResult('未配置开源中国 Cookie', start);
51
+ }
52
+ try {
53
+ const cookieStr = this.buildCookieString(this.cookieData);
54
+ const res = await fetch('https://www.oschina.net/blog/save_draft', {
55
+ method: 'POST',
56
+ headers: {
57
+ 'Content-Type': 'application/json',
58
+ 'Cookie': cookieStr,
59
+ ...this.getCommonHeaders(),
60
+ },
61
+ body: JSON.stringify({
62
+ title: article.title,
63
+ content: article.markdown || '',
64
+ draft: true,
65
+ }),
66
+ });
67
+ const data = await res.json();
68
+ if (data.code === 0 && data.id) {
69
+ return this.createSuccessResult(data.id, `https://www.oschina.net/blog/edit?id=${data.id}`, true, start);
70
+ }
71
+ return this.createErrorResult('发布失败', start);
72
+ }
73
+ catch (err) {
74
+ return this.createErrorResult(err.message, start);
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 平台适配器注册表
3
+ * 使用注册表模式管理所有平台适配器
4
+ */
5
+ import type { IPlatformAdapter, PlatformMeta } from './interface.js';
6
+ import type { RuntimeInterface } from '../runtime/index.js';
7
+ type AdapterConstructor = new () => IPlatformAdapter;
8
+ /**
9
+ * 适配器注册表
10
+ */
11
+ declare class AdapterRegistry {
12
+ private adapters;
13
+ private runtime;
14
+ setRuntime(runtime: RuntimeInterface): void;
15
+ /**
16
+ * 获取所有平台元信息
17
+ */
18
+ getAllMeta(): PlatformMeta[];
19
+ /**
20
+ * 获取已登录的平台列表
21
+ */
22
+ getLoggedInPlatforms(): Promise<PlatformMeta[]>;
23
+ /**
24
+ * 获取适配器实例
25
+ */
26
+ get(platformId: string): IPlatformAdapter | undefined;
27
+ /**
28
+ * 注册适配器
29
+ */
30
+ register(AdapterClass: AdapterConstructor): void;
31
+ /**
32
+ * 初始化所有适配器
33
+ */
34
+ initAll(): Promise<void>;
35
+ /**
36
+ * 获取所有已注册的适配器
37
+ */
38
+ getAll(): Map<string, IPlatformAdapter>;
39
+ }
40
+ export declare const adapterRegistry: AdapterRegistry;
41
+ /**
42
+ * 初始化适配器注册表
43
+ */
44
+ export declare function initAdapterRegistry(runtime: RuntimeInterface): Promise<void>;
45
+ /**
46
+ * 获取适配器
47
+ */
48
+ export declare function getAdapter(platformId: string): IPlatformAdapter | undefined;
49
+ /**
50
+ * 获取所有已登录的平台
51
+ */
52
+ export declare function getLoggedInPlatforms(): Promise<PlatformMeta[]>;
53
+ /**
54
+ * 发布到多个平台
55
+ */
56
+ export declare function publishToPlatforms(platformIds: string[], article: {
57
+ title: string;
58
+ markdown: string;
59
+ html?: string;
60
+ }, onProgress?: (platform: string, result: import('./interface.js').SyncResult) => void): Promise<import('./interface.js').SyncResult[]>;
61
+ export {};
@@ -0,0 +1,146 @@
1
+ import { WeixinAdapter } from './weixin.js';
2
+ import { ZhihuAdapter } from './zhihu.js';
3
+ import { JuejinAdapter } from './juejin.js';
4
+ import { CSDNAdapter } from './csdn.js';
5
+ import { WeiboAdapter } from './weibo.js';
6
+ import { BilibiliAdapter } from './bilibili.js';
7
+ import { BaijiahaoAdapter } from './baijiahao.js';
8
+ import { CnblogsAdapter } from './cnblogs.js';
9
+ import { DoubanAdapter } from './douban.js';
10
+ import { EastmoneyAdapter } from './eastmoney.js';
11
+ import { ImoocAdapter } from './imooc.js';
12
+ import { OschinaAdapter } from './oschina.js';
13
+ import { SegmentfaultAdapter } from './segmentfault.js';
14
+ import { SohuAdapter } from './sohu.js';
15
+ import { WoshipmAdapter } from './woshipm.js';
16
+ import { XueqiuAdapter } from './xueqiu.js';
17
+ import { YuqueAdapter } from './yuque.js';
18
+ import { Cto51Adapter } from './cto51.js';
19
+ import { ToutiaoAdapter } from './toutiao.js';
20
+ import { XiaohongshuAdapter } from './xiaohongshu.js';
21
+ // 所有适配器类
22
+ const ADAPTER_CLASSES = {
23
+ weixin: WeixinAdapter,
24
+ zhihu: ZhihuAdapter,
25
+ juejin: JuejinAdapter,
26
+ csdn: CSDNAdapter,
27
+ weibo: WeiboAdapter,
28
+ bilibili: BilibiliAdapter,
29
+ baijiahao: BaijiahaoAdapter,
30
+ cnblogs: CnblogsAdapter,
31
+ douban: DoubanAdapter,
32
+ eastmoney: EastmoneyAdapter,
33
+ imooc: ImoocAdapter,
34
+ oschina: OschinaAdapter,
35
+ segmentfault: SegmentfaultAdapter,
36
+ sohu: SohuAdapter,
37
+ woshipm: WoshipmAdapter,
38
+ xueqiu: XueqiuAdapter,
39
+ yuque: YuqueAdapter,
40
+ cto51: Cto51Adapter,
41
+ toutiao: ToutiaoAdapter,
42
+ xiaohongshu: XiaohongshuAdapter,
43
+ };
44
+ /**
45
+ * 适配器注册表
46
+ */
47
+ class AdapterRegistry {
48
+ adapters = new Map();
49
+ runtime;
50
+ setRuntime(runtime) {
51
+ this.runtime = runtime;
52
+ }
53
+ /**
54
+ * 获取所有平台元信息
55
+ */
56
+ getAllMeta() {
57
+ return Array.from(this.adapters.values()).map(a => a.meta);
58
+ }
59
+ /**
60
+ * 获取已登录的平台列表
61
+ */
62
+ async getLoggedInPlatforms() {
63
+ const loggedIn = [];
64
+ for (const adapter of this.adapters.values()) {
65
+ const auth = await adapter.checkAuth();
66
+ if (auth.isAuthenticated) {
67
+ loggedIn.push(adapter.meta);
68
+ }
69
+ }
70
+ return loggedIn;
71
+ }
72
+ /**
73
+ * 获取适配器实例
74
+ */
75
+ get(platformId) {
76
+ return this.adapters.get(platformId);
77
+ }
78
+ /**
79
+ * 注册适配器
80
+ */
81
+ register(AdapterClass) {
82
+ const adapter = new AdapterClass();
83
+ this.adapters.set(adapter.meta.id, adapter);
84
+ }
85
+ /**
86
+ * 初始化所有适配器
87
+ */
88
+ async initAll() {
89
+ for (const [id, AdapterClass] of Object.entries(ADAPTER_CLASSES)) {
90
+ const adapter = new AdapterClass();
91
+ await adapter.init(this.runtime);
92
+ this.adapters.set(id, adapter);
93
+ }
94
+ }
95
+ /**
96
+ * 获取所有已注册的适配器
97
+ */
98
+ getAll() {
99
+ return this.adapters;
100
+ }
101
+ }
102
+ // 全局注册表实例
103
+ export const adapterRegistry = new AdapterRegistry();
104
+ /**
105
+ * 初始化适配器注册表
106
+ */
107
+ export async function initAdapterRegistry(runtime) {
108
+ adapterRegistry.setRuntime(runtime);
109
+ await adapterRegistry.initAll();
110
+ }
111
+ /**
112
+ * 获取适配器
113
+ */
114
+ export function getAdapter(platformId) {
115
+ return adapterRegistry.get(platformId);
116
+ }
117
+ /**
118
+ * 获取所有已登录的平台
119
+ */
120
+ export async function getLoggedInPlatforms() {
121
+ return adapterRegistry.getLoggedInPlatforms();
122
+ }
123
+ /**
124
+ * 发布到多个平台
125
+ */
126
+ export async function publishToPlatforms(platformIds, article, onProgress) {
127
+ const results = [];
128
+ for (const platformId of platformIds) {
129
+ const adapter = adapterRegistry.get(platformId);
130
+ if (!adapter) {
131
+ const errorResult = {
132
+ platform: platformId,
133
+ success: false,
134
+ error: `未找到平台适配器: ${platformId}`,
135
+ timestamp: Date.now(),
136
+ };
137
+ results.push(errorResult);
138
+ onProgress?.(platformId, errorResult);
139
+ continue;
140
+ }
141
+ const result = await adapter.publish(article);
142
+ results.push(result);
143
+ onProgress?.(platformId, result);
144
+ }
145
+ return results;
146
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 思否 (SegmentFault) 适配器
3
+ * 认证方式: Cookie
4
+ */
5
+ import { BaseAdapter } from './base-adapter.js';
6
+ import type { Article, AuthResult, PlatformMeta } from './interface.js';
7
+ export declare class SegmentfaultAdapter extends BaseAdapter {
8
+ readonly meta: PlatformMeta;
9
+ private cookieData;
10
+ init(): Promise<void>;
11
+ protected getCookieConfigKey(): string;
12
+ checkAuth(): Promise<AuthResult>;
13
+ publish(article: Article): Promise<import('./interface.js').SyncResult>;
14
+ }