dsh-qq-stack 0.1.4 → 0.1.7

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.
Files changed (4) hide show
  1. package/client.js +10 -3
  2. package/index.js +11 -2
  3. package/install.sh +53 -25
  4. package/package.json +1 -1
package/client.js CHANGED
@@ -49,7 +49,9 @@ window.__ModuleLoader__.load({
49
49
  .fs-field{width:100%;box-sizing:border-box;border:0;border-bottom:1px solid rgba(127,127,127,.28);background:transparent;color:inherit;padding:10px 2px;font-size:15px;outline:none}
50
50
  .fs-wide{padding:11px}
51
51
  .fs-sep{text-align:center;font-size:12px;opacity:.5;margin-top:6px}
52
- .fs-install{font-size:14px;font-weight:600;margin-bottom:6px}`
52
+ .fs-install{font-size:14px;font-weight:600;margin-bottom:6px}
53
+ .fs-bar{height:6px;border-radius:3px;background:rgba(127,127,127,.2);overflow:hidden;margin:8px 0 6px}
54
+ .fs-bar-in{height:100%;background:#12b7f5;border-radius:3px;transition:width .4s}`
53
55
 
54
56
  function Panel() {
55
57
  const [st, setSt] = react.useState(null)
@@ -85,8 +87,13 @@ window.__ModuleLoader__.load({
85
87
  : h('div', { className: 'fs-hint' }, '正在生成二维码…'),
86
88
  ) : null,
87
89
  (st && (!st.installed || st.installing)) ? h('div', { className: 'fs-card' },
88
- h('div', { className: 'fs-install' }, st.installing ? '正在安装 QQ 运行环境…' : '运行环境未就绪'),
89
- h('div', { className: 'fs-hint' }, st.installTail || '首次安装约 250MB,请稍候'),
90
+ h('div', { className: 'fs-install' },
91
+ st.installing ? `正在安装 ${st.installLabel || 'QQ 运行环境'}…` : '运行环境未就绪'),
92
+ (st.installPct >= 0) ? h('div', { className: 'fs-bar' },
93
+ h('div', { className: 'fs-bar-in', style: { width: `${Math.max(2, Math.min(100, st.installPct))}%` } }),
94
+ ) : null,
95
+ h('div', { className: 'fs-hint' },
96
+ st.installPct >= 0 ? `${st.installPct}%` : (st.installTail || '首次安装约 250MB,请稍候')),
90
97
  ) : null,
91
98
  logged ? h('div', { className: 'fs-card fs-account' },
92
99
  h('img', {
package/index.js CHANGED
@@ -230,10 +230,19 @@ function applyInner(ctx, pluginConfig = {}) {
230
230
  try { installing = alive(Number(readFileSync(`${cfg.root}/install.pid`, 'utf8').trim())) } catch {}
231
231
  let installed = existsSync(`${cfg.root}/opt/opt/QQ/qq`)
232
232
  let installTail = ''
233
+ let installLabel = ''
234
+ let installPct = -1
233
235
  try {
234
236
  const raw = readFileSync(`${cfg.root}/logs/install.log`, 'utf8')
235
237
  const lines = raw.split(/[\r\n]+/).map((x) => x.trim()).filter(Boolean)
236
- installTail = lines.slice(-2).join(' ').slice(-160)
238
+ const prog = [...lines].reverse().find((l) => l.startsWith('[progress]'))
239
+ if (prog) {
240
+ const m = prog.match(/\[progress\]\s+(.*?)\s+(\d+)%/)
241
+ if (m) { installLabel = m[1]; installPct = Number(m[2]) }
242
+ installTail = prog.slice(11).trim()
243
+ } else {
244
+ installTail = lines.slice(-1).join(' ').slice(-160)
245
+ }
237
246
  } catch {}
238
247
  const login = qq ? await probeLogin(Number(envFile.DSH_QQ_WS_PORT || cfg.wsPort || 3001), envFile.DSH_QQ_TOKEN || cfg.token) : { loggedIn: false, nickname: '' }
239
248
  if (login.loggedIn) {
@@ -257,7 +266,7 @@ function applyInner(ctx, pluginConfig = {}) {
257
266
  writeFileSync(`${cfg.root}/config.env`, Object.entries(e2).map(([k, x]) => `${k}=${x}`).join('\n') + '\n')
258
267
  } catch {}
259
268
  }
260
- return json({ ok: true, qq, loggedIn: !!login.loggedIn, nickname: login.nickname, uin: login.loggedIn ? login.uin : (envFile.DSH_QQ_UIN || detectedUin), installed, installing, installTail, port: envFile.DSH_QQ_WS_PORT || '3001', token: envFile.DSH_QQ_TOKEN || '', qrAt })
269
+ return json({ ok: true, qq, loggedIn: !!login.loggedIn, nickname: login.nickname, uin: login.loggedIn ? login.uin : (envFile.DSH_QQ_UIN || detectedUin), installed, installing, installTail, installLabel, installPct, port: envFile.DSH_QQ_WS_PORT || '3001', token: envFile.DSH_QQ_TOKEN || '', qrAt })
261
270
  }
262
271
  if (req.method === 'GET' && p === '/qr.png') {
263
272
  let detectedUin = ''
package/install.sh CHANGED
@@ -19,6 +19,42 @@ DSH_QQ_TOKEN=$TOKEN
19
19
  EOF
20
20
  fi
21
21
 
22
+ speed_of() {
23
+ curl -sL -r 0-262144 -o /dev/null --connect-timeout 6 --max-time 8 -w '%{speed_download}' "$1" 2>/dev/null || echo 0
24
+ }
25
+
26
+ pick_mirror() {
27
+ local best="" bestv=0 u v
28
+ echo "[progress] 测速中 0%" >&2
29
+ for u in $NAPCAT_MIRRORS; do
30
+ v=$(speed_of "$u")
31
+ case "$v" in ''|*[!0-9.]*) v=0 ;; esac
32
+ if awk -v a="$v" -v b="$bestv" 'BEGIN{exit !(a>b)}'; then best="$u"; bestv="$v"; fi
33
+ done
34
+ echo "[progress] 选源 $(( ${bestv%.*} / 1024 ))KB/s" >&2
35
+ echo "$best"
36
+ }
37
+
38
+ dl() {
39
+ local url="$1" out="$2" label="$3" total cur pid
40
+ echo "[progress] $label 0%"
41
+ total=$(curl -sIL --connect-timeout 8 --max-time 15 "$url" 2>/dev/null | awk 'tolower($1)=="content-length:"{print $2}' | tail -1)
42
+ curl -fL --retry 3 --connect-timeout 15 -o "$out" "$url" >/dev/null 2>&1 &
43
+ pid=$!
44
+ while kill -0 "$pid" 2>/dev/null; do
45
+ cur=$(stat -c %s "$out" 2>/dev/null || echo 0)
46
+ if [ -n "${total:-}" ] && [ "$total" -gt 0 ] 2>/dev/null; then
47
+ echo "[progress] $label $(( cur * 100 / total ))% ($(( cur / 1048576 ))/$(( total / 1048576 ))MB)"
48
+ else
49
+ echo "[progress] $label $(( cur / 1048576 ))MB"
50
+ fi
51
+ sleep 2
52
+ done
53
+ wait "$pid" || return 1
54
+ echo "[progress] $label 100%"
55
+ return 0
56
+ }
57
+
22
58
  say() { echo "[install $(date +%H:%M:%S)] $*"; }
23
59
 
24
60
  ARCH="$(dpkg --print-architecture 2>/dev/null || uname -m)"
@@ -30,31 +66,18 @@ esac
30
66
  QQ_VER="3.2.34-53644"
31
67
  QQ_DEB_URL="https://qqdl.gtimg.cn/qqfile/QQNT/9.9.36/beta/9ee04bef/linuxqq_${QQ_VER}_${QQ_ARCH}.deb"
32
68
  NAPCAT_ZIP="https://github.com/NapNeko/NapCatQQ/releases/latest/download/NapCat.Shell.zip"
33
-
34
- missing=""
35
- for p in xvfb libnss3 libgbm1 libasound2t64 libasound2 libgtk-3-0 libgtk-3-0t64 dbus-x11 unzip curl; do
36
- dpkg -s "$p" >/dev/null 2>&1 || continue
37
- case "$p" in
38
- libasound2) miss="$miss libasound2" ;;
39
- libasound2t64) [ -n "${miss##*libasound2 }" ] && miss="$miss libasound2t64" ;;
40
- libgtk-3-0) miss="$miss libgtk-3-0" ;;
41
- libgtk-3-0t64) miss="$miss libgtk-3-0t64" ;;
42
- *) miss="$miss $p" ;;
43
- esac
44
- done
45
- # 成对包只留一个(t64 与旧名并存,供不同发行版)
46
- case " $miss " in *" libasound2 "*) miss=$(echo "$miss" | sed 's/ libasound2t64 / /g') ;; *) miss=$(echo "$miss" | sed 's/ libasound2 / /g') ;; esac
47
- case " $miss " in *" libgtk-3-0t64 "*) miss=$(echo "$miss" | sed 's/ libgtk-3-0 / /g') ;; *) miss=$(echo "$miss" | sed 's/ libgtk-3-0t64 / /g') ;; esac
48
- missing="$miss"
49
- if [ -n "$missing" ]; then
50
- say "安装依赖:$missing"
51
- export DEBIAN_FRONTEND=noninteractive
52
- apt-get update -qq && apt-get install -y $missing || { say "依赖安装失败"; exit 1; }
53
- fi
69
+ NAPCAT_MIRRORS="
70
+ https://github.com/NapNeko/NapCatQQ/releases/latest/download/NapCat.Shell.zip
71
+ https://gh-proxy.com/$NAPCAT_ZIP
72
+ https://ghfast.top/$NAPCAT_ZIP
73
+ https://ghproxy.net/$NAPCAT_ZIP
74
+ https://gh-proxy.org/$NAPCAT_ZIP
75
+ https://hub.gitmirror.com/$NAPCAT_ZIP
76
+ "
54
77
 
