fix 一键组合只上传邮箱列表,服务端再从数据库加载完整账号

This commit is contained in:
2026-09-24 16:01:34 +08:00
parent 4767981b42
commit 243ded46e9
10 changed files with 582 additions and 11 deletions
@@ -0,0 +1,12 @@
@echo off
setlocal
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0Install-Clean.ps1"
if errorlevel 1 (
echo.
echo Installation failed. Read the message above, then try again.
pause
exit /b 1
)
echo.
echo Installation completed successfully.
pause
@@ -0,0 +1,136 @@
[CmdletBinding()]
param(
[switch]$NoLaunch,
[switch]$SkipShortcuts,
[switch]$SkipProcessCheck,
[string]$InstallRoot = '',
[string]$RoamingRoot = '',
[string]$LocalRoot = ''
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
function Copy-Tree {
param(
[Parameter(Mandatory = $true)][string]$Source,
[Parameter(Mandatory = $true)][string]$Destination
)
if (-not (Test-Path -LiteralPath $Source -PathType Container)) {
throw "Required source directory is missing: $Source"
}
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
& robocopy.exe $Source $Destination /E /COPY:DAT /DCOPY:DAT /R:2 /W:1 /XJ /NFL /NDL /NP
$code = $LASTEXITCODE
if ($code -gt 7) {
throw "Copy failed with robocopy exit code $code ($Source)"
}
}
function Move-ToBackup {
param([Parameter(Mandatory = $true)][string]$Path)
if (-not (Test-Path -LiteralPath $Path)) {
return $null
}
$parent = Split-Path -Parent $Path
$leaf = Split-Path -Leaf $Path
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$suffix = [Guid]::NewGuid().ToString('N').Substring(0, 6)
$backup = Join-Path $parent ($leaf + '.backup-' + $stamp + '-' + $suffix)
Move-Item -LiteralPath $Path -Destination $backup
return $backup
}
$packageRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$sourceApp = Join-Path $packageRoot 'App'
$sourceRoaming = Join-Path $packageRoot 'Seed\Roaming\BitBrowser'
$sourceLocal = Join-Path $packageRoot 'Seed\Local\BitBrowser'
$targetApp = if ($InstallRoot) { [System.IO.Path]::GetFullPath($InstallRoot) } else { Join-Path $env:LOCALAPPDATA 'Programs\BitBrowser' }
$targetRoaming = if ($RoamingRoot) { [System.IO.Path]::GetFullPath($RoamingRoot) } else { Join-Path $env:APPDATA 'BitBrowser' }
$targetLocal = if ($LocalRoot) { [System.IO.Path]::GetFullPath($LocalRoot) } else { Join-Path $env:LOCALAPPDATA 'BitBrowser' }
$targetExe = Join-Path $targetApp ([string][char]0x6BD4 + [char]0x7279 + [char]0x6D4F + [char]0x89C8 + [char]0x5668 + '.exe')
$expectedExtensionId = 'jiofmdifioeejeilfkpegipdjiopiekl'
$sourceDb = Join-Path $sourceRoaming 'db.sqlite'
$sourceExtensionManifest = Join-Path $sourceRoaming "BitExtensions\$expectedExtensionId\manifest.json"
if (-not $SkipProcessCheck) {
$running = @(Get-CimInstance Win32_Process -ErrorAction SilentlyContinue | Where-Object {
$_.Name -eq ([string][char]0x6BD4 + [char]0x7279 + [char]0x6D4F + [char]0x89C8 + [char]0x5668 + '.exe') -or
($_.ExecutablePath -and $_.ExecutablePath.StartsWith($targetApp, [System.StringComparison]::OrdinalIgnoreCase))
})
if ($running.Count -gt 0) {
throw 'BitBrowser is running. Close it and run this installer again.'
}
}
if (-not (Test-Path -LiteralPath $sourceDb -PathType Leaf)) {
throw 'The clean seed database is missing from this package.'
}
if (-not (Test-Path -LiteralPath $sourceExtensionManifest -PathType Leaf)) {
throw 'The YesCaptcha extension is missing from this package.'
}
Write-Host 'Installing BitBrowser application files...'
Copy-Tree -Source $sourceApp -Destination $targetApp
$backups = @()
$backup = Move-ToBackup -Path $targetRoaming
if ($backup) { $backups += $backup }
$backup = Move-ToBackup -Path $targetLocal
if ($backup) { $backups += $backup }
Write-Host 'Installing clean user data and preserved extensions...'
Copy-Tree -Source $sourceRoaming -Destination $targetRoaming
if (Test-Path -LiteralPath $sourceLocal -PathType Container) {
Copy-Tree -Source $sourceLocal -Destination $targetLocal
}
if (-not (Test-Path -LiteralPath $targetExe -PathType Leaf)) {
throw "Installed executable was not found: $targetExe"
}
$targetDb = Join-Path $targetRoaming 'db.sqlite'
$targetExtensionManifest = Join-Path $targetRoaming "BitExtensions\$expectedExtensionId\manifest.json"
if (-not (Test-Path -LiteralPath $targetExtensionManifest -PathType Leaf)) {
throw "YesCaptcha was not installed: $targetExtensionManifest"
}
if ((Get-FileHash -LiteralPath $sourceDb -Algorithm SHA256).Hash -ne (Get-FileHash -LiteralPath $targetDb -Algorithm SHA256).Hash) {
throw 'The clean database copy failed verification.'
}
if ((Get-FileHash -LiteralPath $sourceExtensionManifest -Algorithm SHA256).Hash -ne (Get-FileHash -LiteralPath $targetExtensionManifest -Algorithm SHA256).Hash) {
throw 'The YesCaptcha extension copy failed verification.'
}
if (-not $SkipShortcuts) {
$shell = New-Object -ComObject WScript.Shell
$desktop = [Environment]::GetFolderPath('Desktop')
$shortcutPath = Join-Path $desktop 'BitBrowser.lnk'
$shortcut = $shell.CreateShortcut($shortcutPath)
$shortcut.TargetPath = $targetExe
$shortcut.WorkingDirectory = $targetApp
$shortcut.IconLocation = $targetExe + ',0'
$shortcut.Save()
$startMenu = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs'
$startShortcutPath = Join-Path $startMenu 'BitBrowser.lnk'
$startShortcut = $shell.CreateShortcut($startShortcutPath)
$startShortcut.TargetPath = $targetExe
$startShortcut.WorkingDirectory = $targetApp
$startShortcut.IconLocation = $targetExe + ',0'
$startShortcut.Save()
}
Write-Host ''
Write-Host "Installed application: $targetApp"
Write-Host "Installed clean data: $targetRoaming"
Write-Host "Verified extension: YesCaptcha 1.4.7 ($expectedExtensionId)"
if ($backups.Count -gt 0) {
Write-Host 'Previous data was preserved at:'
foreach ($item in $backups) { Write-Host " $item" }
}
Write-Host 'No browser profiles, cookies, history, cache, proxy settings, or login token were installed.'
if (-not $NoLaunch) {
Start-Process -FilePath $targetExe -WorkingDirectory $targetApp
}
@@ -0,0 +1,35 @@
比特浏览器干净初始化分享包
==========================
使用方法
--------
1. 解压整个 ZIP,不要只在压缩包里直接运行。
2. 先关闭比特浏览器。
3. 双击“一键安装_保留YesCaptcha人机助手.cmd”(不要直接运行 App 目录里的 EXE)。
4. 首次打开后,使用新机器自己的比特账号登录。
包内保留
--------
- 比特浏览器程序本体
- Chromium 浏览器内核和 chromedriver
- YesCaptcha 验证码助手 1.4.7
- 比特的“服务助手(勿关闭)” 2.0.6
- 插件和内核必需的本地登记
已清空/未包含
------------
- 比特账号登录令牌
- 浏览器环境和窗口列表
- Cookie、历史记录、缓存、会话和站点存储
- 代理设置、日志和任务记录
- 插件的登录状态和使用数据
安全说明
--------
- 如果目标机器已有比特用户数据,安装脚本会将其改名为 BitBrowser.backup-时间戳-随机码,不会直接删除。
- 安装脚本不会复制原机器的 BrowserCache,因此不会携带原有环境资料。
- 程序默认安装到 %LOCALAPPDATA%\Programs\BitBrowser。
- 干净用户数据安装到 %APPDATA%\BitBrowser。
- 已有的外置缓存目录(例如 D:\bitbrowser-cache)不会被删除,新安装也不会引用它。
首次登录后建议新建一个浏览器环境,确认 YesCaptcha 插件已加载。插件本身的账号需要在新机器重新登录。
@@ -0,0 +1,142 @@
#!/usr/bin/env python3
"""Create a sanitized BitBrowser database while preserving extensions and kernels."""
from __future__ import annotations
import argparse
import json
import os
import sqlite3
from pathlib import Path
def quote_identifier(value: str) -> str:
return '"' + value.replace('"', '""') + '"'
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--source", required=True)
parser.add_argument("--output", required=True)
args = parser.parse_args()
source_path = Path(args.source).resolve()
output_path = Path(args.output).resolve()
if source_path == output_path:
raise RuntimeError("The output database must differ from the source database")
if not source_path.is_file():
raise FileNotFoundError(source_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
if output_path.exists():
output_path.unlink()
source = sqlite3.connect(f"file:{source_path.as_posix()}?mode=ro", uri=True)
target = sqlite3.connect(str(output_path))
try:
source.backup(target)
target.execute("PRAGMA foreign_keys = OFF")
tables = [
row[0]
for row in target.execute(
"SELECT name FROM sqlite_master "
"WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name"
)
]
extension_rows = []
if "local_extensions" in tables:
extension_rows = target.execute(
"SELECT name, desc, extension_id, icon, version, is_use "
"FROM local_extensions ORDER BY id"
).fetchall()
chrome_rows = []
if "chrome_versions" in tables:
chrome_rows = target.execute(
"SELECT chrome, version FROM chrome_versions ORDER BY id"
).fetchall()
firefox_rows = []
if "firefox_versions" in tables:
firefox_rows = target.execute(
"SELECT firefox, version FROM firefox_versions ORDER BY id"
).fetchall()
for table in tables:
target.execute(f"DELETE FROM {quote_identifier(table)}")
target.execute("DELETE FROM sqlite_sequence")
if extension_rows:
target.executemany(
"INSERT INTO local_extensions "
"(name, desc, extension_id, icon, version, is_use, cloud_id, main_user_id) "
"VALUES (?, ?, ?, ?, ?, ?, NULL, NULL)",
extension_rows,
)
if chrome_rows:
target.executemany(
"INSERT INTO chrome_versions (chrome, version) VALUES (?, ?)",
chrome_rows,
)
if firefox_rows:
target.executemany(
"INSERT INTO firefox_versions (firefox, version) VALUES (?, ?)",
firefox_rows,
)
target.commit()
target.execute("VACUUM")
target.execute("PRAGMA optimize")
counts = {
table: target.execute(
f"SELECT COUNT(*) FROM {quote_identifier(table)}"
).fetchone()[0]
for table in tables
}
allowed_nonempty = {"local_extensions", "chrome_versions", "firefox_versions"}
unexpected = {
table: count
for table, count in counts.items()
if count and table not in allowed_nonempty
}
if unexpected:
raise RuntimeError(f"Sanitization failed; unexpected rows remain: {unexpected}")
integrity = target.execute("PRAGMA integrity_check").fetchone()[0]
if integrity != "ok":
raise RuntimeError(f"SQLite integrity check failed: {integrity}")
report = {
"source": str(source_path),
"output": str(output_path),
"extensions": [
{
"name": row[0],
"extension_id": row[2],
"version": row[4],
"enabled": bool(row[5]),
}
for row in extension_rows
],
"chrome_versions": [
{"chrome": row[0], "version": row[1]} for row in chrome_rows
],
"firefox_versions": [
{"firefox": row[0], "version": row[1]} for row in firefox_rows
],
"table_counts": counts,
"integrity_check": integrity,
"size_bytes": os.path.getsize(output_path),
}
print(json.dumps(report, ensure_ascii=False, indent=2))
finally:
target.close()
source.close()
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,12 @@
@echo off
setlocal
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "%~dp0Install-Clean.ps1"
if errorlevel 1 (
echo.
echo Installation failed. Close BitBrowser and run this file again.
pause
exit /b 1
)
echo.
echo BitBrowser and YesCaptcha were installed and verified.
pause