diff --git a/packages/cli/src/commands/publish.ts b/packages/cli/src/commands/publish.ts index f62fbce..5e9225a 100644 --- a/packages/cli/src/commands/publish.ts +++ b/packages/cli/src/commands/publish.ts @@ -359,6 +359,7 @@ export const publishCommand = command({ bskyPostRef = await createBlueskyPost(agent, { title: post.frontmatter.title, description: post.frontmatter.description, + bskyPost: post.frontmatter.bskyPost, canonicalUrl, coverImage, publishedAt: post.frontmatter.publishDate, diff --git a/packages/cli/src/lib/atproto.ts b/packages/cli/src/lib/atproto.ts index b999c98..af66579 100644 --- a/packages/cli/src/lib/atproto.ts +++ b/packages/cli/src/lib/atproto.ts @@ -569,6 +569,7 @@ export async function updatePublication( export interface CreateBlueskyPostOptions { title: string; description?: string; + bskyPost?: string; canonicalUrl: string; coverImage?: BlobObject; publishedAt: string; // Used as createdAt for the post @@ -612,19 +613,21 @@ export async function createBlueskyPost( agent: Agent, options: CreateBlueskyPostOptions, ): Promise { - const { title, description, canonicalUrl, coverImage, publishedAt } = options; + const { title, description, bskyPost, canonicalUrl, coverImage, publishedAt } = options; - // Build post text: title + description + URL + // Build post text: title + description // Max 300 graphemes for Bluesky posts const MAX_GRAPHEMES = 300; let postText: string; - const urlPart = `\n\n${canonicalUrl}`; - const urlGraphemes = countGraphemes(urlPart); - if (description) { - // Try: title + description + URL - const fullText = `${title}\n\n${description}${urlPart}`; + if (bskyPost) { + // Custom bsky post overrides any default behavior + postText = bskyPost; + } + else if (description) { + // Try: title + description + const fullText = `${title}\n\n${description}`; if (countGraphemes(fullText) <= MAX_GRAPHEMES) { postText = fullText; } else { @@ -632,53 +635,28 @@ export async function createBlueskyPost( const availableForDesc = MAX_GRAPHEMES - countGraphemes(title) - - countGraphemes("\n\n") - - urlGraphemes - countGraphemes("\n\n"); if (availableForDesc > 10) { const truncatedDesc = truncateToGraphemes( description, availableForDesc, ); - postText = `${title}\n\n${truncatedDesc}${urlPart}`; + postText = `${title}\n\n${truncatedDesc}`; } else { - // Just title + URL - postText = `${title}${urlPart}`; + // Just title + postText = `${title}`; } } } else { - // Just title + URL - postText = `${title}${urlPart}`; + // Just title + postText = `${title}`; } - // Final truncation if still too long (shouldn't happen but safety check) + // Final truncation in case title or bskyPost are longer than expected if (countGraphemes(postText) > MAX_GRAPHEMES) { postText = truncateToGraphemes(postText, MAX_GRAPHEMES); } - // Calculate byte indices for the URL facet - const encoder = new TextEncoder(); - const urlStartInText = postText.lastIndexOf(canonicalUrl); - const beforeUrl = postText.substring(0, urlStartInText); - const byteStart = encoder.encode(beforeUrl).length; - const byteEnd = byteStart + encoder.encode(canonicalUrl).length; - - // Build facets for the URL link - const facets = [ - { - index: { - byteStart, - byteEnd, - }, - features: [ - { - $type: "app.bsky.richtext.facet#link", - uri: canonicalUrl, - }, - ], - }, - ]; - // Build external embed const embed: Record = { $type: "app.bsky.embed.external", @@ -698,7 +676,6 @@ export async function createBlueskyPost( const record: Record = { $type: "app.bsky.feed.post", text: postText, - facets, embed, createdAt: new Date(publishedAt).toISOString(), }; diff --git a/packages/cli/src/lib/types.ts b/packages/cli/src/lib/types.ts index 0381ea4..be237f1 100644 --- a/packages/cli/src/lib/types.ts +++ b/packages/cli/src/lib/types.ts @@ -87,6 +87,7 @@ export function isAppPasswordCredentials( export interface PostFrontmatter { title: string; description?: string; + bskyPost?: string; publishDate: string; tags?: string[]; ogImage?: string;