From 04949048e7d9252b5018df543bcd9b2607a19602 Mon Sep 17 00:00:00 2001 From: 0xsline Date: Sun, 22 Mar 2026 01:52:27 +0800 Subject: [PATCH] feat(bluesky): add Bluesky adapter with 9 commands Bluesky (9 commands, public AT Protocol API, no auth needed): - profile: user profile info (followers, following, posts) - user: recent posts from a user with engagement stats - trending: trending topics on Bluesky - search: search users - feeds: popular feed generators - followers: list user's followers - following: list accounts a user follows - thread: post thread with replies - starter-packs: user's starter packs All commands use the public Bluesky API, no browser or login required. --- docs/adapters/browser/bluesky.md | 53 +++++++++++++++++++++++++++++ src/clis/bluesky/feeds.yaml | 29 ++++++++++++++++ src/clis/bluesky/followers.yaml | 33 ++++++++++++++++++ src/clis/bluesky/following.yaml | 33 ++++++++++++++++++ src/clis/bluesky/profile.yaml | 27 +++++++++++++++ src/clis/bluesky/search.yaml | 34 ++++++++++++++++++ src/clis/bluesky/starter-packs.yaml | 34 ++++++++++++++++++ src/clis/bluesky/thread.yaml | 32 +++++++++++++++++ src/clis/bluesky/trending.yaml | 27 +++++++++++++++ src/clis/bluesky/user.yaml | 34 ++++++++++++++++++ 10 files changed, 336 insertions(+) create mode 100644 docs/adapters/browser/bluesky.md create mode 100644 src/clis/bluesky/feeds.yaml create mode 100644 src/clis/bluesky/followers.yaml create mode 100644 src/clis/bluesky/following.yaml create mode 100644 src/clis/bluesky/profile.yaml create mode 100644 src/clis/bluesky/search.yaml create mode 100644 src/clis/bluesky/starter-packs.yaml create mode 100644 src/clis/bluesky/thread.yaml create mode 100644 src/clis/bluesky/trending.yaml create mode 100644 src/clis/bluesky/user.yaml diff --git a/docs/adapters/browser/bluesky.md b/docs/adapters/browser/bluesky.md new file mode 100644 index 0000000..6e519f3 --- /dev/null +++ b/docs/adapters/browser/bluesky.md @@ -0,0 +1,53 @@ +# Bluesky + +**Mode**: ๐ŸŒ Public ยท **Domain**: `bsky.app` + +## Commands + +| Command | Description | +|---------|-------------| +| `opencli bluesky profile` | User profile info | +| `opencli bluesky user` | Recent posts from a user | +| `opencli bluesky trending` | Trending topics | +| `opencli bluesky search` | Search users | +| `opencli bluesky feeds` | Popular feed generators | +| `opencli bluesky followers` | User's followers | +| `opencli bluesky following` | Accounts a user follows | +| `opencli bluesky thread` | Post thread with replies | +| `opencli bluesky starter-packs` | User's starter packs | + +## Usage Examples + +```bash +# User profile +opencli bluesky profile --handle bsky.app + +# Recent posts +opencli bluesky user --handle bsky.app --limit 10 + +# Trending topics +opencli bluesky trending --limit 10 + +# Search users +opencli bluesky search --query "AI" --limit 10 + +# Popular feeds +opencli bluesky feeds --limit 10 + +# Followers / following +opencli bluesky followers --handle bsky.app --limit 10 +opencli bluesky following --handle bsky.app + +# Post thread with replies +opencli bluesky thread --uri "at://did:.../app.bsky.feed.post/..." + +# Starter packs +opencli bluesky starter-packs --handle bsky.app + +# JSON output +opencli bluesky profile --handle bsky.app -f json +``` + +## Prerequisites + +None โ€” all commands use the public Bluesky AT Protocol API, no browser or login required. diff --git a/src/clis/bluesky/feeds.yaml b/src/clis/bluesky/feeds.yaml new file mode 100644 index 0000000..54e032e --- /dev/null +++ b/src/clis/bluesky/feeds.yaml @@ -0,0 +1,29 @@ +site: bluesky +name: feeds +description: Popular Bluesky feed generators +domain: public.api.bsky.app +strategy: public +browser: false + +args: + limit: + type: int + default: 20 + description: Number of feeds + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.unspecced.getPopularFeedGenerators?limit=${{ args.limit }} + + - select: feeds + + - map: + rank: ${{ index + 1 }} + name: ${{ item.displayName }} + likes: ${{ item.likeCount }} + creator: ${{ item.creator.handle }} + description: ${{ item.description }} + + - limit: ${{ args.limit }} + +columns: [rank, name, likes, creator, description] diff --git a/src/clis/bluesky/followers.yaml b/src/clis/bluesky/followers.yaml new file mode 100644 index 0000000..382d466 --- /dev/null +++ b/src/clis/bluesky/followers.yaml @@ -0,0 +1,33 @@ +site: bluesky +name: followers +description: List followers of a Bluesky user +domain: public.api.bsky.app +strategy: public +browser: false + +args: + handle: + type: str + required: true + positional: true + description: "Bluesky handle" + limit: + type: int + default: 20 + description: Number of followers + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.graph.getFollowers?actor=${{ args.handle }}&limit=${{ args.limit }} + + - select: followers + + - map: + rank: ${{ index + 1 }} + handle: ${{ item.handle }} + name: ${{ item.displayName }} + description: ${{ item.description }} + + - limit: ${{ args.limit }} + +columns: [rank, handle, name, description] diff --git a/src/clis/bluesky/following.yaml b/src/clis/bluesky/following.yaml new file mode 100644 index 0000000..49f29fc --- /dev/null +++ b/src/clis/bluesky/following.yaml @@ -0,0 +1,33 @@ +site: bluesky +name: following +description: List accounts a Bluesky user is following +domain: public.api.bsky.app +strategy: public +browser: false + +args: + handle: + type: str + required: true + positional: true + description: "Bluesky handle" + limit: + type: int + default: 20 + description: Number of accounts + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.graph.getFollows?actor=${{ args.handle }}&limit=${{ args.limit }} + + - select: follows + + - map: + rank: ${{ index + 1 }} + handle: ${{ item.handle }} + name: ${{ item.displayName }} + description: ${{ item.description }} + + - limit: ${{ args.limit }} + +columns: [rank, handle, name, description] diff --git a/src/clis/bluesky/profile.yaml b/src/clis/bluesky/profile.yaml new file mode 100644 index 0000000..ab8f441 --- /dev/null +++ b/src/clis/bluesky/profile.yaml @@ -0,0 +1,27 @@ +site: bluesky +name: profile +description: Get Bluesky user profile info +domain: public.api.bsky.app +strategy: public +browser: false + +args: + handle: + type: str + required: true + positional: true + description: "Bluesky handle (e.g. bsky.app, jay.bsky.team)" + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${{ args.handle }} + + - map: + handle: ${{ item.handle }} + name: ${{ item.displayName }} + followers: ${{ item.followersCount }} + following: ${{ item.followsCount }} + posts: ${{ item.postsCount }} + description: ${{ item.description }} + +columns: [handle, name, followers, following, posts, description] diff --git a/src/clis/bluesky/search.yaml b/src/clis/bluesky/search.yaml new file mode 100644 index 0000000..297fe15 --- /dev/null +++ b/src/clis/bluesky/search.yaml @@ -0,0 +1,34 @@ +site: bluesky +name: search +description: Search Bluesky users +domain: public.api.bsky.app +strategy: public +browser: false + +args: + query: + type: str + required: true + positional: true + description: Search query + limit: + type: int + default: 10 + description: Number of results + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.actor.searchActors?q=${{ args.query }}&limit=${{ args.limit }} + + - select: actors + + - map: + rank: ${{ index + 1 }} + handle: ${{ item.handle }} + name: ${{ item.displayName }} + followers: ${{ item.followersCount }} + description: ${{ item.description }} + + - limit: ${{ args.limit }} + +columns: [rank, handle, name, followers, description] diff --git a/src/clis/bluesky/starter-packs.yaml b/src/clis/bluesky/starter-packs.yaml new file mode 100644 index 0000000..de483ff --- /dev/null +++ b/src/clis/bluesky/starter-packs.yaml @@ -0,0 +1,34 @@ +site: bluesky +name: starter-packs +description: Get starter packs created by a Bluesky user +domain: public.api.bsky.app +strategy: public +browser: false + +args: + handle: + type: str + required: true + positional: true + description: "Bluesky handle" + limit: + type: int + default: 10 + description: Number of starter packs + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.graph.getActorStarterPacks?actor=${{ args.handle }}&limit=${{ args.limit }} + + - select: starterPacks + + - map: + rank: ${{ index + 1 }} + name: ${{ item.record.name }} + description: ${{ item.record.description }} + members: ${{ item.listItemCount }} + joins: ${{ item.joinedAllTimeCount }} + + - limit: ${{ args.limit }} + +columns: [rank, name, description, members, joins] diff --git a/src/clis/bluesky/thread.yaml b/src/clis/bluesky/thread.yaml new file mode 100644 index 0000000..99315a4 --- /dev/null +++ b/src/clis/bluesky/thread.yaml @@ -0,0 +1,32 @@ +site: bluesky +name: thread +description: Get a Bluesky post thread with replies +domain: public.api.bsky.app +strategy: public +browser: false + +args: + uri: + type: str + required: true + positional: true + description: "Post AT URI (at://did:.../app.bsky.feed.post/...) or bsky.app URL" + limit: + type: int + default: 20 + description: Number of replies + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.feed.getPostThread?uri=${{ args.uri }}&depth=2 + + - select: thread + + - map: + author: ${{ item.post.author.handle }} + text: ${{ item.post.record.text }} + likes: ${{ item.post.likeCount }} + reposts: ${{ item.post.repostCount }} + replies_count: ${{ item.post.replyCount }} + +columns: [author, text, likes, reposts, replies_count] diff --git a/src/clis/bluesky/trending.yaml b/src/clis/bluesky/trending.yaml new file mode 100644 index 0000000..28db07b --- /dev/null +++ b/src/clis/bluesky/trending.yaml @@ -0,0 +1,27 @@ +site: bluesky +name: trending +description: Trending topics on Bluesky +domain: public.api.bsky.app +strategy: public +browser: false + +args: + limit: + type: int + default: 20 + description: Number of topics + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.unspecced.getTrendingTopics + + - select: topics + + - map: + rank: ${{ index + 1 }} + topic: ${{ item.topic }} + link: ${{ item.link }} + + - limit: ${{ args.limit }} + +columns: [rank, topic, link] diff --git a/src/clis/bluesky/user.yaml b/src/clis/bluesky/user.yaml new file mode 100644 index 0000000..5d2eb2f --- /dev/null +++ b/src/clis/bluesky/user.yaml @@ -0,0 +1,34 @@ +site: bluesky +name: user +description: Get recent posts from a Bluesky user +domain: public.api.bsky.app +strategy: public +browser: false + +args: + handle: + type: str + required: true + positional: true + description: "Bluesky handle (e.g. bsky.app)" + limit: + type: int + default: 20 + description: Number of posts + +pipeline: + - fetch: + url: https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed?actor=${{ args.handle }}&limit=${{ args.limit }} + + - select: feed + + - map: + rank: ${{ index + 1 }} + text: ${{ item.post.record.text }} + likes: ${{ item.post.likeCount }} + reposts: ${{ item.post.repostCount }} + replies: ${{ item.post.replyCount }} + + - limit: ${{ args.limit }} + +columns: [rank, text, likes, reposts, replies]