dsh-notify-say 0.4.33 → 0.4.35
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/dsh-notify.ps1 +26 -3
- package/lib/client.js +65 -0
- package/lib/config-schema.js +339 -321
- package/lib/config-store.js +5 -0
- package/lib/diagnostics.js +143 -0
- package/lib/index.js +1913 -1854
- package/lib/log-privacy.js +171 -0
- package/package.json +1 -1
- package/test/diagnostics.test.mjs +178 -0
- package/test/log-privacy.test.mjs +196 -0
package/dsh-notify.ps1
CHANGED
|
@@ -52,6 +52,12 @@ param(
|
|
|
52
52
|
[string]$VoiceRoot = '',
|
|
53
53
|
# 用户语音包根目录(可写),仅用于诊断日志。
|
|
54
54
|
[string]$UserVoiceRoot = '',
|
|
55
|
+
# v0.4.34:日志级别。info(默认)= 只记元数据;debug = 记标题与正文。
|
|
56
|
+
#
|
|
57
|
+
# 为什么需要:日志会写进 %TEMP%,用户提 Issue 时经常直接上传。
|
|
58
|
+
# 标题与正文可能含项目名、人名,对诊断「为什么不响」却没帮助。
|
|
59
|
+
[ValidateSet('info', 'debug')]
|
|
60
|
+
[string]$LogLevel = 'info',
|
|
55
61
|
# v0.4.16:数字增益倍数(1.0 = 原样;2.0 = 放大一倍)。
|
|
56
62
|
#
|
|
57
63
|
# 为什么需要:实测本包 247 个语音包峰值中位仅 **40.4%**
|
|
@@ -281,6 +287,23 @@ try {
|
|
|
281
287
|
$logDir = Join-Path ([System.IO.Path]::GetTempPath()) 'dsh-notify-say'
|
|
282
288
|
if (-not (Test-Path -LiteralPath $logDir)) { New-Item -ItemType Directory -Force -Path $logDir | Out-Null }
|
|
283
289
|
$logFile = Join-Path $logDir 'notify.log'
|
|
290
|
+
|
|
291
|
+
# v0.4.34:写一行日志。$detail = 含用户内容(标题/正文),只在 debug 档写。
|
|
292
|
+
#
|
|
293
|
+
# 用函数而不是内联 Add-Content:三处调用点都要同样判断,
|
|
294
|
+
# 内联会让"某处忘了判断"这种遗漏很难看出来。
|
|
295
|
+
function Write-NotifyLog([string]$KindTag, [string]$Extra, [string]$Detail) {
|
|
296
|
+
if (-not $logFile) { return }
|
|
297
|
+
try {
|
|
298
|
+
$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
|
299
|
+
$parts = @($ts, "[$KindTag]", $Extra)
|
|
300
|
+
if ($Detail) {
|
|
301
|
+
if ($LogLevel -eq 'debug') { $parts += $Detail }
|
|
302
|
+
else { $parts += '(内容已隐藏,需 -LogLevel debug)' }
|
|
303
|
+
}
|
|
304
|
+
Add-Content -Path $logFile -Value (($parts -join ' ').Trim()) -Encoding utf8
|
|
305
|
+
} catch { }
|
|
306
|
+
}
|
|
284
307
|
# 审查建议采纳:容量护栏——超过 512KB 整文件重建(best-effort 诊断日志,不做轮转)
|
|
285
308
|
if ((Test-Path -LiteralPath $logFile) -and ((Get-Item -LiteralPath $logFile -ErrorAction SilentlyContinue).Length -gt 524288)) {
|
|
286
309
|
Remove-Item -LiteralPath $logFile -Force -ErrorAction SilentlyContinue
|
|
@@ -475,16 +498,16 @@ $pickedName = if ($script:playFile) { Split-Path $script:playFile -Leaf } else {
|
|
|
475
498
|
if ($Preview) {
|
|
476
499
|
if (-not $NoSound) { Play-VoiceLine }
|
|
477
500
|
$soundTag = if ($NoSound) { '(静音)' } elseif ($script:lastSound) { " + 音效 $script:lastSound" } else { ' + 兜底提示音' }
|
|
478
|
-
|
|
501
|
+
Write-NotifyLog 'preview' ("-Voice $Voice pick=$pickedName$soundTag") ''
|
|
479
502
|
Write-Host ("[dsh-notify-say] OK 试听 [$Kind] pick=" + $pickedName + $soundTag) -ForegroundColor Green
|
|
480
503
|
} elseif ($shown) {
|
|
481
504
|
if (-not $NoSound) { Play-VoiceLine }
|
|
482
505
|
$soundTag = if ($NoSound) { '(静音)' } elseif ($script:lastSound) { " + 音效 $script:lastSound" } else { ' + 兜底提示音' }
|
|
483
|
-
|
|
506
|
+
Write-NotifyLog 'toast' ("pick=$pickedName$soundTag") ("title=$Title body=$Body")
|
|
484
507
|
Write-Host ("[dsh-notify-say] OK Toast [$Kind] pick=" + $pickedName + $soundTag) -ForegroundColor Green
|
|
485
508
|
} else {
|
|
486
509
|
if (-not $NoSound) { Play-VoiceLine }
|
|
487
510
|
$soundTag = if ($NoSound) { '(静音)' } elseif ($script:lastSound) { " + 音效 $script:lastSound" } else { ' + 兜底提示音' }
|
|
488
|
-
|
|
511
|
+
Write-NotifyLog 'FALLBACK' ("pick=$pickedName$soundTag") ("title=$Title body=$Body")
|
|
489
512
|
Write-Host ("[dsh-notify-say] (Toast 不可用,走兜底) [$Kind] pick=" + $pickedName + $soundTag) -ForegroundColor Yellow
|
|
490
513
|
}
|
package/lib/client.js
CHANGED
|
@@ -127,6 +127,15 @@ window.__ModuleLoader__.load({
|
|
|
127
127
|
body: JSON.stringify({ key: key }),
|
|
128
128
|
}).then(function (r) { return r ? r.json() : null }).catch(function () { return null })
|
|
129
129
|
}
|
|
130
|
+
// 导出诊断(v0.4.35):宿主读日志 → 脱敏 → 写文件,返回路径。
|
|
131
|
+
// 用 POST:它会写文件,GET 可被任意网页用 <img> 触发。
|
|
132
|
+
function exportDiagnostics() {
|
|
133
|
+
return fetch(apiUrl('diagnostics'), {
|
|
134
|
+
method: 'POST', cache: 'no-store', credentials: 'same-origin',
|
|
135
|
+
headers: { 'content-type': 'application/json' },
|
|
136
|
+
body: '{}',
|
|
137
|
+
}).then(function (r) { return r ? r.json() : null }).catch(function () { return null })
|
|
138
|
+
}
|
|
130
139
|
|
|
131
140
|
function openSession(ctx, sessionId) {
|
|
132
141
|
try {
|
|
@@ -514,6 +523,22 @@ window.__ModuleLoader__.load({
|
|
|
514
523
|
if (ok) loadPacks()
|
|
515
524
|
})
|
|
516
525
|
}
|
|
526
|
+
// 导出诊断:成功后把路径显示出来(用户要能直接找到文件)。
|
|
527
|
+
function doExportDiagnostics() {
|
|
528
|
+
set(function (p) {
|
|
529
|
+
return { loaded: p.loaded, values: p.values, advOpen: p.advOpen, packs: p.packs, busy: true, msg: '正在导出诊断…', err: '' }
|
|
530
|
+
})
|
|
531
|
+
exportDiagnostics().then(function (r) {
|
|
532
|
+
var ok = r && r.ok
|
|
533
|
+
set(function (p) {
|
|
534
|
+
return {
|
|
535
|
+
loaded: p.loaded, values: p.values, advOpen: p.advOpen, packs: p.packs, busy: false,
|
|
536
|
+
msg: ok ? ("已导出:" + r.path + "(" + r.lines + " 行)") : "",
|
|
537
|
+
err: ok ? "" : ("导出失败:" + ((r && (r.error || r.reason)) || "未知原因")),
|
|
538
|
+
}
|
|
539
|
+
})
|
|
540
|
+
})
|
|
541
|
+
}
|
|
517
542
|
|
|
518
543
|
var v = s.values || {}
|
|
519
544
|
var rows = []
|
|
@@ -1423,6 +1448,46 @@ window.__ModuleLoader__.load({
|
|
|
1423
1448
|
+ '它依赖宿主内部结构,升级后可能失效;失效时只报错,不影响正常播报。'),
|
|
1424
1449
|
),
|
|
1425
1450
|
))
|
|
1451
|
+
|
|
1452
|
+
// ── 日志级别(v0.4.34)──────────────────────────────────────────────
|
|
1453
|
+
//
|
|
1454
|
+
// 默认 info:只记元数据(事件、音源、成败、数量)。
|
|
1455
|
+
// debug:额外记台词正文与 Toast 标题正文 —— **可能含敏感信息**。
|
|
1456
|
+
//
|
|
1457
|
+
// 为什么放在高级区:多数人不需要改,但排查问题时要能开。
|
|
1458
|
+
rows.push(h('div', { key: 'll-row', style: S.row },
|
|
1459
|
+
h('span', { style: S.label }, '日志详细度'),
|
|
1460
|
+
h('select', {
|
|
1461
|
+
value: v.logLevel || 'info',
|
|
1462
|
+
disabled: s.busy,
|
|
1463
|
+
onChange: function (e) { apply({ logLevel: e.target.value }, '日志级别已更新') },
|
|
1464
|
+
},
|
|
1465
|
+
h('option', { value: 'info' }, '只记元数据(默认)'),
|
|
1466
|
+
h('option', { value: 'debug' }, '含台词正文(可能敏感)'),
|
|
1467
|
+
),
|
|
1468
|
+
))
|
|
1469
|
+
rows.push(h('div', { key: 'll-hint', style: S.subHint },
|
|
1470
|
+
v.logLevel === 'debug'
|
|
1471
|
+
? '⚠️ debug 档会把台词和通知正文写进日志。日志在 %TEMP%\\dsh-notify-say\\notify.log,'
|
|
1472
|
+
+ '提 Issue 前请先切回「只记元数据」或自行删改。'
|
|
1473
|
+
: '日志只记事件类型、音源、成败与数量,不含台词正文。排查问题时可切到 debug。'))
|
|
1474
|
+
|
|
1475
|
+
// ── 导出诊断(v0.4.35)───────────────────────────────────────────
|
|
1476
|
+
//
|
|
1477
|
+
// 用户提 Issue 时最需要的东西:一份**已脱敏**的日志。
|
|
1478
|
+
// 让他自己去 %TEMP% 找、手动删用户名,多数人不会做。
|
|
1479
|
+
rows.push(h('div', { key: 'dg-row', style: S.row },
|
|
1480
|
+
h('span', { style: S.label }, '诊断'),
|
|
1481
|
+
h('button', {
|
|
1482
|
+
type: 'button',
|
|
1483
|
+
disabled: s.busy,
|
|
1484
|
+
style: S.btn,
|
|
1485
|
+
onClick: function () { doExportDiagnostics() },
|
|
1486
|
+
}, '导出诊断文件'),
|
|
1487
|
+
))
|
|
1488
|
+
rows.push(h('div', { key: 'dg-hint', style: S.subHint },
|
|
1489
|
+
'导出到日志同目录(%TEMP%\\dsh-notify-say\\)。会自动把用户名替换为 <user>、'
|
|
1490
|
+
+ '绝对路径替换为 <path>,但**仍请自己再看一遍**再上传。'))
|
|
1426
1491
|
}
|
|
1427
1492
|
|
|
1428
1493
|
if (s.msg) rows.push(h('div', { key: 'msg', style: S.ok }, s.msg))
|