@fg-lab/amadeus-qq 1.2.1 → 1.2.2
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/LICENSE +21 -21
- package/README.md +55 -53
- package/README.zh-CN.md +51 -51
- package/REFERENCE.md +49 -49
- package/cordis.patch.yml +6 -6
- package/docs/DATA_MIGRATION.md +26 -26
- package/docs/INSTALL_V1_2.md +22 -22
- package/docs/PUBLISHING.md +28 -26
- package/docs/RELEASE_CHECKLIST.md +23 -23
- package/docs/RELEASE_NOTES.md +38 -38
- package/docs/UPGRADE_POLICY.md +26 -26
- package/docs/verification/IMAGE_READ_FIX_2026-11-07.md +22 -0
- package/docs/verification/LIFE_QQ_BOUNDARY_2026-11-07.md +20 -0
- package/lib/client.js +372 -372
- package/package.json +94 -91
- package/preset.patch.yml +63 -0
- package/scripts/symlink-security.mjs +1 -1
- package/src/account-profile.js +223 -223
- package/src/admin-http.js +361 -361
- package/src/audio.js +428 -428
- package/src/capabilities.js +785 -785
- package/src/client/factory.template.js +82 -82
- package/src/client/logic.js +290 -290
- package/src/config.js +2 -0
- package/src/console/console.css +28 -28
- package/src/console/console.js +3 -0
- package/src/console/index.html +67 -67
- package/src/core.js +21 -4
- package/src/files.js +230 -230
- package/src/index.js +135 -8
- package/src/lease.js +42 -42
- package/src/media.js +66 -3
- package/src/napcat-action-names.js +186 -186
- package/src/native-asr.js +112 -112
- package/src/onebot.js +378 -378
- package/src/outbound-media.js +309 -309
- package/src/owner-workspace.js +394 -394
- package/src/permissions.js +20 -0
- package/src/preset-guard.mjs +16 -2
- package/src/qzone-provider.js +628 -628
- package/src/session-provenance.js +74 -74
- package/src/setup.js +255 -255
- package/src/web-console.js +9 -9
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
__CLIENT_LOGIC__
|
|
2
|
-
|
|
3
|
-
const PANEL_CSS = `
|
|
4
|
-
[data-amadeus-qq]{box-sizing:border-box;color:var(--dsw-alias-label-primary,#203333);font:13px/1.6 system-ui,sans-serif;max-width:760px}
|
|
5
|
-
[data-amadeus-qq] *{box-sizing:border-box}
|
|
6
|
-
[data-amadeus-qq] h2{font-size:21px;margin:0 0 5px}
|
|
7
|
-
[data-amadeus-qq] p{margin:0 0 14px;opacity:.75}
|
|
8
|
-
[data-amadeus-qq] .summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px;margin:14px 0}
|
|
9
|
-
[data-amadeus-qq] .metric{border:1px solid var(--dsw-alias-border-secondary,#8c8c8c55);border-radius:12px;padding:12px;background:var(--dsw-alias-bg-layer-2,#8c8c8c10)}
|
|
10
|
-
[data-amadeus-qq] .metric small{display:block;opacity:.68;font-size:11px}
|
|
11
|
-
[data-amadeus-qq] .metric strong{display:block;font-size:14px;margin-top:3px;word-break:break-word}
|
|
12
|
-
[data-amadeus-qq] button{border:1px solid #178a69;background:#178a69;color:white;border-radius:9px;padding:8px 14px;font:inherit;cursor:pointer}
|
|
13
|
-
[data-amadeus-qq] button:focus-visible{outline:2px solid #178a69;outline-offset:2px}
|
|
14
|
-
[data-amadeus-qq] .error{color:#ab3535;margin:12px 0}
|
|
15
|
-
@media(max-width:560px){[data-amadeus-qq] .summary{grid-template-columns:1fr}}
|
|
16
|
-
`
|
|
17
|
-
|
|
18
|
-
function Panel() {
|
|
19
|
-
const [setup, setSetup] = React.useState(null)
|
|
20
|
-
const [runtime, setRuntime] = React.useState(null)
|
|
21
|
-
const [error, setError] = React.useState('')
|
|
22
|
-
React.useEffect(() => {
|
|
23
|
-
let active = true
|
|
24
|
-
const load = async () => {
|
|
25
|
-
try {
|
|
26
|
-
const [a, b] = await Promise.all([
|
|
27
|
-
fetch('/api/amadeus-qq/setup', { credentials: 'same-origin' }),
|
|
28
|
-
fetch('/api/amadeus-qq/scenes', { credentials: 'same-origin' }),
|
|
29
|
-
])
|
|
30
|
-
const [left, right] = await Promise.all([a.json(), b.json()])
|
|
31
|
-
if (!a.ok || !b.ok || !left.ok || !right.ok) throw new Error('请在 DSH Owner 会话中打开管理控制台')
|
|
32
|
-
if (active) { setSetup(left.data); setRuntime(right.data); setError('') }
|
|
33
|
-
} catch (failure) {
|
|
34
|
-
if (active) setError(failure instanceof Error ? failure.message : '状态读取失败')
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
void load()
|
|
38
|
-
return () => { active = false }
|
|
39
|
-
}, [])
|
|
40
|
-
const workspace = setup?.workspaces?.find(item => item.id === setup.workspaceId)
|
|
41
|
-
const rows = (setup?.groups?.length ?? 0) + (setup?.privatePeers?.length ?? 0)
|
|
42
|
-
const transportText = { connected: '已连接', connecting: '连接中', disconnected: '未连接', disabled: '已暂停' }[runtime?.health?.transport] ?? '未连接'
|
|
43
|
-
const metric = (label, value) => React.createElement('div', { className: 'metric' },
|
|
44
|
-
React.createElement('small', null, label), React.createElement('strong', null, value))
|
|
45
|
-
return React.createElement('div', { 'data-amadeus-qq': 'true' },
|
|
46
|
-
React.createElement('style', null, PANEL_CSS),
|
|
47
|
-
React.createElement('h2', null, 'Amadeus QQ'),
|
|
48
|
-
React.createElement('p', null, '首次设置和详细权限在受 DSH Owner 保护的本地 Web Console 中完成。'),
|
|
49
|
-
error ? React.createElement('div', { className: 'error', role: 'status' }, error) : null,
|
|
50
|
-
React.createElement('div', { className: 'summary' },
|
|
51
|
-
metric('插件', setup?.enabled ? '已启用' : '待配置'),
|
|
52
|
-
metric('NapCat', transportText),
|
|
53
|
-
metric('Bot / Owner', `${setup?.botId || '—'} / ${setup?.ownerId || '—'}`),
|
|
54
|
-
metric('Workspace / 会话', `${workspace?.title || '未选择'} · ${rows} 个`)),
|
|
55
|
-
React.createElement('button', { type: 'button', onClick: () => window.open('/api/amadeus-qq/console', '_blank', 'noopener,noreferrer') },
|
|
56
|
-
setup?.enabled ? '打开 Web Console' : '开始首次设置'))
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
inject: ['slots'],
|
|
61
|
-
apply(ctx) {
|
|
62
|
-
let active
|
|
63
|
-
const activate = () => {
|
|
64
|
-
if (active) return active.dispose
|
|
65
|
-
let dispose = () => {}
|
|
66
|
-
try {
|
|
67
|
-
dispose = ctx.slots.inject('settings.section', () => ctx.slots.register({
|
|
68
|
-
name: 'settings.section', id: 'amadeus-qq', order: 30, label: () => 'Amadeus QQ',
|
|
69
|
-
}, Panel)) || (() => {})
|
|
70
|
-
} catch (error) { console.error('[amadeus-qq] settings.section unavailable', error) }
|
|
71
|
-
const disposal = () => {
|
|
72
|
-
if (!active || active.dispose !== disposal) return
|
|
73
|
-
active = undefined
|
|
74
|
-
try { dispose() } catch {}
|
|
75
|
-
}
|
|
76
|
-
active = { dispose: disposal }
|
|
77
|
-
return disposal
|
|
78
|
-
}
|
|
79
|
-
if (typeof ctx.effect === 'function') ctx.effect(() => activate(), 'amadeus-qq: settings page')
|
|
80
|
-
else activate()
|
|
81
|
-
},
|
|
82
|
-
}
|
|
1
|
+
__CLIENT_LOGIC__
|
|
2
|
+
|
|
3
|
+
const PANEL_CSS = `
|
|
4
|
+
[data-amadeus-qq]{box-sizing:border-box;color:var(--dsw-alias-label-primary,#203333);font:13px/1.6 system-ui,sans-serif;max-width:760px}
|
|
5
|
+
[data-amadeus-qq] *{box-sizing:border-box}
|
|
6
|
+
[data-amadeus-qq] h2{font-size:21px;margin:0 0 5px}
|
|
7
|
+
[data-amadeus-qq] p{margin:0 0 14px;opacity:.75}
|
|
8
|
+
[data-amadeus-qq] .summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px;margin:14px 0}
|
|
9
|
+
[data-amadeus-qq] .metric{border:1px solid var(--dsw-alias-border-secondary,#8c8c8c55);border-radius:12px;padding:12px;background:var(--dsw-alias-bg-layer-2,#8c8c8c10)}
|
|
10
|
+
[data-amadeus-qq] .metric small{display:block;opacity:.68;font-size:11px}
|
|
11
|
+
[data-amadeus-qq] .metric strong{display:block;font-size:14px;margin-top:3px;word-break:break-word}
|
|
12
|
+
[data-amadeus-qq] button{border:1px solid #178a69;background:#178a69;color:white;border-radius:9px;padding:8px 14px;font:inherit;cursor:pointer}
|
|
13
|
+
[data-amadeus-qq] button:focus-visible{outline:2px solid #178a69;outline-offset:2px}
|
|
14
|
+
[data-amadeus-qq] .error{color:#ab3535;margin:12px 0}
|
|
15
|
+
@media(max-width:560px){[data-amadeus-qq] .summary{grid-template-columns:1fr}}
|
|
16
|
+
`
|
|
17
|
+
|
|
18
|
+
function Panel() {
|
|
19
|
+
const [setup, setSetup] = React.useState(null)
|
|
20
|
+
const [runtime, setRuntime] = React.useState(null)
|
|
21
|
+
const [error, setError] = React.useState('')
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
let active = true
|
|
24
|
+
const load = async () => {
|
|
25
|
+
try {
|
|
26
|
+
const [a, b] = await Promise.all([
|
|
27
|
+
fetch('/api/amadeus-qq/setup', { credentials: 'same-origin' }),
|
|
28
|
+
fetch('/api/amadeus-qq/scenes', { credentials: 'same-origin' }),
|
|
29
|
+
])
|
|
30
|
+
const [left, right] = await Promise.all([a.json(), b.json()])
|
|
31
|
+
if (!a.ok || !b.ok || !left.ok || !right.ok) throw new Error('请在 DSH Owner 会话中打开管理控制台')
|
|
32
|
+
if (active) { setSetup(left.data); setRuntime(right.data); setError('') }
|
|
33
|
+
} catch (failure) {
|
|
34
|
+
if (active) setError(failure instanceof Error ? failure.message : '状态读取失败')
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
void load()
|
|
38
|
+
return () => { active = false }
|
|
39
|
+
}, [])
|
|
40
|
+
const workspace = setup?.workspaces?.find(item => item.id === setup.workspaceId)
|
|
41
|
+
const rows = (setup?.groups?.length ?? 0) + (setup?.privatePeers?.length ?? 0)
|
|
42
|
+
const transportText = { connected: '已连接', connecting: '连接中', disconnected: '未连接', disabled: '已暂停' }[runtime?.health?.transport] ?? '未连接'
|
|
43
|
+
const metric = (label, value) => React.createElement('div', { className: 'metric' },
|
|
44
|
+
React.createElement('small', null, label), React.createElement('strong', null, value))
|
|
45
|
+
return React.createElement('div', { 'data-amadeus-qq': 'true' },
|
|
46
|
+
React.createElement('style', null, PANEL_CSS),
|
|
47
|
+
React.createElement('h2', null, 'Amadeus QQ'),
|
|
48
|
+
React.createElement('p', null, '首次设置和详细权限在受 DSH Owner 保护的本地 Web Console 中完成。'),
|
|
49
|
+
error ? React.createElement('div', { className: 'error', role: 'status' }, error) : null,
|
|
50
|
+
React.createElement('div', { className: 'summary' },
|
|
51
|
+
metric('插件', setup?.enabled ? '已启用' : '待配置'),
|
|
52
|
+
metric('NapCat', transportText),
|
|
53
|
+
metric('Bot / Owner', `${setup?.botId || '—'} / ${setup?.ownerId || '—'}`),
|
|
54
|
+
metric('Workspace / 会话', `${workspace?.title || '未选择'} · ${rows} 个`)),
|
|
55
|
+
React.createElement('button', { type: 'button', onClick: () => window.open('/api/amadeus-qq/console', '_blank', 'noopener,noreferrer') },
|
|
56
|
+
setup?.enabled ? '打开 Web Console' : '开始首次设置'))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
inject: ['slots'],
|
|
61
|
+
apply(ctx) {
|
|
62
|
+
let active
|
|
63
|
+
const activate = () => {
|
|
64
|
+
if (active) return active.dispose
|
|
65
|
+
let dispose = () => {}
|
|
66
|
+
try {
|
|
67
|
+
dispose = ctx.slots.inject('settings.section', () => ctx.slots.register({
|
|
68
|
+
name: 'settings.section', id: 'amadeus-qq', order: 30, label: () => 'Amadeus QQ',
|
|
69
|
+
}, Panel)) || (() => {})
|
|
70
|
+
} catch (error) { console.error('[amadeus-qq] settings.section unavailable', error) }
|
|
71
|
+
const disposal = () => {
|
|
72
|
+
if (!active || active.dispose !== disposal) return
|
|
73
|
+
active = undefined
|
|
74
|
+
try { dispose() } catch {}
|
|
75
|
+
}
|
|
76
|
+
active = { dispose: disposal }
|
|
77
|
+
return disposal
|
|
78
|
+
}
|
|
79
|
+
if (typeof ctx.effect === 'function') ctx.effect(() => activate(), 'amadeus-qq: settings page')
|
|
80
|
+
else activate()
|
|
81
|
+
},
|
|
82
|
+
}
|