diff --git a/src/helpers/formatBskyPost.ts b/src/helpers/formatBskyPost.ts index 7acfdefa09..a32993c4fb 100644 --- a/src/helpers/formatBskyPost.ts +++ b/src/helpers/formatBskyPost.ts @@ -7,7 +7,7 @@ import { AppBskyFeedDefs, } from '@atproto/api'; import { isViewRecord } from '@atproto/api/dist/client/types/app/bsky/embed/record.js'; -import { isPostView, isThreadViewPost } from '@atproto/api/dist/client/types/app/bsky/feed/defs.js'; +import { type FeedViewPost,isPostView, isThreadViewPost } from '@atproto/api/dist/client/types/app/bsky/feed/defs.js'; import { produce } from 'immer'; import { first, isUndefined, omitBy } from 'lodash-es'; @@ -143,3 +143,30 @@ export function formatBskyThreadPosts(thread: AppBskyFeedDefs.ThreadViewPost, po } return formatBskyThreadPosts(thread.parent, [post, ...posts]); } + +export function formatBskyFeed(feed: FeedViewPost): Post { + const parent = feed.reply?.parent as PostView | undefined; + return { + publicationId: feed.post.cid, + type: feed.reply ? 'Comment' : 'Post', + postId: feed.post.cid, + parentPostId: parent?.cid, + parentAuthor: parent?.author ? formatBskyProfile(parent.author) : undefined, + timestamp: new Date(feed.post.indexedAt).getTime(), + author: formatBskyProfile(feed.post.author), + metadata: { + locale: '', + content: { + content: `TODO: ${JSON.parse(feed.post.embed as any)}`, + }, + }, + mentions: [], + hasLiked: !!feed.post.viewer?.like, + hasMirrored: !!feed.post.viewer?.repost, + hasBookmarked: false, + source: Source.Bsky, + canComment: true, + commentOn: feed.reply?.parent ? formatBskyPost(feed.reply.parent as PostView) : undefined, + __original__: feed, + }; +} diff --git a/src/helpers/formatBskyProfile.ts b/src/helpers/formatBskyProfile.ts index b354c40165..c30c81aae0 100644 --- a/src/helpers/formatBskyProfile.ts +++ b/src/helpers/formatBskyProfile.ts @@ -30,7 +30,8 @@ export function formatBskyProfile(profile: AppBskyActorDefs.ProfileViewDetailed) viewerContext: { following: !!profile.viewer?.following, followedBy: !!profile.viewer?.followedBy, - blocking: profile.viewer?.blockedBy, + // .blockedBy will block data request as well. + blocking: profile.viewer?.muted, }, }; } diff --git a/src/providers/bsky/SocialMedia.ts b/src/providers/bsky/SocialMedia.ts index fa5133922c..39d2036164 100644 --- a/src/providers/bsky/SocialMedia.ts +++ b/src/providers/bsky/SocialMedia.ts @@ -1,5 +1,6 @@ import { AppBskyActorProfile, RichText } from '@atproto/api'; import { isThreadViewPost, type PostView } from '@atproto/api/dist/client/types/app/bsky/feed/defs.js'; +import { BlockedActorError } from '@atproto/api/dist/client/types/app/bsky/feed/getAuthorFeed.js'; import { safeUnreachable } from '@masknet/kit'; import { compact } from 'lodash-es'; @@ -235,17 +236,24 @@ export class BskySocialMedia implements Provider { ); } async getPostsByProfileId(profileId: string, indicator?: PageIndicator): Promise> { - const res = await bskySessionHolder.agent.getAuthorFeed({ - actor: profileId, - filter: 'posts_and_author_threads', - cursor: indicator?.id, - }); - if (!res.success) throw new Error(`Failed to get post by profile id = ${profileId}.`); - return createPageable( - res.data.feed.map(formatBskyPost), - createIndicator(indicator), - res.data.cursor ? createNextIndicator(indicator, res.data.cursor) : undefined, - ); + try { + const res = await bskySessionHolder.agent.getAuthorFeed({ + actor: profileId, + filter: 'posts_and_author_threads', + cursor: indicator?.id, + }); + if (!res.success) throw new Error(`Failed to get post by profile id = ${profileId}.`); + return createPageable( + res.data.feed.map(formatBskyPost), + createIndicator(indicator), + res.data.cursor ? createNextIndicator(indicator, res.data.cursor) : undefined, + ); + } catch (err) { + if (err instanceof BlockedActorError) { + return createPageable([], createIndicator(indicator), undefined); + } + throw err; + } } async getLikedPostsByProfileId( profileId: string, @@ -558,10 +566,12 @@ export class BskySocialMedia implements Provider { throw new NotImplementedError(); } async blockProfile(profileId: string): Promise { - throw new NotImplementedError(); + const res = await bskySessionHolder.agent.mute(profileId); + return res.success; } async unblockProfile(profileId: string): Promise { - throw new NotImplementedError(); + const res = await bskySessionHolder.agent.unmute(profileId); + return res.success; } async getBlockedProfiles(indicator?: PageIndicator): Promise> { throw new NotImplementedError();