mirror of
https://github.com/misenhower/splatoon3.ink.git
synced 2026-03-21 17:54:13 -05:00
Add error handling and media validation to social media clients
Wrap send() methods in try-catch with descriptive error messages and add early return when media is missing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c1a290e7bc
commit
ca632864f8
|
|
@ -31,40 +31,50 @@ export default class BlueskyClient extends Client
|
|||
}
|
||||
|
||||
async send(status, generator) {
|
||||
await this.login();
|
||||
if (!status.media?.length) {
|
||||
console.error(`[${this.name}] No media provided for ${generator.key}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload images
|
||||
let images = await Promise.all(
|
||||
status.media.map(async m => {
|
||||
// We have to convert the PNG to a JPG for Bluesky because of size limits
|
||||
let jpeg = sharp(m.file).jpeg();
|
||||
let metadata = await jpeg.metadata();
|
||||
let buffer = await jpeg.toBuffer();
|
||||
try {
|
||||
await this.login();
|
||||
|
||||
let response = await this.#agent.uploadBlob(buffer, { encoding: 'image/jpeg' });
|
||||
// Upload images
|
||||
let images = await Promise.all(
|
||||
status.media.map(async m => {
|
||||
// We have to convert the PNG to a JPG for Bluesky because of size limits
|
||||
let jpeg = sharp(m.file).jpeg();
|
||||
let metadata = await jpeg.metadata();
|
||||
let buffer = await jpeg.toBuffer();
|
||||
|
||||
return {
|
||||
image: response.data.blob,
|
||||
alt: m.altText || '',
|
||||
aspectRatio: { width: metadata.width, height: metadata.height },
|
||||
};
|
||||
}),
|
||||
);
|
||||
let response = await this.#agent.uploadBlob(buffer, { encoding: 'image/jpeg' });
|
||||
|
||||
// Send status
|
||||
const rt = new RichText({
|
||||
text: status.status,
|
||||
});
|
||||
return {
|
||||
image: response.data.blob,
|
||||
alt: m.altText || '',
|
||||
aspectRatio: { width: metadata.width, height: metadata.height },
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
await rt.detectFacets(this.#agent);
|
||||
// Send status
|
||||
const rt = new RichText({
|
||||
text: status.status,
|
||||
});
|
||||
|
||||
await this.#agent.post({
|
||||
text: rt.text,
|
||||
facets: rt.facets,
|
||||
embed: {
|
||||
images,
|
||||
$type: 'app.bsky.embed.images',
|
||||
},
|
||||
});
|
||||
await rt.detectFacets(this.#agent);
|
||||
|
||||
await this.#agent.post({
|
||||
text: rt.text,
|
||||
facets: rt.facets,
|
||||
embed: {
|
||||
images,
|
||||
$type: 'app.bsky.embed.images',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${this.name}] Failed to post ${generator.key}:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,35 +23,45 @@ export default class MastodonClient extends Client
|
|||
}
|
||||
|
||||
async send(status, generator) {
|
||||
// Mastodon API
|
||||
const masto = await createRestAPIClient({
|
||||
url: this.#url,
|
||||
accessToken: this.#accessToken,
|
||||
disableVersionCheck: true,
|
||||
disableExperimentalWarning: true,
|
||||
});
|
||||
if (!status.media?.length) {
|
||||
console.error(`[${this.name}] No media provided for ${generator.key}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload images
|
||||
let mediaIds = await Promise.all(
|
||||
status.media.map(async m => {
|
||||
let request = { file: new Blob([m.file]) };
|
||||
if (m.altText) {
|
||||
request.description = m.altText;
|
||||
}
|
||||
try {
|
||||
// Mastodon API
|
||||
const masto = await createRestAPIClient({
|
||||
url: this.#url,
|
||||
accessToken: this.#accessToken,
|
||||
disableVersionCheck: true,
|
||||
disableExperimentalWarning: true,
|
||||
});
|
||||
|
||||
let attachment = await masto.v2.media.create(request);
|
||||
// Upload images
|
||||
let mediaIds = await Promise.all(
|
||||
status.media.map(async m => {
|
||||
let request = { file: new Blob([m.file]) };
|
||||
if (m.altText) {
|
||||
request.description = m.altText;
|
||||
}
|
||||
|
||||
return attachment.id;
|
||||
}),
|
||||
);
|
||||
let attachment = await masto.v2.media.create(request);
|
||||
|
||||
// Send status
|
||||
await masto.v1.statuses.create({
|
||||
status: status.status,
|
||||
spoilerText: status.contentWrapper,
|
||||
sensitive: !!status.contentWrapper, // Without the sensitive property the image is still visible
|
||||
mediaIds,
|
||||
visibility: this.#visibility,
|
||||
});
|
||||
return attachment.id;
|
||||
}),
|
||||
);
|
||||
|
||||
// Send status
|
||||
await masto.v1.statuses.create({
|
||||
status: status.status,
|
||||
spoilerText: status.contentWrapper,
|
||||
sensitive: !!status.contentWrapper, // Without the sensitive property the image is still visible
|
||||
mediaIds,
|
||||
visibility: this.#visibility,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${this.name}] Failed to post ${generator.key}:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,11 +29,21 @@ export default class ThreadsClient extends Client {
|
|||
}
|
||||
|
||||
async send(status, generator) {
|
||||
let jpeg = await sharp(status.media[0].file).jpeg().toBuffer();
|
||||
if (!status.media?.length) {
|
||||
console.error(`[${this.name}] No media provided for ${generator.key}`);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.#api.publish({
|
||||
text: status.status,
|
||||
image: { type: 'image/jpeg', data: jpeg },
|
||||
});
|
||||
try {
|
||||
let jpeg = await sharp(status.media[0].file).jpeg().toBuffer();
|
||||
|
||||
await this.#api.publish({
|
||||
text: status.status,
|
||||
image: { type: 'image/jpeg', data: jpeg },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[${this.name}] Failed to post ${generator.key}:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,20 +30,30 @@ export default class TwitterClient extends Client
|
|||
}
|
||||
|
||||
async send(status, generator) {
|
||||
// Upload images
|
||||
let mediaIds = await Promise.all(
|
||||
status.media.map(async m => {
|
||||
let id = await this.api().v1.uploadMedia(Buffer.from(m.file), { mimeType: m.type });
|
||||
if (!status.media?.length) {
|
||||
console.error(`[${this.name}] No media provided for ${generator.key}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.altText) {
|
||||
await this.api().v1.createMediaMetadata(id, { alt_text: { text: m.altText } });
|
||||
}
|
||||
try {
|
||||
// Upload images
|
||||
let mediaIds = await Promise.all(
|
||||
status.media.map(async m => {
|
||||
let id = await this.api().v1.uploadMedia(Buffer.from(m.file), { mimeType: m.type });
|
||||
|
||||
return id;
|
||||
}),
|
||||
);
|
||||
if (m.altText) {
|
||||
await this.api().v1.createMediaMetadata(id, { alt_text: { text: m.altText } });
|
||||
}
|
||||
|
||||
// Send status
|
||||
await this.api().v2.tweet(status.status, { media: { media_ids: mediaIds } });
|
||||
return id;
|
||||
}),
|
||||
);
|
||||
|
||||
// Send status
|
||||
await this.api().v2.tweet(status.status, { media: { media_ids: mediaIds } });
|
||||
} catch (error) {
|
||||
console.error(`[${this.name}] Failed to post ${generator.key}:`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user