A Astro blog hosted on Vercel
1import { BLUESKY_DID } from "@/consts";
2import formatBlogTitleUrl from "./formatBlogTitleUrl";
3import { AppBskyFeedPost, AtpAgent } from '@atproto/api'
4import { isThreadViewPost } from "@atproto/api/dist/client/types/app/bsky/feed/defs";
5
6async function getBlogPostComments(blogTitle: string) {
7
8 const agent = new AtpAgent({ service: new URL("https://api.bsky.app") });
9
10 const post = await agent.app.bsky.feed.searchPosts({
11 q: `#blog #${formatBlogTitleUrl(blogTitle)}`,
12 author: BLUESKY_DID,
13 limit: 1
14 }).then(({ data }) => {
15 if (!data.posts) return undefined;
16
17 return data.posts[0];
18 }).catch(console.error);
19
20 if (!post) return [];
21
22 if (post.replyCount === 0) return [];
23
24 const comments = await agent.app.bsky.feed.getPostThread({
25 uri: post.uri,
26 depth: 1
27 }).then(({ data }) => {
28 if (!isThreadViewPost(data.thread)) return [];
29
30 if (!data.thread.replies) return [];
31
32 return data.thread.replies.map((reply) => {
33 if (!isThreadViewPost(reply)) return null;
34
35 const record = reply.post.record as AppBskyFeedPost.Record;
36
37 const postId = reply.post.uri.split('/').at(-1);
38
39 if (!postId) return null;
40
41 return {
42 likeCount: reply.post.likeCount,
43 replyCount: reply.post.replyCount,
44 repostCount: reply.post.repostCount,
45 displayName: reply.post.author.displayName,
46 handle: reply.post.author.handle,
47 createdAt: record.createdAt,
48 text: record.text,
49 authorUrl: `https://bsky.app/profile/${reply.post.author.did}`,
50 postUrl: `https://bsky.app/profile/${reply.post.author.did}/post/${postId}`,
51 cid: reply.post.cid
52 // ...reply.post,
53 // record: {
54 // ...reply.post.record as AppBskyFeedPost.Record
55 // }
56 };
57 }).filter(reply => reply !== null);
58 })
59 .catch((error) => {
60 console.error(error);
61 return [];
62 });
63
64 return comments;
65}
66
67export default getBlogPostComments;