Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
修复win版环境搭建
修复环境需求版本软件安装,修复env.json与.env创建带BOM头,修复python环境,修复计划任务
  • Loading branch information
sanshu-rom authored Aug 26, 2025
commit 19ec683dcb85cb856b59b92c38866dac289ec869
153 changes: 104 additions & 49 deletions autorun.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ $ErrorActionPreference = "Stop"
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "当前非管理员权限,正在尝试以管理员身份重新启动..." -ForegroundColor Yellow
$arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`""
$params = $MyInvocation.UnboundArguments
foreach ($p in $params) { $arguments += " `"$p`"" }
if ($UseProxy) { $arguments += " -UseProxy -ProxyHost `"$ProxyHost`"" }
if ($SkipConfirm) { $arguments += " -SkipConfirm" }
Start-Process powershell -ArgumentList $arguments -Verb RunAs
exit
}

Set-Location -LiteralPath $PSScriptRoot

# ---------- 代理 ----------
Expand Down Expand Up @@ -52,11 +51,15 @@ if (-not $SkipConfirm) {
Use-ProxyIfNeeded -Script {
$needNode = $false
if (Test-Cmd "node") {
# 取出三段版本号
$nodeVer = (node -v) -replace '^v','' -split '\.' | ForEach-Object { [int]$_ }
if ($nodeVer[0] -ge 20) {
Write-Host "已检测到 Node v$($nodeVer -join '.') ≥20,跳过安装" -ForegroundColor Green
# 构造一个可比较的整数:主*10000 + 次*100 + 修订
$current = $nodeVer[0]*10000 + $nodeVer[1]*100 + $nodeVer[2]
$require = 20*10000 + 18*100 + 3 # 20.18.3
if ($current -ge $require) {
Write-Host "已检测到 Node v$($nodeVer -join '.') ≥20.18.3,跳过安装" -ForegroundColor Green
} else {
Write-Host "Node 版本低于 20,将使用 nvm 安装/切换到 20" -ForegroundColor Yellow
Write-Host "Node 版本低于 20.18.3,将使用 nvm 安装/切换到 20.18.3" -ForegroundColor Yellow
$needNode = $true
}
} else {
Expand All @@ -76,15 +79,48 @@ Use-ProxyIfNeeded -Script {
}

if ($needNode) {
nvm install 20
nvm use 20
nvm install 20.18.3
nvm use 20.18.3
}

# ---------- 安装 Python 3.11 ----------
$pyExe = "python-3.11.9-amd64.exe"
$pyUrl = "https://www.python.org/ftp/python/3.11.9/$pyExe"
$pyDir = "C:\Python311"
$needPy = $false

if (Test-Cmd "python") {
$ver = (& python -V 2>&1) -replace 'Python ',''
if ($ver -match '^3\.11') {
Write-Host "已检测到 Python 3.11 ($ver),跳过安装" -ForegroundColor Green
} else {
Write-Host "检测到非 3.11 版本,准备覆盖安装 3.11" -ForegroundColor Yellow
$needPy = $true
}
} else {
Write-Host "未检测到 Python,准备安装 3.11" -ForegroundColor Yellow
$needPy = $true
}

if ($needPy) {
Write-Host "正在下载并安装 Python 3.11..." -ForegroundColor Green
$exePath = "$env:TEMP\$pyExe"
Invoke-WebRequestWithProxy $pyUrl $exePath
$proc = Start-Process -FilePath $exePath -ArgumentList `
"/quiet InstallAllUsers=1 TargetDir=$pyDir PrependPath=1" -PassThru
$proc.WaitForExit()
Remove-Item $exePath
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (-not (Test-Cmd "python")) {
Write-Error "Python 3.11 安装失败,脚本终止"
exit 1
}
}

