Files
ebook-skill/tools/lib.ps1
T
cheney 221b1f8add feat: 引入 so-novel submodule 并提供非交互下载工具
- vendor/so-novel: 上游 v1.12.0 (规则驱动的书源抓取/下载引擎)
- tools/src: ToolMain 封装 search/download/toc/sources,stdout 只输出 JSON
- tools/build.ps1: 自动定位/下载 JDK21,按平台显式激活 javet 原生库 profile
- bin/novel.ps1|.cmd: 命令行入口(人读输出或 -Json)
- SKILL.md/README.md: 使用说明与下载原理分析
2026-11-04 15:12:10 +08:00

128 lines
4.8 KiB
PowerShell

# Shared helpers for the ebook-skill command line (Windows PowerShell 5.1+ / pwsh 7+).
$ErrorActionPreference = 'Stop'
function Get-ProjectRoot {
param([string]$Start = $PSScriptRoot)
$dir = (Resolve-Path $Start).Path
while ($dir) {
if (Test-Path (Join-Path $dir 'vendor\so-novel\pom.xml')) { return $dir }
$parent = Split-Path $dir -Parent
if ($parent -eq $dir -or -not $parent) { break }
$dir = $parent
}
throw "Cannot locate project root (vendor/so-novel/pom.xml not found above $Start). Run: git submodule update --init"
}
function Get-ToolPaths {
param([string]$Root = (Get-ProjectRoot))
[pscustomobject]@{
Root = $Root
Vendor = Join-Path $Root 'vendor\so-novel'
Tools = Join-Path $Root 'tools'
Runtime = Join-Path $Root 'tools\runtime'
Build = Join-Path $Root 'tools\build'
Classes = Join-Path $Root 'tools\build\classes'
AppJar = Join-Path $Root 'tools\runtime\app.jar'
ToolJar = Join-Path $Root 'tools\runtime\sonovel-tool.jar'
Config = Join-Path $Root 'tools\runtime\config.ini'
Rules = Join-Path $Root 'tools\runtime\rules'
Books = Join-Path $Root 'books'
}
}
function Test-Jdk21 {
param([string]$JdkHome)
if (-not $JdkHome) { return $false }
$java = Join-Path $JdkHome 'bin\java.exe'
if (-not (Test-Path $java)) { return $false }
try {
$out = (& $java -version 2>&1 | Out-String)
} catch {
return $false
}
if ($out -match 'version "(?:1\.)?(\d+)') {
return ([int]$Matches[1] -ge 21)
}
return $false
}
function Find-Jdk21 {
param([switch]$AllowDownload)
$candidates = New-Object System.Collections.Generic.List[string]
if ($env:EBOOK_NOVEL_JAVA_HOME) { $candidates.Add($env:EBOOK_NOVEL_JAVA_HOME) }
if ($env:JAVA_HOME) { $candidates.Add($env:JAVA_HOME) }
$patterns = @(
(Join-Path $PSScriptRoot '.jdk\*\*'),
(Join-Path $PSScriptRoot '.jdk'),
'C:\Program Files\Java\jdk-21*',
'C:\Program Files\Eclipse Adoptium\jdk-21*',
'C:\Program Files\JetBrains\*\jbr',
(Join-Path $env:LOCALAPPDATA 'mise\installs\java\21*'),
(Join-Path $env:LOCALAPPDATA 'mise\installs\java\2*')
)
foreach ($pattern in $patterns) {
foreach ($dir in (Get-ChildItem -Path $pattern -Directory -ErrorAction SilentlyContinue)) {
$candidates.Add($dir.FullName)
}
}
foreach ($candidate in $candidates) {
if (Test-Jdk21 -JdkHome $candidate) { return (Resolve-Path $candidate).Path }
}
if ($AllowDownload) { return (Install-Jdk21) }
return $null
}
# Downloads a portable Temurin JDK 21 (used only when no local JDK 21 exists).
function Install-Jdk21 {
$dest = Join-Path $PSScriptRoot '.jdk'
New-Item -ItemType Directory -Force $dest | Out-Null
Write-Host '[setup] no JDK 21 found, downloading Temurin 21 from the Tsinghua mirror ...' -ForegroundColor Yellow
$mirror = 'https://mirrors.tuna.tsinghua.edu.cn/Adoptium/21/jdk/x64/windows/'
$listing = (Invoke-WebRequest -Uri $mirror -UseBasicParsing -TimeoutSec 60).Content
$names = [regex]::Matches($listing, 'OpenJDK21U-jdk_x64_windows_hotspot_[0-9._]+\.zip') |
ForEach-Object { $_.Value } | Sort-Object -Unique
if (-not $names) { throw "Could not find a JDK 21 archive at $mirror" }
$zipName = $names[$names.Count - 1]
$zip = Join-Path $env:TEMP $zipName
if (-not (Test-Path $zip)) {
Invoke-WebRequest -Uri ($mirror + $zipName) -OutFile $zip -UseBasicParsing -TimeoutSec 1800
}
Expand-Archive -Path $zip -DestinationPath $dest -Force
$java = Get-ChildItem -Path (Join-Path $dest '*\bin\java.exe') -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $java) { throw "JDK extraction failed under $dest" }
$JdkHome = Split-Path (Split-Path $java.FullName -Parent) -Parent
Write-Host "[setup] JDK 21 installed at $JdkHome" -ForegroundColor Green
return $JdkHome
}
function Get-JavaCommand {
param([string]$Root = (Get-ProjectRoot))
$jdkHome = Find-Jdk21
if (-not $jdkHome) {
throw 'JDK 21 is required. Run tools\build.ps1 (it can download one), or set EBOOK_NOVEL_JAVA_HOME.'
}
return (Join-Path $jdkHome 'bin\java.exe')
}
function Find-JarTool {
# JBR ships without jar.exe, so fall back to any other JDK on the machine.
foreach ($pattern in @('C:\Program Files\Java\*\bin\jar.exe',
(Join-Path $env:LOCALAPPDATA 'mise\installs\java\*\bin\jar.exe'),
'C:\Program Files\Eclipse Adoptium\*\bin\jar.exe')) {
$exe = Get-ChildItem -Path $pattern -ErrorAction SilentlyContinue | Select-Object -First 1
if ($exe) { return $exe.FullName }
}
$cmd = Get-Command jar.exe -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Source }
return $null
}