@harness.farm/social-cli 0.1.2 → 0.1.3
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/adapters/bilibili.yaml +23 -2
- package/adapters/douyin.yaml +20 -1
- package/dist/runner/yaml-runner.js +23 -0
- package/package.json +1 -1
package/adapters/bilibili.yaml
CHANGED
|
@@ -213,10 +213,31 @@ commands:
|
|
|
213
213
|
- upload:
|
|
214
214
|
selector: "input[accept*='.mp4']"
|
|
215
215
|
file: "{{video}}"
|
|
216
|
-
#
|
|
216
|
+
# 等待编辑器渲染(标题输入框出现)
|
|
217
217
|
- wait:
|
|
218
218
|
selector: "input[placeholder='请输入稿件标题']"
|
|
219
|
-
- wait:
|
|
219
|
+
- wait: 1000
|
|
220
|
+
# 等待视频上传+转码真正完成
|
|
221
|
+
# B站上传页:上传中显示进度百分比,完成后显示"上传完成"并且"立即投稿"按钮变为可点击
|
|
222
|
+
- wait_until:
|
|
223
|
+
eval: >-
|
|
224
|
+
(function(){
|
|
225
|
+
var body = document.body.innerText;
|
|
226
|
+
if (body.includes('上传完成') && !body.includes('上传中')) return true;
|
|
227
|
+
var progress = document.querySelector('.upload-progress, [class*=progress], [class*=uploading]');
|
|
228
|
+
if (progress) {
|
|
229
|
+
var text = progress.textContent || '';
|
|
230
|
+
if (text.includes('100%')) return true;
|
|
231
|
+
}
|
|
232
|
+
var btn = document.querySelector('span.submit-add');
|
|
233
|
+
if (btn) {
|
|
234
|
+
var parent = btn.closest('button') || btn.parentElement;
|
|
235
|
+
if (parent && !parent.classList.contains('disabled') && !parent.hasAttribute('disabled')) return true;
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
})()
|
|
239
|
+
timeout: 300000
|
|
240
|
+
interval: 3000
|
|
220
241
|
# 关掉所有弹窗(二创计划 / 定时发布 / 通知)
|
|
221
242
|
- eval: >-
|
|
222
243
|
(function(){
|
package/adapters/douyin.yaml
CHANGED
|
@@ -115,6 +115,22 @@ commands:
|
|
|
115
115
|
- wait:
|
|
116
116
|
selector: "input[placeholder='填写作品标题,为作品获得更多流量']"
|
|
117
117
|
- wait: 1000
|
|
118
|
+
# 等待视频上传完成(进度条消失 或 上传成功文字出现)
|
|
119
|
+
# 抖音上传中会显示进度百分比,上传完成后进度区域消失或显示"上传完成"
|
|
120
|
+
- wait_until:
|
|
121
|
+
eval: >-
|
|
122
|
+
(function(){
|
|
123
|
+
var body = document.body.innerText;
|
|
124
|
+
if (body.includes('上传完成') || body.includes('Upload complete')) return true;
|
|
125
|
+
var progress = document.querySelector('.progress-bar, .upload-progress, [class*=progress]');
|
|
126
|
+
if (!progress) return true;
|
|
127
|
+
var text = progress.textContent || '';
|
|
128
|
+
if (text.includes('100%')) return true;
|
|
129
|
+
var btn = [...document.querySelectorAll('button')].find(function(b){ return b.textContent.trim() === '发布' && !b.disabled; });
|
|
130
|
+
return !!btn;
|
|
131
|
+
})()
|
|
132
|
+
timeout: 300000
|
|
133
|
+
interval: 3000
|
|
118
134
|
# 填写标题
|
|
119
135
|
- fill:
|
|
120
136
|
selector: "input[placeholder='填写作品标题,为作品获得更多流量']"
|
|
@@ -165,9 +181,12 @@ commands:
|
|
|
165
181
|
- capture:
|
|
166
182
|
name: result_url
|
|
167
183
|
eval: "location.href"
|
|
184
|
+
- capture:
|
|
185
|
+
name: success
|
|
186
|
+
eval: "document.body.innerText.includes('发布成功') || document.body.innerText.includes('作品发布') || location.href.includes('/content/manage') || location.href !== 'https://creator.douyin.com/creator-micro/content/upload'"
|
|
168
187
|
- return:
|
|
169
188
|
- field: 状态
|
|
170
|
-
value: "✅ 发布成功"
|
|
189
|
+
value: "{{success === 'true' ? '✅ 发布成功' : '⚠️ 请检查页面'}}"
|
|
171
190
|
- field: 标题
|
|
172
191
|
value: "{{title}}"
|
|
173
192
|
- field: 描述
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
* - extract: { selector, fields: { key: ".sel" | { selector, attr } } }
|
|
27
27
|
* - return: [ { field, value } ] → builds output table
|
|
28
28
|
* - assert: { eval: "js", message: "error msg" }
|
|
29
|
+
* - wait_until: { eval: "js", timeout: 120000, interval: 2000 } # poll until truthy
|
|
29
30
|
*/
|
|
30
31
|
import fs from 'fs';
|
|
31
32
|
import { parse as parseYaml } from 'yaml';
|
|
@@ -200,6 +201,28 @@ export async function runYamlCommand(adapterPath, commandName, argValues, cdpPor
|
|
|
200
201
|
await cdpClient.send('Input.insertText', { text });
|
|
201
202
|
break;
|
|
202
203
|
}
|
|
204
|
+
case 'wait_until': {
|
|
205
|
+
// Poll a JS expression until it returns truthy, with timeout
|
|
206
|
+
const { eval: js, timeout = 120000, interval = 2000 } = val;
|
|
207
|
+
const interpolatedJs = interpolate(js, vars);
|
|
208
|
+
console.log(` → wait_until (timeout: ${timeout / 1000}s, interval: ${interval / 1000}s)`);
|
|
209
|
+
const deadline = Date.now() + timeout;
|
|
210
|
+
let resolved = false;
|
|
211
|
+
while (Date.now() < deadline) {
|
|
212
|
+
const r = exec.eval(interpolatedJs);
|
|
213
|
+
if (r.ok && r.value && r.value !== 'false' && r.value !== '' && r.value !== 0) {
|
|
214
|
+
resolved = true;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
console.log(` ... waiting (${Math.round((deadline - Date.now()) / 1000)}s left)`);
|
|
218
|
+
exec.wait(interval);
|
|
219
|
+
}
|
|
220
|
+
if (!resolved) {
|
|
221
|
+
throw new Error(`wait_until timed out after ${timeout / 1000}s`);
|
|
222
|
+
}
|
|
223
|
+
console.log(` ✅ condition met`);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
203
226
|
}
|
|
204
227
|
}
|
|
205
228
|
// 5. Render output
|