$tools = @{
yarn = { npm install -g yarn }
pm2 = { npm install -g pm2 }
git = { winget install --id Git.Git -e --source winget }
python = { winget install --id Python.Python.3 -e --source winget }
}
foreach ($kv in $tools.GetEnumerator()) {
$cmd = $kv.Key
Expand Down Expand Up @@ -116,43 +152,71 @@ Use-ProxyIfNeeded -Script {
}
Set-Location $projectPath

$configJson = "config\env.json"
# ---------- 生成 env.json(目录不存在则创建,UTF-8 无 BOM) ----------
$configDir = Join-Path $projectPath "config"
$configJson = Join-Path $configDir "env.json"
if (-not (Test-Path $configDir)) {
New-Item -ItemType Directory -Path $configDir -Force | Out-Null
}
if (-not (Test-Path $configJson)) {
@{
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
$jsonText = @{
ali_token = ""; ali_refresh_token = ""; quark_cookie = ""
uc_cookie = ""; bili_cookie = ""; thread = "10"
enable_dr2 = "1"; enable_py = "2"
} | ConvertTo-Json | Set-Content $configJson -Encoding UTF8
} | ConvertTo-Json
[System.IO.File]::WriteAllLines($configJson, $jsonText, $utf8NoBom)
}

$envFile = ".env"
# ---------- 生成 .env(复制后重写为 UTF-8 无 BOM) ----------
$envFile = Join-Path $projectPath ".env"
if (-not (Test-Path $envFile)) {
Copy-Item ".env.development" $envFile
$template = Join-Path $projectPath ".env.development"
Copy-Item $template $envFile

# 强制无 BOM 重写
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
$content = [System.IO.File]::ReadAllText($envFile)
[System.IO.File]::WriteAllText($envFile, $content, $utf8NoBom)

# 交互式替换
$cookieAuth = Read-Host "网盘入库密码(默认 drpys)"
$apiUser = Read-Host "登录用户名(默认 admin)"
$apiPass = Read-Host "登录密码(默认 drpys)"
$apiPwd = Read-Host "订阅PWD值(默认 dzyyds)"
(Get-Content $envFile) `
-replace 'COOKIE_AUTH_CODE = .*', "COOKIE_AUTH_CODE = $(if([string]::IsNullOrWhiteSpace($cookieAuth)){'drpys'}else{$cookieAuth})" `
-replace 'API_AUTH_NAME = .*', "API_AUTH_NAME = $(if([string]::IsNullOrWhiteSpace($apiUser)){'admin'}else{$apiUser})" `
-replace 'API_AUTH_CODE = .*', "API_AUTH_CODE = $(if([string]::IsNullOrWhiteSpace($apiPass)){'drpys'}else{$apiPass})" `
-replace 'API_PWD = .*', "API_PWD = $(if([string]::IsNullOrWhiteSpace($apiPwd)){'dzyyds'}else{$apiPwd})" |
Set-Content $envFile -Encoding UTF8

$newContent = [System.IO.File]::ReadAllText($envFile) `
-replace '(?<=^COOKIE_AUTH_CODE\s*=\s*).*$', $(if([string]::IsNullOrWhiteSpace($cookieAuth)){'drpys'}else{$cookieAuth}) `
-replace '(?<=^API_AUTH_NAME\s*=\s*).*$', $(if([string]::IsNullOrWhiteSpace($apiUser)){'admin'}else{$apiUser}) `
-replace '(?<=^API_AUTH_CODE\s*=\s*).*$', $(if([string]::IsNullOrWhiteSpace($apiPass)){'drpys'}else{$apiPass}) `
-replace '(?<=^API_PWD\s*=\s*).*$', $(if([string]::IsNullOrWhiteSpace($apiPwd)){'dzyyds'}else{$apiPwd})
[System.IO.File]::WriteAllText($envFile, $newContent, $utf8NoBom)
}

# Node 依赖
if (-not (Test-Path "node_modules")) {
Write-Host "首次安装 Node 依赖..." -ForegroundColor Yellow
yarn config set registry https://registry.npmmirror.com/
yarn
yarn install
} elseif ((git diff HEAD^ HEAD --name-only 2>$null) -match [regex]::Escape("yarn.lock")) {
Write-Host "检测到 yarn.lock 变动,更新 Node 依赖..." -ForegroundColor Yellow
yarn install --registry https://registry.npmmirror.com/
}

# Python 依赖
if (-not (Test-Path ".venv\pyvenv.cfg")) {
Write-Host "首次创建 Python 虚拟环境..." -ForegroundColor Yellow
python -m venv .venv
}
& .\.venv\Scripts\Activate.ps1
if ((git diff HEAD^ HEAD --name-only 2>$null) -match "requirements.txt") {
Write-Host "检测到 requirements.txt 变动,更新 Python 依赖..." -ForegroundColor Yellow
& .\.venv\Scripts\Activate.ps1
Write-Host "首次安装 Python 依赖..." -ForegroundColor Yellow
python.exe -m pip install --upgrade pip
pip install -r spider\py\base\requirements.txt -i https://mirrors.cloud.tencent.com/pypi/simple
} else {
& .\.venv\Scripts\Activate.ps1
if ((git diff HEAD^ HEAD --name-only 2>$null) -match [regex]::Escape("spider\py\base\requirements.txt")) {
Write-Host "检测到 requirements.txt 变动,更新 Python 依赖..." -ForegroundColor Yellow
pip install -r spider\py\base\requirements.txt -i https://mirrors.cloud.tencent.com/pypi/simple
}
}

if (-not (pm2 list | Select-String "drpyS.*online")) {
Expand All @@ -168,14 +232,10 @@ Use-ProxyIfNeeded -Script {
$taskStartup = "drpyS_PM2_Startup"
$taskUpdate = "drpyS_Update"

# 获取绝对路径
$pm2 = (Get-Command pm2.cmd -ErrorAction SilentlyContinue).Source
$nodeExe = (Get-Command node.exe -ErrorAction SilentlyContinue).Source

if (-not $pm2 -or -not $nodeExe) {
Write-Warning "找不到 pm2.cmd 或 node.exe,跳过计划任务注册"
} else {
# 删除旧任务
if ($pm2 -and $nodeExe) {
$taskStartup,$taskUpdate | ForEach-Object {
if (Get-ScheduledTask -TaskName $_ -ErrorAction SilentlyContinue) {
Unregister-ScheduledTask -TaskName $_ -Confirm:$false
Expand All @@ -185,35 +245,30 @@ if (-not $pm2 -or -not $nodeExe) {
$commonSettings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable

# 1) 开机自启(直接启动 drpyS,不依赖 dump)
# 开机自启
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -Command `"& { Set-Location '$projectPath'; & '$nodeExe' '$projectPath\index.js' | & '$pm2' start '$projectPath\index.js' --name drpyS --update-env }`"" `
-Argument "-NoProfile -ExecutionPolicy Bypass -Command `"& { `$env:PM2_HOME='C:\$env:USERNAME\.pm2'; Set-Location '$projectPath'; & '$pm2' start '$projectPath\index.js' --name drpyS --update-env }`"" `
-WorkingDirectory $projectPath
$trigger = New-ScheduledTaskTrigger -AtStartup -RandomDelay (New-TimeSpan -Seconds 30)
Register-ScheduledTask -TaskName $taskStartup `
-Action $action -Trigger $trigger -Settings $commonSettings `
-User "SYSTEM" -RunLevel Highest -Force | Out-Null
Write-Host "已创建/更新开机自启任务:$taskStartup" -ForegroundColor Yellow
Register-ScheduledTask -TaskName $taskStartup -Action $action -Trigger $trigger -Settings $commonSettings -User "SYSTEM" -RunLevel Highest -Force | Out-Null
Write-Host "已创建/更新开机自启任务:$taskStartup" -ForegroundColor Green

# 2) 每 24 h 更新
# 每 6 小时更新
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command `"& { Set-Location '$projectPath'; git fetch origin; if (git status -uno | Select-String 'Your branch is behind') { git reset --hard origin/main; yarn --prod --silent; if (git diff HEAD^ HEAD --name-only | Select-String 'spider/py/base/requirements.txt') { python -m venv .venv; & .\.venv\Scripts\Activate.ps1; pip install -r spider\py\base\requirements.txt -q } & '$pm2' restart drpyS } }`"" `
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command `"& { `$env:PM2_HOME='C:\$env:USERNAME\.pm2'; Set-Location '$projectPath'; git fetch origin; if (git status -uno | Select-String 'Your branch is behind') { git reset --hard origin/main; yarn install --registry https://registry.npmmirror.com/; pip install -r spider\py\base\requirements.txt -i https://mirrors.cloud.tencent.com/pypi/simple; & '$pm2' restart drpyS } }`"" `
-WorkingDirectory $projectPath
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 24)
Register-ScheduledTask -TaskName $taskUpdate `
-Action $action -Trigger $trigger -Settings $commonSettings `
-User "SYSTEM" -RunLevel Highest -Force | Out-Null
Write-Host "已创建/更新每 24 小时更新任务:$taskUpdate" -ForegroundColor Yellow
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 6)
Register-ScheduledTask -TaskName $taskUpdate -Action $action -Trigger $trigger -Settings $commonSettings -User "SYSTEM" -RunLevel Highest -Force | Out-Null
Write-Host "已创建/更新每 6 小时更新任务:$taskUpdate" -ForegroundColor Green
}

# ---------- 完成 ----------
$ip = (ipconfig | Select-String "IPv4 地址" | Select-Object -First 1).ToString().Split(":")[-1].Trim()
$ip = (ipconfig | Select-String "IPv4 地址" | Select-Object -First 1).ToString().Split(":")[-1].Trim()
$public = (Invoke-RestMethod "https://ipinfo.io/ip")
Write-Host "内网地址:http://${ip}:5757" -ForegroundColor Yellow
Write-Host "公网地址:http://${public}:5757" -ForegroundColor Yellow
Write-Host "脚本执行完成!重启后 drpyS 自动启动并每 24 小时检查更新。" -ForegroundColor Yellow
Write-Host "脚本只需要执行一次,无需重复执行。" -ForegroundColor Yellow
Write-Host "按任意键退出!!!" -ForegroundColor Yellow
Write-Host "内网地址:http://${ip}:5757" -ForegroundColor Green
Write-Host "公网地址:http://${public}:5757" -ForegroundColor Green
Write-Host "脚本执行完成!重启后 drpyS 自动启动并每 6 小时检查更新。" -ForegroundColor Green
Write-Host "按任意键退出!!!" -ForegroundColor Green
Read-Host