Metadata-Version: 2.4
Name: xianyu-goofish-cli
Version: 0.1.0
Summary: Minimal Goofish (Xianyu) CLI: QR login, search, IM chats
Author-email: 肖佳权 <1259103745@qq.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://git.weisanju.fun/weisanju/xianyu-cli
Project-URL: Repository, https://git.weisanju.fun/weisanju/xianyu-cli
Project-URL: Issues, https://git.weisanju.fun/weisanju/xianyu-cli/issues
Keywords: xianyu,goofish,cli,second-hand,idle-fish
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: patchright>=1.64
Requires-Dist: requests>=2.31
Requires-Dist: websockets>=13
Requires-Dist: pillow>=10
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Dynamic: license-file

# xianyu-goofish-cli

[![ci](https://git.weisanju.fun/weisanju/xianyu-cli/actions/workflows/ci.yml/badge.svg)](https://git.weisanju.fun/weisanju/xianyu-cli/actions/workflows/ci.yml)

极简的闲鱼（Goofish）只读 CLI：**扫码登录 → 搜索商品 → 会话列表 → IM 实时流**。

许可证 Apache-2.0。仓库：<https://git.weisanju.fun/weisanju/xianyu-cli>。

实现上刻意避开了两件最麻烦的事：

1. **不自己复刻 mtop 签名/风控**：搜索时用 Patchright 打开真实 Chrome，监听页面自己发出的
   `mtop.taobao.idlemtopsearch.pc.search` 响应，直接解析 JSON。
2. **不逆向 IM 私有二进制**：闲鱼 WebSocket 实际是 LWP（JSON）协议，`wss://wss-goofish.dingtalk.com/`，
   本 CLI 只做注册、心跳、ack 和解码。

> 本项目是非官方实现，仅用于个人学习与低频只读场景。请遵守闲鱼用户协议；账号风控、封号等后果自负。

## 安装

```bash
pip install xianyu-goofish-cli
patchright install chrome     # 或直接使用系统 Chrome（channel="chrome"）
```

从源码：

```bash
git clone https://git.weisanju.fun/weisanju/xianyu-cli.git
cd xianyu-cli
python -m venv .venv
source .venv/bin/activate
pip install -e .
```

需要本机有 Chrome/Chromium。无桌面环境时用 `xvfb-run` 包一层。

## 使用

```bash
# 扫码登录：有头 Chrome 打开登录页，终端打印二维码，PNG 存在 ~/.xianyu-cli/qr.png
xianyu login

# 检查登录态
xianyu whoami

# 搜索（默认无头；被风控时加 --no-headless 或配合 xvfb-run）
xianyu search "iPad Pro" --limit 10
xianyu search "相机" --pages 2 --json

# 会话列表
xianyu chats --limit 50
xianyu chats --json

# 实时监听私信 60 秒
xianyu watch --seconds 60
xianyu watch --seconds 60 --json
```

全局 `--json` 可用于所有命令。

## 命令与退出码

| 命令 | 说明 |
|---|---|
| `login [--timeout N] [--no-headless]` | 扫码登录，保存 cookie + storage_state |
| `whoami` | 调用 `loginuser.get` 验证登录态 |
| `search <query> [--limit] [--pages] [--no-headless]` | 拦截搜索响应并解析 |
| `chats [--limit]` | `session.sync` 拉会话列表 |
| `watch [--seconds]` | IM WebSocket 实时事件 |

退出码：`0` 成功，`1` 普通错误，`2` 未登录/登录失效，`3` 风控拦截，`130` Ctrl-C。

## 数据位置

```
~/.xianyu-cli/
  cookies.json      # 登录 cookie（0600）
  profile/          # 扫码登录用的 Chrome profile
  storage_state.json
  qr.png            # 最近一次登录二维码
  device.json       # IM 设备 ID（按账号固定）
  im_token.json     # IM accessToken 缓存（30 分钟）
```

可用 `XIANYU_HOME` 改根目录。

## 发布（维护者）

PyPI 分发包名是 `xianyu-goofish-cli`（`xianyu-cli` 已被占用），导入包仍为 `xianyu_cli`，命令为 `xianyu`。

1. 仓库 Settings → Actions → Secrets 添加 `PYPI_API_TOKEN`（PyPI API token，scope 建议只限本项目）。
2. 改 `pyproject.toml` 里的 `version`，提交后打同名 tag：

```bash
git tag v0.1.0
git push origin v0.1.0
```

`.forgejo/workflows/release.yml` 会校验 tag 与版本一致、构建 sdist/wheel、跑 `twine check`，再上传 PyPI。
本地手动发布等价命令：

```bash
python -m pip install --upgrade build twine
python -m build
TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-... python -m twine upload dist/*
```

## 已知限制

- **只读**：v1 不提供发消息、发布、自动回复。
- `search` 依赖页面实际发出搜索请求；未登录/登录失效时页面会弹登录框，CLI 会报“未捕获到搜索响应”。
- 二维码 canvas 被中心 logo 跨域污染，不能 `toDataURL()`，本实现用元素截图。
- 会话列表来自 `session.sync`，可能与 App 端不完全一致。
- IM 协议随时可能变化；`watch` 目前只处理文本/图片/已读/新消息通知。
- 高频请求会触发 `RGV587`，CLI 会直接报错退出，不做自动重试风暴。

## 参考与致谢

协议常量与解析思路参考了以下 Apache-2.0 / MIT 项目：

- [fancyboi999/goofish-cli](https://github.com/fancyboi999/goofish-cli)（Apache-2.0）：浏览器拦截搜索响应、LWP 注册/ack、`session.sync` 字段。
- [cv-cat/XianYuApis](https://github.com/cv-cat/XianYuApis)（MIT）：IM WebSocket 与 mtop 常量。
- [superboyyy/xianyu_spider](https://github.com/superboyyy/xianyu_spider)：IM 解码思路。

本项目为独立实现，未复制上述项目的完整代码；详见 `NOTICE`。
