Commit Graph

122 Commits (2b5d872f0be7922131f72a80208d5adca216955e)
 

Author SHA1 Message Date
郭立lee 2b5d872f0b
feat(sns): sns-feed / sns-search 输出完整 media[] 字段 (#15)
#14 之上增量:把 sns-feed / sns-search 的 media_count 升级成完整 media[] 数组(含 url/thumb/key/token/md5/enc_idx/size + video_md5/duration),下游可直接做图片代理或离线渲染。

- 用 roxmltree(pure Rust,无 C 依赖)替代 regex 抽属性
- 字段命名对齐 artifacts 仓库 Python _parse_media,跨实现 diff 友好
- 14 个 sns 单测:作者新增 6 个 fixture(单图/三图/视频/纯文字/malformed/缺 totalSize)+ 已有 8 个保持
- 与之前 PR #14 的 --user XML fallback 修复 / SNS_MAX_LIMIT / SNS_MAX_SCAN / escape_like_pattern 完全兼容

Author: leeguooooo <guoli@zhihu.com>
Co-fixed-by: wx-cli-coder (rebase + 冲突解决 + 测试模块合并 + media_count 语义文档补充)
2026-04-19 02:22:55 +08:00
JL e8939f315d
feat(sns): sns-notifications / sns-feed / sns-search (#14)
新增 3 个朋友圈相关命令:sns-notifications / sns-feed / sns-search。
PR review 修复(已 push 进同一分支):
- 修 --user 过滤与 XML <username> fallback 打架的 bug(@wx-cli-codex 发现)
- 加 SNS_MAX_LIMIT / SNS_MAX_SCAN 防御性上限
- 抽 escape_like_pattern() helper
- 补 8 个单测(parse_post_xml / escape_like_pattern)

Cargo check 三 target 全过:aarch64-darwin / x86_64-pc-windows-gnu / x86_64-unknown-linux-gnu。
Co-authored-by: fengliu222 <fengliu222@users.noreply.github.com>
2026-04-19 01:58:21 +08:00
郭立lee f0dcd4ea05
docs(readme): explain how to fetch more than 500 messages (#13)
Clarify that the 500-message behavior is only a default limit, not a hard cap.
Document `-n/--limit` examples for history, search, and export in both README and SKILL.
2026-04-18 15:01:15 +08:00
jackwener 697d3fc720 chore: bump version to 0.1.9 2026-04-18 02:11:28 +08:00
jackwener 1e52014a6b perf(daemon): Arc<Names> + tokio RwLock, O(1) clone per IPC request
Was: Arc<std::sync::RwLock<Names>>; each dispatch clone_names() copied
4 HashMaps (~100KB for a user with 2700 contacts) and used std RwLock
which blocks the tokio worker thread during the clone.

Now: Arc<tokio::sync::RwLock<Arc<Names>>>; dispatch takes the read
guard, does Arc::clone (pointer bump), drops the guard, then spawns
the query work. Names is immutable after daemon startup; Arc is ideal.

Smoke tested: `wx sessions --json` returns correct data including
chat_type; 8 concurrent clients finish in 12ms.
2026-04-18 02:10:45 +08:00
JL e977007306
feat(unread): 按 chat_type 分类会话,新增 --filter (#9)
Before: wx unread / sessions / history 把公众号、订阅号折叠入口
(brandsessionholder)、折叠群聊(@placeholder_foldgroup)、认证服务号
全归为 is_group=false,与真私聊混在一起。甚至 username 形如 wxid_* 但
实为公众号的条目也完全分不出来。

改动:
- 新增 chat_type_of(username, names) helper,输出固定为
  group / official_account / folded / private。
- 判据依次:@chatroom → group;brandsessionholder / @placeholder_foldgroup
  → folded;contact.verify_flag != 0 → official_account(覆盖 wxid_*
  伪装为公众号的情况,以及银行/品牌服务号、qqsafe / mphelper 等认证账号);
  gh_* / biz_* / @* 前缀兜底;其余为 private。
- load_names 顺带读 contact.verify_flag,Names::is_verified 封装查询。
- q_sessions / q_unread / q_history / q_new_messages / q_stats 输出
  新增 chat_type 字段,is_group 保留向后兼容并统一由 chat_type 派生。
- wx unread 新增 --filter,clap value_parser 限制可选值为
  all / private / group / official / folded,逗号分隔多选,默认 all。
  例:wx unread --filter private,group 可过滤公众号与折叠入口。
- SKILL.md / README.md 补充新字段与用法说明。
- .gitignore 补 target/(Rust 项目标配)。

性能:默认 wx unread 的 SQL 与改动前相同(保留 LIMIT)。仅当传入
--filter 时改为全表扫再 Rust 侧过滤,否则 SQL LIMIT 会先把匹配
filter 的条目截断导致漏召。
2026-04-18 01:59:35 +08:00
jackwener bfb7048cf0 fix: bind CLI --version to crate version (credit: @leeguooooo #4) 2026-04-18 01:55:37 +08:00
jackwener c564438994 chore: bump version to 0.1.8 2026-04-18 01:50:25 +08:00
jackwener e44990ba01 fix: drop privileges after key scan to avoid root-owned ~/.wx-cli/ (#7 #8)
Root cause: `wx init` does two conceptually-separate things in one
privileged process: (1) scan WeChat memory for keys (needs root) and
(2) write ~/.wx-cli/{all_keys,config}.json (needs only user). When
run under sudo, the files inherit root ownership, so later the daemon
(forked as the user) can't create daemon.sock/log/pid → silent 15s
timeout.

Also: all_keys.json is the raw AES key; 0644 leaked it to every user
on the system.

Fix in init.rs: after the scan completes, immediately setgid+setuid
back to \$SUDO_UID/\$SUDO_GID and set umask 0o077 before any file I/O.
Files are then created as the real user with 0600 by default. Migrate
old broken installs by chown+chmod-recursive before the setuid call.

Fix in transport.rs: pre-check that ~/.wx-cli/ is writable before
spawning daemon; on EACCES print a clear "sudo chown -R ..." hint
instead of the useless "daemon 启动超时" message.
2026-04-18 01:48:42 +08:00
jackwener ae74072b3f docs: add Windows cross-check setup and IPC same-library rule 2026-04-17 16:43:05 +08:00
jackwener 4e6907c5cc chore: bump version to 0.1.7 2026-04-17 16:42:02 +08:00
jackwener 6a2b23486a fix: client connects via interprocess on Windows, not OpenOptions
Server uses interprocess::local_socket, but client was using
std::fs::OpenOptions("\\.\pipe\wx-cli-daemon") which fails to
connect to pipes created by interprocess's tokio listener.

Use the same interprocess client API on both sides for consistency.

Verified with: cargo check --target x86_64-pc-windows-gnu (mingw-w64).
2026-04-17 16:41:32 +08:00
jakevin 33758671d6
Merge pull request #2 from leeguooooo/fix/skill-md-frontmatter
fix(skill): add YAML frontmatter so `skills` CLI can detect SKILL.md
2026-04-17 16:36:33 +08:00
jackwener fe71f1e9f8 chore: bump version to 0.1.6 2026-04-17 15:05:44 +08:00
jackwener 18daf5b22e fix: Windows init and daemon startup (issue #5)
Three related bugs caused "wx init" and daemon startup to fail on Windows:

1. init.rs: create ~/.wx-cli/ before writing all_keys.json (was created
   only before config.json, so first write failed with ENOENT)

2. transport.rs (Windows): daemon.log was always empty because stderr
   was never redirected, and log file open silently fell back to null
   when parent dir didn't exist. Now mirror the Unix version: create
   parent dir, try_clone to redirect both stdout and stderr.

3. server.rs (Windows): interprocess GenericNamespaced auto-prepends
   \\.\pipe\ on Windows. Passing the full path caused a double-prefixed
   pipe name that clients (using raw \\.\pipe\wx-cli-daemon) could
   never connect to, leading to the 15s startup timeout.
2026-04-17 14:01:04 +08:00
leeguooooo 34698faa65 fix(skill): add YAML frontmatter to SKILL.md so `skills` CLI can detect it
The `skills` CLI (https://github.com/openclaw/skills) requires a YAML
frontmatter block with `name` and `description` to recognize a SKILL.md
as a valid skill. The current file declares description as a Markdown
blockquote, which causes:

  $ npx skills add jackwener/wx-cli -g
  No valid skills found. Skills require a SKILL.md with name and description.

Switching to standard frontmatter makes installation work end-to-end.

Verified with `npx skills add . -l`:
  Found 1 skill
    wx-cli
2026-04-17 13:27:07 +09:00
jackwener 2c9df70d44 docs: emphasize YAML is more token-efficient, JSON for jq 2026-04-17 11:19:35 +08:00
jackwener 3473f47d1d docs: use --query instead of -q for clarity 2026-04-17 11:18:32 +08:00
jackwener e4bfc39c8f fix: improve task_for_pid error message and document codesign steps 2026-04-17 10:46:55 +08:00
jackwener 0e2711dcf8 chore: bump to 0.1.5, fix publish to skip already-published versions 2026-04-17 09:25:04 +08:00
jackwener 7c27a83340 fix: add missing wx.js launcher to git (was gitignored by global config) 2026-04-17 09:13:03 +08:00
jackwener a5de749f0a chore: bump version to 0.1.4 2026-04-17 00:41:01 +08:00
jackwener 69c7a5666c docs: add acknowledgment for ylytdeng/wechat-decrypt 2026-04-16 23:54:50 +08:00
jackwener 3eddfa0ffa fix: add permissions:write, fix Windows copy to use PowerShell syntax 2026-04-16 23:49:00 +08:00
jackwener a2239c0dca ci: check linux only (windows needs MSVC tools, covered by build job) 2026-04-16 23:42:31 +08:00
jackwener 2170db93eb ci: remove arm64 from check job (no cross-compiler available) 2026-04-16 23:40:28 +08:00
jackwener ee1da2ffa6 docs: add CLAUDE.md and AGENTS.md with cross-platform check rules 2026-04-16 23:38:47 +08:00
jackwener d8f4c6e87d fix: replace macOS-only libc::__error() with std::io::Error::last_os_error() 2026-04-16 23:35:30 +08:00
jackwener 3413f6c8f4 fix: move anyhow/chrono/dirs/md5/regex back to [dependencies] section 2026-04-16 23:31:41 +08:00
jackwener 2afea74eb9 ci: add cross-platform cargo check job before build 2026-04-16 23:26:08 +08:00
jackwener 6931dfc4cc chore: update Cargo.lock for v0.1.3 2026-04-16 23:25:02 +08:00
jackwener ad256288e1 chore: bump version to 0.1.3 2026-04-16 23:15:48 +08:00
jackwener 59dd6bfa24 fix: Windows build errors (handle_connection, creation_flags, mkdir)
- server.rs: add handle_connection_windows for named pipe connections
- transport.rs: import CommandExt trait for creation_flags on Windows
- release.yml: mkdir -p before binary copy to npm bin dirs
2026-04-16 23:14:58 +08:00
jackwener f9bca1f872 docs: add npx skills add instruction 2026-04-16 23:08:57 +08:00
jackwener 42e5ac38c3 docs: add SKILL.md for AI agent integration 2026-04-16 22:46:13 +08:00
jackwener 65c98e9736 chore: bump version to 0.1.2 2026-04-16 22:43:28 +08:00
jackwener e3518956af chore: rename npm packages to @jackwener scope 2026-04-16 22:41:47 +08:00
jackwener 47d17aeccf feat: npm wrapper + CI publish, fix README YAML/JSON description 2026-04-16 22:33:53 +08:00
jackwener 6cdc806642 chore: Apache-2.0 license, Windows support, install.ps1 2026-04-16 22:30:45 +08:00
jackwener 6d40c7f737 docs: 重写 README,优化结构和命令展示 2026-04-16 22:24:22 +08:00
jackwener df6e48af3e chore: add install.sh one-liner installer 2026-04-16 22:21:11 +08:00
jackwener 33b4249bd5 fix: 系统消息/撤回消息解析,补全消息类型格式化
- type 10000 (系统消息): 解析 <content> 标签,显示 [系统] 内容
- type 10002 (撤回): 解析 <content>,显示 [撤回] 内容
- type 34 (语音) / 43 (视频): 之前漏了,现在显示 [语音]/[视频]
- 避免 raw XML 出现在 history/watch 输出中
2026-04-16 17:22:54 +08:00
jackwener 7f869e7c3b fix: 深度 review 修复 10 个 bug/问题
Critical & High:
- daemon 日志:启动时将 stdout/stderr 重定向到 ~/.wx-cli/daemon.log
  而非 /dev/null,使 wx daemon logs 真正可用
- q_history 找不到聊天时改为 bail! 而非 ok:true+error 字段,
  避免 CLI 静默返回空输出
- init 写 config.json 默认路径改为 ~/.wx-cli/config.json,
  避免写入系统 bin 目录(/usr/local/bin/config.json)
- LIKE 通配符:搜索关键词中的 %/_/\ 现在正确转义
- WAL 路径:改用 OsString.push 拼接 "-wal" 后缀,
  避免 display() 在非 UTF-8 路径上失效
- cmd_stop:检查 kill() 返回值,ESRCH 时给出明确提示

Performance & Code quality:
- full_decrypt:改为流式逐页读写,峰值内存从 2×文件大小降为 O(1)
- Regex:msg_table_re() 用 OnceLock 静态编译,避免热路径重复编译
- mtime_nanos:消除 daemon/mod.rs 与 cache.rs 的重复定义
- use super::super::cli::transport → use super::transport
- 删除未使用的 save_config、Request::to_json_line 死代码
2026-04-16 17:07:15 +08:00
jackwener dfd020a2b9 fix: 引用消息 XML 转义解析 + 搜索容错跳过 corrupt DB
- 引用消息(type=57)的 ref_content 可能是 HTML 转义的 XML,新增
  unescape_html() 先反转义,再递归调用 parse_appmsg 解析嵌套结构
- 全局搜索遍历 msg_db_keys 时,单个 DB open/query 失败改为 eprintln+continue
  而非传播错误,避免一个 corrupt cache 导致整个搜索失败
- search_in_table 失败也改为 skip 而非 abort
2026-04-16 16:48:59 +08:00
jackwener a6fa82adb3 chore: bump version to 0.1.1 2026-04-16 16:18:04 +08:00
jackwener 2fd864b85d fix: 修复消息内容为空的 bug(TEXT/BLOB 兼容),过滤 fts/resource DB,超时调为 120s 2026-04-16 16:16:41 +08:00
jackwener 3e7b4ed8ee fix: 目录和 pipe 名统一改为 wx-cli(原 wechat-cli) 2026-04-16 15:49:35 +08:00
jackwener 6e599dbe33 docs: README 安装方式增加 cargo install wx-cli 2026-04-16 15:29:39 +08:00
jackwener fa7c99f159 chore: 补充 crates.io 发布元数据,包名改为 wx-cli,添加 MIT 许可证 2026-04-16 15:28:59 +08:00
jackwener 79a653b9c6 docs: 重写 README,对齐 Rust 单二进制实现 2026-04-16 15:23:43 +08:00