Files
SnowCatQQ/snowcat-portable-maker.ps1
T
天天的鸟蛋蛋 b9655a5ab1 SnowCat 雪猫底层全源码:NapCat 4.18.28 底座 + SnowLuma 能力移植 + V8 通道适配 9.9.37
26 包 monorepo(TS 全源码):
- snowcat-core: NT 内核 API 封装 + listener(含 9.9.37 六回调适配)+ Packet 发包
- snowcat-onebot: OneBot v11 全动作 + MCP Streamable HTTP 适配器 + 稳定线
- snowcat-webui-frontend/backend: 雪猫控制台(React+HeroUI)
- snowcat-shell: 单文件 bundle 出口(vite inlineDynamicImports)
- snowcat-native: napi2native / MoeHoo / ffmpeg / pty 运行时
- 56 项 SnowLuma 独门动作移植(qzone 全家桶/群相册/装扮/闪照/收藏)
- 工具件: 解包器/启动器/便携制作器/doctor

GitHub 关联已全量指向 DandanLLab/SnowCatQQ
2026-11-12 06:27:36 +08:00

122 lines
6.0 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SnowCat 雪猫 · 便携 QQ 制作器(Portable Maker)
#
# 两条产线(师父令):
# A. 官网最新包 → 一键解码 → 便携结构
# B. 本机已装 QQ → 一键便携化(拷贝 versions 运行时到目标目录)
# 产物形态对齐 OneKey:SnowCat.Portable\<build>\QQ.exe + versions\<ver>\...
# 2026-11-11 立项
param(
[Parameter(ParameterSetName = 'Online')]
[switch]$FromOfficial,
[Parameter(ParameterSetName = 'Local')]
[switch]$FromInstalled,
[Parameter(ParameterSetName = 'Local')]
[string]$SourceQQ = '',
[string]$OutDir = 'D:\SnowCat.Portable',
[string]$Proxy = 'http://127.0.0.1:7890'
)
$ErrorActionPreference = 'Stop'
Write-Host '== SnowCat 雪猫便携 QQ 制作器 ==' -ForegroundColor Cyan
function Get-LatestQQUrl {
# 官网下载配置(cdn-go pcConfig.json)抓 QQNT x64 直链;备用 dldir1 页面正则
try {
$cfg = (Invoke-WebRequest -Uri 'https://qq-web.cdn-go.cn/im.qq.com_new/latest/rainbow/pcConfig.json' -UseBasicParsing -Proxy $Proxy -TimeoutSec 30).Content | ConvertFrom-Json
if ($cfg.Windows.ntDownloadX64Url) { return $cfg.Windows.ntDownloadX64Url }
if ($cfg.Windows.ntDownloadUrl) { return $cfg.Windows.ntDownloadUrl }
} catch {}
# 备用:官网页面直链正则(老路径,dldir1)
$urls = @()
foreach ($page in @('https://im.qq.com/windowsQQ/index.shtml', 'https://im.qq.com/pcqq/index.shtml')) {
try {
$html = (Invoke-WebRequest -Uri $page -UseBasicParsing -Proxy $Proxy -TimeoutSec 30).Content
$urls += [regex]::Matches($html, 'https?://dldir1\.qq\.com/[^\s"''<>]+?\.exe') | ForEach-Object { $_.Value }
} catch {}
}
$urls = $urls | Select-Object -Unique | Where-Object { $_ -match 'QQNT|QQ(?!\d)' }
return $urls | Select-Object -First 1
}
function Convert-ToPortable {
param([string]$InstallerExe, [string]$Out)
$stage = Join-Path $env:TEMP "snowcat-qq-$(Get-Random)"
New-Item -ItemType Directory -Path $stage -Force | Out-Null
Write-Host "[1/4] 解码安装包: $InstallerExe" -ForegroundColor Green
# QQNT 安装包是自解压结构:先试 7z 直接解
$seven = Get-Command 7z -ErrorAction SilentlyContinue
$sevenExe = if ($seven) { '7z' } else { 'C:\Program Files\7-Zip\7z.exe' }
if (-not (Test-Path $sevenExe)) {
# NapCat OneKey 包里自带 7z
$fallback = 'C:\dsh\tmp\onekey-unpack\7z.exe'
if (Test-Path $fallback) { $sevenExe = $fallback } else { throw '需要 7z(装 7-Zip 或跑过 NapCat OneKey 解包)' }
}
& $sevenExe x $InstallerExe "-o$stage" -y | Out-Null
# 找 QQ.exe 与 versions/
$qqExe = Get-ChildItem $stage -Recurse -Filter 'QQ.exe' | Select-Object -First 1
if (-not $qqExe) { throw '解包后未找到 QQ.exe' }
$qqDir = $qqExe.DirectoryName
Write-Host '[2/4] 组装便携结构' -ForegroundColor Green
$dest = Join-Path $Out ('SnowCat.' + (Get-Date -Format 'yyyyMMdd'))
New-Item -ItemType Directory -Path $dest -Force | Out-Null
# 便携壳 = QQ.exe + dll 们 + versions/
Copy-Item "$qqDir\*" $dest -Recurse -Force
$verDir = Get-ChildItem (Join-Path $dest 'versions') -Directory -ErrorAction SilentlyContinue | Select-Object -First 1
$verName = if ($verDir) { $verDir.Name } else { 'unknown' }
# 记录配方
@{
made = (Get-Date -Format 's')
source = $InstallerExe
qq_version = $verName
structure = 'OneKey-compatible portable'
note = 'SnowCat 雪猫便携制作器产物;注入用 snowcat-launch.ps1'
} | ConvertTo-Json | Set-Content (Join-Path $dest 'snowcat-portable.json') -Encoding UTF8
Write-Host "[3/4] 清理暂存" -ForegroundColor Green
Remove-Item $stage -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "[4/4] 完成: $dest (QQ $verName)" -ForegroundColor Cyan
Write-Host "注入: powershell -File snowcat-launch.ps1 -QQPath `"$dest\QQ.exe`"" -ForegroundColor Gray
}
if ($FromOfficial) {
Write-Host '[1/4] 抓取官网最新 QQNT 直链…' -ForegroundColor Green
$url = Get-LatestQQUrl
if (-not $url) { throw '官网直链抓取失败,请手动到 im.qq.com 下载后走 Convert-ToPortable' }
Write-Host "[✓] $url" -ForegroundColor Green
$pkg = Join-Path $env:TEMP 'snowcat-qq-latest.exe'
Write-Host '[2/4] 下载(走代理)…' -ForegroundColor Green
Invoke-WebRequest -Uri $url -OutFile $pkg -Proxy $Proxy -TimeoutSec 1800 -UserAgent 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126'
Convert-ToPortable -InstallerExe $pkg -Out $OutDir
} elseif ($FromInstalled) {
$qq = $SourceQQ
if (-not $qq) {
# 复用启动器的发现逻辑
$reg = Get-ItemProperty 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ' -ErrorAction SilentlyContinue
if ($reg -and $reg.UninstallString) { $qq = (Split-Path $reg.UninstallString.Trim('"') -Parent) + '\QQ.exe' }
}
if (-not $qq -or -not (Test-Path $qq)) { throw '未找到已装 QQ,用 -SourceQQ 指定 QQ.exe' }
Write-Host "[1/4] 已装 QQ: $qq" -ForegroundColor Green
$qqDir = Split-Path $qq -Parent
$dest = Join-Path $Out ('SnowCat.from-installed.' + (Get-Date -Format 'yyyyMMdd'))
Write-Host "[2/4] 拷贝运行时 → $dest" -ForegroundColor Green
New-Item -ItemType Directory -Path $dest -Force | Out-Null
Copy-Item "$qqDir\*" $dest -Recurse -Force
$verDir = Get-ChildItem (Join-Path $dest 'versions') -Directory -ErrorAction SilentlyContinue | Select-Object -First 1
$verName = if ($verDir) { $verDir.Name } else { 'unknown' }
@{ made = (Get-Date -Format 's'); source = $qq; qq_version = $verName } |
ConvertTo-Json | Set-Content (Join-Path $dest 'snowcat-portable.json') -Encoding UTF8
Write-Host "[3/4] 完成: $dest (QQ $verName)" -ForegroundColor Cyan
Write-Host "[4/4] 注入: powershell -File snowcat-launch.ps1 -QQPath `"$dest\QQ.exe`"" -ForegroundColor Gray
} else {
Write-Host '用法:'
Write-Host ' 官网最新包→便携: .\snowcat-portable-maker.ps1 -FromOfficial'
Write-Host ' 已装QQ→便携: .\snowcat-portable-maker.ps1 -FromInstalled [-SourceQQ C:\...\QQ.exe]'
Write-Host ' 输出目录: -OutDir D:\SnowCat.Portable'
}