55
78
  if [ ! -x "$ROOT/opt/opt/QQ/qq" ]; then
56
79
  say "下载 LinuxQQ ${QQ_ARCH}(约 200MB)"
57
- curl -fL --retry 3 -o /tmp/QQ.deb "$QQ_DEB_URL" || { say "LinuxQQ 下载失败"; exit 1; }
80
+ dl "$QQ_DEB_URL" /tmp/QQ.deb "LinuxQQ" || { say "LinuxQQ 下载失败"; exit 1; }
58
81
  dpkg -x /tmp/QQ.deb "$ROOT/opt" || { say "解包失败"; exit 1; }
59
82
  rm -f /tmp/QQ.deb
60
83
  else
@@ -91,9 +114,14 @@ if [ ! -f "$QQ_APP/app_launcher/napcat/napcat.mjs" ]; then
91
114
  if [ -f /tmp/NapCat.Shell.zip ] && unzip -t /tmp/NapCat.Shell.zip >/dev/null 2>&1; then
92
115
  say "复用已下载的 NapCat 包"
93
116
  else
94
- curl -fL --retry 2 -o /tmp/NapCat.Shell.zip "$NAPCAT_ZIP" \
95
- || curl -fL --retry 2 -o /tmp/NapCat.Shell.zip "https://gh-proxy.com/$NAPCAT_ZIP" \
96
- || { say "NapCat 下载失败"; exit 1; }
117
+ MIRROR=$(pick_mirror)
118
+ if [ -n "$MIRROR" ]; then
119
+ say "使用镜像:$MIRROR"
120
+ dl "$MIRROR" /tmp/NapCat.Shell.zip "NapCat" || { say "NapCat 下载失败"; exit 1; }
121
+ else
122
+ say "所有源都不可用"
123
+ exit 1
124
+ fi
97
125
  fi
98
126
  rm -rf /tmp/napcat-unzip && mkdir -p /tmp/napcat-unzip
99
127
  unzip -q -o /tmp/NapCat.Shell.zip -d /tmp/napcat-unzip || { say "NapCat 解压失败"; exit 1; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-qq-stack",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "description": "DeepSeek Harness 的 QQ 协议端底座:LinuxQQ + NapCat 随引擎自启,扫码一次后自动快登。",