Fix image posting for Discord and Mastodon
Discord: payload_json was missing the attachments array, so uploaded files were orphaned and not shown in the message (Discord API v10 requirement). Mastodon: media_ids[] sent as URL-encoded form was unreliable — switch to JSON body. Also poll /api/v1/media/:id when upload returns 202 (async) to wait until the image is processed before attaching it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1a366bef63
commit
4767fe0109
1 changed files with 34 additions and 9 deletions
|
|
@ -86,7 +86,7 @@ function ensure_li_token(string $base, array &$config): ?string {
|
|||
return $li['access_token'];
|
||||
}
|
||||
|
||||
// Upload image to Mastodon, return media_id or null
|
||||
// Upload image to Mastodon, return media_id or null (polls until ready if async)
|
||||
function mastodon_upload_image(string $api_base, string $token, string $image_path): ?string {
|
||||
if (!file_exists($image_path)) return null;
|
||||
$ch = curl_init($api_base . '/api/v2/media');
|
||||
|
|
@ -99,7 +99,25 @@ function mastodon_upload_image(string $api_base, string $token, string $image_pa
|
|||
$resp = json_decode(curl_exec($ch), true);
|
||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($status === 200 || $status === 202) return $resp['id'] ?? null;
|
||||
|
||||
if ($status === 200) return $resp['id'] ?? null;
|
||||
|
||||
// 202 = media accepted but still processing — poll until URL is set (max 10s)
|
||||
if ($status === 202) {
|
||||
$media_id = $resp['id'] ?? null;
|
||||
if (!$media_id) return null;
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
sleep(1);
|
||||
$ch2 = curl_init($api_base . '/api/v1/media/' . $media_id);
|
||||
curl_setopt_array($ch2, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token]]);
|
||||
$poll = json_decode(curl_exec($ch2), true);
|
||||
curl_close($ch2);
|
||||
if (!empty($poll['url'])) return $media_id;
|
||||
}
|
||||
log_msg(' Mastodon media still processing after 10s — attaching anyway');
|
||||
return $media_id;
|
||||
}
|
||||
|
||||
log_msg(' Mastodon media upload HTTP ' . $status);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -151,12 +169,19 @@ function linkedin_upload_image(string $token, string $author, string $image_path
|
|||
// Discord multipart post (with optional file attachment)
|
||||
function discord_post(string $webhook_url, string $text, ?string $image_path): array {
|
||||
$boundary = '----FormBoundary' . bin2hex(random_bytes(8));
|
||||
$has_file = $image_path && file_exists($image_path);
|
||||
$filename = $has_file ? basename($image_path) : null;
|
||||
|
||||
// payload_json must declare attachments array so Discord links the uploaded file
|
||||
$payload = ['content' => $text];
|
||||
if ($has_file) $payload['attachments'] = [['id' => 0, 'filename' => $filename]];
|
||||
|
||||
$body = "--$boundary\r\n";
|
||||
$body .= "Content-Disposition: form-data; name=\"payload_json\"\r\n\r\n";
|
||||
$body .= json_encode(['content' => $text]) . "\r\n";
|
||||
if ($image_path && file_exists($image_path)) {
|
||||
$body .= json_encode($payload) . "\r\n";
|
||||
if ($has_file) {
|
||||
$body .= "--$boundary\r\n";
|
||||
$body .= 'Content-Disposition: form-data; name="files[0]"; filename="' . basename($image_path) . '"' . "\r\n";
|
||||
$body .= 'Content-Disposition: form-data; name="files[0]"; filename="' . $filename . '"' . "\r\n";
|
||||
$body .= 'Content-Type: ' . (mime_content_type($image_path) ?: 'image/jpeg') . "\r\n\r\n";
|
||||
$body .= file_get_contents($image_path) . "\r\n";
|
||||
}
|
||||
|
|
@ -229,13 +254,13 @@ foreach ($targets as $t) {
|
|||
if ($mid) $media_ids[] = $mid;
|
||||
}
|
||||
$params = ['status' => $content];
|
||||
if ($media_ids) $params['media_ids[]'] = $media_ids[0];
|
||||
if ($media_ids) $params['media_ids'] = $media_ids;
|
||||
$ch = curl_init($api_base . '/api/v1/statuses');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($params),
|
||||
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, 'Content-Type: application/x-www-form-urlencoded'],
|
||||
CURLOPT_POSTFIELDS => json_encode($params),
|
||||
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, 'Content-Type: application/json'],
|
||||
]);
|
||||
$resp = curl_exec($ch);
|
||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue