Metadata-Version: 2.5
Name: yixi-cli
Version: 0.1.0
Summary: 一席命令行工具：登录、查询、下载与配置
Project-URL: Homepage, https://github.com/QinGeneral/yixi-cli
Project-URL: Repository, https://github.com/QinGeneral/yixi-cli
Project-URL: Issues, https://github.com/QinGeneral/yixi-cli/issues
Requires-Python: >=3.10
Requires-Dist: platformdirs<5,>=4
Requires-Dist: requests<3,>=2.31
Requires-Dist: rich<15,>=13
Requires-Dist: typer<1,>=0.12
Provides-Extra: browser
Requires-Dist: selenium<5,>=4.18; extra == 'browser'
Provides-Extra: dev
Requires-Dist: pytest<10,>=8; extra == 'dev'
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
Description-Content-Type: text/markdown

# yixi-cli

一席命令行工具，参考 `geektime_cli` 的 Typer + Rich 结构，支持浏览器登录、课程与章节查询、图文/音视频下载及用户级配置。使用当前官网 v3 API。

## 安装

需要 Python 3.10+。从 PyPI 安装：

```sh
uv tool install 'yixi-cli[browser]'
yixi --help
```

更新已安装的 CLI：

```sh
uv tool upgrade yixi-cli
```

也可以从源码安装到虚拟环境：

```sh
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[browser]'
yixi --version
```

浏览器登录需要 Google Chrome，`browser` extra 安装 Selenium。直接导入 token 时可只安装 `uv tool install yixi-cli`。HLS（m3u8）下载需要 PATH 中的 `ffmpeg`，直接 MP4/音频下载不需要。

## 登录

```sh
yixi login                    # 在 Chrome 中手动完成官网登录
yixi login --check            # 向服务端验证登录状态
yixi login --token            # 隐藏输入官网 token
yixi login --token-file /path/to/token.txt
yixi logout
```

`--token-file` 支持纯文本、`{"token": "..."}`，也支持包含 `Authorization` 或 `Cookie` 的 header JSON。验证成功才保存新凭据；登录失败不会覆盖旧凭据。工具不发送短信或代填密码。

配置和凭据保存在 `platformdirs` 返回的用户配置目录；`yixi config path` 可查看路径。凭据文件通过原子替换保存，Unix 权限为 `0600`，不写入仓库。可用 `YIXI_CONFIG_DIR` 指定配置目录，`YIXI_TOKEN` 提供临时 token；环境变量优先于已保存的凭据，因此 `logout` 不会取消环境变量。

## 查询

```sh
yixi course list
yixi course list --type all --limit 3
yixi course list --type wanxiang,zhiya --json
yixi course info 39 --type wanxiang
yixi course chapters 39 --type wanxiang
yixi course chapters 'https://www.yixi.tv/#/wanxiang/detail?id=39&episodeId=261' --json
yixi article detail 261 --type wanxiang
```

栏目：`speech` 演讲、`record` 记录、`wanxiang` 万象、`zhiya` 枝桠、`activity` 现场。`activity` 即旧脚本下载的“现场”；`record` 是官网新增的“记录”栏目。查询目录默认列出 20 个演讲；`--limit 0` 获取全部，多个栏目的查询限制分别计算。

`course info/chapters` 使用课程 ID；`article detail` 使用章节 ID。万象、枝桠的两类 ID 不可混用。数字课程 ID 必须带 `--type`；官网详情链接可自动识别栏目，也支持 `https://yixi.tv/h5/speech/1447/` 这样的演讲分享链接。

## 下载

```sh
yixi download 1450 --type speech --text-only
yixi download 'https://yixi.tv/h5/speech/1447/' --video-only
yixi download 79 --type zhiya --audio-only --with-media
yixi download 'https://www.yixi.tv/#/wanxiang/detail?id=39&episodeId=261' --text-only
yixi download --type all --limit 3 --dry-run
yixi download --type speech --limit 1 --quality best -o ~/Downloads/Yixi
yixi download --type record --quality all -o .
```

默认下载“演讲、现场、记录、万象、枝桠”，输出至 `./Yixi`。省略 TARGET 会分页遍历选定栏目；下载的 `--limit` 是所有栏目的总课程数上限，0 表示不限。课程 ID 下载全部章节；带 `episodeId` 的官网链接只下载指定章节。

旧版已保存的 `types` 配置继续生效。要将演讲加入默认下载，可执行 `yixi config set types speech,activity,record,wanxiang,zhiya`；也可用 `yixi download --type speech -o /path/to/一席` 单独补下载，文件保存到 `演讲/`。

默认保存 Markdown 图文、可用音频和最高可用清晰度视频。`--text-only` 仅保存图文；`--audio-only`、`--video-only` 选择媒体类型，`--with-media` 可覆盖配置中的图文模式。`--quality` 可选 `best`、`all`、`高清`、`标清`。服务端提供文稿时附在 Markdown 中，保留原始 HTML 排版；没有文稿时保存介绍。工具按当前账号权限获取服务端返回的链接。

已有非空媒体文件默认跳过，`--force` 重新下载。新文件下载完成后才替换目标，中断不会把半成品当成已完成。HLS 由 ffmpeg 处理播放列表和加密分片。媒体失败或所选媒体不可用时，汇总原因并返回非零退出码；已保存的图文仍保留。`--dry-run` 只读取目录与详情，不写配置或下载文件。

输出按栏目分目录，万象、枝桠再按课程分目录。指定 `-o .` 可复用原目录中路径、名称和扩展名一致的媒体文件。旧版枝桠的平铺文件、音频扩展名或课程名称不一致时不会自动搬迁。“现场”输出至 `现场/`，“记录”输出至 `记录/`。现场接口现在只返回单个视频地址（保存为 `视频.mp4`）；同一条目已有旧版 `高清`/`标清`/`超清` 视频时默认跳过，`--force` 才重新下载。

## 配置

```sh
yixi config show
yixi config show --json
yixi config set output_dir ~/Downloads/Yixi
yixi config set types speech,record
yixi config set text_only true
yixi config set quality all
yixi config set limit 3
yixi config reset --confirm
```

| 配置项 | 默认值 | 含义 |
| --- | --- | --- |
| `output_dir` | `./Yixi` | 下载目录 |
| `types` | `speech,activity,record,wanxiang,zhiya` | 默认下载栏目 |
| `limit` | `0` | 下载总课程上限 |
| `text_only` | `false` | 仅图文 |
| `quality` | `best` | 视频清晰度 |
| `timeout` | `30` | HTTP 超时秒数 |
| `retries` | `3` | GET 请求重试次数，0–10 |
| `interval` | `1` | API 请求间隔秒数 |
| `page_size` | `50` | 分页大小，1–200 |

命令行选项覆盖本次运行的配置，不更改保存的配置。非法值和损坏的 JSON 明确报错。

## 开发

```sh
uv venv --python 3.13
uv pip install -e '.[dev,browser]'
.venv/bin/python -m pytest -q
.venv/bin/ruff check .
.venv/bin/python -m yixi_dl --help
```

代码位于 `src/yixi_dl`，分为 CLI、配置、HTTP、认证、API 和下载模块。测试使用模拟响应及临时目录，不需要账号，不修改用户配置。HLS 集成测试使用本地 HTTP 服务和 ffmpeg 生成的一秒静音素材，验证加密播放列表合并；没有 ffmpeg 时跳过。

原始三个 Python 文件保存在被 Git 忽略的 `.legacy-backup/`，其中可能包含原始凭据。旧入口 `yixi_downloader.py` 现在只转发到 CLI，不再在导入时启动批量下载。已有课程目录、音视频、缓存、虚拟环境及本地凭据不纳入 Git；发布包仅包含项目源码和文档。

官网接口没有稳定性承诺；若返回格式变更，工具会提示错误。浏览器登录需由使用者完成真实账户验证。

## 发布

GitHub 仓库为 [QinGeneral/yixi-cli](https://github.com/QinGeneral/yixi-cli)，PyPI 包名为 `yixi-cli`，安装后提供 `yixi` 命令。

`.github/workflows/release.yml` 在推送 `v<版本>` 标签时运行测试、检查代码、构建并验证 wheel 和源码包，再通过 GitHub 的 `pypi` environment 和 PyPI Trusted Publishing 发布。首次发布需要在 PyPI 注册对应的 GitHub publisher，字段为 owner `QinGeneral`、repository `yixi-cli`、workflow `release.yml`、environment `pypi`。后续发布同时更新 `pyproject.toml` 与 `src/yixi_dl/__init__.py` 中的版本，再推送对应标签。已发布版本不可覆盖。
