Skip to content

Latest commit

 

History

History
292 lines (201 loc) · 8.33 KB

File metadata and controls

292 lines (201 loc) · 8.33 KB

开发指南

这份文档面向维护者,记录当前项目结构、构建方式、测试方式和一些约定。

它不是用户说明书。面向用户的内容请看 usage.md

如果想看后续待办和演进方向,可以继续看 todo.md

文档分工

  • README.mddocs/installation.mddocs/usage.mddocs/faq.md 记录当前对用户生效的行为和用法。
  • docs/dev/development.mddocs/dev/command.md 记录当前维护者需要了解的结构、命令和约定。
  • docs/dev/todo.md 只作为 backlog 使用,不应该当作“当前已经实现的功能清单”。
  • 某项功能已经落地后,应尽快把说明同步到现状文档里,并从 todo.md 里移除或改写成下一步增强项。

项目结构

goani-cli/
├── cmd/
│   ├── goani/          # 主程序入口
│   └── goani-debug-*/  # 手动调试工具
├── internal/
│   ├── app/            # 应用编排
│   ├── cli/            # 命令入口与注册
│   │   └── commands/   # 具体命令实现
│   ├── player/         # 播放器、配置和 HLS 代理
│   ├── source/         # 媒体源模型、订阅、归类和抓取
│   │   └── webselector/ # 站点解析实现
│   ├── ui/
│   │   ├── console/    # 传统终端交互
│   │   └── tui/        # Bubble Tea TUI 页面
│   └── version/        # 版本信息
├── internal/workflow/  # 搜索、播放、配置等跨层流程
└── docs/               # 用户文档和开发文档

当前比较重要的拆分点是:

  • internal/ui/console 负责传统命令行交互。
  • internal/ui/tui 负责 TUI 页面。
  • internal/player/hlsproxy.go 和相关 HLS 工具负责统一的 m3u8 本地兼容层,包括 playlist 改写、短时分片缓存、请求去重和轻量预取。
  • internal/source/episode_group.go 负责剧集归类和重复线路合并。
  • internal/cli/commands 尽量只保留命令入口,跨层流程已经开始下沉到 internal/workflow

构建

前置要求

  • Go 1.22+
  • 如果使用 make,需要 GNU Make 和 Bash 兼容环境

构建产物规范

  • 仓库内保留型构建产物统一放在 bin/
  • 临时验证用的二进制建议输出到系统临时目录,例如 Windows 下用 $env:TEMP
  • 不建议在仓库根目录直接生成 goanigoani.exe,避免和源码、文档混在一起。
  • 交给用户手工验证时,默认统一编译到 bin/goani-test.exe,避免和 agent 自己的临时验证产物混淆。

本地构建

mkdir -p bin
go build -o ./bin/goani ./cmd/goani

Windows PowerShell:

New-Item -ItemType Directory -Force .\bin | Out-Null
go build -o .\bin\goani.exe .\cmd\goani

手工测试约定

如果是 agent 自己做快速验证,优先编到系统临时目录:

go build -o $env:TEMP\goani-check.exe .\cmd\goani

如果是交给用户在自己的 pwsh 窗口里直接测试,统一编到:

New-Item -ItemType Directory -Force .\bin | Out-Null
go build -o .\bin\goani-test.exe .\cmd\goani

后续默认让用户运行:

.\bin\goani-test.exe

使用 Makefile

make build
make build-all
make test
make install

其中 make test 当前等价于:

go test ./...

版本信息注入

mkdir -p bin
go build -ldflags="-s -w \
  -X github.com/Yyyangshenghao/goani-cli/internal/version.Version=v0.1.0 \
  -X github.com/Yyyangshenghao/goani-cli/internal/version.GitCommit=$(git rev-parse --short HEAD) \
  -X github.com/Yyyangshenghao/goani-cli/internal/version.BuildDate=$(date -u '+%Y-%m-%d_%H:%M:%S')" \
  -o ./bin/goani ./cmd/goani

PowerShell 示例:

$version = "v0.1.0"
$gitCommit = git rev-parse --short HEAD
$buildDate = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd_HH:mm:ss")
New-Item -ItemType Directory -Force .\bin | Out-Null

go build -ldflags "-s -w -X github.com/Yyyangshenghao/goani-cli/internal/version.Version=$version -X github.com/Yyyangshenghao/goani-cli/internal/version.GitCommit=$gitCommit -X github.com/Yyyangshenghao/goani-cli/internal/version.BuildDate=$buildDate" -o .\bin\goani.exe .\cmd\goani

