dsh-bili-scroll 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/AGENTS.md +16 -3
- package/client.js +48 -1
- package/index.js +74 -2
- package/package.json +1 -1
- package/prompts/duty.md +9 -1
package/AGENTS.md
CHANGED
|
@@ -9,12 +9,25 @@
|
|
|
9
9
|
只有它自己也下不动时(网络到不了 GitHub / 加速代理 / PyPI 镜像),才需要引导用户手动装。
|
|
10
10
|
· 它是**直连 GitHub → 国内加速代理 → PyPI 镜像**依次试的,并且会**核对官方 sha256** ✓
|
|
11
11
|
· ⚠️ 若用户机器上的**杀软拦了这次下载**:让他把 `%USERPROFILE%\.dsh\bili-duty\bin\` 加白,或干脆自己装 uv / Python 3.10+ ✓
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
· ⭐ **万一下载链路都不通**(有用户反馈"桌面版上这条链路经常不通"):**手动放一份 `uv.exe` 到 `<家目录>\bin\` 就行**
|
|
13
|
+
—— 插件会**优先用那里那一份**,跳过下载 ✓
|
|
14
|
+
2. `dsh plugin --profile web add dsh-bili-scroll`(npm,推荐)
|
|
15
|
+
· 备选:`dsh plugin --profile web add github:c1overzz/dsh-bili-scroll`
|
|
16
|
+
· ⚠️ **升级旧版**:如果用户在设置页看到的按钮叫「**重装依赖**」(不是「**重装主依赖**」),
|
|
17
|
+
说明装的还是 **0.1.0** —— 那一版建 Python 环境时缺一个参数,**依赖装不上、二维码也画不出来**。
|
|
18
|
+
让用户重跑一次上面那条 `add` 就是升级(然后再重启一次)。
|
|
14
19
|
3. ⚠️ **提醒用户重启一次 dsh**(必须,bundle 层要重启才组装)。
|
|
15
|
-
4. 让用户进 **设置 → 刷B
|
|
20
|
+
4. 让用户进 **设置 → 刷B站**:点「**装主依赖**」→ 点「**扫码登录**」(手机扫码,选"记住我 / 长期")。
|
|
21
|
+
· 装完可以用设置页的「**测一下**」自检:它真跑一次登录检查 + 一次搜索,直接回答"能不能用"。
|
|
16
22
|
5. **别擅自打开「自动评论并 @ 你」** —— 那是拿用户的号说话;要用得让用户自己填「要 @ 谁」。
|
|
17
23
|
|
|
24
|
+
## ⚠️ 已知环境差异(有用户反馈)
|
|
25
|
+
|
|
26
|
+
- **桌面版 DSH(NEXT)/ 0.2.x**:本插件跑那一轮用的是 `dsh --profile headless --patch <overlay> <prompt>`,
|
|
27
|
+
**只在 npm 0.1.7-rc.x + web profile 上实测过** ✓。桌面版上有人反馈"自动跑会卡住" ——
|
|
28
|
+
**先跟用户确认 dsh 版本与 profile**,别硬跑;跑不起来就先只用手动「现在跑一轮」。
|
|
29
|
+
- **别让用户自己去装环境** ✗:插件自带一份 uv 与依赖安装能力,先照上面第 1 条处理。
|
|
30
|
+
|
|
18
31
|
## 仓库结构(改代码时看这里)
|
|
19
32
|
|
|
20
33
|
- `index.js` —— host 半端:11 个工具 + 谷时定时器 + HTTP 接口 + 设置命名空间
|
package/client.js
CHANGED
|
@@ -134,11 +134,13 @@ window.__ModuleLoader__.load({
|
|
|
134
134
|
const [msgTone, setMsgTone] = React.useState('')
|
|
135
135
|
const [kws, setKws] = React.useState(null)
|
|
136
136
|
const [ws, setWs] = React.useState(null)
|
|
137
|
-
const [rl, setRl] = React.useState(null)
|
|
137
|
+
const [rl, setRl] = React.useState(null)
|
|
138
|
+
const [newVer, setNewVer] = React.useState('') // 发现的新版本号(空 = 没发现) // 日报形态:full / brief / off
|
|
138
139
|
// ⚠️ 输入框必须绑"本地草稿":页面每 5 秒轮询 /status,服务端那份会把 config 盖掉
|
|
139
140
|
// ⇒ 直接绑 cfg 的话,用户打字打到一半就被冲没了 ✗(2026-10-14 陌生人验收时抓到)
|
|
140
141
|
const [perDay, setPerDay] = React.useState(null)
|
|
141
142
|
const [perRound, setPerRound] = React.useState(null)
|
|
143
|
+
const [replyPer, setReplyPer] = React.useState(null)
|
|
142
144
|
const [mention, setMention] = React.useState(null)
|
|
143
145
|
const [login, setLogin] = React.useState(null)
|
|
144
146
|
const [runNote, setRunNote] = React.useState(null)
|
|
@@ -153,6 +155,7 @@ window.__ModuleLoader__.load({
|
|
|
153
155
|
if (cfg && rl === null) setRl(cfg.reportLevel || 'full')
|
|
154
156
|
if (cfg && perDay === null) setPerDay(String(cfg.perDay ?? 5))
|
|
155
157
|
if (cfg && perRound === null) setPerRound(String(cfg.commentPerRound ?? 1))
|
|
158
|
+
if (cfg && replyPer === null) setReplyPer(String(cfg.replyPerRound ?? 1))
|
|
156
159
|
if (cfg && mention === null) setMention(cfg.mentionName || '')
|
|
157
160
|
}, [cfg])
|
|
158
161
|
|
|
@@ -200,6 +203,30 @@ window.__ModuleLoader__.load({
|
|
|
200
203
|
} catch (e) { say(String(e?.message ?? e), 'warn') }
|
|
201
204
|
}
|
|
202
205
|
|
|
206
|
+
const onUpgrade = async () => {
|
|
207
|
+
setBusy('upgrade')
|
|
208
|
+
try {
|
|
209
|
+
const r = await jpost('/upgrade', {})
|
|
210
|
+
say((r && r.hint) || '正在升级', 'good')
|
|
211
|
+
say('升级过程写在下面的「主依赖的日志」里 —— 完了记得重启一次 dsh(不重启还是旧版)', 'warn')
|
|
212
|
+
} catch (e) { say(String(e?.message ?? e), 'warn') } finally { setBusy('') }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const onCheckUpdate = async () => {
|
|
216
|
+
setBusy('update')
|
|
217
|
+
try {
|
|
218
|
+
const r = await jget('/update')
|
|
219
|
+
if (r && r.ok && r.latest) {
|
|
220
|
+
if (r.hasNew) {
|
|
221
|
+
setNewVer(r.latest)
|
|
222
|
+
say('有新版 v' + r.latest + '(你的是 v' + r.current + ')—— 点右边的「一键升级」,完了重启一次 dsh', 'warn')
|
|
223
|
+
} else say('已经是最新版 v' + r.current, 'good')
|
|
224
|
+
} else {
|
|
225
|
+
say('查不到最新版(可能网络不通)—— 你现在的版本是 v' + ((r && r.current) || '?'))
|
|
226
|
+
}
|
|
227
|
+
} catch (e) { say(String(e?.message ?? e), 'warn') } finally { setBusy('') }
|
|
228
|
+
}
|
|
229
|
+
|
|
203
230
|
const onCheck = async () => {
|
|
204
231
|
setBusy('check')
|
|
205
232
|
say('')
|
|
@@ -286,6 +313,7 @@ window.__ModuleLoader__.load({
|
|
|
286
313
|
h('span', { 'data-bd-badge': '' }, `今天已挑 ${st.ranToday} / ${cfg.perDay} 条`),
|
|
287
314
|
h('span', { 'data-bd-badge': '' }, '环境' + (st.venvReady ? '已就绪' : (st.installing ? '正在装' : '未装'))),
|
|
288
315
|
h('span', { 'data-bd-badge': '' }, st.loggedIn ? 'B站已登录' : 'B站未登录'),
|
|
316
|
+
h('span', { 'data-bd-badge': '' }, 'v' + (st.version || '?')),
|
|
289
317
|
h('div', { 'data-bd-grow': '' }),
|
|
290
318
|
h('button', { 'data-bd-btn': '', disabled: busy === 'run', onClick: onRun }, '现在跑一轮')),
|
|
291
319
|
runNote ? h('div', { 'data-bd-msg': '', 'data-good': runNote.tone === 'good' ? '' : undefined,
|
|
@@ -327,6 +355,23 @@ window.__ModuleLoader__.load({
|
|
|
327
355
|
/* ── 发言与转写 ── */
|
|
328
356
|
h('div', { 'data-bd-sec': '' },
|
|
329
357
|
h('div', { 'data-bd-h': '' }, '它会不会替你说话'),
|
|
358
|
+
h(ToggleRow, {
|
|
359
|
+
label: '回复评论(只回楼中楼)',
|
|
360
|
+
note: '默认关;开了之后它只回「直接回复到你那条评论下面的人」,不参与讨论',
|
|
361
|
+
on: sw('replyToComments'),
|
|
362
|
+
onChange: (v) => patch({ replyToComments: v }, '回复评论'),
|
|
363
|
+
}),
|
|
364
|
+
sw('replyToComments') ? h('div', { 'data-bd-sub': '' },
|
|
365
|
+
h('div', { 'data-bd-row': '' },
|
|
366
|
+
h('div', { 'data-bd-grow': '' },
|
|
367
|
+
h('div', { 'data-bd-label': '' }, '每轮最多回几条'),
|
|
368
|
+
h('div', { 'data-bd-note': '' }, '只回直接回在你那条评论下面的人')),
|
|
369
|
+
h('input', {
|
|
370
|
+
'data-bd-input': '', 'data-bd-num': '', type: 'number', min: 1, max: 10,
|
|
371
|
+
value: replyPer ?? '',
|
|
372
|
+
onChange: (e) => setReplyPer(e.target.value),
|
|
373
|
+
onBlur: () => { const n = Math.max(1, Math.min(Number(replyPer) || 1, 10)); setReplyPer(String(n)); patch({ replyPerRound: n }, '每轮几条回复') },
|
|
374
|
+
}))) : null,
|
|
330
375
|
h(ToggleRow, {
|
|
331
376
|
label: '自动评论并 @ 你',
|
|
332
377
|
note: '默认关;开了之后它会在挑中的视频下面留评论,并 @ 你填的那个人',
|
|
@@ -404,6 +449,8 @@ window.__ModuleLoader__.load({
|
|
|
404
449
|
h('button', { 'data-bd-btn': '', disabled: busy === 'install', onClick: onInstall },
|
|
405
450
|
st.venvReady ? '重装主依赖' : '装主依赖(建 venv)'),
|
|
406
451
|
h('button', { 'data-bd-btn': '', disabled: busy === 'check', onClick: onCheck }, '测一下'),
|
|
452
|
+
h('button', { 'data-bd-btn': '', disabled: busy === 'update', onClick: onCheckUpdate }, '检查更新'),
|
|
453
|
+
newVer ? h('button', { 'data-bd-btn': '', 'data-primary': '', disabled: busy === 'upgrade', onClick: onUpgrade }, '一键升级到 v' + newVer) : null,
|
|
407
454
|
h('button', { 'data-bd-btn': '', disabled: busy === 'login', onClick: onLoginStart }, '扫码登录'),
|
|
408
455
|
h('div', { 'data-bd-note': '' },
|
|
409
456
|
!st.venvReady ? (st.installFailed ? '上次没装成 → 看下面日志' : '还没装 → 先点「装主依赖」')
|
package/index.js
CHANGED
|
@@ -66,10 +66,21 @@ export const Config = z.object({
|
|
|
66
66
|
workspace: z.string().default('').extra('volatile', true),
|
|
67
67
|
/** 日报形态:full=完整(现状)· brief=每条一两行 · off=不写报告(只发评论) */
|
|
68
68
|
reportLevel: z.string().default('full').extra('volatile', true),
|
|
69
|
+
/** 回复评论:默认关。开了之后只回「直接回复到它那条评论下面的人」 */
|
|
70
|
+
replyToComments: z.boolean().default(false).extra('volatile', true),
|
|
71
|
+
/** 每轮最多回几条 */
|
|
72
|
+
replyPerRound: z.number().default(1).extra('volatile', true),
|
|
69
73
|
})
|
|
70
74
|
|
|
71
75
|
export function apply(ctx, config) {
|
|
72
76
|
const pluginDir = dirname(fileURLToPath(import.meta.url))
|
|
77
|
+
// ⭐ 自己的版本号(从 package.json 读,设置页要显示它)
|
|
78
|
+
let myVer = ''
|
|
79
|
+
const myVersion = () => {
|
|
80
|
+
if (myVer) return myVer
|
|
81
|
+
try { myVer = String(JSON.parse(readFileSync(join(pluginDir, 'package.json'), 'utf8')).version || '') } catch { myVer = '' }
|
|
82
|
+
return myVer
|
|
83
|
+
}
|
|
73
84
|
const stateDir = stateDirOf(ctx)
|
|
74
85
|
|
|
75
86
|
// ⭐ "就绪"必须检查依赖真的装上了,不能只看目录存不存在
|
|
@@ -115,7 +126,7 @@ export function apply(ctx, config) {
|
|
|
115
126
|
*/
|
|
116
127
|
const DEFAULTS = {
|
|
117
128
|
perDay: 5, peakValley: false, noon: true, night: true, autoComment: false, transcribe: false, asrModel: 'small',
|
|
118
|
-
keywords: [], commentPerRound: 1, mentionName: '', pythonPath: 'python', dshBin: '', headlessProfile: 'headless', overlayMcp: true, workspace: '', reportLevel: 'full',
|
|
129
|
+
keywords: [], commentPerRound: 1, mentionName: '', pythonPath: 'python', dshBin: '', headlessProfile: 'headless', overlayMcp: true, workspace: '', reportLevel: 'full', replyToComments: false, replyPerRound: 1,
|
|
119
130
|
}
|
|
120
131
|
const normalize = (src, base) => {
|
|
121
132
|
const out = { ...base }
|
|
@@ -376,6 +387,30 @@ export function apply(ctx, config) {
|
|
|
376
387
|
return st
|
|
377
388
|
}
|
|
378
389
|
|
|
390
|
+
// ⭐ 一键升级:由宿主自己跑 `dsh plugin --profile web add dsh-bili-scroll`
|
|
391
|
+
// ⚠️ 装完必须重启 dsh 才生效;⚠️ Windows 上"替换正在运行的插件"可能被文件占用挡住(我们踩过)
|
|
392
|
+
let upgrading = false
|
|
393
|
+
const runUpgrade = () => {
|
|
394
|
+
if (upgrading) return { ok: true, busy: true, log: installLogFile, hint: '正在升级,别重复点' }
|
|
395
|
+
upgrading = true
|
|
396
|
+
appendInstall('\n=== ' + new Date().toISOString() + ' 开始升级(add dsh-bili-scroll)===\n')
|
|
397
|
+
;(async () => {
|
|
398
|
+
try {
|
|
399
|
+
const dsh = resolveDsh()
|
|
400
|
+
// ⭐ 照抄那一轮的形状:resolveDsh 返回 { command, args, shell }
|
|
401
|
+
// (写错就退化成裸 'dsh',而宿主 PATH 里常常没有它 ⇒ 静默失败)
|
|
402
|
+
let cmd = dsh.command || 'dsh'
|
|
403
|
+
let args = [...(dsh.args || []), 'plugin', '--profile', 'web', 'add', 'dsh-bili-scroll']
|
|
404
|
+
if (dsh.shell) { args = ['/c', cmd, ...args]; cmd = 'cmd.exe' }
|
|
405
|
+
appendInstall('$ ' + cmd + ' ' + args.join(' ') + '\n')
|
|
406
|
+
const code = await spawnTo(cmd, args, { sink: appendInstall })
|
|
407
|
+
if (code === 0) appendInstall('=== 升级完成 —— 重启一次 dsh 才生效 ===\n')
|
|
408
|
+
else appendInstall('=== 升级没成功(exit ' + code + ')。可以自己手动跑一次:dsh plugin --profile web add dsh-bili-scroll ===\n')
|
|
409
|
+
} catch (e) { appendInstall('升级崩了:' + (e?.stack ?? e) + '\n') } finally { upgrading = false }
|
|
410
|
+
})()
|
|
411
|
+
return { ok: true, started: true, log: installLogFile, hint: '正在升级 —— 完成后重启一次 dsh 才生效' }
|
|
412
|
+
}
|
|
413
|
+
|
|
379
414
|
const resolveDsh = () => {
|
|
380
415
|
const explicit = String(cfg.dshBin || '').trim()
|
|
381
416
|
if (explicit && existsSync(explicit)) return { command: process.execPath, args: [explicit], shell: false }
|
|
@@ -427,6 +462,9 @@ export function apply(ctx, config) {
|
|
|
427
462
|
+ `自动评论并 @ ${cfg.mentionName || '(还没填要 @ 谁)'} 是${cfg.autoComment && cfg.mentionName
|
|
428
463
|
? `开着的(每轮最多 ${cfg.commentPerRound} 条评论,每条在正文里纯文本 @ ${cfg.mentionName},150 字内)`
|
|
429
464
|
: '关着的(只写报告,别发评论)'}。`
|
|
465
|
+
+ (cfg.replyToComments
|
|
466
|
+
? `回复评论:开着(每轮最多回 ${Number(cfg.replyPerRound) || 1} 条)—— 只回「直接回复到你那条评论下面的人」,回完记进报告;找不到你那条评论就跳过,别硬找。`
|
|
467
|
+
: `回复评论:关着(一个字都不要回任何人 —— 有人回复你那条评论也不要理)。`)
|
|
430
468
|
+ `最后用一句话汇报你挑到了什么。现在几点了自己看一眼系统时间。`
|
|
431
469
|
}
|
|
432
470
|
|
|
@@ -729,6 +767,8 @@ export function apply(ctx, config) {
|
|
|
729
767
|
return out
|
|
730
768
|
}
|
|
731
769
|
|
|
770
|
+
let updateCache = null // { at, latest } —— 检查更新的结果缓存
|
|
771
|
+
|
|
732
772
|
const status = () => {
|
|
733
773
|
const st = readJson(dutyStateFile, {})
|
|
734
774
|
const today = dayKey()
|
|
@@ -743,6 +783,7 @@ export function apply(ctx, config) {
|
|
|
743
783
|
lastWhy: st.lastWhy || null,
|
|
744
784
|
loggedIn: hasCredential(),
|
|
745
785
|
venvReady: venvReadyNow(),
|
|
786
|
+
version: myVersion(),
|
|
746
787
|
installFailed: !installing && !venvReadyNow() && (() => { try { return readFileSync(installLogFile, 'utf8').length > 0 } catch { return false } })(),
|
|
747
788
|
installing,
|
|
748
789
|
// ── 本地转写那一套的状态(设置页要显示进度)──
|
|
@@ -773,11 +814,13 @@ export function apply(ctx, config) {
|
|
|
773
814
|
const patch = {}
|
|
774
815
|
for (const k of ['perDay', 'peakValley', 'noon', 'night', 'autoComment', 'transcribe', 'asrModel',
|
|
775
816
|
'commentPerRound', 'mentionName',
|
|
776
|
-
'keywords', 'pythonPath', 'dshBin', 'headlessProfile', 'workspace', 'reportLevel']) {
|
|
817
|
+
'keywords', 'pythonPath', 'dshBin', 'headlessProfile', 'workspace', 'reportLevel', 'replyToComments', 'replyPerRound']) {
|
|
777
818
|
if (k in body) patch[k] = body[k]
|
|
778
819
|
}
|
|
779
820
|
if ('perDay' in patch) patch.perDay = Math.max(0, Math.min(Number(patch.perDay) || 0, 50))
|
|
780
821
|
if ('reportLevel' in patch) patch.reportLevel = ['full', 'brief', 'off'].includes(String(patch.reportLevel)) ? String(patch.reportLevel) : 'full'
|
|
822
|
+
if ('replyToComments' in patch) patch.replyToComments = Boolean(patch.replyToComments)
|
|
823
|
+
if ('replyPerRound' in patch) patch.replyPerRound = Math.max(1, Math.min(Number(patch.replyPerRound) || 1, 10))
|
|
781
824
|
saveCfg(patch)
|
|
782
825
|
log(`设置已更新:${JSON.stringify(patch)}`)
|
|
783
826
|
return sendJson(res, 200, { ok: true, config: cfg })
|
|
@@ -837,6 +880,35 @@ export function apply(ctx, config) {
|
|
|
837
880
|
return sendJson(res, 200, { ok: false, error: lastErr, dir })
|
|
838
881
|
}
|
|
839
882
|
|
|
883
|
+
// 「一键升级」:点了它自己跑 add(⚠️ 之后要重启才生效)
|
|
884
|
+
if (req.method === 'POST' && path === '/api/bili-duty/upgrade') return sendJson(res, 200, runUpgrade())
|
|
885
|
+
|
|
886
|
+
// 「检查更新」:⚠️ 只在用户点按钮时才联网(不偷偷发请求 ✓),结果缓存一天 ✓
|
|
887
|
+
if (req.method === 'GET' && path === '/api/bili-duty/update') {
|
|
888
|
+
const out = { ok: true, current: myVersion(), latest: '', hasNew: false, page: 'https://www.npmjs.com/package/dsh-bili-scroll' }
|
|
889
|
+
try {
|
|
890
|
+
if (updateCache && Date.now() - updateCache.at < 24 * 3600 * 1000) out.latest = updateCache.latest
|
|
891
|
+
else {
|
|
892
|
+
const ctrl = new AbortController()
|
|
893
|
+
const timer = setTimeout(() => ctrl.abort(), 8000)
|
|
894
|
+
const r = await fetch('https://registry.npmjs.org/dsh-bili-scroll/latest', { signal: ctrl.signal })
|
|
895
|
+
clearTimeout(timer)
|
|
896
|
+
const j = await r.json()
|
|
897
|
+
out.latest = String(j.version || '')
|
|
898
|
+
updateCache = { at: Date.now(), latest: out.latest }
|
|
899
|
+
}
|
|
900
|
+
} catch (e) { out.ok = false; out.error = String(e?.message ?? e); return sendJson(res, 200, out) }
|
|
901
|
+
// ⭐ 要比谁更新,不能只比不相等 —— 否则本地版本高于 npm 时会误报有新版
|
|
902
|
+
const vnum = (v) => String(v || '').split('.').map((x) => parseInt(x, 10) || 0)
|
|
903
|
+
const cmp = (a, b) => {
|
|
904
|
+
const x = vnum(a), y = vnum(b)
|
|
905
|
+
for (let i = 0; i < 3; i++) { if ((x[i] || 0) !== (y[i] || 0)) return (x[i] || 0) - (y[i] || 0) }
|
|
906
|
+
return 0
|
|
907
|
+
}
|
|
908
|
+
out.hasNew = Boolean(out.latest) && cmp(out.latest, out.current) > 0
|
|
909
|
+
return sendJson(res, 200, out)
|
|
910
|
+
}
|
|
911
|
+
|
|
840
912
|
// 「测一下」:真跑一次,回答"能不能用"
|
|
841
913
|
if (req.method === 'POST' && path === '/api/bili-duty/check') {
|
|
842
914
|
return sendJson(res, 200, await checkUp())
|
package/package.json
CHANGED
package/prompts/duty.md
CHANGED
|
@@ -22,7 +22,15 @@
|
|
|
22
22
|
## 边界(这是别人的账号,这几条不能碰)
|
|
23
23
|
|
|
24
24
|
- ⚠️ **只发它自己那一条「@ 使用者」的新评论**,发完就走。
|
|
25
|
-
- ⚠️
|
|
25
|
+
- ⚠️ **默认不要回复任何人的评论**(包括有人回复到它那条评论下面的)。
|
|
26
|
+
⭐ **只有开头告诉你「回复评论:开着」时**才可以回 —— 而且只回「**直接回复到它那条评论下面的人**」,
|
|
27
|
+
**每轮最多回它说的那个条数**,回完把内容记进报告。
|
|
28
|
+
- ⭐ **发完评论,把「视频 BV 号 + 评论 rpid + 时间 + 正文前 20 字」一起记进判重表的「评论记录」**
|
|
29
|
+
—— 有了 rpid,下一轮就能**直接定位到那条评论**,不用在几百条评论里翻。
|
|
30
|
+
- ⭐ **要回评论时,先看判重表的「评论记录」** —— 那里记着它自己在哪几个视频发过评论、发了什么;
|
|
31
|
+
⚠️ **查的范围别太窄**:把判重表里**最近 7 天内自己发过的评论都过一遍**(漏掉一条,那个人就永远收不到回复 ✗);
|
|
32
|
+
实在太多就按时间**从新到旧**挑最近 **5~8 条**。找不到就跳过,别硬找、别硬凑。
|
|
33
|
+
- ⚠️ 真要回的时候:不承诺功能、不争论、不替使用者做决定,不确定就说不确定。
|
|
26
34
|
- ⚠️ **不要参与讨论、不要争辩、不要替使用者答问题**。有人问技术问题,就写进报告里,让使用者自己回。
|
|
27
35
|
- ⚠️ **同一个视频下不要留第二条评论**(判重表记着)。
|
|
28
36
|
- 理由:它发出去的每个字,都算在**使用者本人的账号**上 —— 越界就是替他惹麻烦。
|