also looking at this
Bluesky publishing v2: rich-text facets + image upload
#9
8 files
+347
-12
| @@ -31,9 +31,18 @@ export default new Action({ | ||
| 31 | 31 | |
| 32 | 32 | const imageUrl = String(request.get('image_url') || '').trim() |
| 33 | 33 | const imageAlt = String(request.get('image_alt') || '').trim() |
| 34 | const media = imageUrl | |
| 35 | ? [{ url: imageUrl, altText: imageAlt || undefined }] | |
| 36 | : undefined | |
| 34 | ||
| 35 | const media: NonNullable<Parameters<typeof crosspost.publish>[2]>['media'] = [] | |
| 36 | const uploaded = request.file?.('image') | |
| 37 | if (uploaded?.buffer && uploaded.buffer.byteLength > 0) { | |
| 38 | media.push({ | |
| 39 | bytes: new Uint8Array(uploaded.buffer), | |
| 40 | mimeType: uploaded.mimetype || 'image/jpeg', | |
| 41 | altText: imageAlt || undefined, | |
| 42 | }) | |
| 43 | } | |
| 44 | if (imageUrl) | |
| 45 | media.push({ url: imageUrl, altText: imageAlt || undefined }) | |
| 37 | 46 | |
| 38 | 47 | // Optional multi-segment thread: JSON array of post texts. Segments are |
| 39 | 48 | // reply-chained on providers that support it (Bluesky). |
| @@ -45,9 +54,10 @@ export default new Action({ | ||
| 45 | 54 | catch {} |
| 46 | 55 | |
| 47 | 56 | try { |
| 57 | const content = { external, media: media.length ? media : undefined } | |
| 48 | 58 | const data = thread.length > 1 |
| 49 | ? await crosspost.publishThread(thread, providers, { external, media }) | |
| 50 | : await crosspost.publish(thread[0] || text, providers, { external, media }) | |
| 59 | ? await crosspost.publishThread(thread, providers, content) | |
| 60 | : await crosspost.publish(thread[0] || text, providers, content) | |
| 51 | 61 | // Surface a partial-failure (some targets failed) as a 207-style payload |
| 52 | 62 | // while still returning 200 so the client can report per-provider state. |
| 53 | 63 | const allFailed = data.results.length > 0 && data.results.every(result => !result.ok) |