测试

自动化测试

真实的 Go 单元测试应放在被测包旁边,文件名以 *_test.go 结尾。当前已经在这些位置放了测试:

  • internal/player/hlsproxy_test.go
  • internal/source/episode_group_test.go

统一运行:

go test ./...

基础静态检查:

go vet ./...

更完整的 lint 检查:

go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8 run

CI 会在 push / pull request 上自动执行:

  • golangci-lint
  • go test ./...
  • go build -o <temp> ./cmd/goani

手动调试入口

手动 smoke 工具现在放在 cmd/goani-debug-* 下,它们是开发辅助程序,不是 go test 识别的测试文件。

例如:

go run .\cmd\goani-debug-source
go run .\cmd\goani-debug-player
go run .\cmd\goani-debug-potplayer
go run .\cmd\goani-debug-playback

这类程序适合做本地验证、播放器探针和临时排查。后续如果再增加,优先保持“开发工具”定位,不要把它们当成自动测试。

本地播放器回归测试

播放器回归现在分成两步:

  1. 先采集真实 m3u8 样本
go run .\cmd\goani-debug-playback

默认会把样本写到 internal/player/testdata/m3u8_samples.local.json

  1. 再跑本地 smoke 或手工播放器矩阵
$env:GOANI_RUN_LIVE_PLAYBACK_SMOKE = "1"
go test ./internal/player -run TestLivePlaybackSmoke -v
$env:GOANI_RUN_MANUAL_PLAYER_TESTS = "1"
go test ./internal/player -run TestManualPlayerPlaybackMatrix -v

可选环境变量:

  • GOANI_PLAYBACK_SAMPLE_FILE 指定自定义样本文件路径
  • GOANI_PLAYBACK_PLAYERS=mpv,potplayer 只跑指定播放器

手工播放器矩阵只会测试 config.json 里已经明确配置过路径、且当前路径可用的播放器;不会把系统里自动探测到但未配置的播放器带进测试。


架构说明

当前命令模型

  • goani 默认显示帮助
  • goani tui 进入主 TUI
  • goani searchgoani playgoani sourcegoani config 继续作为显式 CLI 入口
  • proxy-hls 是内部隐藏命令,只给播放器兼容层使用,不对普通用户展示

命令与编排

命令层应该尽量薄,负责:

  • 解析参数
  • 调用应用编排
  • 将状态交给 TUI 或 CLI 输出

复杂流程尽量放在应用层或专门的流程函数里,例如:

  • 搜索后串起选番、选集、线路选择和播放
  • 配置页的保存回调
  • m3u8 的统一本地兼容层播放

媒体源与播放器

媒体源、播放器和配置都已经开始分层:

  • internal/source 负责媒体源、订阅、归类和解析
  • internal/player 负责播放器发现、默认播放器和 HLS 兼容层
  • internal/app 负责把配置、播放器和媒体源组织成一个应用对象
  • internal/workflow 负责把 CLI、TUI、播放器和媒体源串成完整操作流程

当前比较重要的实现约定是:

  • GroupEpisodes 优先按数字归类,再兜底到标题。
  • goani config player <name> <path> 只保存路径,不自动设置默认播放器。
  • goani play 会在真正播放时补默认播放器。
  • 所有 m3u8 线路都会优先走统一的本地 HLS 兼容层。

命令注册

命令通过 init() 注册,新增命令需要实现 Command 接口并调用 Register()

func init() {
	Register(&MyCommand{})
}

如果是内部命令,记得实现 HiddenCommand,避免显示到顶层帮助里。


贡献建议

  1. 改动尽量按功能块提交,不要把文档、代码和测试混成一坨。
  2. 复杂逻辑优先补 *_test.go,不要只靠 cmd/goani-debug-* 里的手动工具。
  3. 注释要解释边界、原因和副作用,不要重复函数名本身。
  4. 改完后至少跑一次 go test ./...go build;如果改动涉及多个 Go 文件,优先再跑一次 golangci-lint

提交规范

建议继续使用 Conventional Commits:

  • feat: 新功能
  • fix: 修复问题
  • docs: 文档更新
  • refactor: 结构调整
  • test: 测试相关
  • chore: 构建或工具调整