Commit Graph

89 Commits

Author SHA1 Message Date
Kagura ab44d9f542 fix(xiaoyuzhou): migrate from broken SSR scraping to authenticated API (fixes #1023) (#1059)
* fix(xiaoyuzhou): migrate from broken SSR scraping to authenticated API (fixes #1023)

Xiaoyuzhou removed SSR rendering — /podcast/<id> and /episode/<id> pages
now return 404, breaking fetchPageProps() which scraped __NEXT_DATA__.

Migrate podcast, podcast-episodes, episode, and download commands to use
the existing authenticated API client (requestXiaoyuzhouJson) that
transcript.js already uses successfully.

Changes:
- podcast.js: use /v1/podcast/get API endpoint
- podcast-episodes.js: use /v1/podcast/listEpisode API endpoint
- episode.js: use /v1/episode/get API endpoint
- download.js: use /v1/episode/get API endpoint
- utils.js: remove unused fetchPageProps, keep format helpers
- Update all affected tests (download.test.js, utils.test.js)
- Change strategy from PUBLIC to LOCAL (requires credentials)

* fix(xiaoyuzhou): align local strategy contract

* fix(xiaoyuzhou): align local api metadata

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-16 23:15:40 +08:00
jakevin 4ebada6b99 docs: add adapter docs for eastmoney, tdx, ths (#1061)
#1025 merged hot-rank adapters for eastmoney/tdx/ths but the
accompanying docs were missing. This breaks the Doc Check CI
workflow on every PR ('--strict' mode, exits non-zero when
`scripts/check-doc-coverage.sh` finds adapters without docs),
blocking merges across the board.

Adds a doc page per adapter, registers them in the adapters
index table, and adds sidebar entries in the VitePress config.
2026-04-16 22:57:03 +08:00
Cosmostima 44b4107f36 feat(nowcoder): add 牛客网 adapter with 16 commands (#1036)
* feat(nowcoder): add 牛客网 adapter with 16 commands

Add adapters for Nowcoder (牛客网), China's leading tech job-seeking
and interview preparation community.

- 7 Public commands: hot, trending, topics, recommend, creators, companies, jobs
- 9 Cookie commands: search, suggest, experience, referral, salary, papers, practice, notifications, detail
- All post-list commands include id field for drill-down to detail
- Documentation: adapter page, index table, sidebar entry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(nowcoder): register adapter and document usage

---------

Co-authored-by: tima <tima@cosmos-macmini.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-15 22:51:55 +08:00
Howard 44147e54c1 feat(youtube): add feed, history, watch-later, subscriptions, playlist, like, unlike, subscribe, unsubscribe (#1029)
* feat(youtube): add feed, history, watch-later, subscriptions, playlist, like, unlike, subscribe, unsubscribe

* fix(youtube): normalize subscriptions channel fields

* docs(skills): add youtube command coverage

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-15 12:43:27 +08:00
槑囿脑袋 677e37b7a4 feat(xiaoyuzhou): add episode download and transcript support (#1031)
* feat(xiaoyuzhou): add episode audio download

* feat(xiaoyuzhou): add transcript download support

* docs(xiaoyuzhou): clarify credential file requirement

* fix(xiaoyuzhou): remove env credential fallback
2026-04-15 12:35:27 +08:00
flizzywine ba3a674d7b feat(grok): add image command for grok.com image generation (#906)
* feat(grok): add image command for grok.com image generation

Add `opencli grok image <prompt>` which submits a prompt via the existing
grok.com browser session and returns the generated image URLs from the
latest assistant bubble.

Because assets.grok.com URLs are gated by Cloudflare and cannot be
downloaded with a plain HTTP client, the --out flag triggers an in-page
fetch(credentials: 'include') so the browser session's cookies and
referer are attached, then writes the decoded blob to disk.

Flags:
- --new       start a fresh chat before sending
- --timeout   max seconds to wait for the image (default 240)
- --count     minimum number of images to wait for before returning
- --out       directory to save downloaded images

Ships with unit tests for the helpers (isOnGrok, normalizeBooleanFlag,
dedupeBySrc, imagesSignature, extFromContentType, buildFilename).

* fix(grok): harden image composer and bubble detection

* fix(grok): harden image flow and docs

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-14 20:42:43 +08:00
warkcod 0e38fd8c37 Feat/douban book subject (#993)
* chore: ignore local worktrees

* feat(douban): support book subject details
2026-04-14 20:41:14 +08:00
AstroHan cd48917a39 fix(xiaohongshu): require signed note URLs (#996)
* fix(xiaohongshu): require signed note urls

* chore: drop generated manifest from pr
2026-04-14 20:40:58 +08:00
CissiBot 45d6f5b09f feat(uiverse): add Uiverse code and preview adapters (#1000)
* feat(uiverse): add code and preview adapters

* fix(manifest): register uiverse commands

* docs(uiverse): add usage examples

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-14 20:38:38 +08:00
XavierCai 3ebc46f978 feat(bilibili): favorite command supports specifying fid (#1013)
* feat(bilibili): favorite command supports specifying fid

* fix(bilibili): sync favorite help and docs contract

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-14 20:37:54 +08:00
jakevin 847c8317b6 fix(twitter): register lists command in manifest (#1011) 2026-04-14 10:37:34 +08:00
SherlockSalvatore 2aee4caa10 feat(mubu): add Mubu adapter with 5 commands (#964)
* feat(mubu): add mubu (mubu.com) adapter with 5 commands

Commands: doc, docs, notes, recent, search.

- Uses COOKIE strategy; API calls via in-page XHR with Jwt-Token
  from localStorage (matches the web app's own mechanism).
- Renders node trees to Markdown (default) or plain text;
  supports tables, tasks, images, emoji, mentions, strikethrough,
  underline, and nested structures.
- notes supports flexible time ranges: single day, month, year,
  or custom --from/--to spans, plus a --list overview mode.
- search returns full-text matches with hit count and snippets
  for both folders and documents.

* fix(manifest): register mubu commands in runtime manifest

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-13 16:50:32 +08:00
jakevin c42b040af4 Rename chatgpt adapters: desktop → chatgpt-app, web → chatgpt (#989)
* Rename chatgpt adapters: desktop → chatgpt-app, web → chatgpt

Aligns with existing `-app` suffix convention (discord-app, doubao-app):
- clis/chatgpt/ (desktop, AppleScript) → clis/chatgpt-app/
- clis/chatgptweb/ (browser, chatgpt.com) → clis/chatgpt/
- electron-apps.ts: chatgpt → chatgpt-app
- Updated all docs and README references

Closes #283

* Fix review findings: update cli-manifest.json and skill docs

- cli-manifest.json: update site/modulePath/sourceFile from chatgpt to chatgpt-app
- skills/opencli-usage/desktop.md: update commands from chatgpt to chatgpt-app
2026-04-13 14:33:32 +08:00
Tony Simons 4d1fa8a6e2 feat(clis/chatgptweb): add ChatGPT web image generation command (#973)
* feat(clis/chatgptweb): add ChatGPT web image generation command

Add `opencli chatgptweb image` command that generates images using
ChatGPT web (GPT-4o image generation) and saves them locally.

Features:
- Navigates to chatgpt.com/new with full page reload to ensure clean state
- Uses Playwright's page.type() for reliable text input in TipTap editor
- Closes sidebar if open (covers the chat composer on some layouts)
- Polls for response completion (handles thinking/throttling states)
- Extracts generated images from DOM (backend-api/estuary/content URLs)
- Downloads and saves as PNG/JPEG files to user-specified directory
- Supports --op for output directory and --sd to skip download

Files:
- clis/chatgptweb/image.js: CLI command definition
- clis/chatgptweb/utils.js: DOM helpers, send/wait/export functions

Works cross-platform (Linux/macOS/Windows) via OpenCLI browser automation.

* fix(chatgptweb): stabilize image generation flow

* docs(chatgptweb): add browser adapter guide

---------

Co-authored-by: Tony Simons <tony@tonysimons.dev>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-12 21:24:03 +08:00
Harvey Yue aa47de726d feat(bilibili): add feed-detail and enhance feed command (#974)
* feat(bilibili): add feed-detail and enhance feed command

* docs: add binance adapter documentation

* docs: add feed-detail command to bilibili docs

* docs: sync bilibili adapter contract for feed-detail

* docs: add ke adapter page for doc coverage

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-12 21:19:12 +08:00
Ivan Xia 20e024a001 feat(maimai): add talent search with multi-dimensional filters (#977)
* feat(maimai): add talent search with multi-dimensional filters

Add maimai.cn talent search adapter with support for:
- Keyword search (query)
- Company filtering (multiple companies supported)
- School filtering (with 985/211 options)
- Location filtering (province/city)
- Work experience and education level filters
- Industry and position filters
- Direct chat availability
- Sort by relevance, activity, work years, or education

Features:
- Reuses Chrome login session for authentication
- Extracts candidate info: name, job title, company, work history
- Shows work years, education, age, active status
- Displays skill tags and mutual friends count

* fix docs and strategy for maimai adapter

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-12 16:16:55 +08:00
Alex Yang 01957bf654 feat(discord-app): add delete command to remove a message by ID (#976)
* feat(discord-app): add delete command to remove a message by ID

Adds a new `delete` command for the discord-app CLI that deletes a
message in the active channel by its snowflake ID. Uses the UI strategy
to hover the message, open the "More" menu, click "Delete Message", and
confirm the deletion dialog.

* docs: add binance adapter doc and update discord doc with delete command
2026-04-12 16:07:14 +08:00
iiilin b0a019121e feat(weibo): support for-you and following feed types (#959)
* feat(weibo): support for-you and following feed types

* docs: clarify weibo feed types

---------

Co-authored-by: iiilin <19162130+iiilin@users.noreply.github.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-11 22:04:01 +08:00
GanFanNewOrder 606bc59f7b fix(jianyu): stabilize search and add detail extraction contract (#912)
* fix(jianyu): stabilize search and add detail extraction contract

* fix(jianyu): require query evidence for search results

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-09 21:28:20 +08:00
AstroHan caebede7c2 fix: repair baseline main ci checks (#901) 2026-04-09 12:19:44 +08:00
ziiiiiwang 2883620ba2 Feat : add Gitee adapters and docs (#845)
* feat: add gitee adapters and docs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: compact gitee trending table output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: add gitee adapter documentation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(gitee): avoid faking user index values

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-09 01:29:48 +08:00
X 61b247f90c feat(quark): add Quark Drive adapter (#858)
* feat(quark): add Quark Drive adapter (ls, mkdir, mv, rename, rm, save, share-tree)

Browser-based adapter for Quark Cloud Drive (pan.quark.cn) using cookie
strategy. Supports file browsing, folder management, and saving shared
files with task polling for async operations.

* fix(quark): address review feedback on adapter correctness and docs

- ls: fix depth off-by-one (default 0 now lists target folder only)
- save/mv: report success only after pollTask confirms completion; throw on timeout
- save/mv: reject combining --to and --to-fid instead of silently preferring --to-fid
- utils: check content-type before calling r.json() to handle non-JSON responses gracefully
- tests: add quark graceful auth-failure E2E cases for all 7 commands
- docs: add Browser Bridge extension to prerequisites; fix mkdir --parent example; expand command table with positional args; add Notes section explaining stoken flow

* fix(quark): map auth failures and cover utils

* fix(quark): reuse auth mapping for share-tree

---------

Co-authored-by: xzy <xzy@mbp-m5.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-08 00:28:59 +08:00
AstroHan ce559da7fc feat(zhihu): add interaction commands (#868)
* feat(zhihu): add interaction commands

* fix(zhihu): tighten interaction target anchoring

* fix(zhihu): scope comment authorship proof

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-07 23:17:51 +08:00
GanFanNewOrder 9c5571eba3 feat(jianyu): add search adapter for bid notices (#849)
* feat(jianyu): add search adapter for bid notices

* docs(jianyu): add adapter usage guide

* docs(jianyu): neutralize examples and add adapter guide

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
2026-04-07 19:20:00 +08:00
tiaot33 5553300597 feat(linux-do): split topic content into a dedicated command (#821)
* feat(linux-do): split topic content into a dedicated command

Move the old main-post path out of linux-do topic so topic stays a summarized first-page reader while topic-content becomes the Markdown-focused entrypoint for full post bodies.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(linux-do): update topic content handling to include YAML front matter

* fix(linux-do): update default output format to plain for topic-content rendering

* fix(linux-do): replace js-yaml with inline YAML serialization for topic-content

Adapters must only import node builtins, relative modules, or opencli
public APIs. Hand-roll the simple front matter serialization to remove
the third-party js-yaml dependency.

* fix(linux-do): refine YAML quoting to only escape colons followed by space

Colons in URLs (e.g. https://) are valid unquoted YAML values. Only
quote when a colon is followed by a space or appears at end of line.

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-06 02:59:56 +08:00
BruceLoveDecimal d2ae28786c feat:add 1688 assets downloadable (#820)
* feat:add 1688 assets downloadable

* fix: remove duplicate visitedRoots declaration and fix normalizeMediaUrl re-export

- Remove unused outer `visitedRoots` variable in scriptToReadAssets()
- Move normalizeMediaUrl test to import from shared.ts where it's defined
- Remove unused normalizeMediaUrl import from assets.ts

---------

Co-authored-by: 刘启灏 <liuqihao@liuqihaodeMacBook-Pro.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-06 01:59:39 +08:00
jakevin ab58aa4098 fix(docs): update outdated paths and command lists across all docs (#787)
- Replace 140 instances of `src/clis/` → `clis/` across 12 doc files
  (path changed after repo restructure)
- Remove non-command `rpc` and `rankings` from notebooklm/amazon
  command lists in README, README.zh-CN, SKILL.md, and adapters index
  (these are internal utility modules, not user-facing commands)
- Add `deep-research` and `deep-research-result` to gemini adapter doc
- Add `movers-shakers` and `new-releases` to amazon adapter doc
- Update notebooklm doc examples to use canonical commands instead of
  deprecated aliases (`metadata` → `get`, `notes-list` → `note-list`)
- Bump SKILL.md version to 1.6.3
2026-04-05 03:53:52 +08:00
kevin.zhang 8bd36aaa37 fix(hupu): add mentions command (#757)
* feat(hupu): add hupu cli adapter

* fix(hupu): prevent detail from returning the wrong thread

* refactor: deduplicate shared utilities in hupu adapter

- Merge postHupuJson and postHupuReplyJson into single function with mode parameter
- Move stripHtml and decodeHtmlEntities to utils.ts, remove duplicate definitions

* fix(hupu): add mentions command

* fix: move mentions.ts to clis/hupu/, remove src/clis/hupu duplicates

Post PR #782 restructure: adapter files live at root clis/, not src/clis/.

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-05 03:26:40 +08:00
Xule Lin d2051cdab7 feat(lesswrong): add LessWrong adapter (#773)
* feat(lesswrong): add LessWrong adapter

15 commands for the LessWrong rationality and AI alignment community:
- Post listings: curated, frontpage, new, top, top-week/month/year
- Content: read (full post), comments, shortform (quick takes)
- Discovery: tag, tags, sequences
- Users: user (profile), user-posts

All commands use the public GraphQL API (no browser required).
Time-filtered views use the `after` date parameter.
Tag lookup resolves slugs to IDs via the `tagBySlug` view.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: move lesswrong adapter to clis/ (post PR #782 restructure)

New adapter files were created at src/clis/lesswrong/ but PR #782 moved
all adapters to root clis/. Move to correct location.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-05 03:21:48 +08:00
kevin.zhang e0a66af0f0 feat(hupu): add Hupu adapter (#751)
* feat(hupu): add hupu cli adapter

* fix(hupu): prevent detail from returning the wrong thread

* refactor: deduplicate shared utilities in hupu adapter

- Merge postHupuJson and postHupuReplyJson into single function with mode parameter
- Move stripHtml and decodeHtmlEntities to utils.ts, remove duplicate definitions

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-04 16:03:14 +08:00
yulin7645 6364934423 feat(xiaoe): add 小鹅通 (Xiaoe-tech) student platform adapter (#617)
* feat(xiaoe): add 小鹅通 (Xiaoe-tech) student platform adapter

Add 5 YAML adapters for 小鹅通 (xiaoe-tech.com), the leading Chinese
online education platform:

- courses: list purchased courses with URLs and shop names
- detail: course info (name, price, user count, shop)
- catalog: full course outline supporting normal courses (type 50),
  columns (type 6), and big columns (type 8)
- play-url: get M3U8 play URL via direct API for video courses,
  and Vue component tree search + Performance API polling for
  live replay courses
- content: extract rich-text page content as plain text

Technical notes:
- Strategy: cookie (reuses Chrome login session)
- Framework: Vue 2 + Vuex Store (SPA)
- Video courses use a two-step API chain:
  detail_info.get → play_sign → getPlayUrl → M3U8
- Live replays use Performance API + Vue data tree polling
- Catalog expands chapters via Vue component method getSecitonList()
- Supports multiple stores (cross-domain cookie sharing via
  study.xiaoe-tech.com)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* review: stop truncating xiaoe content

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-04 15:54:14 +08:00
yichuanzhao99-ctrl 8eefa3b1c9 增加新浪财经热搜股票榜 (#736)
* 增加新浪财经热搜股票榜

* fix: address review issues in stock-rank adapter

- Fix string interpolation injection: use JSON.stringify for market param
- Add choices validation for market arg (cn/hk/us/wh/ft)
- Normalize column names to lowercase (rank/name/symbol/market/price/change/url)
- Add navigateBefore: false to avoid redundant navigation
- Add null safety on tabEl with optional chaining
- Remove unused waitForElement helper and unnecessary await on querySelectorAll
- Remove unrelated ?from=opencli tracking change from rolling-news.ts
- Remove ?from=opencli tracking from stock-rank URLs

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-04 15:16:05 +08:00
GanFanNewOrder 81de69be3a feat(1688): add browser adapter and docs (#650)
* feat(1688): add browser adapter and docs

* fix(1688): retry alternate store seed offers

* feat(1688): harden adapter contracts and search pagination

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
2026-04-04 14:45:32 +08:00
tiaot33 f377ec000c feat(元宝): add browser adapter and docs (#693)
* feat(yuanbao): add browser adapter and docs

* refactor(yuanbao): normalize adapter failures to CliError

* refactor: extract shared yuanbao helpers to reduce duplication

Move isOnYuanbao, ensureYuanbaoPage, hasLoginGate, authRequired,
and IS_VISIBLE_JS to shared.ts. This eliminates identical copies
across ask.ts and new.ts, reducing correctness risk when modifying
shared logic.

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-03 17:03:48 +08:00
BruceLoveDecimal 0ce46b15bb feat:add xianyu (#696)
* feat:add xianyu

feat:add xianyu

feat:add xianyu

* chore:add xianyu docs

* fix:update xianyu after review

---------

Co-authored-by: 刘启灏 <liuqihao@liuqihaodeMacBook-Pro.local>
2026-04-03 12:30:28 +08:00
jakevin 706e01dbca docs: fix outdated adapter counts, missing commands and adapters (#704)
* docs: fix outdated adapter counts, missing commands, and absent adapters

- Update version 1.6.0 → 1.6.1 in skills/opencli-usage/SKILL.md
- Update site count 70+ → 73+ across README.md, README.zh-CN.md,
  docs/comparison.md
- Remove non-existent adapters (kimi, deepseek, qwen) from SKILL.md
- Add missing commands for xiaohongshu (+note, comments, download,
  publish), weibo (+search, feed, user, me, post, comments),
  jike (+post, topic, user), linux-do (+hot, latest, category),
  doubao (+detail, history, meeting-summary, meeting-transcript),
  weread (+notebooks), chatgpt (+model), wikipedia (+random, trending),
  stackoverflow (+unanswered), producthunt (fix command list)
- Add entirely missing adapters: band, zsxq, bluesky, douyin, 36kr,
  ones, tieba, gemini, notebooklm, imdb, spotify, paperreview
- Update docs/adapters/index.md with same fixes
- Add opencli-operate to Related Skills section

* docs: second-pass audit fixes — deeper inconsistencies

Skills sub-files (browser.md, public-api.md):
- Remove phantom kimi/deepseek/qwen adapters (no src/clis/ dirs)
- Replace with real gemini and notebooklm sections
- Add missing weibo commands (search, feed, user, me, post, comments)
- Add missing xiaohongshu commands (note, comments, download, publish)
- Add missing doubao commands (detail, history, meeting-summary, meeting-transcript)
- Add 7 entirely missing adapter sections: bluesky, douyin, band, zsxq,
  tieba, 36kr, ones
- Fix producthunt: remove non-existent week/month/search, add hot/browse/posts
- Add wikipedia random and trending

SKILL.md command table:
- Add twitter `likes`, xueqiu `comments`, douban `movie-hot`/`book-hot`
- Add entirely missing `amazon` adapter
- Add linux-do `latest`
- Remove producthunt non-existent `search`

Individual adapter docs:
- docs/adapters/browser/weibo.md: add 5 missing commands
- docs/adapters/browser/doubao.md: add 4 missing commands
- docs/adapters/browser/wikipedia.md: add random and trending
- docs/adapters/browser/36kr.md: fix contradictory prerequisites
- docs/adapters/index.md: add twitter `likes`
- docs/developer/contributing.md: add missing `positional: true`
- package.json: fix description to include "Electron App"
2026-04-03 01:05:47 +08:00
jakevin fe82b3882f docs: update outdated adapter counts, operate commands, and skill references (#701)
- Update adapter count from 50+/60+/66+ to 70+ across all docs (actual: 74 sites)
- Add missing operate commands (eval, network, init, verify) to README
- Add opencli-operate skill to Install AI Skills section in both READMEs
- Replace outdated "Playwright MCP Bridge" with "Browser Bridge" in doubao docs
2026-04-02 23:32:36 +08:00
fii6 abd46bccba feat(gemini): add Gemini web adapter with minimal output (#619)
* feat(gemini): add web adapter with minimal output

* fix(gemini): use defaultFormat for minimal output

* fix(gemini): preserve full transcript responses

* docs(gemini): add browser adapter guide

* review: wire gemini into adapter indexes

---------

Co-authored-by: fii6 <246637913+fii6@users.noreply.github.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-02 13:39:35 +08:00
GanFanNewOrder d721eb6c6c feat(amazon): add browser adapter and docs (#659)
* feat(amazon): add browser adapter and docs

* review: wire amazon into discovery docs

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-02 13:32:23 +08:00
jakevin 773178345d refactor: remove bind-current, restore owned-only browser automation model (#664)
* fix(notebooklm): remove bind-current workflow

* fix: relax notebook ID check in open.ts and clean up idle timeout test

- open.ts: only throw when page kind is not 'notebook'; log a warning
  instead of throwing when the notebook ID doesn't match exactly
- background.test.ts: remove unused tabs[1] setup in idle timeout test
  that was leftover from borrowed-session era

* build: rebuild extension dist after bind-current removal
2026-04-01 23:23:48 +08:00
muqiao215 0204dbb018 feat(notebooklm): add read commands and compatibility layer (#622)
* feat(notebooklm): add read commands and compatibility layer

* review: trim notebooklm artifacts and sync docs

---------

Co-authored-by: qiaoqiao147 <camtup044@gmail.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-31 13:19:47 +08:00
ahahaha d0803857f1 feat(xiaohongshu): add note command and nested reply support for comments (#599)
* feat(xiaohongshu): add note command and nested reply support for comments

Add `xiaohongshu note` command to read full note content (title, author,
description, engagement metrics, tags) from public note pages.

Enhance `xiaohongshu comments` with `--with-replies` flag to extract
nested replies (楼中楼), including reply_to attribution and per-reply
like counts. Limit logic counts only top-level comments so replies
are included for free.

Extract shared `parseNoteId` into side-effect-free `note-helpers.ts`
to avoid cross-module command registration leakage.

Normalize non-numeric engagement placeholders ("赞"/"收藏"/"评论")
to "0" for zero-count notes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(xiaohongshu): add note and comments --with-replies to adapter docs

Update xiaohongshu adapter documentation and README command table
to reflect the new note command and enhanced comments with nested
reply support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(xiaohongshu): fix download example to show both note-id and url

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(xiaohongshu): expand nested reply threads before scraping

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-30 23:29:30 +08:00
AstroHan cf79ec5c23 feat(xueqiu): add comments command (#587)
* feat: add xueqiu comments command

* docs(xueqiu): add comments command docs

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-30 01:22:44 +08:00
Zhangchen 8c00ad9f02 feat(browser): add ONES adapter support for tasks and worklog commands (#386)
* feat(browser): add ONES adapter support for tasks and worklog commands
Add ONES auth/session commands, task listing/details utilities, and worklog operations, with related docs and helper utilities.

* fix(ones): harden worklog and task-list adapter behavior

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-30 01:06:38 +08:00
AstroHan a32b65be4a feat: add Tieba browser adapters in TypeScript (#581)
* feat(tieba): add browser adapters for hot posts search and read

* fix(tieba): stabilize search and e2e coverage

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-29 22:39:26 +08:00
jakevin f8e9b08223 fix(zsxq): require active group context (#579)
* fix(zsxq): require active group context

* docs(zsxq): add adapter guide
2026-03-29 17:29:36 +08:00
bhutano 1ae1c82c4a feat(spotify): add Spotify playback adapter (#560)
* feat(spotify): add Spotify playback adapter

Adds a new adapter for controlling Spotify via the official Web API.
Uses Strategy.PUBLIC with OAuth2 — no browser session required.

Commands: auth, status, play, pause, next, prev, volume, search, queue, shuffle, repeat.
Credentials are loaded from ~/.opencli/spotify.env or environment variables.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): rename index.ts → spotify.ts and fix CliError calls

- Renamed src/clis/spotify/index.ts to spotify.ts so the build-manifest
  picks it up (index.js is intentionally excluded from manifest scanning)
- Fixed 4 CliError calls: constructor now requires (code, message, hint?)
  so each throw now passes an appropriate error code as first argument

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): fix token refresh corruption, env parse, null guards, validation

- refreshAccessToken: check res.ok before parsing; construct Tokens object
  directly instead of mutating loadTokens() result to avoid writing
  undefined/NaN on Spotify error responses; preserve existing refresh_token
  when Spotify omits it from the response
- loadEnv: split on first '=' only so values containing '=' are preserved
- SCOPES: remove write/library/top scopes not used by any command
- status: guard against data.item being null (active device but no track)
- volume: validate 0-100 range before API call
- auth: check tokenRes.ok on initial token exchange; add server.on('error')
  handler for EADDRINUSE; add 5-minute timeout with clearTimeout on close

* feat(postinstall): auto-create ~/.opencli/spotify.env template on install

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): guard null progress, podcast items, missing tracks data, corrupted tokens, invalid search limit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): improve missing credentials error with step-by-step guidance

* fix(spotify): harden setup and add docs coverage

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-29 17:28:37 +08:00
康厚超 440c001a20 feat(band): add Band.us adapter — bands, posts, mentions, post commands (#532)
* feat(band): add bands, posts, and mentions commands for band.us

- bands: lists all Bands via get_band_list_with_filter intercept
- posts: lists posts from a Band via get_posts_and_announcements intercept
- mentions: shows @mention notifications via get_news intercept

All use Strategy.INTERCEPT since band.us API requires an HMAC md header
generated by its own JS. SPA navigation to /band/{no}/post triggers the
band list and posts APIs; bell + @メンション tab click triggers mentions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(band): clean up all three band adapters

- Fix doc comments: Band uses XHR not fetch; clarify INTERCEPT rationale
- bands: replace for-loop with flatMap; explain why band page nav is needed
- posts: remove item.post ?? item fallback (API always wraps in post); rename
  finalRequests → requests for consistency; extract stripBandTags helper
- mentions: remove redundant ?? defaults (args have defaults defined); fix
  unreadOnly bug (was not applied to post/comment modes); consolidate Band tag
  stripping to single regex; cast kwargs types directly instead of converting;
  add comments explaining last-response strategy and 'referred' filter flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/posts): handle mixed post/announcement items from API

get_posts_and_announcements returns both regular posts and announcements
that have different shapes — some lack post_no and wrap differently.
Restore item.post ?? item fallback and filter out items with no resolvable
identifier to prevent undefined in URLs and empty rows in output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(band): add post command — full post export with comments and photo download

Exports the complete content of a single Band post:
- Post body (with Band markup tags stripped)
- All comments in chronological order
- Photo URLs shown inline, or downloaded with --output <dir>

Uses Strategy.INTERCEPT with a broad 'band.us' pattern to capture both the
batch request (embedding get_post) and get_comments in one SPA navigation.
Responses are identified client-side by shape: batch_result array vs items
array with comment_id fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(band): replace XHR interception with direct DOM extraction

- bands, posts, post: navigate directly to target URL instead of home→SPA detour
- All three switch from Strategy.INTERCEPT to Strategy.COOKIE with navigateBefore: false
  (bands uses framework pre-nav to home; posts/post disable it and goto target directly)
- DOM extraction polls for specific content elements rather than fixed waits
- post: confirm selectors via browser inspection (a.text, time.time, .sCommentList,
  .sReplyList for nested replies); add --comments flag to skip comment fetch
- posts: extract from rendered post list DOM; correct comment item selector (div.cComment)
- Fix: post empty-result guard changed from && to handle null data safely
- Fix: photo download now checks HTTP status code before piping to avoid writing
  redirect HTML into image files
- Fix: mentions unread client-side filter skipped for 'mentioned' mode since
  server already filtered via 未確認のみ button click

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address code review feedback

- post: replace manual http/https download with shared downloadMedia utility
  (handles redirects, timeouts, stream errors correctly)
- post: fix photo URL resolution to use location.href as base, handling
  protocol-relative and relative URLs without throwing
- post: switch to node:-prefixed imports per repo convention
- post/posts: remove redundant ArgumentError guards — framework already
  validates required args before func() is called
- mentions: INTERCEPT strategy is intentional (Band HMAC prevents DOM-only
  approach for notifications; update PR description to clarify)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address second round of code review feedback

- bands: tighten href selector to /band/{id}(?:/post)?$ so feed/post-detail
  links are excluded; only sidebar navigation links match
- mentions: replace fixed page.wait(2) sleeps with polling on
  getInterceptedRequests() — waits up to 8 s per action, exits as soon
  as the expected number of captures arrives (avoids flakiness on slow XHR)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): fix selector bugs found during testing

- bands: use a.bandCover._link + p.uriText + span.member em selectors
  (previous a[href*="/band/"] + .bandName combo leaked "メンバー" text)
- posts: use article.cContentsCard._postMainWrap + span.count selectors
  (previous li._postListItem selector matched nothing; DOM changed)
- mentions: fix page.wait(500) → page.wait(0.5) (was waiting 500s not ms);
  use timestamp-suffixed URL to force fresh page load each run so the
  notification panel is closed; fix get_news vs get_news_count capture
  ambiguity with result_data.news check; replace cumulative waitForCaptures
  with waitForOneCapture (getInterceptedRequests clears array on each call)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/mentions): use CSS class selector for bell button instead of locale-dependent text match

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address third round of code review feedback

- post: pass browser cookies to downloadMedia so Band's login-protected
  photo URLs don't fail with 401/403
- post: include photos.length in empty-result guard so photo-only posts
  are not falsely reported as not found
- mentions: accumulate captures across poll iterations so get_news_count
  responses don't cause early exit before the real get_news arrives
- mentions: update docstring to match actual implementation (client-side
  filtering, no tab-click)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address fourth round of code review feedback

- mentions: fail fast with a clear error when bell button is not found,
  instead of silently no-op and waiting 8s before EmptyResultError
- post: use shared formatCookieHeader() instead of manual cookie string
  construction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address fifth round of code review feedback

- mentions: replace fixed page.wait(2) with polling for bell button
  readiness (up to 10s), eliminating the fixed sleep and fail-fast
  when the selector is missing
- mentions: add explicit !newsReq guard with a clear error message when
  get_news capture times out, instead of falling through to a misleading
  "No notifications found"
- posts: skip posts with no permalink href instead of emitting a bogus
  'https://www.band.us' URL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address sixth round of code review feedback

- post: only send Band cookies to *.band.us photo URLs; third-party CDN
  URLs are downloaded without cookies to avoid cross-domain cookie leakage
- bands: strip non-digit chars before parseInt so member counts like
  "1,234" parse correctly
- posts: same fix for comment counts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address seventh round of code review feedback

- posts: check limit before push so --limit 0 returns empty result
- post: indent replies proportionally by depth ('  '.repeat(depth))
  so multi-level threads remain readable in table output

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/bands): anchor href regex to prevent matching post-detail URLs

Pattern now requires /band/{id} or /band/{id}/post (with optional trailing
slash) so deeper paths like /band/{id}/post/{postNo} are excluded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address ninth round of code review feedback

- mentions: guard bell click with a boolean return so a disappearing
  element throws a clear EmptyResultError instead of a raw TypeError
- post: wait for comment list container instead of first .cComment so
  posts with zero comments don't incur a fixed 6s delay

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): use page.getCookies() for login detection across all commands

Replaces document.cookie.includes('band_session') with
page.getCookies({ domain: 'band.us' }) so login detection works even
if Band.us marks the session cookie as HttpOnly in the future.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address eleventh round of code review feedback

- mentions: replace EmptyResultError with SelectorError for missing/
  disappeared bell button — produces a clearer SELECTOR error code
- post: assign per-photo filenames using a global index across both
  download batches so band-hosted and CDN photos don't overwrite each other

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address twelfth round of code review feedback

- post: derive file extension from URL path and include in filename
  (e.g. photo_1.jpg) so downloaded photos have correct extensions
- posts: remove dead code guard (!url && !content) — url is always
  non-empty here since href-empty posts are already skipped above

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/post): use url-scoped getCookies for photo download auth

Domain-scoped getCookies may omit host-only cookies scoped to www.band.us;
using url: 'https://www.band.us' ensures all relevant cookies are included
in the auth header for Band-hosted photo downloads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(band): add adapter documentation and sidebar entry

Required by CI doc-check --strict: every adapter in src/clis/ must have
a corresponding docs/adapters/browser/*.md file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(e2e): wire band auth coverage into default matrix

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-29 17:19:26 +08:00
jakevin 5c655ee3c8 feat(sinafinance): rewrite stock as public API, no browser required (#563)
* feat(sinafinance): rewrite stock as public API adapter

Replace browser-based DOM scraping with direct Sina public APIs:
  suggest3.sinajs.cn — symbol search (GBK, no auth)
  hq.sinajs.cn       — real-time quote (GBK, no auth)

Strategy.PUBLIC, browser: false — no Chrome or login required.
Supports A股 (sh/sz), 港股 (hk prefix), 美股 (gb_ prefix).
US MarketCap parsed from hq field [12]; formatted as T/B/M.

* feat(exit-codes): add Unix-standard exit codes to all CliError types

Introduce EXIT_CODES constant table (sysexits.h conventions) and wire
exitCode into every CliError subclass so the process exit code reflects
the semantic type of failure:

  0   success (default)
  1   generic / unexpected error
  2   argument / usage error        (ArgumentError)
 66   empty result / not found      (EmptyResultError, SelectorError)
 69   service unavailable           (BrowserConnectError, AdapterLoadError)
 77   permission / auth required    (AuthRequiredError)
 78   configuration error           (ConfigError)
124   timeout                       (TimeoutError)
130   Ctrl-C / SIGINT               (unchanged, tui.ts)

resolveExitCode() in commanderAdapter.ts reads err.exitCode for typed
CliErrors, and falls back to pattern-matching message text for untyped
adapter errors (auth pattern → 77, not-found pattern → 66, else → 1).

Shell scripts can now distinguish error categories:
  opencli spotify status || echo "exit $?"   # 69 if browser not running
  opencli github issues --repo x 2>/dev/null; [ $? -eq 77 ] && opencli github auth

* review: regex escape sym, fix change precision, optimize suggest type param
2026-03-28 21:59:44 +08:00
yichuanzhao99-ctrl 0b15561025 添加新浪财经行情及滚动新闻抓取 (#546)
* 添加新浪财经行情及滚动新闻抓取

* review: fix injection vuln, dead code, typos, hardcoded waits

rolling-news:
- Remove dead dateToTimestampParams function and unused CliError import
- Fix column field name typo: clomn → column
- Replace page.wait(5) with selector-based wait
- Remove all commented-out code

stock:
- Fix P0 JS injection: use JSON.stringify() to safely embed args.key/market
- Add null guard for inputEl before calling .focus()
- waitForElement returns null instead of throwing on timeout
- Replace page.wait(5) with selector-based wait
- Extract MARKET_CN/HK/US as named constants
- Throw CliError on NOT_FOUND instead of silent empty return

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-28 21:46:33 +08:00