@zenalexa/unicli 0.209.0 → 0.210.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 +56 -15
- package/README.md +228 -278
- package/dist/adapters/cursor/cursor.d.ts +2 -1
- package/dist/adapters/cursor/cursor.d.ts.map +1 -1
- package/dist/adapters/cursor/cursor.js +87 -1
- package/dist/adapters/cursor/cursor.js.map +1 -1
- package/dist/adapters/discord-app/discord-app.d.ts +1 -1
- package/dist/adapters/discord-app/discord-app.js +94 -1
- package/dist/adapters/discord-app/discord-app.js.map +1 -1
- package/dist/browser/bridge.d.ts +45 -0
- package/dist/browser/bridge.d.ts.map +1 -1
- package/dist/browser/bridge.js +94 -1
- package/dist/browser/bridge.js.map +1 -1
- package/dist/browser/cdp-client.d.ts +24 -1
- package/dist/browser/cdp-client.d.ts.map +1 -1
- package/dist/browser/cdp-client.js +56 -2
- package/dist/browser/cdp-client.js.map +1 -1
- package/dist/browser/launcher.d.ts +5 -0
- package/dist/browser/launcher.d.ts.map +1 -1
- package/dist/browser/launcher.js +7 -0
- package/dist/browser/launcher.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +67 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/browser.d.ts.map +1 -1
- package/dist/commands/browser.js +79 -1
- package/dist/commands/browser.js.map +1 -1
- package/dist/commands/ext.d.ts +11 -0
- package/dist/commands/ext.d.ts.map +1 -0
- package/dist/commands/ext.js +122 -0
- package/dist/commands/ext.js.map +1 -0
- package/dist/commands/skills.d.ts +2 -3
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +2 -3
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +12 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +137 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/engine/yaml-runner.d.ts +10 -0
- package/dist/engine/yaml-runner.d.ts.map +1 -1
- package/dist/engine/yaml-runner.js +51 -3
- package/dist/engine/yaml-runner.js.map +1 -1
- package/dist/hub/index.d.ts +37 -0
- package/dist/hub/index.d.ts.map +1 -0
- package/dist/hub/index.js +98 -0
- package/dist/hub/index.js.map +1 -0
- package/dist/hub/passthrough.d.ts +21 -0
- package/dist/hub/passthrough.d.ts.map +1 -0
- package/dist/hub/passthrough.js +71 -0
- package/dist/hub/passthrough.js.map +1 -0
- package/dist/manifest.json +1770 -64
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -1
- package/src/adapters/36kr/latest.yaml +36 -0
- package/src/adapters/arxiv/trending.yaml +37 -0
- package/src/adapters/baidu/hot.yaml +37 -0
- package/src/adapters/baidu/search.yaml +41 -0
- package/src/adapters/bbc/technology.yaml +26 -0
- package/src/adapters/bbc/top.yaml +26 -0
- package/src/adapters/bbc/world.yaml +26 -0
- package/src/adapters/bilibili/coin.yaml +33 -0
- package/src/adapters/bilibili/later.yaml +31 -0
- package/src/adapters/bilibili/live.yaml +41 -0
- package/src/adapters/bilibili/trending.yaml +29 -0
- package/src/adapters/binance/hot.yaml +39 -0
- package/src/adapters/binance/kline.yaml +35 -0
- package/src/adapters/binance/ticker.yaml +33 -0
- package/src/adapters/bluesky/likes.yaml +35 -0
- package/src/adapters/bluesky/notifications.yaml +30 -0
- package/src/adapters/bluesky/post.yaml +25 -0
- package/src/adapters/chrome/bookmarks.yaml +26 -0
- package/src/adapters/chrome/tabs.yaml +25 -0
- package/src/adapters/cnki/search.yaml +40 -0
- package/src/adapters/cnn/technology.yaml +26 -0
- package/src/adapters/cocoapods/info.yaml +33 -0
- package/src/adapters/coinbase/prices.yaml +27 -0
- package/src/adapters/coinbase/rates.yaml +24 -0
- package/src/adapters/coupang/hot.yaml +29 -0
- package/src/adapters/crates-io/info.yaml +29 -0
- package/src/adapters/crates-io/versions.yaml +33 -0
- package/src/adapters/ctrip/hot.yaml +28 -0
- package/src/adapters/cursor/cursor.ts +91 -1
- package/src/adapters/dangdang/hot.yaml +38 -0
- package/src/adapters/dangdang/search.yaml +43 -0
- package/src/adapters/deepseek/chat.yaml +33 -0
- package/src/adapters/deepseek/models.yaml +18 -0
- package/src/adapters/devto/latest.yaml +29 -0
- package/src/adapters/devto/search.yaml +34 -0
- package/src/adapters/dianping/hot.yaml +43 -0
- package/src/adapters/dianping/search.yaml +48 -0
- package/src/adapters/discord-app/discord-app.ts +99 -1
- package/src/adapters/docker/networks.yaml +20 -0
- package/src/adapters/docker/volumes.yaml +19 -0
- package/src/adapters/docker-hub/info.yaml +26 -0
- package/src/adapters/docker-hub/tags.yaml +34 -0
- package/src/adapters/douban/group-hot.yaml +29 -0
- package/src/adapters/douban/new-movies.yaml +32 -0
- package/src/adapters/douban/tv-hot.yaml +32 -0
- package/src/adapters/doubao/ask.yaml +64 -0
- package/src/adapters/doubao/new.yaml +18 -0
- package/src/adapters/doubao/status.yaml +21 -0
- package/src/adapters/douyu/hot.yaml +34 -0
- package/src/adapters/douyu/search.yaml +42 -0
- package/src/adapters/eastmoney/fund.yaml +36 -0
- package/src/adapters/eastmoney/market.yaml +26 -0
- package/src/adapters/ele/hot.yaml +40 -0
- package/src/adapters/ele/search.yaml +47 -0
- package/src/adapters/exchangerate/list.yaml +25 -0
- package/src/adapters/facebook/marketplace.yaml +43 -0
- package/src/adapters/facebook/post.yaml +29 -0
- package/src/adapters/futu/hot.yaml +49 -0
- package/src/adapters/futu/quote.yaml +46 -0
- package/src/adapters/gitee/repos.yaml +34 -0
- package/src/adapters/github-trending/developers.yaml +33 -0
- package/src/adapters/github-trending/weekly.yaml +34 -0
- package/src/adapters/gitlab/projects.yaml +34 -0
- package/src/adapters/godot/scene-export.yaml +1 -1
- package/src/adapters/hackernews/comments.yaml +36 -0
- package/src/adapters/hackernews/item.yaml +28 -0
- package/src/adapters/hf/datasets.yaml +34 -0
- package/src/adapters/hf/spaces.yaml +34 -0
- package/src/adapters/homebrew/search.yaml +27 -0
- package/src/adapters/huggingface-papers/search.yaml +33 -0
- package/src/adapters/imdb/box-office.yaml +28 -0
- package/src/adapters/infoq/latest.yaml +26 -0
- package/src/adapters/instagram/activity.yaml +45 -0
- package/src/adapters/instagram/highlights.yaml +48 -0
- package/src/adapters/instagram/reels-trending.yaml +51 -0
- package/src/adapters/instagram/reels.yaml +34 -0
- package/src/adapters/instagram/stories.yaml +29 -0
- package/src/adapters/instagram/suggested.yaml +40 -0
- package/src/adapters/instagram/tags.yaml +52 -0
- package/src/adapters/itch-io/search.yaml +35 -0
- package/src/adapters/itch-io/top.yaml +31 -0
- package/src/adapters/ithome/hot.yaml +27 -0
- package/src/adapters/ithome/latest.yaml +26 -0
- package/src/adapters/jianyu/search.yaml +42 -0
- package/src/adapters/ke/ershoufang.yaml +75 -0
- package/src/adapters/ke/xiaoqu.yaml +73 -0
- package/src/adapters/kuaishou/hot.yaml +39 -0
- package/src/adapters/kuaishou/search.yaml +44 -0
- package/src/adapters/linkedin/jobs.yaml +47 -0
- package/src/adapters/lobsters/search.yaml +35 -0
- package/src/adapters/macos/active-app.yaml +16 -0
- package/src/adapters/macos/apps-list.yaml +14 -0
- package/src/adapters/macos/apps.yaml +31 -0
- package/src/adapters/macos/battery.yaml +26 -0
- package/src/adapters/macos/bluetooth.yaml +14 -0
- package/src/adapters/macos/brightness.yaml +22 -0
- package/src/adapters/macos/caffeinate.yaml +25 -0
- package/src/adapters/macos/calendar-create.yaml +81 -0
- package/src/adapters/macos/calendar-list.yaml +53 -0
- package/src/adapters/macos/calendar-today.yaml +30 -0
- package/src/adapters/macos/clipboard.yaml +23 -0
- package/src/adapters/macos/contacts-search.yaml +59 -0
- package/src/adapters/macos/dark-mode.yaml +19 -0
- package/src/adapters/macos/disk-info.yaml +31 -0
- package/src/adapters/macos/disk-usage.yaml +14 -0
- package/src/adapters/macos/do-not-disturb.yaml +21 -0
- package/src/adapters/macos/empty-trash.yaml +16 -0
- package/src/adapters/macos/finder-recent.yaml +24 -0
- package/src/adapters/macos/finder-selection.yaml +22 -0
- package/src/adapters/macos/finder-tags.yaml +40 -0
- package/src/adapters/macos/lock-screen.yaml +16 -0
- package/src/adapters/macos/mail-send.yaml +54 -0
- package/src/adapters/macos/mail-status.yaml +38 -0
- package/src/adapters/macos/messages-send.yaml +42 -0
- package/src/adapters/macos/music-control.yaml +43 -0
- package/src/adapters/macos/music-now.yaml +34 -0
- package/src/adapters/macos/notes-list.yaml +30 -0
- package/src/adapters/macos/notes-search.yaml +45 -0
- package/src/adapters/macos/notification.yaml +27 -0
- package/src/adapters/macos/notify.yaml +46 -0
- package/src/adapters/macos/open-app.yaml +21 -0
- package/src/adapters/macos/open.yaml +24 -0
- package/src/adapters/macos/photos-search.yaml +44 -0
- package/src/adapters/macos/processes.yaml +14 -0
- package/src/adapters/macos/reminder-create.yaml +75 -0
- package/src/adapters/macos/reminders-complete.yaml +33 -0
- package/src/adapters/macos/reminders-list.yaml +28 -0
- package/src/adapters/macos/safari-tabs.yaml +26 -0
- package/src/adapters/macos/say.yaml +36 -0
- package/src/adapters/macos/screen-lock.yaml +16 -0
- package/src/adapters/macos/screenshot.yaml +34 -0
- package/src/adapters/macos/shortcuts-list.yaml +14 -0
- package/src/adapters/macos/shortcuts-run.yaml +28 -0
- package/src/adapters/macos/sleep.yaml +14 -0
- package/src/adapters/macos/spotlight.yaml +43 -0
- package/src/adapters/macos/system-info.yaml +32 -0
- package/src/adapters/macos/trash.yaml +32 -0
- package/src/adapters/macos/uptime.yaml +14 -0
- package/src/adapters/macos/volume.yaml +19 -0
- package/src/adapters/macos/wifi-info.yaml +14 -0
- package/src/adapters/macos/wifi.yaml +63 -0
- package/src/adapters/maimai/search.yaml +62 -0
- package/src/adapters/maoyan/hot.yaml +33 -0
- package/src/adapters/maoyan/search.yaml +40 -0
- package/src/adapters/mastodon/timeline.yaml +33 -0
- package/src/adapters/mastodon/user.yaml +32 -0
- package/src/adapters/medium/article.yaml +22 -0
- package/src/adapters/medium/trending.yaml +30 -0
- package/src/adapters/meituan/hot.yaml +26 -0
- package/src/adapters/mubu/list.yaml +36 -0
- package/src/adapters/mubu/search.yaml +54 -0
- package/src/adapters/netease-music/playlist.yaml +34 -0
- package/src/adapters/netease-music/top.yaml +33 -0
- package/src/adapters/notion/databases.yaml +41 -0
- package/src/adapters/notion/pages.yaml +44 -0
- package/src/adapters/notion/search.yaml +41 -0
- package/src/adapters/npm/downloads.yaml +28 -0
- package/src/adapters/npm/info.yaml +25 -0
- package/src/adapters/npm/search.yaml +35 -0
- package/src/adapters/npm/versions.yaml +33 -0
- package/src/adapters/npm-trends/trending.yaml +17 -0
- package/src/adapters/nytimes/search.yaml +35 -0
- package/src/adapters/obsidian/daily.yaml +23 -0
- package/src/adapters/obsidian/open.yaml +26 -0
- package/src/adapters/obsidian/search.yaml +28 -0
- package/src/adapters/ollama/generate.yaml +33 -0
- package/src/adapters/ollama/models.yaml +29 -0
- package/src/adapters/ollama/ps.yaml +20 -0
- package/src/adapters/openrouter/search.yaml +31 -0
- package/src/adapters/perplexity/ask.yaml +33 -0
- package/src/adapters/pexels/curated.yaml +31 -0
- package/src/adapters/pinduoduo/search.yaml +36 -0
- package/src/adapters/producthunt/search.yaml +41 -0
- package/src/adapters/pypi/search.yaml +37 -0
- package/src/adapters/pypi/versions.yaml +31 -0
- package/src/adapters/quark/ls.yaml +39 -0
- package/src/adapters/quark/search.yaml +39 -0
- package/src/adapters/qweather/forecast.yaml +37 -0
- package/src/adapters/reddit/new.yaml +34 -0
- package/src/adapters/reddit/rising.yaml +33 -0
- package/src/adapters/reddit/top.yaml +40 -0
- package/src/adapters/reddit/trending.yaml +25 -0
- package/src/adapters/replicate/run.yaml +39 -0
- package/src/adapters/reuters/latest.yaml +26 -0
- package/src/adapters/sinafinance/market.yaml +21 -0
- package/src/adapters/slack/messages.yaml +41 -0
- package/src/adapters/slack/post.yaml +32 -0
- package/src/adapters/slack/search.yaml +28 -0
- package/src/adapters/slack/send.yaml +35 -0
- package/src/adapters/slack/status.yaml +19 -0
- package/src/adapters/slack/users.yaml +37 -0
- package/src/adapters/slock/servers.yaml +32 -0
- package/src/adapters/spotify/now-playing.yaml +28 -0
- package/src/adapters/spotify/playlists.yaml +37 -0
- package/src/adapters/spotify/top-tracks.yaml +42 -0
- package/src/adapters/stackoverflow/question.yaml +34 -0
- package/src/adapters/stackoverflow/tags.yaml +30 -0
- package/src/adapters/steam/app-details.yaml +32 -0
- package/src/adapters/steam/new-releases.yaml +28 -0
- package/src/adapters/steam/search.yaml +36 -0
- package/src/adapters/steam/specials.yaml +29 -0
- package/src/adapters/steam/wishlist.yaml +36 -0
- package/src/adapters/substack/trending.yaml +28 -0
- package/src/adapters/taobao/hot.yaml +31 -0
- package/src/adapters/taobao/search.yaml +44 -0
- package/src/adapters/techcrunch/search.yaml +33 -0
- package/src/adapters/theverge/search.yaml +33 -0
- package/src/adapters/threads/hot.yaml +44 -0
- package/src/adapters/threads/search.yaml +47 -0
- package/src/adapters/tiktok/trending.yaml +28 -0
- package/src/adapters/toutiao/hot.yaml +31 -0
- package/src/adapters/toutiao/search.yaml +47 -0
- package/src/adapters/twitch/games.yaml +31 -0
- package/src/adapters/twitch/search.yaml +39 -0
- package/src/adapters/twitch/streams.yaml +38 -0
- package/src/adapters/twitter/lists.yaml +49 -0
- package/src/adapters/twitter/media.yaml +48 -0
- package/src/adapters/twitter/mentions.yaml +38 -0
- package/src/adapters/twitter/mute.yaml +42 -0
- package/src/adapters/twitter/pin.yaml +43 -0
- package/src/adapters/twitter/quotes.yaml +43 -0
- package/src/adapters/twitter/retweets.yaml +44 -0
- package/src/adapters/twitter/spaces.yaml +43 -0
- package/src/adapters/twitter/unmute.yaml +42 -0
- package/src/adapters/unsplash/random.yaml +27 -0
- package/src/adapters/v2ex/search.yaml +36 -0
- package/src/adapters/vscode/extensions.yaml +23 -0
- package/src/adapters/vscode/install-ext.yaml +26 -0
- package/src/adapters/vscode/open.yaml +25 -0
- package/src/adapters/wechat-channels/hot.yaml +39 -0
- package/src/adapters/wechat-channels/search.yaml +57 -0
- package/src/adapters/weibo/trending.yaml +28 -0
- package/src/adapters/weixin/hot.yaml +22 -0
- package/src/adapters/wikipedia/today.yaml +25 -0
- package/src/adapters/xiaohongshu/follow.yaml +35 -0
- package/src/adapters/xiaohongshu/hashtag.yaml +44 -0
- package/src/adapters/xiaohongshu/hot.yaml +34 -0
- package/src/adapters/xiaohongshu/like.yaml +27 -0
- package/src/adapters/xiaohongshu/profile.yaml +39 -0
- package/src/adapters/xiaohongshu/save.yaml +27 -0
- package/src/adapters/xiaohongshu/suggest.yaml +34 -0
- package/src/adapters/xiaohongshu/trending.yaml +35 -0
- package/src/adapters/xiaohongshu/unfollow.yaml +40 -0
- package/src/adapters/xueqiu/market.yaml +25 -0
- package/src/adapters/yahoo-finance/quote.yaml +35 -0
- package/src/adapters/yahoo-finance/search.yaml +42 -0
- package/src/adapters/yahoo-finance/trending.yaml +30 -0
- package/src/adapters/youtube/playlist.yaml +43 -0
- package/src/adapters/youtube/shorts.yaml +42 -0
- package/src/adapters/youtube/trending.yaml +41 -0
- package/src/adapters/zhihu/answer.yaml +29 -0
- package/src/adapters/zhihu/answers.yaml +38 -0
- package/src/adapters/zhihu/article.yaml +27 -0
- package/src/adapters/zhihu/articles.yaml +38 -0
- package/src/adapters/zhihu/collections.yaml +37 -0
- package/src/adapters/zhihu/columns.yaml +38 -0
- package/src/adapters/zhihu/comment.yaml +42 -0
- package/src/adapters/zhihu/followers.yaml +37 -0
- package/src/adapters/zhihu/following.yaml +37 -0
- package/src/adapters/zhihu/pins.yaml +37 -0
- package/src/adapters/zhihu/topic.yaml +35 -0
- package/src/adapters/zhihu/topics.yaml +37 -0
- package/src/adapters/zhihu/trending.yaml +36 -0
- package/src/adapters/zhihu/user.yaml +30 -0
- package/src/adapters/zoom/join.yaml +24 -0
- package/src/adapters/zoom/start.yaml +17 -0
- package/src/hub/external-clis.yaml +343 -0
- package/src/hub/index.ts +128 -0
- package/src/hub/passthrough.ts +85 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Desktop adapter — list open Chrome tabs via JXA (macOS)
|
|
2
|
+
site: chrome
|
|
3
|
+
name: tabs
|
|
4
|
+
description: List all open tabs in Google Chrome (macOS)
|
|
5
|
+
type: desktop
|
|
6
|
+
detect: Darwin
|
|
7
|
+
strategy: public
|
|
8
|
+
|
|
9
|
+
pipeline:
|
|
10
|
+
- exec:
|
|
11
|
+
command: osascript
|
|
12
|
+
args:
|
|
13
|
+
- "-l"
|
|
14
|
+
- "JavaScript"
|
|
15
|
+
- "-e"
|
|
16
|
+
- "var chrome = Application('Google Chrome'); var tabs = []; chrome.windows().forEach(function(w, wi) { w.tabs().forEach(function(t) { tabs.push({window: wi, title: t.title(), url: t.url()}); }); }); JSON.stringify(tabs);"
|
|
17
|
+
parse: json
|
|
18
|
+
timeout: 10000
|
|
19
|
+
|
|
20
|
+
- map:
|
|
21
|
+
window: "${{ item.window }}"
|
|
22
|
+
title: "${{ item.title }}"
|
|
23
|
+
url: "${{ item.url }}"
|
|
24
|
+
|
|
25
|
+
columns: [window, title, url]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
site: cnki
|
|
2
|
+
name: search
|
|
3
|
+
description: Search CNKI academic papers
|
|
4
|
+
domain: scholar.cnki.net
|
|
5
|
+
type: web-api
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
query:
|
|
10
|
+
type: str
|
|
11
|
+
required: true
|
|
12
|
+
positional: true
|
|
13
|
+
description: Search query
|
|
14
|
+
limit:
|
|
15
|
+
type: int
|
|
16
|
+
default: 20
|
|
17
|
+
description: Maximum results
|
|
18
|
+
|
|
19
|
+
pipeline:
|
|
20
|
+
- fetch:
|
|
21
|
+
url: https://scholar.cnki.net/api/search
|
|
22
|
+
params:
|
|
23
|
+
q: "${{ args.query }}"
|
|
24
|
+
page: "1"
|
|
25
|
+
size: "${{ args.limit }}"
|
|
26
|
+
sort: relevant
|
|
27
|
+
|
|
28
|
+
- select: data.items
|
|
29
|
+
|
|
30
|
+
- map:
|
|
31
|
+
rank: ${{ index + 1 }}
|
|
32
|
+
title: "${{ (item.title || '') | strip_html }}"
|
|
33
|
+
authors: "${{ (item.authors || []).map(a => a.name).join(', ') }}"
|
|
34
|
+
source: "${{ item.publicationName || '' }}"
|
|
35
|
+
year: "${{ item.year || '' }}"
|
|
36
|
+
citations: ${{ item.citedCount || 0 }}
|
|
37
|
+
|
|
38
|
+
- limit: ${{ args.limit }}
|
|
39
|
+
|
|
40
|
+
columns: [rank, title, authors, source, year, citations]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
site: cnn
|
|
2
|
+
name: technology
|
|
3
|
+
description: CNN technology news
|
|
4
|
+
domain: edition.cnn.com
|
|
5
|
+
type: web-api
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
limit:
|
|
10
|
+
type: int
|
|
11
|
+
default: 20
|
|
12
|
+
|
|
13
|
+
pipeline:
|
|
14
|
+
- fetch_text:
|
|
15
|
+
url: http://rss.cnn.com/rss/edition_technology.rss
|
|
16
|
+
|
|
17
|
+
- parse_rss:
|
|
18
|
+
fields:
|
|
19
|
+
title: title
|
|
20
|
+
description: description
|
|
21
|
+
link: link
|
|
22
|
+
pubDate: pubDate
|
|
23
|
+
|
|
24
|
+
- limit: "${{ args.limit }}"
|
|
25
|
+
|
|
26
|
+
columns: [title, description, pubDate]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
site: cocoapods
|
|
2
|
+
name: info
|
|
3
|
+
description: Get CocoaPods pod details
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: cocoapods.org
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
pod:
|
|
10
|
+
required: true
|
|
11
|
+
positional: true
|
|
12
|
+
description: Pod name (e.g. "Alamofire", "SnapKit")
|
|
13
|
+
|
|
14
|
+
pipeline:
|
|
15
|
+
- fetch:
|
|
16
|
+
url: "https://trunk.cocoapods.org/api/v1/pods/${{ args.pod }}"
|
|
17
|
+
|
|
18
|
+
- map:
|
|
19
|
+
name: ${{ item.name || '' }}
|
|
20
|
+
versions: "${{ item.versions ? item.versions.length : 0 }}"
|
|
21
|
+
|
|
22
|
+
- fetch:
|
|
23
|
+
url: "https://trunk.cocoapods.org/api/v1/pods/${{ args.pod }}/specs/latest"
|
|
24
|
+
|
|
25
|
+
- map:
|
|
26
|
+
name: ${{ item.name }}
|
|
27
|
+
version: ${{ item.version }}
|
|
28
|
+
summary: "${{ item.summary || '' }}"
|
|
29
|
+
homepage: "${{ item.homepage || '' }}"
|
|
30
|
+
license: "${{ item.license ? (item.license.type || item.license) : '' }}"
|
|
31
|
+
source: "${{ item.source ? item.source.git || '' : '' }}"
|
|
32
|
+
|
|
33
|
+
columns: [name, version, summary, homepage, license]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
site: coinbase
|
|
2
|
+
name: prices
|
|
3
|
+
description: Get cryptocurrency spot prices from Coinbase
|
|
4
|
+
domain: api.coinbase.com
|
|
5
|
+
type: web-api
|
|
6
|
+
strategy: public
|
|
7
|
+
browser: false
|
|
8
|
+
|
|
9
|
+
args:
|
|
10
|
+
pair:
|
|
11
|
+
type: str
|
|
12
|
+
default: BTC-USD
|
|
13
|
+
positional: true
|
|
14
|
+
description: Trading pair (e.g. BTC-USD, ETH-USD)
|
|
15
|
+
|
|
16
|
+
pipeline:
|
|
17
|
+
- fetch:
|
|
18
|
+
url: https://api.coinbase.com/v2/prices/${{ args.pair }}/spot
|
|
19
|
+
|
|
20
|
+
- select: data
|
|
21
|
+
|
|
22
|
+
- map:
|
|
23
|
+
pair: ${{ args.pair }}
|
|
24
|
+
price: ${{ item.amount }}
|
|
25
|
+
currency: ${{ item.currency }}
|
|
26
|
+
|
|
27
|
+
columns: [pair, price, currency]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
site: coinbase
|
|
2
|
+
name: rates
|
|
3
|
+
description: Get cryptocurrency exchange rates from Coinbase
|
|
4
|
+
domain: api.coinbase.com
|
|
5
|
+
type: web-api
|
|
6
|
+
strategy: public
|
|
7
|
+
browser: false
|
|
8
|
+
|
|
9
|
+
args:
|
|
10
|
+
currency:
|
|
11
|
+
type: str
|
|
12
|
+
default: USD
|
|
13
|
+
positional: true
|
|
14
|
+
description: Base currency for rates (e.g. USD, EUR, BTC)
|
|
15
|
+
|
|
16
|
+
pipeline:
|
|
17
|
+
- fetch:
|
|
18
|
+
url: https://api.coinbase.com/v2/exchange-rates
|
|
19
|
+
params:
|
|
20
|
+
currency: ${{ args.currency }}
|
|
21
|
+
|
|
22
|
+
- select: data
|
|
23
|
+
|
|
24
|
+
columns: [currency, rates]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
site: coupang
|
|
2
|
+
name: hot
|
|
3
|
+
description: Coupang trending/popular products
|
|
4
|
+
domain: www.coupang.com
|
|
5
|
+
type: web-api
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
limit:
|
|
10
|
+
type: int
|
|
11
|
+
default: 20
|
|
12
|
+
|
|
13
|
+
pipeline:
|
|
14
|
+
- fetch:
|
|
15
|
+
url: https://www.coupang.com/np/goldbox
|
|
16
|
+
headers:
|
|
17
|
+
Accept: application/json
|
|
18
|
+
|
|
19
|
+
- select: data.products
|
|
20
|
+
|
|
21
|
+
- map:
|
|
22
|
+
rank: ${{ index + 1 }}
|
|
23
|
+
title: "${{ (item.name || item.title || '') | truncate(80) }}"
|
|
24
|
+
price: "${{ item.price || item.salePrice || '' }}"
|
|
25
|
+
discount: "${{ item.discountRate || '' }}"
|
|
26
|
+
|
|
27
|
+
- limit: ${{ args.limit }}
|
|
28
|
+
|
|
29
|
+
columns: [rank, title, price, discount]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
site: crates-io
|
|
2
|
+
name: info
|
|
3
|
+
description: Get Rust crate details from crates.io
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: crates.io
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
crate:
|
|
10
|
+
required: true
|
|
11
|
+
positional: true
|
|
12
|
+
description: Crate name
|
|
13
|
+
|
|
14
|
+
pipeline:
|
|
15
|
+
- fetch:
|
|
16
|
+
url: "https://crates.io/api/v1/crates/${{ args.crate }}"
|
|
17
|
+
headers:
|
|
18
|
+
User-Agent: "unicli (github.com/olo-dot-io/uni-cli)"
|
|
19
|
+
|
|
20
|
+
- select: crate
|
|
21
|
+
|
|
22
|
+
- map:
|
|
23
|
+
name: ${{ item.name }}
|
|
24
|
+
version: ${{ item.max_version }}
|
|
25
|
+
downloads: ${{ item.downloads }}
|
|
26
|
+
description: ${{ item.description }}
|
|
27
|
+
repository: ${{ item.repository }}
|
|
28
|
+
|
|
29
|
+
columns: [name, version, downloads, description, repository]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
site: crates-io
|
|
2
|
+
name: versions
|
|
3
|
+
description: List versions of a Rust crate
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: crates.io
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
crate:
|
|
10
|
+
required: true
|
|
11
|
+
positional: true
|
|
12
|
+
description: Crate name
|
|
13
|
+
limit:
|
|
14
|
+
type: int
|
|
15
|
+
default: 20
|
|
16
|
+
|
|
17
|
+
pipeline:
|
|
18
|
+
- fetch:
|
|
19
|
+
url: "https://crates.io/api/v1/crates/${{ args.crate }}/versions"
|
|
20
|
+
headers:
|
|
21
|
+
User-Agent: "unicli (github.com/olo-dot-io/uni-cli)"
|
|
22
|
+
|
|
23
|
+
- select: versions
|
|
24
|
+
|
|
25
|
+
- map:
|
|
26
|
+
version: ${{ item.num }}
|
|
27
|
+
downloads: ${{ item.downloads }}
|
|
28
|
+
created: "${{ item.created_at }}"
|
|
29
|
+
yanked: ${{ item.yanked }}
|
|
30
|
+
|
|
31
|
+
- limit: ${{ args.limit }}
|
|
32
|
+
|
|
33
|
+
columns: [version, downloads, created, yanked]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
site: ctrip
|
|
2
|
+
name: hot
|
|
3
|
+
description: Ctrip popular travel destinations
|
|
4
|
+
domain: m.ctrip.com
|
|
5
|
+
type: web-api
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
limit:
|
|
10
|
+
type: int
|
|
11
|
+
default: 20
|
|
12
|
+
|
|
13
|
+
pipeline:
|
|
14
|
+
- fetch:
|
|
15
|
+
url: https://m.ctrip.com/restapi/h5api/searchapp/search
|
|
16
|
+
params:
|
|
17
|
+
action: hotcity
|
|
18
|
+
|
|
19
|
+
- select: data
|
|
20
|
+
|
|
21
|
+
- map:
|
|
22
|
+
rank: ${{ index + 1 }}
|
|
23
|
+
name: "${{ item.word || item.name || '' }}"
|
|
24
|
+
type: "${{ item.type || '' }}"
|
|
25
|
+
|
|
26
|
+
- limit: ${{ args.limit }}
|
|
27
|
+
|
|
28
|
+
columns: [rank, name, type]
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cursor IDE adapter -- AI chat + composer + code extraction.
|
|
3
3
|
*
|
|
4
|
-
* Commands: ask, send, read, model, status, new, screenshot, dump,
|
|
4
|
+
* Commands: ask, send, read, model, status, new, screenshot, dump,
|
|
5
|
+
* composer, extract-code, export, history
|
|
5
6
|
*/
|
|
6
7
|
|
|
8
|
+
import { writeFileSync } from "node:fs";
|
|
7
9
|
import {
|
|
8
10
|
registerAIChatCommands,
|
|
9
11
|
connectElectronApp,
|
|
@@ -66,3 +68,91 @@ cli({
|
|
|
66
68
|
return code as unknown[];
|
|
67
69
|
},
|
|
68
70
|
});
|
|
71
|
+
|
|
72
|
+
// export -- Export current conversation to Markdown file
|
|
73
|
+
cli({
|
|
74
|
+
site: "cursor",
|
|
75
|
+
name: "export",
|
|
76
|
+
description: "Export the current Cursor conversation to a Markdown file",
|
|
77
|
+
strategy: Strategy.PUBLIC,
|
|
78
|
+
args: [
|
|
79
|
+
{
|
|
80
|
+
name: "output",
|
|
81
|
+
required: false,
|
|
82
|
+
positional: true,
|
|
83
|
+
default: "/tmp/cursor-export.md",
|
|
84
|
+
description: "Output file path",
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
func: async (_page: unknown, kwargs: Record<string, unknown>) => {
|
|
88
|
+
const outputPath = String(kwargs.output ?? "/tmp/cursor-export.md");
|
|
89
|
+
const p = await connectElectronApp("cursor");
|
|
90
|
+
const md = (await p.evaluate(`
|
|
91
|
+
(() => {
|
|
92
|
+
const selectors = '[data-message-role]';
|
|
93
|
+
const messages = Array.from(document.querySelectorAll(selectors));
|
|
94
|
+
if (messages.length === 0) {
|
|
95
|
+
const main = document.querySelector('main, [role="main"], .messages-list');
|
|
96
|
+
if (main) return [main.innerText || main.textContent];
|
|
97
|
+
return [document.body.innerText];
|
|
98
|
+
}
|
|
99
|
+
return messages.map((m, i) => {
|
|
100
|
+
const role = m.getAttribute('data-message-role');
|
|
101
|
+
const root = m.querySelector('.markdown-root');
|
|
102
|
+
const text = root ? root.innerText : m.innerText;
|
|
103
|
+
return '## ' + (role === 'human' ? 'User' : 'Assistant') + '\\n\\n' + (text || '').trim();
|
|
104
|
+
}).join('\\n\\n---\\n\\n');
|
|
105
|
+
})()
|
|
106
|
+
`)) as string;
|
|
107
|
+
|
|
108
|
+
writeFileSync(outputPath, `# Cursor Conversation Export\n\n${md}`);
|
|
109
|
+
const messageCount = (md.match(/^## /gm) || []).length;
|
|
110
|
+
return [{ status: "exported", file: outputPath, messages: messageCount }];
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// history -- List recent chat sessions from Cursor sidebar
|
|
115
|
+
cli({
|
|
116
|
+
site: "cursor",
|
|
117
|
+
name: "history",
|
|
118
|
+
description: "List recent chat sessions from the Cursor sidebar",
|
|
119
|
+
strategy: Strategy.PUBLIC,
|
|
120
|
+
func: async () => {
|
|
121
|
+
const p = await connectElectronApp("cursor");
|
|
122
|
+
const items = (await p.evaluate(`
|
|
123
|
+
(() => {
|
|
124
|
+
const results = [];
|
|
125
|
+
const entries = document.querySelectorAll(
|
|
126
|
+
'.agent-sidebar-list-item, [data-testid="chat-history-item"], .chat-history-item, .tree-item'
|
|
127
|
+
);
|
|
128
|
+
entries.forEach((item, i) => {
|
|
129
|
+
const title = (item.textContent || item.innerText || '').trim().substring(0, 100);
|
|
130
|
+
if (title) results.push({ index: i + 1, title });
|
|
131
|
+
});
|
|
132
|
+
if (results.length === 0) {
|
|
133
|
+
const sidebar = document.querySelector(
|
|
134
|
+
'.sidebar, [class*="sidebar"], .agent-sidebar, .side-bar-container'
|
|
135
|
+
);
|
|
136
|
+
if (sidebar) {
|
|
137
|
+
const links = sidebar.querySelectorAll('a, [role="treeitem"], [role="option"]');
|
|
138
|
+
links.forEach((link, i) => {
|
|
139
|
+
const text = (link.textContent || '').trim().substring(0, 100);
|
|
140
|
+
if (text) results.push({ index: i + 1, title: text });
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return results;
|
|
145
|
+
})()
|
|
146
|
+
`)) as unknown[];
|
|
147
|
+
|
|
148
|
+
if (!items || (items as Array<unknown>).length === 0) {
|
|
149
|
+
return [
|
|
150
|
+
{
|
|
151
|
+
index: 0,
|
|
152
|
+
title: "No chat history found. Open the AI sidebar first.",
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
return items;
|
|
157
|
+
},
|
|
158
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
site: dangdang
|
|
2
|
+
name: hot
|
|
3
|
+
description: Dangdang bestseller book list
|
|
4
|
+
domain: bang.dangdang.com
|
|
5
|
+
strategy: intercept
|
|
6
|
+
browser: true
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
limit:
|
|
10
|
+
type: int
|
|
11
|
+
default: 20
|
|
12
|
+
description: Number of books
|
|
13
|
+
|
|
14
|
+
columns: [rank, title, author, publisher, price, rating, url]
|
|
15
|
+
|
|
16
|
+
pipeline:
|
|
17
|
+
- navigate:
|
|
18
|
+
url: http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-recent7-0-0-1-1
|
|
19
|
+
settleMs: 3000
|
|
20
|
+
|
|
21
|
+
- evaluate: |
|
|
22
|
+
(async () => {
|
|
23
|
+
const limit = ${{ args.limit }};
|
|
24
|
+
const clean = v => (v || '').replace(/\s+/g, ' ').trim();
|
|
25
|
+
const items = document.querySelectorAll('.bang_list li, .bang_list_mode li, ul.bang_list li');
|
|
26
|
+
return Array.from(items).slice(0, limit).map((item, i) => {
|
|
27
|
+
const link = item.querySelector('.name a, [class*="title"] a');
|
|
28
|
+
const title = clean(link?.textContent);
|
|
29
|
+
const author = clean(item.querySelector('.publisher_info a, [class*="author"] a')?.textContent);
|
|
30
|
+
const publisher = clean(item.querySelector('.publisher_info span a, [class*="press"] a')?.textContent);
|
|
31
|
+
const price = clean(item.querySelector('.price .price_n, .price_e')?.textContent);
|
|
32
|
+
const rating = clean(item.querySelector('[class*="star"], .rating')?.textContent);
|
|
33
|
+
return {
|
|
34
|
+
rank: i + 1, title, author, publisher, price, rating,
|
|
35
|
+
url: link?.href || '',
|
|
36
|
+
};
|
|
37
|
+
}).filter(r => r.title);
|
|
38
|
+
})()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
site: dangdang
|
|
2
|
+
name: search
|
|
3
|
+
description: Search books on Dangdang
|
|
4
|
+
domain: www.dangdang.com
|
|
5
|
+
strategy: intercept
|
|
6
|
+
browser: true
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
query:
|
|
10
|
+
type: str
|
|
11
|
+
required: true
|
|
12
|
+
positional: true
|
|
13
|
+
description: Search keyword
|
|
14
|
+
limit:
|
|
15
|
+
type: int
|
|
16
|
+
default: 20
|
|
17
|
+
description: Number of results
|
|
18
|
+
|
|
19
|
+
columns: [rank, title, author, publisher, price, rating, url]
|
|
20
|
+
|
|
21
|
+
pipeline:
|
|
22
|
+
- navigate:
|
|
23
|
+
url: http://search.dangdang.com/?key=${{ args.query | urlencode }}&act=input
|
|
24
|
+
settleMs: 3000
|
|
25
|
+
|
|
26
|
+
- evaluate: |
|
|
27
|
+
(async () => {
|
|
28
|
+
const limit = ${{ args.limit }};
|
|
29
|
+
const clean = v => (v || '').replace(/\s+/g, ' ').trim();
|
|
30
|
+
const items = document.querySelectorAll('ul.bigimg li, [class*="list_item"], .shoplist li');
|
|
31
|
+
return Array.from(items).slice(0, limit).map((item, i) => {
|
|
32
|
+
const link = item.querySelector('a[href*="product.dangdang.com"], a[name="itemlist-title"]');
|
|
33
|
+
const title = clean(link?.textContent || item.querySelector('[class*="name"], .title')?.textContent);
|
|
34
|
+
const author = clean(item.querySelector('[class*="search_book_author"] a, .author a')?.textContent);
|
|
35
|
+
const publisher = clean(item.querySelector('[class*="press"] a, .publisher a, [class*="publisher"]')?.textContent);
|
|
36
|
+
const price = clean(item.querySelector('[class*="price"] .search_now_price, .price_n')?.textContent);
|
|
37
|
+
const rating = clean(item.querySelector('[class*="star"], .rating')?.textContent);
|
|
38
|
+
return {
|
|
39
|
+
rank: i + 1, title, author, publisher, price, rating,
|
|
40
|
+
url: link?.href || '',
|
|
41
|
+
};
|
|
42
|
+
}).filter(r => r.title);
|
|
43
|
+
})()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
site: deepseek
|
|
2
|
+
name: chat
|
|
3
|
+
description: Chat with DeepSeek AI (OpenAI-compatible API)
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: api.deepseek.com
|
|
6
|
+
strategy: header
|
|
7
|
+
args:
|
|
8
|
+
prompt:
|
|
9
|
+
required: true
|
|
10
|
+
positional: true
|
|
11
|
+
description: Chat message
|
|
12
|
+
model:
|
|
13
|
+
required: false
|
|
14
|
+
default: deepseek-chat
|
|
15
|
+
description: Model name (deepseek-chat, deepseek-reasoner)
|
|
16
|
+
pipeline:
|
|
17
|
+
- fetch:
|
|
18
|
+
url: "https://api.deepseek.com/chat/completions"
|
|
19
|
+
method: POST
|
|
20
|
+
headers:
|
|
21
|
+
Content-Type: application/json
|
|
22
|
+
Authorization: "Bearer ${{ env.DEEPSEEK_API_KEY }}"
|
|
23
|
+
body:
|
|
24
|
+
model: "${{ args.model | default('deepseek-chat') }}"
|
|
25
|
+
messages:
|
|
26
|
+
- role: user
|
|
27
|
+
content: "${{ args.prompt }}"
|
|
28
|
+
- select: choices
|
|
29
|
+
- map:
|
|
30
|
+
content: "${{ item.message.content }}"
|
|
31
|
+
role: "${{ item.message.role }}"
|
|
32
|
+
finish_reason: "${{ item.finish_reason }}"
|
|
33
|
+
columns: [content]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
site: deepseek
|
|
2
|
+
name: models
|
|
3
|
+
description: List available DeepSeek models
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: api.deepseek.com
|
|
6
|
+
strategy: header
|
|
7
|
+
args: {}
|
|
8
|
+
pipeline:
|
|
9
|
+
- fetch:
|
|
10
|
+
url: "https://api.deepseek.com/models"
|
|
11
|
+
headers:
|
|
12
|
+
Authorization: "Bearer ${{ env.DEEPSEEK_API_KEY }}"
|
|
13
|
+
- select: data
|
|
14
|
+
- map:
|
|
15
|
+
id: "${{ item.id }}"
|
|
16
|
+
object: "${{ item.object }}"
|
|
17
|
+
owned_by: "${{ item.owned_by }}"
|
|
18
|
+
columns: [id, object, owned_by]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
site: devto
|
|
2
|
+
name: latest
|
|
3
|
+
description: Latest Dev.to articles
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: dev.to
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
limit:
|
|
10
|
+
type: int
|
|
11
|
+
default: 20
|
|
12
|
+
|
|
13
|
+
pipeline:
|
|
14
|
+
- fetch:
|
|
15
|
+
url: https://dev.to/api/articles/latest
|
|
16
|
+
params:
|
|
17
|
+
per_page: "${{ args.limit }}"
|
|
18
|
+
|
|
19
|
+
- map:
|
|
20
|
+
title: ${{ item.title }}
|
|
21
|
+
author: "${{ item.user ? item.user.name : '' }}"
|
|
22
|
+
reactions: ${{ item.positive_reactions_count }}
|
|
23
|
+
comments: ${{ item.comments_count }}
|
|
24
|
+
tags: "${{ (item.tag_list || []).join(', ') }}"
|
|
25
|
+
url: ${{ item.url }}
|
|
26
|
+
|
|
27
|
+
- limit: ${{ args.limit }}
|
|
28
|
+
|
|
29
|
+
columns: [title, author, reactions, comments, tags]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
site: devto
|
|
2
|
+
name: search
|
|
3
|
+
description: Search Dev.to articles
|
|
4
|
+
type: web-api
|
|
5
|
+
domain: dev.to
|
|
6
|
+
strategy: public
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
query:
|
|
10
|
+
type: str
|
|
11
|
+
required: true
|
|
12
|
+
positional: true
|
|
13
|
+
limit:
|
|
14
|
+
type: int
|
|
15
|
+
default: 20
|
|
16
|
+
|
|
17
|
+
pipeline:
|
|
18
|
+
- fetch:
|
|
19
|
+
url: https://dev.to/api/articles
|
|
20
|
+
params:
|
|
21
|
+
tag: "${{ args.query }}"
|
|
22
|
+
per_page: "${{ args.limit }}"
|
|
23
|
+
|
|
24
|
+
- map:
|
|
25
|
+
title: ${{ item.title }}
|
|
26
|
+
author: "${{ item.user ? item.user.name : '' }}"
|
|
27
|
+
reactions: ${{ item.positive_reactions_count }}
|
|
28
|
+
comments: ${{ item.comments_count }}
|
|
29
|
+
published: ${{ item.published_at }}
|
|
30
|
+
url: ${{ item.url }}
|
|
31
|
+
|
|
32
|
+
- limit: ${{ args.limit }}
|
|
33
|
+
|
|
34
|
+
columns: [title, author, reactions, comments, published]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
site: dianping
|
|
2
|
+
name: hot
|
|
3
|
+
description: Dianping trending restaurants
|
|
4
|
+
domain: www.dianping.com
|
|
5
|
+
strategy: intercept
|
|
6
|
+
browser: true
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
city:
|
|
10
|
+
type: str
|
|
11
|
+
default: beijing
|
|
12
|
+
description: City slug (e.g. beijing, shanghai, guangzhou)
|
|
13
|
+
limit:
|
|
14
|
+
type: int
|
|
15
|
+
default: 20
|
|
16
|
+
description: Number of restaurants
|
|
17
|
+
|
|
18
|
+
columns: [rank, name, category, rating, avg_price, address, url]
|
|
19
|
+
|
|
20
|
+
pipeline:
|
|
21
|
+
- navigate:
|
|
22
|
+
url: https://www.dianping.com/${{ args.city }}/ch10
|
|
23
|
+
settleMs: 4000
|
|
24
|
+
|
|
25
|
+
- evaluate: |
|
|
26
|
+
(async () => {
|
|
27
|
+
const limit = ${{ args.limit }};
|
|
28
|
+
const clean = v => (v || '').replace(/\s+/g, ' ').trim();
|
|
29
|
+
const cards = document.querySelectorAll('[class*="shop-list"] li, .shoplist li, [class*="poi-list"] li');
|
|
30
|
+
return Array.from(cards).slice(0, limit).map((card, i) => {
|
|
31
|
+
const link = card.querySelector('a[href*="/shop/"]');
|
|
32
|
+
const name = clean(link?.textContent || card.querySelector('[class*="tit"], h4')?.textContent);
|
|
33
|
+
const category = clean(card.querySelector('[class*="tag"], [class*="cuisine"], .tag')?.textContent);
|
|
34
|
+
const rating = clean(card.querySelector('[class*="score"], [class*="star"]')?.textContent);
|
|
35
|
+
const price = clean(card.querySelector('[class*="price"], .mean-price')?.textContent);
|
|
36
|
+
const address = clean(card.querySelector('[class*="addr"], .addr')?.textContent);
|
|
37
|
+
return {
|
|
38
|
+
rank: i + 1, name, category, rating,
|
|
39
|
+
avg_price: price, address,
|
|
40
|
+
url: link?.href || '',
|
|
41
|
+
};
|
|
42
|
+
}).filter(r => r.name);
|
|
43
|
+
})()
|