also looking at this
Bluesky publishing v2: rich-text facets + image upload
#9
8 files
+347
-12
| @@ -187,9 +187,33 @@ export class BlueskyService { | ||
| 187 | 187 | const publishInput = { text: post.body } as Parameters<BlueskyDriver['publish']>[1] & { |
| 188 | 188 | external?: { uri: string, title: string, description?: string } |
| 189 | 189 | reply?: { root: { uri: string, cid: string }, parent: { uri: string, cid: string } } |
| 190 | media?: Array<{ bytes?: Uint8Array, mimeType?: string, altText?: string }> | |
| 190 | 191 | } |
| 191 | 192 | if (content?.external) publishInput.external = content.external |
| 192 | 193 | if (content?.reply) publishInput.reply = content.reply |
| 194 | if (content?.media?.length) { | |
| 195 | // The driver embeds raw bytes; fetch URL-only media server-side. | |
| 196 | const media: Array<{ bytes: Uint8Array, mimeType?: string, altText?: string }> = [] | |
| 197 | for (const item of content.media.slice(0, 4)) { | |
| 198 | if (item.bytes?.length) { | |
| 199 | media.push({ bytes: item.bytes, mimeType: item.mimeType, altText: item.altText }) | |
| 200 | } | |
| 201 | else if (item.url) { | |
| 202 | try { | |
| 203 | const response = await fetch(item.url) | |
| 204 | if (!response.ok) continue | |
| 205 | const bytes = new Uint8Array(await response.arrayBuffer()) | |
| 206 | media.push({ | |
| 207 | bytes, | |
| 208 | mimeType: item.mimeType || response.headers.get('content-type') || 'image/jpeg', | |
| 209 | altText: item.altText, | |
| 210 | }) | |
| 211 | } | |
| 212 | catch {} | |
| 213 | } | |
| 214 | } | |
| 215 | if (media.length) publishInput.media = media | |
| 216 | } | |
| 193 | 217 | |
| 194 | 218 | await database.insertInto('post_targets').values({ |
| 195 | 219 | uuid: targetUuid, |