@skrillex1224/chrome-article-publish-extension 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.
package/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # @skrillex1224/chrome-article-publish-extension
2
+
3
+ Direct article publishing adapters for Chrome extensions. The package runs in a Manifest V3 extension context and reuses the user's logged-in browser sessions.
4
+
5
+ ## What It Exposes
6
+
7
+ - `checkAuth(request)`: check whether the current extension browser profile is logged in to a platform.
8
+ - `publish(request)`: publish or submit an article through the platform's public frontend API behavior.
9
+ - `getStatus(request)`: query the platform's official management/detail/status source with the `statusRef` returned by `publish()`.
10
+ - `createExtensionRuntime(config?)`: Chrome extension runtime implementation used by the three methods.
11
+
12
+ The host extension owns UI, local task state, retry buttons, storage, and polling cadence.
13
+
14
+ ## Supported Platforms
15
+
16
+ | id | Platform | Notes |
17
+ |---|---|---|
18
+ | `bilibili` | Bilibili Opus | Supports cover and structured Opus payload. Tables degrade to readable text. |
19
+ | `weixin` | WeChat Official Account | Supports cover, body images, summary, and security QR events. |
20
+ | `douyin` | Douyin image-text | Renders Markdown into image cards, then publishes image-text notes. |
21
+ | `cnblogs` | Cnblogs | Supports article publish, tags, cover metadata. |
22
+ | `juejin` | Juejin | Supports cover and real tag ids when the account is eligible. |
23
+ | `baijiahao` | Baijiahao | Resolves public URLs from official page data after management status says published. |
24
+ | `csdn` | CSDN | Supports cover/tags; account daily quota can block publish. |
25
+ | `51cto` | 51CTO | Supports cover/tags/category mapping. |
26
+ | `sohu` | Sohu | Publish/status works; platform policy can reject content. |
27
+ | `netease` | Netease | Publish/status works; muted accounts cannot pass live publish. |
28
+ | `toutiao` | Toutiao | Uses current creator management feed for status. |
29
+ | `tencent` | Tencent Content Platform | Uses official frontend publish service and management list. |
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ npm install @skrillex1224/chrome-article-publish-extension
35
+ ```
36
+
37
+ ## Chrome Extension Requirements
38
+
39
+ Your host extension needs the browser capabilities the adapters use:
40
+
41
+ ```json
42
+ {
43
+ "permissions": [
44
+ "storage",
45
+ "unlimitedStorage",
46
+ "cookies",
47
+ "declarativeNetRequest",
48
+ "declarativeNetRequestWithHostAccess",
49
+ "scripting",
50
+ "tabs",
51
+ "downloads"
52
+ ],
53
+ "host_permissions": ["http://*/*", "https://*/*"],
54
+ "background": { "type": "module" }
55
+ }
56
+ ```
57
+
58
+ The user must log in to each target platform in the same Chrome profile that runs the extension.
59
+
60
+ ## Usage
61
+
62
+ ```ts
63
+ import {
64
+ checkAuth,
65
+ createExtensionRuntime,
66
+ getStatus,
67
+ publish,
68
+ } from '@skrillex1224/chrome-article-publish-extension'
69
+
70
+ const runtime = createExtensionRuntime({ timeout: 120_000 })
71
+
72
+ const auth = await checkAuth({ platform: 'bilibili', runtime })
73
+ if (!auth.isAuthenticated) {
74
+ throw new Error(auth.error || 'Not authenticated')
75
+ }
76
+
77
+ const result = await publish({
78
+ platform: 'bilibili',
79
+ runtime,
80
+ article: {
81
+ title: 'My article',
82
+ markdown: '# Heading\n\nArticle body.',
83
+ summary: 'Short summary',
84
+ cover: 'https://example.com/cover.jpg',
85
+ tags: ['tag-a', 'tag-b'],
86
+ },
87
+ async onEvent(event) {
88
+ if (event.type === 'security_check') {
89
+ console.log(event.method, event.url, event.expiresAt)
90
+ }
91
+ },
92
+ })
93
+
94
+ if (result.state === 'failed') {
95
+ throw new Error(result.error.message)
96
+ }
97
+
98
+ const status = await getStatus({
99
+ platform: 'bilibili',
100
+ runtime,
101
+ statusRef: result.statusRef,
102
+ })
103
+
104
+ console.log(status.state, status.postUrl, status.message)
105
+ ```
106
+
107
+ ## API
108
+
109
+ ### `checkAuth(request)`
110
+
111
+ ```ts
112
+ type CheckAuthRequest = {
113
+ platform: string
114
+ runtime: RuntimeInterface
115
+ }
116
+
117
+ type AuthResult = {
118
+ isAuthenticated: boolean
119
+ username?: string
120
+ userId?: string
121
+ avatar?: string
122
+ error?: string
123
+ }
124
+ ```
125
+
126
+ Use this before showing a platform as ready to publish.
127
+
128
+ ### `publish(request)`
129
+
130
+ ```ts
131
+ type PublishRequest = {
132
+ platform: string
133
+ runtime: RuntimeInterface
134
+ article: Article | PublishArticleInput
135
+ onEvent?: (event: PublishEvent) => void | Promise<void>
136
+ options?: {
137
+ onImageProgress?: (current: number, total: number) => void
138
+ }
139
+ }
140
+
141
+ type PublishArticleInput = {
142
+ title: string
143
+ description?: string
144
+ body?: string
145
+ content?: string
146
+ markdown?: string
147
+ html?: string
148
+ cover?: string
149
+ tags?: string[]
150
+ category?: string
151
+ source?: { url: string; platform: string }
152
+ }
153
+ ```
154
+
155
+ `publish()` returns only:
156
+
157
+ ```ts
158
+ type PublishResult =
159
+ | {
160
+ platform: string
161
+ state: 'succeeded'
162
+ statusRef: PublishStatusRef
163
+ postId?: string
164
+ postUrl?: string
165
+ timestamp: number
166
+ }
167
+ | {
168
+ platform: string
169
+ state: 'failed'
170
+ error: { message: string; code?: string }
171
+ timestamp: number
172
+ }
173
+ ```
174
+
175
+ If a platform needs QR, CAPTCHA, or a manual security check, `publish()` emits `onEvent({ type: 'security_check', ... })` and waits until the platform flow completes or times out.
176
+
177
+ ### `getStatus(request)`
178
+
179
+ ```ts
180
+ type GetStatusRequest = {
181
+ platform: string
182
+ runtime: RuntimeInterface
183
+ statusRef: PublishStatusRef
184
+ }
185
+
186
+ type PublishStatusResult = {
187
+ platform: string
188
+ state: 'published' | 'reviewing' | 'rejected' | 'not_found' | 'unknown'
189
+ message?: string
190
+ postUrl?: string
191
+ checkedAt: number
192
+ }
193
+ ```
194
+
195
+ Store `statusRef` exactly as returned by `publish()`. Do not parse it in the host UI.
196
+
197
+ ## Runtime
198
+
199
+ ```ts
200
+ const runtime = createExtensionRuntime({
201
+ timeout: 120_000,
202
+ })
203
+ ```
204
+
205
+ `timeout` controls extension `fetch()` timeout in milliseconds. Keep it higher for platforms that upload images or generated Markdown cards.
206
+
207
+ ## Testing In A Host Extension
208
+
209
+ After loading the built extension in Chrome with remote debugging enabled:
210
+
211
+ ```bash
212
+ CDP_URL=http://127.0.0.1:9224 \
213
+ EXTENSION_ID=<your-extension-id> \
214
+ node scripts/e2e-check-auth.mjs
215
+ ```
216
+
217
+ The script sends `GET_PLATFORMS` and `CHECK_AUTH` through `chrome.runtime.sendMessage` and prints one row per platform.
218
+
219
+ ## Not Included
220
+
221
+ - No UI framework.
222
+ - No task database.
223
+ - No retry scheduler.
224
+ - No cross-profile cookie copying.
225
+ - No platform button-click publishing.
226
+ - No compatibility with Wechatsync's old public result shape.