@zenalexa/unicli 0.219.0 → 0.220.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -9
- package/README.md +55 -249
- package/README.zh-CN.md +55 -249
- package/dist/adapters/1point3acres/forum.d.ts +58 -0
- package/dist/adapters/1point3acres/forum.d.ts.map +1 -0
- package/dist/adapters/1point3acres/forum.js +708 -0
- package/dist/adapters/1point3acres/forum.js.map +1 -0
- package/dist/adapters/aibase/news.d.ts +21 -0
- package/dist/adapters/aibase/news.d.ts.map +1 -0
- package/dist/adapters/aibase/news.js +96 -0
- package/dist/adapters/aibase/news.js.map +1 -0
- package/dist/adapters/arxiv/papers.d.ts +27 -0
- package/dist/adapters/arxiv/papers.d.ts.map +1 -0
- package/dist/adapters/arxiv/papers.js +193 -0
- package/dist/adapters/arxiv/papers.js.map +1 -0
- package/dist/adapters/bbc/topic.d.ts +24 -0
- package/dist/adapters/bbc/topic.d.ts.map +1 -0
- package/dist/adapters/bbc/topic.js +122 -0
- package/dist/adapters/bbc/topic.js.map +1 -0
- package/dist/adapters/chatgpt/web.d.ts +24 -0
- package/dist/adapters/chatgpt/web.d.ts.map +1 -0
- package/dist/adapters/chatgpt/web.js +242 -0
- package/dist/adapters/chatgpt/web.js.map +1 -0
- package/dist/adapters/claude/web.d.ts +24 -0
- package/dist/adapters/claude/web.d.ts.map +1 -0
- package/dist/adapters/claude/web.js +575 -0
- package/dist/adapters/claude/web.js.map +1 -0
- package/dist/adapters/codex/projects.d.ts +27 -0
- package/dist/adapters/codex/projects.d.ts.map +1 -0
- package/dist/adapters/codex/projects.js +147 -0
- package/dist/adapters/codex/projects.js.map +1 -0
- package/dist/adapters/coingecko/markets.d.ts +19 -0
- package/dist/adapters/coingecko/markets.d.ts.map +1 -0
- package/dist/adapters/coingecko/markets.js +474 -0
- package/dist/adapters/coingecko/markets.js.map +1 -0
- package/dist/adapters/coupang/product.d.ts +27 -0
- package/dist/adapters/coupang/product.d.ts.map +1 -0
- package/dist/adapters/coupang/product.js +211 -0
- package/dist/adapters/coupang/product.js.map +1 -0
- package/dist/adapters/crates/registry.d.ts +44 -0
- package/dist/adapters/crates/registry.d.ts.map +1 -0
- package/dist/adapters/crates/registry.js +186 -0
- package/dist/adapters/crates/registry.js.map +1 -0
- package/dist/adapters/ctrip/travel.d.ts +83 -0
- package/dist/adapters/ctrip/travel.d.ts.map +1 -0
- package/dist/adapters/ctrip/travel.js +630 -0
- package/dist/adapters/ctrip/travel.js.map +1 -0
- package/dist/adapters/dblp/publications.d.ts +41 -0
- package/dist/adapters/dblp/publications.d.ts.map +1 -0
- package/dist/adapters/dblp/publications.js +409 -0
- package/dist/adapters/dblp/publications.js.map +1 -0
- package/dist/adapters/deepseek/web.d.ts +1 -1
- package/dist/adapters/deepseek/web.d.ts.map +1 -1
- package/dist/adapters/deepseek/web.js +66 -1
- package/dist/adapters/deepseek/web.js.map +1 -1
- package/dist/adapters/defillama/protocols.d.ts +13 -0
- package/dist/adapters/defillama/protocols.d.ts.map +1 -0
- package/dist/adapters/defillama/protocols.js +218 -0
- package/dist/adapters/defillama/protocols.js.map +1 -0
- package/dist/adapters/devto/read.d.ts +26 -0
- package/dist/adapters/devto/read.d.ts.map +1 -0
- package/dist/adapters/devto/read.js +110 -0
- package/dist/adapters/devto/read.js.map +1 -0
- package/dist/adapters/dianping/shop.d.ts +38 -0
- package/dist/adapters/dianping/shop.d.ts.map +1 -0
- package/dist/adapters/dianping/shop.js +194 -0
- package/dist/adapters/dianping/shop.js.map +1 -0
- package/dist/adapters/dockerhub/registry.d.ts +36 -0
- package/dist/adapters/dockerhub/registry.d.ts.map +1 -0
- package/dist/adapters/dockerhub/registry.js +172 -0
- package/dist/adapters/dockerhub/registry.js.map +1 -0
- package/dist/adapters/endoflife/product.d.ts +11 -0
- package/dist/adapters/endoflife/product.d.ts.map +1 -0
- package/dist/adapters/endoflife/product.js +113 -0
- package/dist/adapters/endoflife/product.js.map +1 -0
- package/dist/adapters/facebook/marketplace-extra.d.ts +9 -0
- package/dist/adapters/facebook/marketplace-extra.d.ts.map +1 -0
- package/dist/adapters/facebook/marketplace-extra.js +170 -0
- package/dist/adapters/facebook/marketplace-extra.js.map +1 -0
- package/dist/adapters/flathub/apps.d.ts +17 -0
- package/dist/adapters/flathub/apps.d.ts.map +1 -0
- package/dist/adapters/flathub/apps.js +220 -0
- package/dist/adapters/flathub/apps.js.map +1 -0
- package/dist/adapters/goproxy/module.d.ts +24 -0
- package/dist/adapters/goproxy/module.d.ts.map +1 -0
- package/dist/adapters/goproxy/module.js +221 -0
- package/dist/adapters/goproxy/module.js.map +1 -0
- package/dist/adapters/grok/web.d.ts +29 -0
- package/dist/adapters/grok/web.d.ts.map +1 -0
- package/dist/adapters/grok/web.js +553 -0
- package/dist/adapters/grok/web.js.map +1 -0
- package/dist/adapters/hackernews/read.d.ts +31 -0
- package/dist/adapters/hackernews/read.d.ts.map +1 -0
- package/dist/adapters/hackernews/read.js +201 -0
- package/dist/adapters/hackernews/read.js.map +1 -0
- package/dist/adapters/hf/paper.d.ts +22 -0
- package/dist/adapters/hf/paper.d.ts.map +1 -0
- package/dist/adapters/hf/paper.js +112 -0
- package/dist/adapters/hf/paper.js.map +1 -0
- package/dist/adapters/homebrew/packages.d.ts +52 -0
- package/dist/adapters/homebrew/packages.d.ts.map +1 -0
- package/dist/adapters/homebrew/packages.js +240 -0
- package/dist/adapters/homebrew/packages.js.map +1 -0
- package/dist/adapters/indeed/jobs.d.ts +38 -0
- package/dist/adapters/indeed/jobs.d.ts.map +1 -0
- package/dist/adapters/indeed/jobs.js +300 -0
- package/dist/adapters/indeed/jobs.js.map +1 -0
- package/dist/adapters/instagram/collections.d.ts +9 -0
- package/dist/adapters/instagram/collections.d.ts.map +1 -0
- package/dist/adapters/instagram/collections.js +174 -0
- package/dist/adapters/instagram/collections.js.map +1 -0
- package/dist/adapters/lichess/players.d.ts +46 -0
- package/dist/adapters/lichess/players.d.ts.map +1 -0
- package/dist/adapters/lichess/players.js +221 -0
- package/dist/adapters/lichess/players.js.map +1 -0
- package/dist/adapters/lobsters/read-domain.d.ts +35 -0
- package/dist/adapters/lobsters/read-domain.d.ts.map +1 -0
- package/dist/adapters/lobsters/read-domain.js +306 -0
- package/dist/adapters/lobsters/read-domain.js.map +1 -0
- package/dist/adapters/maven/artifact.d.ts +30 -0
- package/dist/adapters/maven/artifact.d.ts.map +1 -0
- package/dist/adapters/maven/artifact.js +121 -0
- package/dist/adapters/maven/artifact.js.map +1 -0
- package/dist/adapters/mdn/search.d.ts +11 -0
- package/dist/adapters/mdn/search.d.ts.map +1 -0
- package/dist/adapters/mdn/search.js +115 -0
- package/dist/adapters/mdn/search.js.map +1 -0
- package/dist/adapters/medium/tag.d.ts +15 -0
- package/dist/adapters/medium/tag.d.ts.map +1 -0
- package/dist/adapters/medium/tag.js +148 -0
- package/dist/adapters/medium/tag.js.map +1 -0
- package/dist/adapters/npm/package.d.ts +32 -0
- package/dist/adapters/npm/package.d.ts.map +1 -0
- package/dist/adapters/npm/package.js +141 -0
- package/dist/adapters/npm/package.js.map +1 -0
- package/dist/adapters/nuget/package.d.ts +34 -0
- package/dist/adapters/nuget/package.d.ts.map +1 -0
- package/dist/adapters/nuget/package.js +135 -0
- package/dist/adapters/nuget/package.js.map +1 -0
- package/dist/adapters/nvd/cve.d.ts +42 -0
- package/dist/adapters/nvd/cve.d.ts.map +1 -0
- package/dist/adapters/nvd/cve.js +132 -0
- package/dist/adapters/nvd/cve.js.map +1 -0
- package/dist/adapters/oeis/sequences.d.ts +14 -0
- package/dist/adapters/oeis/sequences.d.ts.map +1 -0
- package/dist/adapters/oeis/sequences.js +219 -0
- package/dist/adapters/oeis/sequences.js.map +1 -0
- package/dist/adapters/openalex/works.d.ts +43 -0
- package/dist/adapters/openalex/works.d.ts.map +1 -0
- package/dist/adapters/openalex/works.js +267 -0
- package/dist/adapters/openalex/works.js.map +1 -0
- package/dist/adapters/openfda/records.d.ts +18 -0
- package/dist/adapters/openfda/records.d.ts.map +1 -0
- package/dist/adapters/openfda/records.js +209 -0
- package/dist/adapters/openfda/records.js.map +1 -0
- package/dist/adapters/openreview/papers.d.ts +34 -0
- package/dist/adapters/openreview/papers.d.ts.map +1 -0
- package/dist/adapters/openreview/papers.js +463 -0
- package/dist/adapters/openreview/papers.js.map +1 -0
- package/dist/adapters/osv/security.d.ts +36 -0
- package/dist/adapters/osv/security.d.ts.map +1 -0
- package/dist/adapters/osv/security.js +247 -0
- package/dist/adapters/osv/security.js.map +1 -0
- package/dist/adapters/packagist/package.d.ts +31 -0
- package/dist/adapters/packagist/package.d.ts.map +1 -0
- package/dist/adapters/packagist/package.js +108 -0
- package/dist/adapters/packagist/package.js.map +1 -0
- package/dist/adapters/pubmed/articles.d.ts +31 -0
- package/dist/adapters/pubmed/articles.d.ts.map +1 -0
- package/dist/adapters/pubmed/articles.js +385 -0
- package/dist/adapters/pubmed/articles.js.map +1 -0
- package/dist/adapters/pypi/package.d.ts +38 -0
- package/dist/adapters/pypi/package.d.ts.map +1 -0
- package/dist/adapters/pypi/package.js +235 -0
- package/dist/adapters/pypi/package.js.map +1 -0
- package/dist/adapters/qwen/web.d.ts +26 -0
- package/dist/adapters/qwen/web.d.ts.map +1 -0
- package/dist/adapters/qwen/web.js +672 -0
- package/dist/adapters/qwen/web.js.map +1 -0
- package/dist/adapters/reddit/account.d.ts +12 -0
- package/dist/adapters/reddit/account.d.ts.map +1 -0
- package/dist/adapters/reddit/account.js +409 -0
- package/dist/adapters/reddit/account.js.map +1 -0
- package/dist/adapters/rednote/web.d.ts +30 -0
- package/dist/adapters/rednote/web.d.ts.map +1 -0
- package/dist/adapters/rednote/web.js +858 -0
- package/dist/adapters/rednote/web.js.map +1 -0
- package/dist/adapters/rest-countries/countries.d.ts +14 -0
- package/dist/adapters/rest-countries/countries.d.ts.map +1 -0
- package/dist/adapters/rest-countries/countries.js +231 -0
- package/dist/adapters/rest-countries/countries.js.map +1 -0
- package/dist/adapters/reuters/article-detail.d.ts +37 -0
- package/dist/adapters/reuters/article-detail.d.ts.map +1 -0
- package/dist/adapters/reuters/article-detail.js +139 -0
- package/dist/adapters/reuters/article-detail.js.map +1 -0
- package/dist/adapters/rfc/rfc.d.ts +11 -0
- package/dist/adapters/rfc/rfc.d.ts.map +1 -0
- package/dist/adapters/rfc/rfc.js +121 -0
- package/dist/adapters/rfc/rfc.js.map +1 -0
- package/dist/adapters/rubygems/gem.d.ts +26 -0
- package/dist/adapters/rubygems/gem.d.ts.map +1 -0
- package/dist/adapters/rubygems/gem.js +96 -0
- package/dist/adapters/rubygems/gem.js.map +1 -0
- package/dist/adapters/stackoverflow/questions.d.ts +79 -0
- package/dist/adapters/stackoverflow/questions.d.ts.map +1 -0
- package/dist/adapters/stackoverflow/questions.js +504 -0
- package/dist/adapters/stackoverflow/questions.js.map +1 -0
- package/dist/adapters/steam/app.d.ts +39 -0
- package/dist/adapters/steam/app.d.ts.map +1 -0
- package/dist/adapters/steam/app.js +165 -0
- package/dist/adapters/steam/app.js.map +1 -0
- package/dist/adapters/tiktok/creator-videos.d.ts +52 -0
- package/dist/adapters/tiktok/creator-videos.d.ts.map +1 -0
- package/dist/adapters/tiktok/creator-videos.js +267 -0
- package/dist/adapters/tiktok/creator-videos.js.map +1 -0
- package/dist/adapters/tvmaze/shows.d.ts +13 -0
- package/dist/adapters/tvmaze/shows.d.ts.map +1 -0
- package/dist/adapters/tvmaze/shows.js +240 -0
- package/dist/adapters/tvmaze/shows.js.map +1 -0
- package/dist/adapters/twitter/bookmark-folders.d.ts +33 -0
- package/dist/adapters/twitter/bookmark-folders.d.ts.map +1 -0
- package/dist/adapters/twitter/bookmark-folders.js +290 -0
- package/dist/adapters/twitter/bookmark-folders.js.map +1 -0
- package/dist/adapters/twitter/quote.d.ts +18 -0
- package/dist/adapters/twitter/quote.d.ts.map +1 -0
- package/dist/adapters/twitter/quote.js +285 -0
- package/dist/adapters/twitter/quote.js.map +1 -0
- package/dist/adapters/twitter/tweet-actions.d.ts +12 -0
- package/dist/adapters/twitter/tweet-actions.d.ts.map +1 -0
- package/dist/adapters/twitter/tweet-actions.js +145 -0
- package/dist/adapters/twitter/tweet-actions.js.map +1 -0
- package/dist/adapters/twitter/tweet-url.d.ts +15 -0
- package/dist/adapters/twitter/tweet-url.d.ts.map +1 -0
- package/dist/adapters/twitter/tweet-url.js +57 -0
- package/dist/adapters/twitter/tweet-url.js.map +1 -0
- package/dist/adapters/uisdc/news.d.ts +22 -0
- package/dist/adapters/uisdc/news.d.ts.map +1 -0
- package/dist/adapters/uisdc/news.js +91 -0
- package/dist/adapters/uisdc/news.js.map +1 -0
- package/dist/adapters/weibo/favorites-publish.d.ts +28 -0
- package/dist/adapters/weibo/favorites-publish.d.ts.map +1 -0
- package/dist/adapters/weibo/favorites-publish.js +356 -0
- package/dist/adapters/weibo/favorites-publish.js.map +1 -0
- package/dist/adapters/wikidata/entities.d.ts +15 -0
- package/dist/adapters/wikidata/entities.d.ts.map +1 -0
- package/dist/adapters/wikidata/entities.js +219 -0
- package/dist/adapters/wikidata/entities.js.map +1 -0
- package/dist/adapters/wikipedia/page.d.ts +21 -0
- package/dist/adapters/wikipedia/page.d.ts.map +1 -0
- package/dist/adapters/wikipedia/page.js +116 -0
- package/dist/adapters/wikipedia/page.js.map +1 -0
- package/dist/adapters/wttr/weather.d.ts +12 -0
- package/dist/adapters/wttr/weather.d.ts.map +1 -0
- package/dist/adapters/wttr/weather.js +207 -0
- package/dist/adapters/wttr/weather.js.map +1 -0
- package/dist/adapters/xianyu/publish.d.ts +31 -0
- package/dist/adapters/xianyu/publish.d.ts.map +1 -0
- package/dist/adapters/xianyu/publish.js +349 -0
- package/dist/adapters/xianyu/publish.js.map +1 -0
- package/dist/adapters/xiaohongshu/user-helpers.d.ts +2 -2
- package/dist/adapters/xiaohongshu/user-helpers.d.ts.map +1 -1
- package/dist/adapters/xiaohongshu/user-helpers.js +5 -4
- package/dist/adapters/xiaohongshu/user-helpers.js.map +1 -1
- package/dist/adapters/yuanbao/web.d.ts +27 -0
- package/dist/adapters/yuanbao/web.d.ts.map +1 -0
- package/dist/adapters/yuanbao/web.js +365 -0
- package/dist/adapters/yuanbao/web.js.map +1 -0
- package/dist/adapters/zhihu/collection.d.ts +33 -0
- package/dist/adapters/zhihu/collection.d.ts.map +1 -0
- package/dist/adapters/zhihu/collection.js +185 -0
- package/dist/adapters/zhihu/collection.js.map +1 -0
- package/dist/adapters/zlibrary/web.d.ts +19 -0
- package/dist/adapters/zlibrary/web.d.ts.map +1 -0
- package/dist/adapters/zlibrary/web.js +153 -0
- package/dist/adapters/zlibrary/web.js.map +1 -0
- package/dist/browser/daemon-client.js +2 -2
- package/dist/browser/daemon-client.js.map +1 -1
- package/dist/discovery/macos-dynamic.d.ts.map +1 -1
- package/dist/discovery/macos-dynamic.js +17 -3
- package/dist/discovery/macos-dynamic.js.map +1 -1
- package/dist/manifest-compact.txt +10 -10
- package/dist/manifest-search.json +1 -1
- package/dist/manifest.json +5130 -112
- package/dist/transport/refs.d.ts +5 -3
- package/dist/transport/refs.d.ts.map +1 -1
- package/dist/transport/refs.js +8 -1
- package/dist/transport/refs.js.map +1 -1
- package/dist/transport/sidecar-binary.d.ts +7 -0
- package/dist/transport/sidecar-binary.d.ts.map +1 -1
- package/dist/transport/sidecar-binary.js +28 -8
- package/dist/transport/sidecar-binary.js.map +1 -1
- package/package.json +4 -3
- package/server.json +3 -3
- package/skills/unicli/SKILL.md +1 -1
- package/skills/unicli-claude-code/SKILL.md +1 -1
- package/skills/unicli-hermes/SKILL.md +1 -1
- package/src/adapters/1point3acres/forum.test.ts +300 -0
- package/src/adapters/1point3acres/forum.ts +852 -0
- package/src/adapters/aibase/news.test.ts +42 -0
- package/src/adapters/aibase/news.ts +118 -0
- package/src/adapters/arxiv/papers.test.ts +59 -0
- package/src/adapters/arxiv/papers.ts +226 -0
- package/src/adapters/bbc/topic.test.ts +52 -0
- package/src/adapters/bbc/topic.ts +149 -0
- package/src/adapters/chatgpt/web.test.ts +121 -0
- package/src/adapters/chatgpt/web.ts +286 -0
- package/src/adapters/claude/web.test.ts +206 -0
- package/src/adapters/claude/web.ts +684 -0
- package/src/adapters/codex/projects.test.ts +77 -0
- package/src/adapters/codex/projects.ts +178 -0
- package/src/adapters/coingecko/markets.test.ts +156 -0
- package/src/adapters/coingecko/markets.ts +574 -0
- package/src/adapters/coupang/product.test.ts +111 -0
- package/src/adapters/coupang/product.ts +256 -0
- package/src/adapters/crates/registry.test.ts +89 -0
- package/src/adapters/crates/registry.ts +247 -0
- package/src/adapters/ctrip/travel.test.ts +359 -0
- package/src/adapters/ctrip/travel.ts +792 -0
- package/src/adapters/dblp/publications.test.ts +123 -0
- package/src/adapters/dblp/publications.ts +494 -0
- package/src/adapters/deepseek/web.test.ts +69 -0
- package/src/adapters/deepseek/web.ts +78 -1
- package/src/adapters/defillama/protocols.test.ts +75 -0
- package/src/adapters/defillama/protocols.ts +253 -0
- package/src/adapters/devto/read.test.ts +49 -0
- package/src/adapters/devto/read.ts +145 -0
- package/src/adapters/dianping/shop.test.ts +134 -0
- package/src/adapters/dianping/shop.ts +261 -0
- package/src/adapters/dockerhub/registry.test.ts +97 -0
- package/src/adapters/dockerhub/registry.ts +223 -0
- package/src/adapters/endoflife/product.test.ts +50 -0
- package/src/adapters/endoflife/product.ts +128 -0
- package/src/adapters/facebook/marketplace-extra.test.ts +132 -0
- package/src/adapters/facebook/marketplace-extra.ts +213 -0
- package/src/adapters/flathub/apps.test.ts +85 -0
- package/src/adapters/flathub/apps.ts +254 -0
- package/src/adapters/goproxy/module.test.ts +72 -0
- package/src/adapters/goproxy/module.ts +258 -0
- package/src/adapters/grok/web.test.ts +181 -0
- package/src/adapters/grok/web.ts +640 -0
- package/src/adapters/hackernews/read.test.ts +68 -0
- package/src/adapters/hackernews/read.ts +265 -0
- package/src/adapters/hf/paper.test.ts +48 -0
- package/src/adapters/hf/paper.ts +138 -0
- package/src/adapters/homebrew/packages.test.ts +109 -0
- package/src/adapters/homebrew/packages.ts +304 -0
- package/src/adapters/indeed/jobs.test.ts +230 -0
- package/src/adapters/indeed/jobs.ts +375 -0
- package/src/adapters/instagram/collections.test.ts +94 -0
- package/src/adapters/instagram/collections.ts +206 -0
- package/src/adapters/lichess/players.test.ts +99 -0
- package/src/adapters/lichess/players.ts +277 -0
- package/src/adapters/lobsters/read-domain.test.ts +121 -0
- package/src/adapters/lobsters/read-domain.ts +400 -0
- package/src/adapters/maven/artifact.test.ts +67 -0
- package/src/adapters/maven/artifact.ts +155 -0
- package/src/adapters/mdn/search.test.ts +39 -0
- package/src/adapters/mdn/search.ts +133 -0
- package/src/adapters/medium/tag.test.ts +64 -0
- package/src/adapters/medium/tag.ts +164 -0
- package/src/adapters/npm/package.test.ts +53 -0
- package/src/adapters/npm/package.ts +177 -0
- package/src/adapters/nuget/package.test.ts +102 -0
- package/src/adapters/nuget/package.ts +193 -0
- package/src/adapters/nvd/cve.test.ts +66 -0
- package/src/adapters/nvd/cve.ts +182 -0
- package/src/adapters/oeis/sequences.test.ts +71 -0
- package/src/adapters/oeis/sequences.ts +234 -0
- package/src/adapters/openalex/works.test.ts +99 -0
- package/src/adapters/openalex/works.ts +319 -0
- package/src/adapters/openfda/records.test.ts +90 -0
- package/src/adapters/openfda/records.ts +239 -0
- package/src/adapters/openreview/papers.test.ts +139 -0
- package/src/adapters/openreview/papers.ts +560 -0
- package/src/adapters/osv/security.test.ts +91 -0
- package/src/adapters/osv/security.ts +298 -0
- package/src/adapters/packagist/package.test.ts +62 -0
- package/src/adapters/packagist/package.ts +146 -0
- package/src/adapters/pubmed/articles.test.ts +96 -0
- package/src/adapters/pubmed/articles.ts +497 -0
- package/src/adapters/pypi/package.test.ts +131 -0
- package/src/adapters/pypi/package.ts +297 -0
- package/src/adapters/qwen/web.test.ts +176 -0
- package/src/adapters/qwen/web.ts +758 -0
- package/src/adapters/reddit/account.test.ts +56 -0
- package/src/adapters/reddit/account.ts +493 -0
- package/src/adapters/rednote/web.test.ts +354 -0
- package/src/adapters/rednote/web.ts +968 -0
- package/src/adapters/rest-countries/countries.test.ts +80 -0
- package/src/adapters/rest-countries/countries.ts +271 -0
- package/src/adapters/reuters/article-detail.test.ts +65 -0
- package/src/adapters/reuters/article-detail.ts +186 -0
- package/src/adapters/rfc/rfc.test.ts +37 -0
- package/src/adapters/rfc/rfc.ts +133 -0
- package/src/adapters/rubygems/gem.test.ts +43 -0
- package/src/adapters/rubygems/gem.ts +126 -0
- package/src/adapters/stackoverflow/questions.test.ts +207 -0
- package/src/adapters/stackoverflow/questions.ts +765 -0
- package/src/adapters/steam/app.test.ts +68 -0
- package/src/adapters/steam/app.ts +218 -0
- package/src/adapters/tiktok/creator-videos.test.ts +158 -0
- package/src/adapters/tiktok/creator-videos.ts +370 -0
- package/src/adapters/tvmaze/shows.test.ts +93 -0
- package/src/adapters/tvmaze/shows.ts +271 -0
- package/src/adapters/twitter/bookmark-folders.test.ts +164 -0
- package/src/adapters/twitter/bookmark-folders.ts +366 -0
- package/src/adapters/twitter/quote.test.ts +157 -0
- package/src/adapters/twitter/quote.ts +332 -0
- package/src/adapters/twitter/tweet-actions.test.ts +51 -0
- package/src/adapters/twitter/tweet-actions.ts +187 -0
- package/src/adapters/twitter/tweet-url.ts +65 -0
- package/src/adapters/uisdc/news.test.ts +46 -0
- package/src/adapters/uisdc/news.ts +111 -0
- package/src/adapters/weibo/favorites-publish.test.ts +177 -0
- package/src/adapters/weibo/favorites-publish.ts +426 -0
- package/src/adapters/wikidata/entities.test.ts +103 -0
- package/src/adapters/wikidata/entities.ts +253 -0
- package/src/adapters/wikipedia/page.test.ts +49 -0
- package/src/adapters/wikipedia/page.ts +158 -0
- package/src/adapters/wttr/weather.test.ts +99 -0
- package/src/adapters/wttr/weather.ts +239 -0
- package/src/adapters/xianyu/publish.test.ts +210 -0
- package/src/adapters/xianyu/publish.ts +420 -0
- package/src/adapters/xiaohongshu/user-helpers.ts +5 -2
- package/src/adapters/yuanbao/web.test.ts +144 -0
- package/src/adapters/yuanbao/web.ts +435 -0
- package/src/adapters/zhihu/collection.test.ts +96 -0
- package/src/adapters/zhihu/collection.ts +239 -0
- package/src/adapters/zlibrary/web.test.ts +104 -0
- package/src/adapters/zlibrary/web.ts +192 -0
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @owner src/adapters/1point3acres/forum.ts
|
|
3
|
+
* @does Register agent-facing 1Point3Acres Discuz forum, thread, search, notification, and profile commands.
|
|
4
|
+
* @needs Public www.1point3acres.com/bbs HTML plus browser cookies for search and notifications.
|
|
5
|
+
* @feeds surface coverage ledger, Chinese forum research workflows, and Discuz thread/profile extraction.
|
|
6
|
+
* @breaks Discuz template drift, GBK decoding changes, guest alert copy changes, or protected-search cookie policy changes.
|
|
7
|
+
*/
|
|
8
|
+
import { formatCookieHeader } from "../../engine/cookies.js";
|
|
9
|
+
import { cli, Strategy } from "../../registry.js";
|
|
10
|
+
export const ONEPOINT_BASE = "https://www.1point3acres.com/bbs";
|
|
11
|
+
const ONEPOINT_HOST = "www.1point3acres.com";
|
|
12
|
+
const USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0 Safari/537.36";
|
|
13
|
+
export const ONEPOINT_THREAD_LIST_COLUMNS = [
|
|
14
|
+
"rank",
|
|
15
|
+
"tid",
|
|
16
|
+
"title",
|
|
17
|
+
"forum",
|
|
18
|
+
"author",
|
|
19
|
+
"replies",
|
|
20
|
+
"views",
|
|
21
|
+
"lastReplyTime",
|
|
22
|
+
"url",
|
|
23
|
+
];
|
|
24
|
+
export const ONEPOINT_LATEST_COLUMNS = [
|
|
25
|
+
"rank",
|
|
26
|
+
"tid",
|
|
27
|
+
"title",
|
|
28
|
+
"forum",
|
|
29
|
+
"author",
|
|
30
|
+
"replies",
|
|
31
|
+
"views",
|
|
32
|
+
"postTime",
|
|
33
|
+
"url",
|
|
34
|
+
];
|
|
35
|
+
export const ONEPOINT_FORUM_COLUMNS = [
|
|
36
|
+
"rank",
|
|
37
|
+
"tid",
|
|
38
|
+
"kind",
|
|
39
|
+
"title",
|
|
40
|
+
"author",
|
|
41
|
+
"replies",
|
|
42
|
+
"views",
|
|
43
|
+
"lastReplyTime",
|
|
44
|
+
"url",
|
|
45
|
+
];
|
|
46
|
+
export const ONEPOINT_FORUMS_COLUMNS = ["fid", "name", "url"];
|
|
47
|
+
export const ONEPOINT_SEARCH_COLUMNS = [
|
|
48
|
+
"rank",
|
|
49
|
+
"tid",
|
|
50
|
+
"title",
|
|
51
|
+
"forum",
|
|
52
|
+
"author",
|
|
53
|
+
"replies",
|
|
54
|
+
"views",
|
|
55
|
+
"postTime",
|
|
56
|
+
"url",
|
|
57
|
+
];
|
|
58
|
+
export const ONEPOINT_THREAD_COLUMNS = [
|
|
59
|
+
"floor",
|
|
60
|
+
"pid",
|
|
61
|
+
"author",
|
|
62
|
+
"postTime",
|
|
63
|
+
"content",
|
|
64
|
+
"url",
|
|
65
|
+
];
|
|
66
|
+
export const ONEPOINT_USER_COLUMNS = [
|
|
67
|
+
"uid",
|
|
68
|
+
"username",
|
|
69
|
+
"group",
|
|
70
|
+
"credits",
|
|
71
|
+
"rice",
|
|
72
|
+
"posts",
|
|
73
|
+
"threads",
|
|
74
|
+
"digests",
|
|
75
|
+
"registerTime",
|
|
76
|
+
"lastAccess",
|
|
77
|
+
"profileUrl",
|
|
78
|
+
];
|
|
79
|
+
export const ONEPOINT_NOTIFICATION_COLUMNS = [
|
|
80
|
+
"index",
|
|
81
|
+
"from",
|
|
82
|
+
"summary",
|
|
83
|
+
"time",
|
|
84
|
+
"threadUrl",
|
|
85
|
+
];
|
|
86
|
+
function cleanString(value) {
|
|
87
|
+
return typeof value === "string"
|
|
88
|
+
? value.trim()
|
|
89
|
+
: value == null
|
|
90
|
+
? ""
|
|
91
|
+
: String(value).trim();
|
|
92
|
+
}
|
|
93
|
+
export function normalizeOnePointPositiveInteger(value, defaultValue, label = "value", opts = {}) {
|
|
94
|
+
const raw = value ?? defaultValue;
|
|
95
|
+
const parsed = Number(raw);
|
|
96
|
+
const min = opts.min ?? 1;
|
|
97
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
98
|
+
throw new Error(`${label} must be a positive integer`);
|
|
99
|
+
}
|
|
100
|
+
if (parsed < min) {
|
|
101
|
+
throw new Error(`${label} must be >= ${min}`);
|
|
102
|
+
}
|
|
103
|
+
return parsed;
|
|
104
|
+
}
|
|
105
|
+
export function normalizeOnePointLimit(value, defaultValue, maxValue, label = "limit") {
|
|
106
|
+
const limit = normalizeOnePointPositiveInteger(value, defaultValue, label);
|
|
107
|
+
if (limit > maxValue)
|
|
108
|
+
throw new Error(`${label} must be <= ${maxValue}`);
|
|
109
|
+
return limit;
|
|
110
|
+
}
|
|
111
|
+
export function decodeOnePointEntities(value) {
|
|
112
|
+
if (!value)
|
|
113
|
+
return "";
|
|
114
|
+
const map = {
|
|
115
|
+
" ": " ",
|
|
116
|
+
"&": "&",
|
|
117
|
+
"<": "<",
|
|
118
|
+
">": ">",
|
|
119
|
+
""": '"',
|
|
120
|
+
"'": "'",
|
|
121
|
+
"'": "'",
|
|
122
|
+
};
|
|
123
|
+
return value
|
|
124
|
+
.replace(/&#(\d+);/g, (_, n) => String.fromCodePoint(Number(n)))
|
|
125
|
+
.replace(/&#[xX]([0-9a-fA-F]+);/g, (_, n) => String.fromCodePoint(parseInt(n, 16)))
|
|
126
|
+
.replace(/&(nbsp|amp|lt|gt|quot|#39|apos);/g, (m) => map[m] || m);
|
|
127
|
+
}
|
|
128
|
+
export function stripOnePointHtml(html) {
|
|
129
|
+
if (!html)
|
|
130
|
+
return "";
|
|
131
|
+
return decodeOnePointEntities(String(html)
|
|
132
|
+
.replace(/<br\s*\/?>/gi, "\n")
|
|
133
|
+
.replace(/<\/(p|div|li|tr)>/gi, "\n")
|
|
134
|
+
.replace(/<[^>]+>/g, ""))
|
|
135
|
+
.replace(/[ \t]+\n/g, "\n")
|
|
136
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
137
|
+
.trim();
|
|
138
|
+
}
|
|
139
|
+
export function truncateOnePoint(value, limit = 300) {
|
|
140
|
+
if (!value)
|
|
141
|
+
return "";
|
|
142
|
+
return value.length > limit ? `${value.slice(0, limit)}...` : value;
|
|
143
|
+
}
|
|
144
|
+
function extract(html, regex, group = 1) {
|
|
145
|
+
const match = html.match(regex);
|
|
146
|
+
return match ? match[group] : "";
|
|
147
|
+
}
|
|
148
|
+
async function readResponseText(response) {
|
|
149
|
+
const buffer = await response.arrayBuffer();
|
|
150
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
151
|
+
if (/utf-?8/i.test(contentType)) {
|
|
152
|
+
return new TextDecoder("utf-8").decode(buffer);
|
|
153
|
+
}
|
|
154
|
+
return new TextDecoder("gbk").decode(buffer);
|
|
155
|
+
}
|
|
156
|
+
export async function fetchOnePointHtml(url, options = {}) {
|
|
157
|
+
let response;
|
|
158
|
+
try {
|
|
159
|
+
response = await fetch(url, {
|
|
160
|
+
headers: {
|
|
161
|
+
"User-Agent": USER_AGENT,
|
|
162
|
+
Accept: "text/html,application/xhtml+xml",
|
|
163
|
+
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
|
164
|
+
...(options.cookie ? { Cookie: options.cookie } : {}),
|
|
165
|
+
...options.headers,
|
|
166
|
+
},
|
|
167
|
+
redirect: "follow",
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
throw new Error(`1point3acres request failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
172
|
+
}
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
throw new Error(`1point3acres request failed: HTTP ${response.status} ${response.statusText} from ${url}`);
|
|
175
|
+
}
|
|
176
|
+
return readResponseText(response);
|
|
177
|
+
}
|
|
178
|
+
export async function getOnePointCookie(page) {
|
|
179
|
+
const candidate = page;
|
|
180
|
+
if (typeof candidate?.cookies !== "function")
|
|
181
|
+
return "";
|
|
182
|
+
const cookies = await candidate.cookies();
|
|
183
|
+
return formatCookieHeader(cookies);
|
|
184
|
+
}
|
|
185
|
+
export function assertOnePointNotGuestAlert(html) {
|
|
186
|
+
if (/<title>提示信息 \| 一亩三分地<\/title>/.test(html) &&
|
|
187
|
+
/无法进行此操作|请登录/.test(html)) {
|
|
188
|
+
throw new Error("Login to www.1point3acres.com is required");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
export function parseOnePointThreadRows(html) {
|
|
192
|
+
const rows = [];
|
|
193
|
+
const regex = /<tbody id="(normalthread|stickthread)_(\d+)"[^>]*>([\s\S]*?)<\/tbody>/g;
|
|
194
|
+
let match;
|
|
195
|
+
while ((match = regex.exec(html))) {
|
|
196
|
+
rows.push({ kind: match[1], tid: match[2], inner: match[3] });
|
|
197
|
+
}
|
|
198
|
+
return rows;
|
|
199
|
+
}
|
|
200
|
+
export function parseOnePointThreadRow(row) {
|
|
201
|
+
const { kind, tid, inner } = row;
|
|
202
|
+
const titleMatches = [
|
|
203
|
+
...inner.matchAll(/<a [^>]*class="[^"]*\bxst\b[^"]*"[^>]*>([^<]+)<\/a>/g),
|
|
204
|
+
];
|
|
205
|
+
const title = titleMatches.length
|
|
206
|
+
? decodeOnePointEntities(titleMatches[titleMatches.length - 1][1].trim())
|
|
207
|
+
: "";
|
|
208
|
+
const forumMatch = inner.match(/<a href="forum-(\d+)-1\.html"[^>]*target="_blank"[^>]*>([^<]+)<\/a>/);
|
|
209
|
+
const fid = forumMatch ? forumMatch[1] : "";
|
|
210
|
+
const forumName = forumMatch
|
|
211
|
+
? decodeOnePointEntities(forumMatch[2].trim())
|
|
212
|
+
: "";
|
|
213
|
+
const byBlocks = [
|
|
214
|
+
...inner.matchAll(/<td class="by"[^>]*>([\s\S]*?)<\/td>/g),
|
|
215
|
+
].map((match) => match[1]);
|
|
216
|
+
const readCite = (block) => {
|
|
217
|
+
const match = block.match(/<cite[^>]*>([\s\S]*?)<\/cite>/);
|
|
218
|
+
if (!match)
|
|
219
|
+
return "";
|
|
220
|
+
return decodeOnePointEntities(match[1].replace(/<[^>]+>/g, "").trim());
|
|
221
|
+
};
|
|
222
|
+
const readTime = (block) => {
|
|
223
|
+
const titleMatch = block.match(/<span [^>]*title="([^"]+)"[^>]*>/);
|
|
224
|
+
if (titleMatch)
|
|
225
|
+
return titleMatch[1].trim();
|
|
226
|
+
const plainLink = block.match(/<em>[\s\S]*?<a [^>]*>\s*([^<]+?)\s*<\/a>/);
|
|
227
|
+
if (plainLink)
|
|
228
|
+
return decodeOnePointEntities(plainLink[1].trim());
|
|
229
|
+
const plainSpan = block.match(/<em>[\s\S]*?<span[^>]*>\s*([^<]+?)\s*<\/span>/);
|
|
230
|
+
if (plainSpan)
|
|
231
|
+
return decodeOnePointEntities(plainSpan[1].trim());
|
|
232
|
+
const bare = block.match(/<em>\s*([^<]+?)\s*<\/em>/);
|
|
233
|
+
return bare ? decodeOnePointEntities(bare[1].trim()) : "";
|
|
234
|
+
};
|
|
235
|
+
let authorBlock = "";
|
|
236
|
+
let lastBlock = "";
|
|
237
|
+
for (const block of byBlocks) {
|
|
238
|
+
if (!/<cite/.test(block))
|
|
239
|
+
continue;
|
|
240
|
+
if (!authorBlock)
|
|
241
|
+
authorBlock = block;
|
|
242
|
+
lastBlock = block;
|
|
243
|
+
}
|
|
244
|
+
const numberMatch = inner.match(/<td class="num"[^>]*>\s*<a[^>]*class="xi2"[^>]*>(\d+)<\/a>(?:\s*<em>(\d+)<\/em>)?/);
|
|
245
|
+
return {
|
|
246
|
+
tid,
|
|
247
|
+
kind,
|
|
248
|
+
title,
|
|
249
|
+
author: authorBlock ? readCite(authorBlock) : "",
|
|
250
|
+
forum: forumName,
|
|
251
|
+
fid,
|
|
252
|
+
replies: numberMatch ? Number(numberMatch[1]) : 0,
|
|
253
|
+
views: numberMatch?.[2] ? Number(numberMatch[2]) : 0,
|
|
254
|
+
postTime: authorBlock ? readTime(authorBlock) : "",
|
|
255
|
+
lastReplyUser: lastBlock && lastBlock !== authorBlock ? readCite(lastBlock) : "",
|
|
256
|
+
lastReplyTime: lastBlock && lastBlock !== authorBlock ? readTime(lastBlock) : "",
|
|
257
|
+
url: `${ONEPOINT_BASE}/thread-${tid}-1-1.html`,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
export function parseOnePointThreadList(html) {
|
|
261
|
+
return parseOnePointThreadRows(html)
|
|
262
|
+
.map(parseOnePointThreadRow)
|
|
263
|
+
.filter((thread) => thread.title);
|
|
264
|
+
}
|
|
265
|
+
export function parseOnePointSearchList(html) {
|
|
266
|
+
const items = [];
|
|
267
|
+
const regex = /<li class="pbw" id="(\d+)">([\s\S]*?)<\/li>/g;
|
|
268
|
+
let match;
|
|
269
|
+
while ((match = regex.exec(html))) {
|
|
270
|
+
const [, tid, inner] = match;
|
|
271
|
+
const titleMatch = inner.match(/<h3[^>]*>\s*<a [^>]*>([\s\S]*?)<\/a>/);
|
|
272
|
+
const title = decodeOnePointEntities((titleMatch ? titleMatch[1] : "").replace(/<[^>]+>/g, "")).trim();
|
|
273
|
+
if (!title)
|
|
274
|
+
continue;
|
|
275
|
+
const statsMatch = inner.match(/<p class="xg1">\s*([\d,]+)\s*个回复\s*-\s*([\d,]+)\s*次查看\s*<\/p>/);
|
|
276
|
+
const metaMatch = inner.match(/<p>\s*<span>([^<]+)<\/span>[\s\S]*?<a [^>]*space-uid-\d+[^>]*>([^<]+?)<\/a>[\s\S]*?<a [^>]*href="forum-(\d+)-[^"]*"[^>]*>([^<]+?)<\/a>/);
|
|
277
|
+
const postTime = metaMatch
|
|
278
|
+
? decodeOnePointEntities(metaMatch[1].trim())
|
|
279
|
+
: "";
|
|
280
|
+
const author = metaMatch ? decodeOnePointEntities(metaMatch[2].trim()) : "";
|
|
281
|
+
const fid = metaMatch ? metaMatch[3] : "";
|
|
282
|
+
const forum = metaMatch ? decodeOnePointEntities(metaMatch[4].trim()) : "";
|
|
283
|
+
items.push({
|
|
284
|
+
tid,
|
|
285
|
+
title,
|
|
286
|
+
author,
|
|
287
|
+
forum,
|
|
288
|
+
fid,
|
|
289
|
+
replies: statsMatch ? Number(statsMatch[1].replace(/,/g, "")) : 0,
|
|
290
|
+
views: statsMatch ? Number(statsMatch[2].replace(/,/g, "")) : 0,
|
|
291
|
+
postTime,
|
|
292
|
+
lastReplyUser: "",
|
|
293
|
+
lastReplyTime: postTime,
|
|
294
|
+
kind: "search",
|
|
295
|
+
url: `${ONEPOINT_BASE}/thread-${tid}-1-1.html`,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return items;
|
|
299
|
+
}
|
|
300
|
+
function mapThreadListRow(thread, index) {
|
|
301
|
+
return {
|
|
302
|
+
rank: index + 1,
|
|
303
|
+
tid: thread.tid,
|
|
304
|
+
title: thread.title,
|
|
305
|
+
forum: thread.forum,
|
|
306
|
+
author: thread.author,
|
|
307
|
+
replies: thread.replies,
|
|
308
|
+
views: thread.views,
|
|
309
|
+
lastReplyTime: thread.lastReplyTime,
|
|
310
|
+
url: thread.url,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
async function runGuideCommand(view, kwargs) {
|
|
314
|
+
const limit = normalizeOnePointLimit(kwargs.limit, 20, 50);
|
|
315
|
+
const html = await fetchOnePointHtml(`${ONEPOINT_BASE}/forum.php?mod=guide&view=${view}`);
|
|
316
|
+
return parseOnePointThreadList(html)
|
|
317
|
+
.slice(0, limit)
|
|
318
|
+
.map((thread, index) => view === "new"
|
|
319
|
+
? {
|
|
320
|
+
rank: index + 1,
|
|
321
|
+
tid: thread.tid,
|
|
322
|
+
title: thread.title,
|
|
323
|
+
forum: thread.forum,
|
|
324
|
+
author: thread.author,
|
|
325
|
+
replies: thread.replies,
|
|
326
|
+
views: thread.views,
|
|
327
|
+
postTime: thread.postTime,
|
|
328
|
+
url: thread.url,
|
|
329
|
+
}
|
|
330
|
+
: mapThreadListRow(thread, index));
|
|
331
|
+
}
|
|
332
|
+
cli({
|
|
333
|
+
site: "1point3acres",
|
|
334
|
+
name: "hot",
|
|
335
|
+
description: "Read hot 1Point3Acres threads",
|
|
336
|
+
domain: ONEPOINT_HOST,
|
|
337
|
+
strategy: Strategy.PUBLIC,
|
|
338
|
+
browser: false,
|
|
339
|
+
args: [
|
|
340
|
+
{
|
|
341
|
+
name: "limit",
|
|
342
|
+
type: "int",
|
|
343
|
+
default: 20,
|
|
344
|
+
description: "Number of rows to return, max 50",
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
columns: ONEPOINT_THREAD_LIST_COLUMNS,
|
|
348
|
+
func: async (_page, kwargs) => runGuideCommand("hot", kwargs),
|
|
349
|
+
});
|
|
350
|
+
cli({
|
|
351
|
+
site: "1point3acres",
|
|
352
|
+
name: "latest",
|
|
353
|
+
description: "Read latest 1Point3Acres threads",
|
|
354
|
+
domain: ONEPOINT_HOST,
|
|
355
|
+
strategy: Strategy.PUBLIC,
|
|
356
|
+
browser: false,
|
|
357
|
+
args: [
|
|
358
|
+
{
|
|
359
|
+
name: "limit",
|
|
360
|
+
type: "int",
|
|
361
|
+
default: 20,
|
|
362
|
+
description: "Number of rows to return, max 50",
|
|
363
|
+
},
|
|
364
|
+
],
|
|
365
|
+
columns: ONEPOINT_LATEST_COLUMNS,
|
|
366
|
+
func: async (_page, kwargs) => runGuideCommand("new", kwargs),
|
|
367
|
+
});
|
|
368
|
+
cli({
|
|
369
|
+
site: "1point3acres",
|
|
370
|
+
name: "digest",
|
|
371
|
+
description: "Read digest 1Point3Acres threads",
|
|
372
|
+
domain: ONEPOINT_HOST,
|
|
373
|
+
strategy: Strategy.PUBLIC,
|
|
374
|
+
browser: false,
|
|
375
|
+
args: [
|
|
376
|
+
{
|
|
377
|
+
name: "limit",
|
|
378
|
+
type: "int",
|
|
379
|
+
default: 20,
|
|
380
|
+
description: "Number of rows to return, max 50",
|
|
381
|
+
},
|
|
382
|
+
],
|
|
383
|
+
columns: ONEPOINT_THREAD_LIST_COLUMNS,
|
|
384
|
+
func: async (_page, kwargs) => runGuideCommand("digest", kwargs),
|
|
385
|
+
});
|
|
386
|
+
cli({
|
|
387
|
+
site: "1point3acres",
|
|
388
|
+
name: "forum",
|
|
389
|
+
description: "Browse threads from a 1Point3Acres forum by fid",
|
|
390
|
+
domain: ONEPOINT_HOST,
|
|
391
|
+
strategy: Strategy.PUBLIC,
|
|
392
|
+
browser: false,
|
|
393
|
+
args: [
|
|
394
|
+
{ name: "fid", required: true, positional: true, description: "Forum id" },
|
|
395
|
+
{ name: "page", type: "int", default: 1, description: "Page number" },
|
|
396
|
+
{
|
|
397
|
+
name: "limit",
|
|
398
|
+
type: "int",
|
|
399
|
+
default: 20,
|
|
400
|
+
description: "Number of rows to return, max 50",
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
columns: ONEPOINT_FORUM_COLUMNS,
|
|
404
|
+
func: async (_page, kwargs) => {
|
|
405
|
+
const fid = cleanString(kwargs.fid);
|
|
406
|
+
if (!/^\d+$/.test(fid))
|
|
407
|
+
throw new Error("fid must be a numeric forum id");
|
|
408
|
+
const page = normalizeOnePointPositiveInteger(kwargs.page, 1, "page");
|
|
409
|
+
const limit = normalizeOnePointLimit(kwargs.limit, 20, 50);
|
|
410
|
+
const html = await fetchOnePointHtml(`${ONEPOINT_BASE}/forum-${fid}-${page}.html`);
|
|
411
|
+
if (parseOnePointThreadRows(html).length === 0)
|
|
412
|
+
return [];
|
|
413
|
+
return parseOnePointThreadList(html)
|
|
414
|
+
.slice(0, limit)
|
|
415
|
+
.map((thread, index) => ({
|
|
416
|
+
rank: index + 1,
|
|
417
|
+
tid: thread.tid,
|
|
418
|
+
kind: thread.kind === "stickthread" ? "sticky" : "normal",
|
|
419
|
+
title: thread.title,
|
|
420
|
+
author: thread.author,
|
|
421
|
+
replies: thread.replies,
|
|
422
|
+
views: thread.views,
|
|
423
|
+
lastReplyTime: thread.lastReplyTime,
|
|
424
|
+
url: thread.url,
|
|
425
|
+
}));
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
cli({
|
|
429
|
+
site: "1point3acres",
|
|
430
|
+
name: "forums",
|
|
431
|
+
description: "List 1Point3Acres forum ids and names",
|
|
432
|
+
domain: ONEPOINT_HOST,
|
|
433
|
+
strategy: Strategy.PUBLIC,
|
|
434
|
+
browser: false,
|
|
435
|
+
args: [
|
|
436
|
+
{
|
|
437
|
+
name: "filter",
|
|
438
|
+
type: "str",
|
|
439
|
+
default: "",
|
|
440
|
+
description: "Filter by forum name substring",
|
|
441
|
+
},
|
|
442
|
+
],
|
|
443
|
+
columns: ONEPOINT_FORUMS_COLUMNS,
|
|
444
|
+
func: async (_page, kwargs) => {
|
|
445
|
+
const html = await fetchOnePointHtml(`${ONEPOINT_BASE}/forum.php`);
|
|
446
|
+
const seen = new Map();
|
|
447
|
+
const regex = /<a href="forum-(\d+)-1\.html"[^>]*class="[^"]*overflow-hidden[^"]*"[^>]*>\s*([^<]+?)\s*<\/a>/g;
|
|
448
|
+
let match;
|
|
449
|
+
while ((match = regex.exec(html))) {
|
|
450
|
+
const fid = match[1];
|
|
451
|
+
const name = decodeOnePointEntities(match[2].trim())
|
|
452
|
+
.replace(/^\[(.+)\]$/, "$1")
|
|
453
|
+
.trim();
|
|
454
|
+
if (name && !seen.has(fid))
|
|
455
|
+
seen.set(fid, name);
|
|
456
|
+
}
|
|
457
|
+
const filter = cleanString(kwargs.filter).toLowerCase();
|
|
458
|
+
return [...seen]
|
|
459
|
+
.filter(([, name]) => !filter || name.toLowerCase().includes(filter))
|
|
460
|
+
.map(([fid, name]) => ({
|
|
461
|
+
fid,
|
|
462
|
+
name,
|
|
463
|
+
url: `${ONEPOINT_BASE}/forum-${fid}-1.html`,
|
|
464
|
+
}));
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
cli({
|
|
468
|
+
site: "1point3acres",
|
|
469
|
+
name: "search",
|
|
470
|
+
description: "Search 1Point3Acres forum posts using browser cookies",
|
|
471
|
+
domain: ONEPOINT_HOST,
|
|
472
|
+
strategy: Strategy.COOKIE,
|
|
473
|
+
browser: true,
|
|
474
|
+
args: [
|
|
475
|
+
{ name: "query", required: true, positional: true, description: "Keyword" },
|
|
476
|
+
{
|
|
477
|
+
name: "limit",
|
|
478
|
+
type: "int",
|
|
479
|
+
default: 20,
|
|
480
|
+
description: "Number of rows to return, max 50",
|
|
481
|
+
},
|
|
482
|
+
{ name: "fid", type: "str", default: "", description: "Optional forum id" },
|
|
483
|
+
],
|
|
484
|
+
columns: ONEPOINT_SEARCH_COLUMNS,
|
|
485
|
+
func: async (page, kwargs) => {
|
|
486
|
+
const query = cleanString(kwargs.query);
|
|
487
|
+
if (!query)
|
|
488
|
+
throw new Error("query cannot be empty");
|
|
489
|
+
const limit = normalizeOnePointLimit(kwargs.limit, 20, 50);
|
|
490
|
+
const fid = cleanString(kwargs.fid);
|
|
491
|
+
if (fid && !/^\d+$/.test(fid))
|
|
492
|
+
throw new Error("fid must be a numeric forum id");
|
|
493
|
+
const cookie = await getOnePointCookie(page);
|
|
494
|
+
const params = new URLSearchParams({
|
|
495
|
+
mod: "forum",
|
|
496
|
+
srchtxt: query,
|
|
497
|
+
searchsubmit: "yes",
|
|
498
|
+
...(fid ? { srchfid: fid } : {}),
|
|
499
|
+
});
|
|
500
|
+
const html = await fetchOnePointHtml(`${ONEPOINT_BASE}/search.php?${params}`, {
|
|
501
|
+
cookie,
|
|
502
|
+
headers: { Referer: `${ONEPOINT_BASE}/` },
|
|
503
|
+
});
|
|
504
|
+
assertOnePointNotGuestAlert(html);
|
|
505
|
+
const items = parseOnePointSearchList(html);
|
|
506
|
+
if (items.length === 0)
|
|
507
|
+
throw new Error(`No 1Point3Acres search results for "${query}"`);
|
|
508
|
+
return items.slice(0, limit).map((thread, index) => ({
|
|
509
|
+
rank: index + 1,
|
|
510
|
+
tid: thread.tid,
|
|
511
|
+
title: thread.title,
|
|
512
|
+
forum: thread.forum,
|
|
513
|
+
author: thread.author,
|
|
514
|
+
replies: thread.replies,
|
|
515
|
+
views: thread.views,
|
|
516
|
+
postTime: thread.postTime,
|
|
517
|
+
url: thread.url,
|
|
518
|
+
}));
|
|
519
|
+
},
|
|
520
|
+
});
|
|
521
|
+
cli({
|
|
522
|
+
site: "1point3acres",
|
|
523
|
+
name: "thread",
|
|
524
|
+
description: "Read a 1Point3Acres thread page with floor rows",
|
|
525
|
+
domain: ONEPOINT_HOST,
|
|
526
|
+
strategy: Strategy.PUBLIC,
|
|
527
|
+
browser: false,
|
|
528
|
+
args: [
|
|
529
|
+
{ name: "tid", required: true, positional: true, description: "Thread id" },
|
|
530
|
+
{ name: "page", type: "int", default: 1, description: "Thread page" },
|
|
531
|
+
{
|
|
532
|
+
name: "limit",
|
|
533
|
+
type: "int",
|
|
534
|
+
default: 10,
|
|
535
|
+
description: "Number of floors",
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: "contentLimit",
|
|
539
|
+
type: "int",
|
|
540
|
+
default: 400,
|
|
541
|
+
description: "Max content characters per floor",
|
|
542
|
+
},
|
|
543
|
+
],
|
|
544
|
+
columns: ONEPOINT_THREAD_COLUMNS,
|
|
545
|
+
func: async (_page, kwargs) => {
|
|
546
|
+
const tid = cleanString(kwargs.tid);
|
|
547
|
+
if (!/^\d+$/.test(tid))
|
|
548
|
+
throw new Error("tid must be a numeric thread id");
|
|
549
|
+
const page = normalizeOnePointPositiveInteger(kwargs.page, 1, "page");
|
|
550
|
+
const limit = normalizeOnePointPositiveInteger(kwargs.limit, 10, "limit");
|
|
551
|
+
const contentLimit = normalizeOnePointPositiveInteger(kwargs.contentLimit, 400, "contentLimit", { min: 50 });
|
|
552
|
+
const html = await fetchOnePointHtml(`${ONEPOINT_BASE}/thread-${tid}-${page}-1.html`);
|
|
553
|
+
if (!/id="postlist"/.test(html) && !/id="post_\d+"/.test(html)) {
|
|
554
|
+
throw new Error(`Thread ${tid} does not exist or is unavailable`);
|
|
555
|
+
}
|
|
556
|
+
const offsets = [];
|
|
557
|
+
const regex = /<div id="post_(\d+)"[^>]*>/g;
|
|
558
|
+
let match;
|
|
559
|
+
while ((match = regex.exec(html))) {
|
|
560
|
+
offsets.push({ postId: match[1], offset: match.index });
|
|
561
|
+
}
|
|
562
|
+
const rows = [];
|
|
563
|
+
for (let index = 0; index < offsets.length && rows.length < limit; index += 1) {
|
|
564
|
+
const current = offsets[index];
|
|
565
|
+
const end = index + 1 < offsets.length ? offsets[index + 1].offset : html.length;
|
|
566
|
+
const block = html.slice(current.offset, end);
|
|
567
|
+
const authiBlock = extract(block, /(<div class="authi"[\s\S]*?<\/div>)/);
|
|
568
|
+
const author = decodeOnePointEntities(extract(authiBlock || block, /<a [^>]*class="[^"]*\bxi2\b[^"]*"[^>]*>\s*([^<]+?)\s*<\/a>/)) ||
|
|
569
|
+
decodeOnePointEntities(extract(authiBlock || block, /<a [^>]*href="space-uid-\d+\.html"[^>]*>\s*([^<]+?)\s*<\/a>/));
|
|
570
|
+
const postTime = extract(authiBlock, /<span title="([^"]+)">/) ||
|
|
571
|
+
extract(block, /id="authorposton\d+"[^>]*>\s*<span title="([^"]+)">/);
|
|
572
|
+
const floorText = extract(block, /<em>(\d+)<\/em>\s*#?\s*<\/a>/) ||
|
|
573
|
+
extract(block, /id="postnum\d+"[^>]*>\s*<em>(\d+)<\/em>/);
|
|
574
|
+
const content = truncateOnePoint(stripOnePointHtml(extract(block, /id="postmessage_\d+"[^>]*>([\s\S]*?)<\/td>/)), contentLimit);
|
|
575
|
+
rows.push({
|
|
576
|
+
floor: floorText
|
|
577
|
+
? Number(floorText)
|
|
578
|
+
: page === 1 && index === 0
|
|
579
|
+
? 1
|
|
580
|
+
: (page - 1) * 10 + index + 1,
|
|
581
|
+
pid: current.postId,
|
|
582
|
+
author,
|
|
583
|
+
postTime: postTime.trim(),
|
|
584
|
+
content,
|
|
585
|
+
url: `${ONEPOINT_BASE}/forum.php?mod=redirect&goto=findpost&ptid=${tid}&pid=${current.postId}`,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
if (page === 1 && rows.length > 0) {
|
|
589
|
+
const title = decodeOnePointEntities(extract(html, /<span id="thread_subject">([^<]+)<\/span>/).trim() ||
|
|
590
|
+
extract(html, /<title>([^<]+?)\s*[-|]/).trim());
|
|
591
|
+
if (title)
|
|
592
|
+
rows[0].content = `[${title}]\n${rows[0].content}`;
|
|
593
|
+
}
|
|
594
|
+
if (!rows.length)
|
|
595
|
+
throw new Error(`Thread ${tid} page ${page} has no readable floors`);
|
|
596
|
+
return rows;
|
|
597
|
+
},
|
|
598
|
+
});
|
|
599
|
+
cli({
|
|
600
|
+
site: "1point3acres",
|
|
601
|
+
name: "user",
|
|
602
|
+
description: "Read a 1Point3Acres user profile",
|
|
603
|
+
domain: ONEPOINT_HOST,
|
|
604
|
+
strategy: Strategy.PUBLIC,
|
|
605
|
+
browser: false,
|
|
606
|
+
args: [
|
|
607
|
+
{
|
|
608
|
+
name: "who",
|
|
609
|
+
required: true,
|
|
610
|
+
positional: true,
|
|
611
|
+
description: "Username or numeric uid",
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
columns: ONEPOINT_USER_COLUMNS,
|
|
615
|
+
func: async (_page, kwargs) => {
|
|
616
|
+
const who = cleanString(kwargs.who);
|
|
617
|
+
if (!who)
|
|
618
|
+
throw new Error("who cannot be empty");
|
|
619
|
+
const url = /^\d+$/.test(who)
|
|
620
|
+
? `${ONEPOINT_BASE}/space-uid-${who}.html`
|
|
621
|
+
: `${ONEPOINT_BASE}/space-username-${encodeURIComponent(who)}.html`;
|
|
622
|
+
const html = await fetchOnePointHtml(url);
|
|
623
|
+
if (/<title>提示信息/.test(html) && /(没有找到|不存在)/.test(html)) {
|
|
624
|
+
throw new Error(`User "${who}" does not exist`);
|
|
625
|
+
}
|
|
626
|
+
const pick = (regex) => decodeOnePointEntities(extract(html, regex).trim());
|
|
627
|
+
const pickLi = (label) => {
|
|
628
|
+
const regex = new RegExp(`<li>\\s*${label}[::\\s]*(?:<[^>]+>)?\\s*([^<]+?)\\s*(?:<|$)`);
|
|
629
|
+
return pick(regex);
|
|
630
|
+
};
|
|
631
|
+
const username = pick(/<p class="mtm[^"]*"[^>]*>\s*<a [^>]*>([^<]+?)<\/a>/) ||
|
|
632
|
+
pick(/<title>([^<]+?)的个人资料/);
|
|
633
|
+
const uid = pick(/uid=(\d+)/) || pick(/space-uid-(\d+)\.html/);
|
|
634
|
+
return [
|
|
635
|
+
{
|
|
636
|
+
uid,
|
|
637
|
+
username,
|
|
638
|
+
group: pickLi("用户组"),
|
|
639
|
+
credits: pickLi("积分"),
|
|
640
|
+
rice: pickLi("大米"),
|
|
641
|
+
posts: pickLi("帖子数"),
|
|
642
|
+
threads: pickLi("主题数"),
|
|
643
|
+
digests: pickLi("精华数"),
|
|
644
|
+
registerTime: pickLi("注册时间"),
|
|
645
|
+
lastAccess: pickLi("最后访问"),
|
|
646
|
+
profileUrl: uid ? `${ONEPOINT_BASE}/space-uid-${uid}.html` : url,
|
|
647
|
+
},
|
|
648
|
+
];
|
|
649
|
+
},
|
|
650
|
+
});
|
|
651
|
+
cli({
|
|
652
|
+
site: "1point3acres",
|
|
653
|
+
name: "notifications",
|
|
654
|
+
description: "Read 1Point3Acres account notifications using browser cookies",
|
|
655
|
+
domain: ONEPOINT_HOST,
|
|
656
|
+
strategy: Strategy.COOKIE,
|
|
657
|
+
browser: true,
|
|
658
|
+
args: [
|
|
659
|
+
{
|
|
660
|
+
name: "kind",
|
|
661
|
+
type: "str",
|
|
662
|
+
default: "mypost",
|
|
663
|
+
description: "Notice type: mypost, interactive, system, or app",
|
|
664
|
+
},
|
|
665
|
+
{ name: "limit", type: "int", default: 20, description: "Number of rows" },
|
|
666
|
+
],
|
|
667
|
+
columns: ONEPOINT_NOTIFICATION_COLUMNS,
|
|
668
|
+
func: async (page, kwargs) => {
|
|
669
|
+
const kind = cleanString(kwargs.kind || "mypost");
|
|
670
|
+
const limit = normalizeOnePointPositiveInteger(kwargs.limit, 20, "limit");
|
|
671
|
+
const cookie = await getOnePointCookie(page);
|
|
672
|
+
const html = await fetchOnePointHtml(`${ONEPOINT_BASE}/home.php?mod=space&do=notice&view=${encodeURIComponent(kind)}`, { cookie, headers: { Referer: `${ONEPOINT_BASE}/` } });
|
|
673
|
+
if (/<title>提示信息/.test(html) && /请登录/.test(html)) {
|
|
674
|
+
throw new Error("Login to www.1point3acres.com is required");
|
|
675
|
+
}
|
|
676
|
+
if (/暂时没有提醒内容/.test(html)) {
|
|
677
|
+
throw new Error("No 1Point3Acres notifications are available");
|
|
678
|
+
}
|
|
679
|
+
const rows = [];
|
|
680
|
+
const regex = /<dl class="[^"]*cl[^"]*"[^>]*>([\s\S]*?)<\/dl>/g;
|
|
681
|
+
let match;
|
|
682
|
+
let index = 0;
|
|
683
|
+
while ((match = regex.exec(html)) && rows.length < limit) {
|
|
684
|
+
const block = match[1];
|
|
685
|
+
const from = decodeOnePointEntities(extract(block, /<dt>([\s\S]*?)<\/dt>/))
|
|
686
|
+
.replace(/<[^>]+>/g, "")
|
|
687
|
+
.trim();
|
|
688
|
+
const summaryRaw = extract(block, /<dd class="ntc_body">([\s\S]*?)<\/dd>/) ||
|
|
689
|
+
extract(block, /<dd>([\s\S]*?)<\/dd>/);
|
|
690
|
+
const summary = truncateOnePoint(stripOnePointHtml(summaryRaw), 200);
|
|
691
|
+
const time = extract(block, /<dd class="[^"]*xg1[^"]*"[^>]*>([\s\S]*?)<\/dd>/)
|
|
692
|
+
.replace(/<[^>]+>/g, "")
|
|
693
|
+
.trim();
|
|
694
|
+
const link = summaryRaw.match(/href="([^"]*thread-\d+[^"]*)"/);
|
|
695
|
+
const threadUrl = link
|
|
696
|
+
? link[1].startsWith("http")
|
|
697
|
+
? link[1]
|
|
698
|
+
: `${ONEPOINT_BASE}/${link[1]}`
|
|
699
|
+
: "";
|
|
700
|
+
index += 1;
|
|
701
|
+
if (!from && !summary)
|
|
702
|
+
continue;
|
|
703
|
+
rows.push({ index, from, summary, time, threadUrl });
|
|
704
|
+
}
|
|
705
|
+
return rows;
|
|
706
|
+
},
|
|
707
|
+
});
|
|
708
|
+
//# sourceMappingURL=forum.js.map
|