@opentiny/webmcp-cli 0.0.4 → 0.0.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/README.md +1 -1
- package/dist/bin.cjs +233 -19
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +233 -19
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +168 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +168 -5
- package/dist/index.js.map +1 -1
- package/dist/inject-bundle.js +2704 -1420
- package/dist/webmcp-tools/creator.xiaohongshu.com.js +1 -1
- package/dist/webmcp-tools/editor.csdn.net.js +1 -1
- package/dist/webmcp-tools/excalidraw.com.js +1 -1
- package/dist/webmcp-tools/juejin.cn.js +1 -1
- package/dist/webmcp-tools/my.oschina.net.js +1 -1
- package/dist/webmcp-tools/segmentfault.com.js +856 -0
- package/dist/webmcp-tools/www.baidu.com.js +1 -1
- package/dist/webmcp-tools/xiaohongshu.com.js +1 -1
- package/dist/webmcp-tools/zhuanlan.zhihu.com.js +238 -0
- package/package.json +5 -4
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
;(function(){
|
|
2
|
+
"use strict";
|
|
3
|
+
(() => {
|
|
4
|
+
// webmcp-tools/segmentfault.com/index.ts
|
|
5
|
+
var CONFIG = {
|
|
6
|
+
autoSaveDelay: 4500,
|
|
7
|
+
// 思否自动保存约4秒,留余量
|
|
8
|
+
stepInterval: 150,
|
|
9
|
+
// 步骤间最小间隔
|
|
10
|
+
tagSuggestionDelay: 800,
|
|
11
|
+
// 标签下拉等待
|
|
12
|
+
elementTimeout: 6e3
|
|
13
|
+
// 元素查找超时
|
|
14
|
+
};
|
|
15
|
+
var SELECTORS = {
|
|
16
|
+
howtowrite: {
|
|
17
|
+
indicator: '.howtowrite, [class*="howtowrite"], .sf-write-guide',
|
|
18
|
+
continueBtn: [
|
|
19
|
+
'button:contains("\u6211\u5DF2\u77E5\u6653")',
|
|
20
|
+
'button:contains("\u7EE7\u7EED\u64B0\u5199")',
|
|
21
|
+
'a:contains("\u6211\u5DF2\u77E5\u6653")',
|
|
22
|
+
".howtowrite button",
|
|
23
|
+
".sf-write-guide button",
|
|
24
|
+
"button.ant-btn-primary"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
editor: {
|
|
28
|
+
indicator: '.write-page, .article-editor, [class*="write-page"], #write-page, .sf-write',
|
|
29
|
+
titleInput: [
|
|
30
|
+
'input[placeholder*="\u6807\u9898"]',
|
|
31
|
+
'input[placeholder*="\u8BF7\u8F93\u5165\u6587\u7AE0\u6807\u9898"]',
|
|
32
|
+
'input[name="title"]',
|
|
33
|
+
".write-title input",
|
|
34
|
+
".article-title input",
|
|
35
|
+
'input[maxlength="100"]'
|
|
36
|
+
],
|
|
37
|
+
codeMirror: ".CodeMirror, .cm-editor, .CodeMirror-wrap",
|
|
38
|
+
codeMirrorTextarea: ".CodeMirror textarea",
|
|
39
|
+
markdownTextarea: [
|
|
40
|
+
'textarea[name="content"]',
|
|
41
|
+
'textarea[name="body"]',
|
|
42
|
+
".editor textarea",
|
|
43
|
+
'textarea[placeholder*="\u5185\u5BB9"]',
|
|
44
|
+
'textarea[placeholder*="\u8BF7\u8F93\u5165\u6B63\u6587"]'
|
|
45
|
+
],
|
|
46
|
+
articleType: {
|
|
47
|
+
original: [
|
|
48
|
+
'input[value="original"]',
|
|
49
|
+
'input[value="1"]',
|
|
50
|
+
'label:contains("\u539F\u521B") input[type="radio"]',
|
|
51
|
+
'[name="type"][value="original"]'
|
|
52
|
+
],
|
|
53
|
+
repost: [
|
|
54
|
+
'input[value="repost"]',
|
|
55
|
+
'input[value="2"]',
|
|
56
|
+
'label:contains("\u8F6C\u8F7D") input[type="radio"]',
|
|
57
|
+
'[name="type"][value="repost"]'
|
|
58
|
+
],
|
|
59
|
+
translate: [
|
|
60
|
+
'input[value="translate"]',
|
|
61
|
+
'input[value="3"]',
|
|
62
|
+
'label:contains("\u7FFB\u8BD1") input[type="radio"]',
|
|
63
|
+
'[name="type"][value="translate"]'
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
publishScope: {
|
|
67
|
+
personal: [
|
|
68
|
+
'input[value="personal"]',
|
|
69
|
+
'input[value="0"]',
|
|
70
|
+
'label:contains("\u4E2A\u4EBA") input[type="radio"]',
|
|
71
|
+
'[name="scope"][value="personal"]'
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
tagInput: [
|
|
75
|
+
'input[placeholder*="\u6807\u7B7E"]',
|
|
76
|
+
'input[placeholder*="\u6DFB\u52A0\u6807\u7B7E"]',
|
|
77
|
+
".tag-input input",
|
|
78
|
+
'[class*="tag"] input[type="text"]',
|
|
79
|
+
'input[name="tags"]'
|
|
80
|
+
],
|
|
81
|
+
selectedTags: [
|
|
82
|
+
".selected-tag",
|
|
83
|
+
".tag-item.selected",
|
|
84
|
+
".ant-tag",
|
|
85
|
+
'[class*="tag"][class*="selected"]'
|
|
86
|
+
],
|
|
87
|
+
tagRemoveBtn: [
|
|
88
|
+
".tag-remove",
|
|
89
|
+
".tag-close",
|
|
90
|
+
".ant-tag-close-icon",
|
|
91
|
+
'[class*="tag"] [class*="remove"]',
|
|
92
|
+
'[class*="tag"] [class*="close"]'
|
|
93
|
+
],
|
|
94
|
+
tagSuggestions: [
|
|
95
|
+
".tag-suggestion",
|
|
96
|
+
".dropdown-item",
|
|
97
|
+
".ant-select-dropdown .ant-select-item",
|
|
98
|
+
'[class*="suggestion"]'
|
|
99
|
+
],
|
|
100
|
+
categorySelect: [
|
|
101
|
+
'select[name="category"]',
|
|
102
|
+
'select[name="column"]',
|
|
103
|
+
".category-select",
|
|
104
|
+
'select[class*="category"]'
|
|
105
|
+
],
|
|
106
|
+
copyrightToggle: [
|
|
107
|
+
'input[name="copyright"]',
|
|
108
|
+
'[class*="copyright"] input[type="checkbox"]',
|
|
109
|
+
'label:contains("\u7248\u6743") input[type="checkbox"]'
|
|
110
|
+
],
|
|
111
|
+
scheduledPublish: {
|
|
112
|
+
triggerBtn: [
|
|
113
|
+
'button:contains("\u5B9A\u65F6\u53D1\u5E03")',
|
|
114
|
+
'button:contains("\u5B9A\u65F6")',
|
|
115
|
+
'label:contains("\u5B9A\u65F6\u53D1\u5E03")',
|
|
116
|
+
'[class*="scheduled"]',
|
|
117
|
+
'[class*="timing"]'
|
|
118
|
+
],
|
|
119
|
+
datetimeInput: [
|
|
120
|
+
'input[type="datetime-local"]',
|
|
121
|
+
'[class*="datetime"] input',
|
|
122
|
+
".ant-picker-input input"
|
|
123
|
+
],
|
|
124
|
+
confirmBtn: [
|
|
125
|
+
'button:contains("\u786E\u8BA4")',
|
|
126
|
+
'button:contains("\u786E\u5B9A")',
|
|
127
|
+
'button:contains("\u8BBE\u7F6E")',
|
|
128
|
+
".ant-picker-ok button"
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
discardDraftBtn: [
|
|
132
|
+
'button:contains("\u820D\u5F03\u8349\u7A3F")',
|
|
133
|
+
'button:contains("\u653E\u5F03\u8349\u7A3F")',
|
|
134
|
+
'[class*="discard"]',
|
|
135
|
+
'[class*="abandon"]'
|
|
136
|
+
],
|
|
137
|
+
publishBtn: [
|
|
138
|
+
'button:contains("\u53D1\u5E03")',
|
|
139
|
+
'button:contains("\u53D1\u5E03\u6587\u7AE0")',
|
|
140
|
+
".btn-publish",
|
|
141
|
+
'[class*="publish"]',
|
|
142
|
+
'button[type="submit"]'
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
function findElement(selectors) {
|
|
147
|
+
const list = Array.isArray(selectors) ? selectors : [selectors];
|
|
148
|
+
for (const sel of list) {
|
|
149
|
+
try {
|
|
150
|
+
if (sel.includes(":contains(")) {
|
|
151
|
+
const match = sel.match(/^(.+):contains\("(.+)"\)$/);
|
|
152
|
+
if (match) {
|
|
153
|
+
const [, tag, text] = match;
|
|
154
|
+
for (const el2 of document.querySelectorAll(tag)) {
|
|
155
|
+
if (el2.textContent?.includes(text)) return el2;
|
|
156
|
+
}
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const el = document.querySelector(sel);
|
|
161
|
+
if (el) return el;
|
|
162
|
+
} catch (e) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function findElements(selectors) {
|
|
169
|
+
const list = Array.isArray(selectors) ? selectors : [selectors];
|
|
170
|
+
const results = [];
|
|
171
|
+
for (const sel of list) {
|
|
172
|
+
try {
|
|
173
|
+
if (sel.includes(":contains(")) {
|
|
174
|
+
const match = sel.match(/^(.+):contains\("(.+)"\)$/);
|
|
175
|
+
if (match) {
|
|
176
|
+
const [, tag, text] = match;
|
|
177
|
+
for (const el of document.querySelectorAll(tag)) {
|
|
178
|
+
if (el.textContent?.includes(text)) results.push(el);
|
|
179
|
+
}
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
results.push(...Array.from(document.querySelectorAll(sel)));
|
|
184
|
+
} catch (e) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return results;
|
|
189
|
+
}
|
|
190
|
+
function waitForElement(selector, timeout = CONFIG.elementTimeout) {
|
|
191
|
+
return new Promise((resolve) => {
|
|
192
|
+
const el = findElement(selector);
|
|
193
|
+
if (el) {
|
|
194
|
+
resolve(el);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const observer = new MutationObserver(() => {
|
|
198
|
+
const found = findElement(selector);
|
|
199
|
+
if (found) {
|
|
200
|
+
observer.disconnect();
|
|
201
|
+
resolve(found);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
205
|
+
setTimeout(() => {
|
|
206
|
+
observer.disconnect();
|
|
207
|
+
resolve(findElement(selector));
|
|
208
|
+
}, timeout);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function sleep(ms) {
|
|
212
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
213
|
+
}
|
|
214
|
+
function getNativeValueSetter(element) {
|
|
215
|
+
const proto = element instanceof HTMLInputElement ? window.HTMLInputElement.prototype : window.HTMLTextAreaElement.prototype;
|
|
216
|
+
return Object.getOwnPropertyDescriptor(proto, "value")?.set;
|
|
217
|
+
}
|
|
218
|
+
function setInputValue(element, value) {
|
|
219
|
+
const nativeSetter = getNativeValueSetter(element);
|
|
220
|
+
if (nativeSetter) nativeSetter.call(element, value);
|
|
221
|
+
else element.value = value;
|
|
222
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
223
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
224
|
+
}
|
|
225
|
+
async function simulateInput(element, text) {
|
|
226
|
+
const nativeSetter = getNativeValueSetter(element);
|
|
227
|
+
element.focus();
|
|
228
|
+
element.click();
|
|
229
|
+
await sleep(30);
|
|
230
|
+
if (nativeSetter) nativeSetter.call(element, "");
|
|
231
|
+
else element.value = "";
|
|
232
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
233
|
+
await sleep(20);
|
|
234
|
+
for (let i = 0; i < text.length; i++) {
|
|
235
|
+
const char = text[i];
|
|
236
|
+
if (nativeSetter) nativeSetter.call(element, element.value + char);
|
|
237
|
+
else element.value += char;
|
|
238
|
+
element.dispatchEvent(new KeyboardEvent("keydown", { key: char, bubbles: true }));
|
|
239
|
+
element.dispatchEvent(new InputEvent("input", { bubbles: true, inputType: "insertText", data: char }));
|
|
240
|
+
element.dispatchEvent(new KeyboardEvent("keyup", { key: char, bubbles: true }));
|
|
241
|
+
await sleep(15 + Math.random() * 20);
|
|
242
|
+
}
|
|
243
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
244
|
+
element.dispatchEvent(new Event("blur", { bubbles: true }));
|
|
245
|
+
const tracker = element._valueTracker;
|
|
246
|
+
if (tracker) tracker.setValue("");
|
|
247
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
248
|
+
}
|
|
249
|
+
function getCodeMirrorInstance() {
|
|
250
|
+
const cm5El = document.querySelector(".CodeMirror");
|
|
251
|
+
if (cm5El?.CodeMirror) return cm5El.CodeMirror;
|
|
252
|
+
if (window.CodeMirror) {
|
|
253
|
+
const editors = document.querySelectorAll(".CodeMirror");
|
|
254
|
+
for (const el of Array.from(editors)) {
|
|
255
|
+
const cm = el.CodeMirror;
|
|
256
|
+
if (cm) return cm;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const cm6El = document.querySelector(".cm-editor");
|
|
260
|
+
const view = cm6El?.cmView?.view ?? cm6El?.CodeMirror?.view ?? cm6El?.view;
|
|
261
|
+
if (view) return view;
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
function setCodeMirrorContent(content) {
|
|
265
|
+
const normalized = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
266
|
+
const cm = getCodeMirrorInstance();
|
|
267
|
+
if (!cm) return false;
|
|
268
|
+
if (cm.setValue) {
|
|
269
|
+
cm.setValue(normalized);
|
|
270
|
+
cm.refresh();
|
|
271
|
+
if (cm.trigger) cm.trigger("change", cm);
|
|
272
|
+
const textarea = document.querySelector(".CodeMirror textarea");
|
|
273
|
+
if (textarea) {
|
|
274
|
+
textarea.value = normalized;
|
|
275
|
+
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
276
|
+
textarea.dispatchEvent(new Event("change", { bubbles: true }));
|
|
277
|
+
}
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
if (cm.dispatch) {
|
|
281
|
+
cm.dispatch({ changes: { from: 0, to: cm.state.doc.length, insert: normalized } });
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
function getCodeMirrorContentLength() {
|
|
287
|
+
const cm = getCodeMirrorInstance();
|
|
288
|
+
if (!cm) return 0;
|
|
289
|
+
if (cm.getValue) return cm.getValue().length;
|
|
290
|
+
if (cm.state?.doc) return cm.state.doc.length;
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
function clearCodeMirror() {
|
|
294
|
+
return setCodeMirrorContent("");
|
|
295
|
+
}
|
|
296
|
+
function detectPageType() {
|
|
297
|
+
const url = window.location.href;
|
|
298
|
+
if (url.includes("/user/login")) return "login";
|
|
299
|
+
if (url.includes("/howtowrite")) return "howtowrite";
|
|
300
|
+
if (url.includes("/write")) return "editor";
|
|
301
|
+
if (findElement(SELECTORS.howtowrite.indicator)) return "howtowrite";
|
|
302
|
+
if (findElement(SELECTORS.editor.indicator)) return "editor";
|
|
303
|
+
return "unknown";
|
|
304
|
+
}
|
|
305
|
+
async function waitForPageType(expected, timeout = 8e3) {
|
|
306
|
+
const startTime = Date.now();
|
|
307
|
+
while (Date.now() - startTime < timeout) {
|
|
308
|
+
const current = detectPageType();
|
|
309
|
+
if (expected.includes(current)) return current;
|
|
310
|
+
await sleep(300);
|
|
311
|
+
}
|
|
312
|
+
return detectPageType();
|
|
313
|
+
}
|
|
314
|
+
async function navigateToWrite() {
|
|
315
|
+
const pageType = detectPageType();
|
|
316
|
+
if (pageType === "editor") return { success: true, data: { page_type: "editor" }, message: "\u5DF2\u5728\u7F16\u8F91\u5668\u9875\u9762" };
|
|
317
|
+
if (pageType === "login") return { success: false, error: "NOT_LOGGED_IN", errorCode: "NOT_LOGGED_IN", message: "\u8BF7\u5148\u767B\u5F55 SegmentFault" };
|
|
318
|
+
if (pageType === "howtowrite") return { success: true, data: { page_type: "howtowrite" }, message: "\u5728\u5F15\u5BFC\u9875\uFF0C\u9700\u70B9\u51FB\u7EE7\u7EED" };
|
|
319
|
+
window.location.href = "https://segmentfault.com/howtowrite";
|
|
320
|
+
return { success: true, data: { page_type: "navigating" }, message: "\u6B63\u5728\u5BFC\u822A\u5230\u5F15\u5BFC\u9875..." };
|
|
321
|
+
}
|
|
322
|
+
async function clickHowtowriteContinue() {
|
|
323
|
+
if (detectPageType() !== "howtowrite") {
|
|
324
|
+
return { success: false, error: "NOT_HOWTOWRITE", errorCode: "NOT_HOWTOWRITE", message: "\u4E0D\u5728\u5F15\u5BFC\u9875" };
|
|
325
|
+
}
|
|
326
|
+
const btn = findElement(SELECTORS.howtowrite.continueBtn);
|
|
327
|
+
if (!btn) return { success: false, error: "BUTTON_NOT_FOUND", errorCode: "BUTTON_NOT_FOUND", message: "\u672A\u627E\u5230\u7EE7\u7EED\u6309\u94AE" };
|
|
328
|
+
btn.click();
|
|
329
|
+
const newType = await waitForPageType(["editor"], 6e3);
|
|
330
|
+
return {
|
|
331
|
+
success: newType === "editor",
|
|
332
|
+
data: { page_type: newType },
|
|
333
|
+
message: newType === "editor" ? "\u5DF2\u8FDB\u5165\u7F16\u8F91\u5668" : `\u5F53\u524D: ${newType}`
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
async function setTitle(title) {
|
|
337
|
+
if (!title?.trim()) return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A" };
|
|
338
|
+
if (title.length < 5) return { success: false, error: "TOO_SHORT", errorCode: "TOO_SHORT", message: "\u6807\u9898\u81F3\u5C115\u5B57\u7B26" };
|
|
339
|
+
if (title.length > 100) return { success: false, error: "TOO_LONG", errorCode: "TOO_LONG", message: "\u6807\u9898\u6700\u591A100\u5B57\u7B26" };
|
|
340
|
+
const input = await waitForElement(SELECTORS.editor.titleInput, 6e3);
|
|
341
|
+
if (!input) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u6807\u9898\u8F93\u5165\u6846" };
|
|
342
|
+
await simulateInput(input, title);
|
|
343
|
+
await sleep(100);
|
|
344
|
+
const final = input.value?.trim();
|
|
345
|
+
if (final !== title) {
|
|
346
|
+
setInputValue(input, title);
|
|
347
|
+
await sleep(50);
|
|
348
|
+
}
|
|
349
|
+
if (input.value?.trim() !== title) {
|
|
350
|
+
return { success: false, error: "SET_FAILED", errorCode: "SET_FAILED", message: `\u6807\u9898\u5199\u5165\u5931\u8D25: "${input.value?.trim()}"` };
|
|
351
|
+
}
|
|
352
|
+
return { success: true, message: `\u6807\u9898\u5DF2\u8BBE\u7F6E` };
|
|
353
|
+
}
|
|
354
|
+
async function setContent(content) {
|
|
355
|
+
if (!content?.trim()) return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u6B63\u6587\u4E0D\u80FD\u4E3A\u7A7A" };
|
|
356
|
+
if (setCodeMirrorContent(content)) {
|
|
357
|
+
await sleep(300);
|
|
358
|
+
return { success: true, message: `\u6B63\u6587\u5DF2\u8BBE\u7F6E\uFF08CodeMirror\uFF0C${content.length}\u5B57\u7B26\uFF09` };
|
|
359
|
+
}
|
|
360
|
+
const textarea = await waitForElement(SELECTORS.editor.markdownTextarea, 3e3);
|
|
361
|
+
if (textarea) {
|
|
362
|
+
await simulateInput(textarea, content);
|
|
363
|
+
await sleep(200);
|
|
364
|
+
if (textarea.value?.trim() === content.trim()) {
|
|
365
|
+
return { success: true, message: `\u6B63\u6587\u5DF2\u8BBE\u7F6E\uFF08textarea\uFF0C${content.length}\u5B57\u7B26\uFF09` };
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const richEditor = document.querySelector('[contenteditable="true"]');
|
|
369
|
+
if (richEditor) {
|
|
370
|
+
richEditor.focus();
|
|
371
|
+
richEditor.innerHTML = `<p>${content.replace(/\n/g, "</p><p>")}</p>`;
|
|
372
|
+
richEditor.dispatchEvent(new InputEvent("input", { bubbles: true }));
|
|
373
|
+
await sleep(200);
|
|
374
|
+
return { success: true, message: `\u6B63\u6587\u5DF2\u8BBE\u7F6E\uFF08\u5BCC\u6587\u672C\uFF0C${content.length}\u5B57\u7B26\uFF09` };
|
|
375
|
+
}
|
|
376
|
+
return { success: false, error: "EDITOR_NOT_FOUND", errorCode: "EDITOR_NOT_FOUND", message: "\u672A\u627E\u5230\u7F16\u8F91\u5668" };
|
|
377
|
+
}
|
|
378
|
+
async function setArticleType(type = "original") {
|
|
379
|
+
const validTypes = ["original", "repost", "translate"];
|
|
380
|
+
if (!validTypes.includes(type)) return { success: false, error: "INVALID_TYPE", errorCode: "INVALID_TYPE", message: "\u7C7B\u578B\u5FC5\u987B\u662F original/repost/translate" };
|
|
381
|
+
const selectors = SELECTORS.editor.articleType[type];
|
|
382
|
+
const el = findElement(selectors);
|
|
383
|
+
if (!el) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: `\u672A\u627E\u5230\u7C7B\u578B: ${type}` };
|
|
384
|
+
if (el.checked) return { success: true, message: `\u6587\u7AE0\u7C7B\u578B\u5DF2\u662F: ${type}` };
|
|
385
|
+
const label = el.closest("label") || document.querySelector(`label[for="${el.id}"]`);
|
|
386
|
+
if (label) label.click();
|
|
387
|
+
else el.click();
|
|
388
|
+
el.checked = true;
|
|
389
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
390
|
+
await sleep(100);
|
|
391
|
+
return { success: true, message: `\u6587\u7AE0\u7C7B\u578B: ${type}` };
|
|
392
|
+
}
|
|
393
|
+
async function setPublishScope(scope = "personal") {
|
|
394
|
+
if (scope === "personal") {
|
|
395
|
+
const el = findElement(SELECTORS.editor.publishScope.personal);
|
|
396
|
+
if (!el) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u4E2A\u4EBA\u6587\u7AE0\u9009\u9879" };
|
|
397
|
+
if (el.checked) return { success: true, message: "\u53D1\u5E03\u8303\u56F4\u5DF2\u662F: \u4E2A\u4EBA\u6587\u7AE0" };
|
|
398
|
+
const label = el.closest("label") || document.querySelector(`label[for="${el.id}"]`);
|
|
399
|
+
if (label) label.click();
|
|
400
|
+
else el.click();
|
|
401
|
+
el.checked = true;
|
|
402
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
403
|
+
await sleep(100);
|
|
404
|
+
return { success: true, message: "\u53D1\u5E03\u8303\u56F4: \u4E2A\u4EBA\u6587\u7AE0" };
|
|
405
|
+
}
|
|
406
|
+
return { success: true, message: `\u53D1\u5E03\u8303\u56F4: ${scope}` };
|
|
407
|
+
}
|
|
408
|
+
async function addTags(tags = ["\u524D\u7AEF", "AI"], clearExisting = false) {
|
|
409
|
+
if (!tags?.length) return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A" };
|
|
410
|
+
if (tags.length > 5) return { success: false, error: "TOO_MANY", errorCode: "TOO_MANY", message: "\u6700\u591A5\u4E2A\u6807\u7B7E" };
|
|
411
|
+
const input = await waitForElement(SELECTORS.editor.tagInput, 6e3);
|
|
412
|
+
if (!input) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u6807\u7B7E\u8F93\u5165\u6846" };
|
|
413
|
+
if (clearExisting) {
|
|
414
|
+
const existing = findElements(SELECTORS.editor.tagRemoveBtn);
|
|
415
|
+
for (const btn of existing) {
|
|
416
|
+
btn.click();
|
|
417
|
+
await sleep(200);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const added = [];
|
|
421
|
+
const failed = [];
|
|
422
|
+
for (const tag of tags) {
|
|
423
|
+
let success = false;
|
|
424
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
425
|
+
input.focus();
|
|
426
|
+
input.value = "";
|
|
427
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
428
|
+
await sleep(50);
|
|
429
|
+
await simulateInput(input, tag);
|
|
430
|
+
await sleep(CONFIG.tagSuggestionDelay);
|
|
431
|
+
const suggestions = findElements(SELECTORS.editor.tagSuggestions);
|
|
432
|
+
let clicked = false;
|
|
433
|
+
for (const s of suggestions) {
|
|
434
|
+
const text = s.textContent?.trim() || "";
|
|
435
|
+
if (text === tag || text.includes(tag)) {
|
|
436
|
+
s.click();
|
|
437
|
+
clicked = true;
|
|
438
|
+
await sleep(300);
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (!clicked) {
|
|
443
|
+
input.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", bubbles: true }));
|
|
444
|
+
input.dispatchEvent(new KeyboardEvent("keyup", { key: "Enter", bubbles: true }));
|
|
445
|
+
await sleep(500);
|
|
446
|
+
}
|
|
447
|
+
const currentTags = findElements(SELECTORS.editor.selectedTags).map((el) => el.textContent?.trim().replace(/\s*[×x]$/, ""));
|
|
448
|
+
if (currentTags.some((t) => t === tag || t?.includes(tag))) {
|
|
449
|
+
success = true;
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
await sleep(300);
|
|
453
|
+
}
|
|
454
|
+
success ? added.push(tag) : failed.push(tag);
|
|
455
|
+
await sleep(150);
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
success: added.length > 0,
|
|
459
|
+
data: { added, failed },
|
|
460
|
+
message: `\u6807\u7B7E: \u6210\u529F${added.length}\u4E2A${failed.length ? `, \u5931\u8D25[${failed.join(", ")}]` : ""}`
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
async function setCategory(category) {
|
|
464
|
+
if (!category?.trim()) return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u5206\u7C7B\u4E0D\u80FD\u4E3A\u7A7A" };
|
|
465
|
+
const select = await waitForElement(SELECTORS.editor.categorySelect, 4e3);
|
|
466
|
+
if (!select) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u5206\u7C7B\u9009\u62E9\u5668" };
|
|
467
|
+
let retries = 10;
|
|
468
|
+
while (select.options.length <= 1 && retries-- > 0) await sleep(200);
|
|
469
|
+
const opt = Array.from(select.options).find(
|
|
470
|
+
(o) => o.textContent?.includes(category) || o.value.includes(category)
|
|
471
|
+
);
|
|
472
|
+
if (!opt) {
|
|
473
|
+
return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: `\u672A\u627E\u5230\u5206\u7C7B: ${category}` };
|
|
474
|
+
}
|
|
475
|
+
select.value = opt.value;
|
|
476
|
+
select.dispatchEvent(new Event("change", { bubbles: true }));
|
|
477
|
+
select.dispatchEvent(new Event("input", { bubbles: true }));
|
|
478
|
+
await sleep(100);
|
|
479
|
+
return { success: true, message: `\u5206\u7C7B: ${opt.textContent?.trim()}` };
|
|
480
|
+
}
|
|
481
|
+
async function setCopyright(enabled = true) {
|
|
482
|
+
const el = findElement(SELECTORS.editor.copyrightToggle);
|
|
483
|
+
if (!el) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u7248\u6743\u5F00\u5173" };
|
|
484
|
+
if (el.checked === enabled) return { success: true, message: `\u7248\u6743\u5DF2\u662F: ${enabled ? "\u5F00\u542F" : "\u5173\u95ED"}` };
|
|
485
|
+
const label = el.closest("label") || el.parentElement;
|
|
486
|
+
if (label) label.click();
|
|
487
|
+
else el.click();
|
|
488
|
+
await sleep(200);
|
|
489
|
+
return { success: true, message: `\u7248\u6743: ${enabled ? "\u5F00\u542F" : "\u5173\u95ED"}` };
|
|
490
|
+
}
|
|
491
|
+
async function setScheduledPublish(scheduledTime) {
|
|
492
|
+
if (!scheduledTime) return { success: true, message: "\u672A\u8BBE\u7F6E\u5B9A\u65F6\u53D1\u5E03\uFF0C\u4F7F\u7528\u7ACB\u5373\u53D1\u5E03" };
|
|
493
|
+
const date = new Date(scheduledTime);
|
|
494
|
+
if (isNaN(date.getTime())) return { success: false, error: "INVALID_TIME", errorCode: "INVALID_TIME", message: "\u65F6\u95F4\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u4F7F\u7528 ISO 8601 \u683C\u5F0F" };
|
|
495
|
+
const now = /* @__PURE__ */ new Date();
|
|
496
|
+
if (date <= now) return { success: false, error: "PAST_TIME", errorCode: "PAST_TIME", message: "\u5B9A\u65F6\u53D1\u5E03\u65F6\u95F4\u5FC5\u987B\u5927\u4E8E\u5F53\u524D\u65F6\u95F4" };
|
|
497
|
+
const triggerBtn = findElement(SELECTORS.editor.scheduledPublish.triggerBtn);
|
|
498
|
+
if (!triggerBtn) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u5B9A\u65F6\u53D1\u5E03\u9009\u9879" };
|
|
499
|
+
triggerBtn.click();
|
|
500
|
+
await sleep(600);
|
|
501
|
+
const datetimeInput = findElement(SELECTORS.editor.scheduledPublish.datetimeInput);
|
|
502
|
+
if (datetimeInput) {
|
|
503
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
504
|
+
const localStr = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
505
|
+
setInputValue(datetimeInput, localStr);
|
|
506
|
+
await sleep(300);
|
|
507
|
+
const confirmBtn = findElement(SELECTORS.editor.scheduledPublish.confirmBtn);
|
|
508
|
+
if (confirmBtn) {
|
|
509
|
+
confirmBtn.click();
|
|
510
|
+
await sleep(300);
|
|
511
|
+
}
|
|
512
|
+
return { success: true, message: `\u5B9A\u65F6\u53D1\u5E03\u5DF2\u8BBE\u7F6E: ${scheduledTime}` };
|
|
513
|
+
}
|
|
514
|
+
return { success: false, error: "NOT_IMPLEMENTED", errorCode: "NOT_IMPLEMENTED", message: "\u6682\u4E0D\u652F\u6301\u6B64\u7C7B\u578B\u7684\u5B9A\u65F6\u53D1\u5E03 UI" };
|
|
515
|
+
}
|
|
516
|
+
async function discardDraft() {
|
|
517
|
+
const pageType = detectPageType();
|
|
518
|
+
if (pageType !== "editor") return { success: false, error: "NOT_EDITOR", errorCode: "NOT_EDITOR", message: "\u4E0D\u5728\u7F16\u8F91\u5668\u9875\u9762" };
|
|
519
|
+
const discardBtn = findElement(SELECTORS.editor.discardDraftBtn);
|
|
520
|
+
if (discardBtn) {
|
|
521
|
+
discardBtn.click();
|
|
522
|
+
await sleep(800);
|
|
523
|
+
const confirmBtn = findElement(['button:contains("\u786E\u8BA4")', 'button:contains("\u786E\u5B9A")', ".ant-modal-confirm-btns button:last-child"]);
|
|
524
|
+
if (confirmBtn) {
|
|
525
|
+
confirmBtn.click();
|
|
526
|
+
await sleep(600);
|
|
527
|
+
}
|
|
528
|
+
return { success: true, message: "\u5DF2\u820D\u5F03\u8349\u7A3F" };
|
|
529
|
+
}
|
|
530
|
+
const results = [];
|
|
531
|
+
const titleInput = findElement(SELECTORS.editor.titleInput);
|
|
532
|
+
if (titleInput) {
|
|
533
|
+
setInputValue(titleInput, "");
|
|
534
|
+
results.push("\u6807\u9898\u5DF2\u6E05\u7A7A");
|
|
535
|
+
}
|
|
536
|
+
if (clearCodeMirror()) results.push("\u6B63\u6587\u5DF2\u6E05\u7A7A");
|
|
537
|
+
else {
|
|
538
|
+
const textarea = findElement(SELECTORS.editor.markdownTextarea);
|
|
539
|
+
if (textarea) {
|
|
540
|
+
setInputValue(textarea, "");
|
|
541
|
+
results.push("\u6B63\u6587\u5DF2\u6E05\u7A7A");
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
const existingTags = findElements(SELECTORS.editor.tagRemoveBtn);
|
|
545
|
+
for (const btn of existingTags) {
|
|
546
|
+
btn.click();
|
|
547
|
+
await sleep(150);
|
|
548
|
+
}
|
|
549
|
+
if (existingTags.length > 0) results.push(`\u5DF2\u79FB\u9664 ${existingTags.length} \u4E2A\u6807\u7B7E`);
|
|
550
|
+
return { success: true, data: { cleared_items: results.length }, message: `\u8349\u7A3F\u5DF2\u820D\u5F03
|
|
551
|
+
${results.join("\n")}` };
|
|
552
|
+
}
|
|
553
|
+
async function getState() {
|
|
554
|
+
const pageType = detectPageType();
|
|
555
|
+
if (pageType !== "editor") {
|
|
556
|
+
return { success: true, data: { page_type: pageType, can_publish: false }, message: `\u5F53\u524D\u9875\u9762: ${pageType}` };
|
|
557
|
+
}
|
|
558
|
+
const titleInput = findElement(SELECTORS.editor.titleInput);
|
|
559
|
+
const title = titleInput?.value?.trim() || "";
|
|
560
|
+
let contentLen = getCodeMirrorContentLength();
|
|
561
|
+
if (contentLen === 0) {
|
|
562
|
+
const ta = findElement(SELECTORS.editor.markdownTextarea);
|
|
563
|
+
if (ta) contentLen = ta.value?.length || 0;
|
|
564
|
+
}
|
|
565
|
+
const tags = findElements(SELECTORS.editor.selectedTags).map((el) => el.textContent?.trim().replace(/\s*[×x]$/, "")).filter(Boolean);
|
|
566
|
+
const catSelect = findElement(SELECTORS.editor.categorySelect);
|
|
567
|
+
const category = catSelect?.options[catSelect.selectedIndex]?.textContent?.trim() || "";
|
|
568
|
+
const copyrightEl = findElement(SELECTORS.editor.copyrightToggle);
|
|
569
|
+
const copyrightEnabled = copyrightEl?.checked ?? true;
|
|
570
|
+
const errors = [];
|
|
571
|
+
if (title.length < 5) errors.push("\u6807\u9898\u8FC7\u77ED");
|
|
572
|
+
if (title.length > 100) errors.push("\u6807\u9898\u8FC7\u957F");
|
|
573
|
+
if (contentLen === 0) errors.push("\u6B63\u6587\u4E3A\u7A7A");
|
|
574
|
+
if (tags.length === 0) errors.push("\u672A\u6DFB\u52A0\u6807\u7B7E");
|
|
575
|
+
if (!category || category.includes("\u9009\u62E9")) errors.push("\u672A\u9009\u62E9\u5206\u7C7B");
|
|
576
|
+
return {
|
|
577
|
+
success: true,
|
|
578
|
+
data: {
|
|
579
|
+
page_type: "editor",
|
|
580
|
+
title,
|
|
581
|
+
title_valid: title.length >= 5 && title.length <= 100,
|
|
582
|
+
content_length: contentLen,
|
|
583
|
+
content_valid: contentLen > 0,
|
|
584
|
+
tags,
|
|
585
|
+
tags_valid: tags.length > 0 && tags.length <= 5,
|
|
586
|
+
category,
|
|
587
|
+
category_valid: !!category && !category.includes("\u9009\u62E9"),
|
|
588
|
+
copyright: copyrightEnabled,
|
|
589
|
+
can_publish: errors.length === 0,
|
|
590
|
+
errors,
|
|
591
|
+
draft_url: "https://segmentfault.com/user/draft"
|
|
592
|
+
},
|
|
593
|
+
message: errors.length ? `\u5B58\u5728 ${errors.length} \u4E2A\u95EE\u9898: ${errors.join("; ")}` : "\u72B6\u6001\u6B63\u5E38\uFF0C\u53EF\u53D1\u5E03"
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
async function publish(confirm = false) {
|
|
597
|
+
if (!confirm) {
|
|
598
|
+
return {
|
|
599
|
+
success: false,
|
|
600
|
+
error: "NOT_CONFIRMED",
|
|
601
|
+
errorCode: "NOT_CONFIRMED",
|
|
602
|
+
message: '\u8BF7\u5148\u5BA1\u6838\u8349\u7A3F\uFF08https://segmentfault.com/user/draft\uFF09\uFF0C\u786E\u8BA4\u540E\u56DE\u590D"\u786E\u8BA4\u53D1\u5E03"\u5E76\u4F20\u5165 confirm: true',
|
|
603
|
+
data: { draft_url: "https://segmentfault.com/user/draft" }
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
const state = await getState();
|
|
607
|
+
if (!state.data?.can_publish) {
|
|
608
|
+
return { success: false, error: "CANNOT_PUBLISH", errorCode: "CANNOT_PUBLISH", message: `\u65E0\u6CD5\u53D1\u5E03: ${state.data?.errors?.join(", ")}` };
|
|
609
|
+
}
|
|
610
|
+
const btn = findElement(SELECTORS.editor.publishBtn);
|
|
611
|
+
if (!btn) return { success: false, error: "NOT_FOUND", errorCode: "NOT_FOUND", message: "\u672A\u627E\u5230\u53D1\u5E03\u6309\u94AE" };
|
|
612
|
+
btn.click();
|
|
613
|
+
await sleep(2500);
|
|
614
|
+
const url = window.location.href;
|
|
615
|
+
if (url.includes("/a/")) {
|
|
616
|
+
return { success: true, data: { url, article_id: url.match(/\/a\/(\d+)/)?.[1] }, message: `\u53D1\u5E03\u6210\u529F: ${url}` };
|
|
617
|
+
}
|
|
618
|
+
const confirmBtn = findElement(['button:contains("\u786E\u8BA4")', 'button:contains("\u786E\u5B9A")', ".ant-modal-confirm-btns button:last-child"]);
|
|
619
|
+
if (confirmBtn) {
|
|
620
|
+
confirmBtn.click();
|
|
621
|
+
await sleep(1500);
|
|
622
|
+
const finalUrl = window.location.href;
|
|
623
|
+
if (finalUrl.includes("/a/")) {
|
|
624
|
+
return { success: true, data: { url: finalUrl, article_id: finalUrl.match(/\/a\/(\d+)/)?.[1] }, message: `\u53D1\u5E03\u6210\u529F: ${finalUrl}` };
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return { success: true, message: "\u53D1\u5E03\u8BF7\u6C42\u5DF2\u63D0\u4EA4" };
|
|
628
|
+
}
|
|
629
|
+
async function writeArticle(params) {
|
|
630
|
+
const results = [];
|
|
631
|
+
const r1 = await setTitle(params.title);
|
|
632
|
+
if (!r1.success) return r1;
|
|
633
|
+
results.push(r1.message);
|
|
634
|
+
await sleep(150);
|
|
635
|
+
const r2 = await setContent(params.content);
|
|
636
|
+
if (!r2.success) return r2;
|
|
637
|
+
results.push(r2.message);
|
|
638
|
+
await sleep(150);
|
|
639
|
+
const r3 = await setArticleType(params.type || "original");
|
|
640
|
+
if (r3.success) results.push(r3.message);
|
|
641
|
+
await sleep(100);
|
|
642
|
+
const r4 = await setPublishScope(params.scope || "personal");
|
|
643
|
+
if (r4.success) results.push(r4.message);
|
|
644
|
+
await sleep(100);
|
|
645
|
+
const r5 = await addTags(params.tags || ["\u524D\u7AEF", "AI"]);
|
|
646
|
+
results.push(r5.message);
|
|
647
|
+
await sleep(150);
|
|
648
|
+
const r6 = await setCategory(params.category);
|
|
649
|
+
if (!r6.success) return r6;
|
|
650
|
+
results.push(r6.message);
|
|
651
|
+
await sleep(100);
|
|
652
|
+
const r7 = await setCopyright(params.copyright !== false);
|
|
653
|
+
if (r7.success) results.push(r7.message);
|
|
654
|
+
await sleep(100);
|
|
655
|
+
await sleep(CONFIG.autoSaveDelay);
|
|
656
|
+
return {
|
|
657
|
+
success: true,
|
|
658
|
+
data: { steps: results.length, draft_url: "https://segmentfault.com/user/draft" },
|
|
659
|
+
message: `\u2705 \u6587\u7AE0\u5199\u5165\u5B8C\u6210\uFF01\uFF08\u601D\u5426\u5DF2\u81EA\u52A8\u4FDD\u5B58\u8349\u7A3F\uFF09
|
|
660
|
+
${results.join("\n")}
|
|
661
|
+
|
|
662
|
+
\u{1F4CE} \u5C01\u9762\u56FE\u7247\uFF1A\u8BF7\u624B\u52A8\u4E0A\u4F20\uFF08\u5982\u9700\uFF09
|
|
663
|
+
\u{1F50D} \u8BF7\u524D\u5F80\u8349\u7A3F\u7BB1\u5BA1\u6838: https://segmentfault.com/user/draft
|
|
664
|
+
\u2705 \u5BA1\u6838\u901A\u8FC7\u540E\u56DE\u590D"\u786E\u8BA4\u53D1\u5E03"\u6267\u884C\u53D1\u5E03`
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
async function publishFullFlow(params) {
|
|
668
|
+
const results = [];
|
|
669
|
+
const data = { steps_completed: 0, draft_url: "https://segmentfault.com/user/draft" };
|
|
670
|
+
const pageType = detectPageType();
|
|
671
|
+
if (pageType === "login") {
|
|
672
|
+
return { success: false, error: "NOT_LOGGED_IN", errorCode: "NOT_LOGGED_IN", message: "\u8BF7\u5148\u767B\u5F55 SegmentFault" };
|
|
673
|
+
}
|
|
674
|
+
if (pageType === "editor") {
|
|
675
|
+
results.push("\u{1F4CD} \u5F53\u524D\u5DF2\u5728\u7F16\u8F91\u5668");
|
|
676
|
+
} else if (pageType === "howtowrite") {
|
|
677
|
+
results.push("\u{1F4CD} \u5F53\u524D\u5728\u5F15\u5BFC\u9875");
|
|
678
|
+
} else {
|
|
679
|
+
window.location.href = "https://segmentfault.com/howtowrite";
|
|
680
|
+
results.push("\u{1F680} \u5DF2\u5BFC\u822A\u5230\u5F15\u5BFC\u9875");
|
|
681
|
+
const arrived = await waitForPageType(["howtowrite", "editor"], 8e3);
|
|
682
|
+
if (arrived === "unknown") {
|
|
683
|
+
return { success: false, error: "NAV_TIMEOUT", errorCode: "NAV_TIMEOUT", message: "\u9875\u9762\u52A0\u8F7D\u8D85\u65F6" };
|
|
684
|
+
}
|
|
685
|
+
await sleep(1e3);
|
|
686
|
+
}
|
|
687
|
+
if (detectPageType() === "howtowrite") {
|
|
688
|
+
const continueResult = await clickHowtowriteContinue();
|
|
689
|
+
if (continueResult.success) {
|
|
690
|
+
results.push("\u2705 \u5DF2\u901A\u8FC7\u5F15\u5BFC\u9875\uFF0C\u8FDB\u5165\u7F16\u8F91\u5668");
|
|
691
|
+
} else {
|
|
692
|
+
return { success: false, error: "GUIDE_FAILED", errorCode: "GUIDE_FAILED", message: `\u5F15\u5BFC\u9875\u5904\u7406\u5931\u8D25: ${continueResult.message}` };
|
|
693
|
+
}
|
|
694
|
+
await sleep(800);
|
|
695
|
+
}
|
|
696
|
+
if (detectPageType() !== "editor") {
|
|
697
|
+
return { success: false, error: "NOT_EDITOR", errorCode: "NOT_EDITOR", message: "\u672A\u80FD\u8FDB\u5165\u7F16\u8F91\u5668\u9875\u9762" };
|
|
698
|
+
}
|
|
699
|
+
const titleReady = await waitForElement(SELECTORS.editor.titleInput, 5e3);
|
|
700
|
+
if (!titleReady) {
|
|
701
|
+
return { success: false, error: "EDITOR_NOT_READY", errorCode: "EDITOR_NOT_READY", message: "\u7F16\u8F91\u5668\u672A\u5C31\u7EEA\uFF08\u6807\u9898\u8F93\u5165\u6846\u672A\u627E\u5230\uFF09" };
|
|
702
|
+
}
|
|
703
|
+
const r1 = await setTitle(params.title);
|
|
704
|
+
if (!r1.success) return r1;
|
|
705
|
+
results.push(`\u2705 ${r1.message}`);
|
|
706
|
+
await sleep(100);
|
|
707
|
+
const r2 = await setContent(params.content);
|
|
708
|
+
if (!r2.success) return r2;
|
|
709
|
+
results.push(`\u2705 ${r2.message}`);
|
|
710
|
+
await sleep(100);
|
|
711
|
+
const r3 = await setArticleType(params.type || "original");
|
|
712
|
+
if (r3.success) results.push(`\u2705 ${r3.message}`);
|
|
713
|
+
await sleep(100);
|
|
714
|
+
const r4 = await setPublishScope(params.scope || "personal");
|
|
715
|
+
if (r4.success) results.push(`\u2705 ${r4.message}`);
|
|
716
|
+
await sleep(100);
|
|
717
|
+
const r5 = await addTags(params.tags || ["\u524D\u7AEF", "AI"]);
|
|
718
|
+
results.push(`\u2705 ${r5.message}`);
|
|
719
|
+
await sleep(100);
|
|
720
|
+
const r6 = await setCategory(params.category);
|
|
721
|
+
if (!r6.success) return r6;
|
|
722
|
+
results.push(`\u2705 ${r6.message}`);
|
|
723
|
+
await sleep(100);
|
|
724
|
+
const r7 = await setCopyright(params.copyright !== false);
|
|
725
|
+
if (r7.success) results.push(`\u2705 ${r7.message}`);
|
|
726
|
+
await sleep(100);
|
|
727
|
+
data.steps_completed = 7;
|
|
728
|
+
if (params.scheduled_time) {
|
|
729
|
+
const scheduledResult = await setScheduledPublish(params.scheduled_time);
|
|
730
|
+
if (scheduledResult.success) {
|
|
731
|
+
results.push(`\u2705 ${scheduledResult.message}`);
|
|
732
|
+
data.scheduled = true;
|
|
733
|
+
data.scheduled_time = params.scheduled_time;
|
|
734
|
+
} else {
|
|
735
|
+
results.push(`\u26A0\uFE0F \u5B9A\u65F6\u53D1\u5E03\u5931\u8D25: ${scheduledResult.message}`);
|
|
736
|
+
data.scheduled = false;
|
|
737
|
+
}
|
|
738
|
+
await sleep(300);
|
|
739
|
+
} else {
|
|
740
|
+
data.scheduled = false;
|
|
741
|
+
results.push("\u23F0 \u672A\u8BBE\u7F6E\u5B9A\u65F6\u53D1\u5E03\uFF08\u7ACB\u5373\u53D1\u5E03\uFF09");
|
|
742
|
+
}
|
|
743
|
+
data.cover_upload_needed = true;
|
|
744
|
+
results.push("\u{1F4CE} \u5C01\u9762\u56FE\u7247\uFF1A\u8BF7\u624B\u52A8\u4E0A\u4F20\uFF08\u5982\u9700\uFF09");
|
|
745
|
+
results.push(`\u23F3 \u7B49\u5F85\u601D\u5426\u81EA\u52A8\u4FDD\u5B58\uFF08${CONFIG.autoSaveDelay}ms\uFF09...`);
|
|
746
|
+
await sleep(CONFIG.autoSaveDelay);
|
|
747
|
+
const finalState = await getState();
|
|
748
|
+
data.validation = finalState.data;
|
|
749
|
+
data.steps_completed = 10;
|
|
750
|
+
return {
|
|
751
|
+
success: true,
|
|
752
|
+
data,
|
|
753
|
+
message: `\u2705 \u6587\u7AE0\u5199\u5165\u5B8C\u6210\uFF01\u6587\u7AE0\u5DF2\u4FDD\u5B58\u81F3\u8349\u7A3F\u7BB1
|
|
754
|
+
|
|
755
|
+
${results.join("\n")}
|
|
756
|
+
|
|
757
|
+
\u{1F50D} \u8BF7\u524D\u5F80\u8349\u7A3F\u7BB1\u5BA1\u6838: https://segmentfault.com/user/draft
|
|
758
|
+
\u2705 \u5BA1\u6838\u65E0\u8BEF\u540E\uFF0C\u56DE\u590D"\u786E\u8BA4\u53D1\u5E03"\u6267\u884C\u6B63\u5F0F\u53D1\u5E03`
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
function registerTool() {
|
|
762
|
+
if (typeof navigator === "undefined" || !navigator.modelContext) {
|
|
763
|
+
console.warn("[SF Tool] document.modelContext \u4E0D\u53EF\u7528");
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
navigator.modelContext.registerTool({
|
|
767
|
+
name: "segmentfault_publish_article",
|
|
768
|
+
description: "SegmentFault \u6587\u7AE0\u53D1\u5E03\u5DE5\u5177 v6 \u7CBE\u7B80\u5FEB\u901F\u7248\u3002\u5BFC\u822A\u5230 howtowrite \u2192 \u5FEB\u901F\u8FC7\u5F15\u5BFC \u2192 \u586B\u5165\u6807\u9898\u6B63\u6587 \u2192 \u8BBE\u7F6E\u9009\u9879 \u2192 \u4FDD\u5B58\u8349\u7A3F\u3002",
|
|
769
|
+
inputSchema: {
|
|
770
|
+
type: "object",
|
|
771
|
+
properties: {
|
|
772
|
+
action: {
|
|
773
|
+
type: "string",
|
|
774
|
+
enum: [
|
|
775
|
+
"publish_full_flow",
|
|
776
|
+
"navigate_to_write",
|
|
777
|
+
"click_howtowrite_continue",
|
|
778
|
+
"write_article",
|
|
779
|
+
"set_title",
|
|
780
|
+
"set_content",
|
|
781
|
+
"set_article_type",
|
|
782
|
+
"set_publish_scope",
|
|
783
|
+
"add_tags",
|
|
784
|
+
"set_category",
|
|
785
|
+
"set_copyright",
|
|
786
|
+
"set_scheduled_publish",
|
|
787
|
+
"discard_draft",
|
|
788
|
+
"get_state",
|
|
789
|
+
"publish"
|
|
790
|
+
],
|
|
791
|
+
description: "\u64CD\u4F5C\u7C7B\u578B"
|
|
792
|
+
},
|
|
793
|
+
title: { type: "string", description: "\u6587\u7AE0\u6807\u9898\uFF0C5-100\u5B57\u7B26" },
|
|
794
|
+
content: { type: "string", description: "\u6587\u7AE0\u6B63\u6587\uFF0C\u652F\u6301 Markdown" },
|
|
795
|
+
category: { type: "string", description: '\u5206\u7C7B\u540D\u79F0\uFF0C\u5982"\u524D\u7AEF"' },
|
|
796
|
+
tags: { type: "array", items: { type: "string" }, description: '\u6807\u7B7E\u6570\u7EC4\uFF0C\u9ED8\u8BA4["\u524D\u7AEF","AI"]' },
|
|
797
|
+
clear_existing: { type: "boolean", description: "\u662F\u5426\u6E05\u7A7A\u5DF2\u6709\u6807\u7B7E" },
|
|
798
|
+
type: { type: "string", enum: ["original", "repost", "translate"], description: "\u6587\u7AE0\u7C7B\u578B\uFF0C\u9ED8\u8BA4\u539F\u521B" },
|
|
799
|
+
scope: { type: "string", enum: ["personal"], description: "\u53D1\u5E03\u8303\u56F4\uFF0C\u9ED8\u8BA4 personal" },
|
|
800
|
+
copyright: { type: "boolean", description: "\u7248\u6743\u5F00\u5173\uFF0C\u9ED8\u8BA4 true" },
|
|
801
|
+
scheduled_time: { type: "string", description: "\u5B9A\u65F6\u53D1\u5E03\u65F6\u95F4\uFF0CISO 8601\u683C\u5F0F" },
|
|
802
|
+
confirm: { type: "boolean", description: "\u53D1\u5E03\u786E\u8BA4\uFF0C\u5FC5\u987B true" }
|
|
803
|
+
},
|
|
804
|
+
required: ["action"]
|
|
805
|
+
},
|
|
806
|
+
execute: async (args) => {
|
|
807
|
+
try {
|
|
808
|
+
switch (args.action) {
|
|
809
|
+
case "publish_full_flow":
|
|
810
|
+
return await publishFullFlow(args);
|
|
811
|
+
case "navigate_to_write":
|
|
812
|
+
return await navigateToWrite();
|
|
813
|
+
case "click_howtowrite_continue":
|
|
814
|
+
return await clickHowtowriteContinue();
|
|
815
|
+
case "write_article":
|
|
816
|
+
return await writeArticle(args);
|
|
817
|
+
case "set_title":
|
|
818
|
+
return await setTitle(args.title);
|
|
819
|
+
case "set_content":
|
|
820
|
+
return await setContent(args.content);
|
|
821
|
+
case "set_article_type":
|
|
822
|
+
return await setArticleType(args.type);
|
|
823
|
+
case "set_publish_scope":
|
|
824
|
+
return await setPublishScope(args.scope);
|
|
825
|
+
case "add_tags":
|
|
826
|
+
return await addTags(args.tags, args.clear_existing);
|
|
827
|
+
case "set_category":
|
|
828
|
+
return await setCategory(args.category);
|
|
829
|
+
case "set_copyright":
|
|
830
|
+
return await setCopyright(args.enabled);
|
|
831
|
+
case "set_scheduled_publish":
|
|
832
|
+
return await setScheduledPublish(args.scheduled_time);
|
|
833
|
+
case "discard_draft":
|
|
834
|
+
return await discardDraft();
|
|
835
|
+
case "get_state":
|
|
836
|
+
return await getState();
|
|
837
|
+
case "publish":
|
|
838
|
+
return await publish(args.confirm);
|
|
839
|
+
default:
|
|
840
|
+
return { success: false, error: "UNKNOWN_ACTION", errorCode: "UNKNOWN_ACTION", message: `\u672A\u77E5\u64CD\u4F5C: ${args.action}` };
|
|
841
|
+
}
|
|
842
|
+
} catch (err) {
|
|
843
|
+
console.error("[SF Tool] \u6267\u884C\u9519\u8BEF:", err);
|
|
844
|
+
return { success: false, error: "EXEC_ERROR", errorCode: "EXEC_ERROR", message: err instanceof Error ? err.message : String(err) };
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
console.log("[SF Tool] \u2705 \u5DF2\u6CE8\u518C segmentfault_publish_article v6\uFF08\u7CBE\u7B80\u5FEB\u901F\u7248\uFF09");
|
|
849
|
+
}
|
|
850
|
+
if (document.readyState === "loading") {
|
|
851
|
+
document.addEventListener("DOMContentLoaded", registerTool);
|
|
852
|
+
} else {
|
|
853
|
+
registerTool();
|
|
854
|
+
}
|
|
855
|
+
})();
|
|
856
|
+
})();
|