Publish per-image alt text to Discord attachments
This commit is contained in:
parent
6115362c07
commit
f12f525d54
2 changed files with 86 additions and 1 deletions
|
|
@ -126,7 +126,14 @@ private function sendWithMedia(string $channelId, array $payload, Collection $me
|
|||
|
||||
$filename = $item->original_filename ?: (basename($item->path) ?: "media-{$index}");
|
||||
$request = $request->attach("files[{$index}]", file_get_contents($tempFile), $filename);
|
||||
$attachments[] = ['id' => $index, 'filename' => $filename];
|
||||
|
||||
$attachment = ['id' => $index, 'filename' => $filename];
|
||||
|
||||
if ($alt = $item->altText()) {
|
||||
$attachment['description'] = mb_substr($alt, 0, Platform::Discord->altTextMaxLength());
|
||||
}
|
||||
|
||||
$attachments[] = $attachment;
|
||||
}
|
||||
|
||||
$payload['attachments'] = $attachments;
|
||||
|
|
|
|||
|
|
@ -168,6 +168,84 @@ function fakeDiscord(array $messageResponse = ['id' => '777'], int $status = 200
|
|||
});
|
||||
});
|
||||
|
||||
test('sets the attachment description from image alt text, capped at the platform max', function () {
|
||||
$longAlt = str_repeat('a', 2000);
|
||||
|
||||
$this->post->update([
|
||||
'media' => [[
|
||||
'id' => 'm1',
|
||||
'path' => 'media/2026-01/pic.jpg',
|
||||
'url' => 'https://example.com/media/2026-01/pic.jpg',
|
||||
'mime_type' => 'image/jpeg',
|
||||
'original_filename' => 'pic.jpg',
|
||||
'meta' => ['alt_text' => $longAlt],
|
||||
]],
|
||||
]);
|
||||
|
||||
$this->mock(MediaOptimizer::class)
|
||||
->shouldReceive('optimizeImage')
|
||||
->andReturnUsing(fn () => tap(tempnam(sys_get_temp_dir(), 'discord_test_'), fn ($f) => file_put_contents($f, str_repeat('x', 1024))));
|
||||
|
||||
Http::fake([
|
||||
config('trypost.platforms.discord.api').'/guilds/*/channels' => Http::response([['id' => '444555666', 'name' => 'general', 'type' => 0]], 200),
|
||||
config('trypost.platforms.discord.api').'/guilds/*/roles' => Http::response([['id' => '111222333', 'name' => '@everyone', 'permissions' => '3072']], 200),
|
||||
config('trypost.platforms.discord.api').'/guilds/*/members/*' => Http::response(['roles' => []], 200),
|
||||
'example.com/*' => Http::response(str_repeat('x', 1024), 200),
|
||||
config('trypost.platforms.discord.api').'/channels/*/messages' => Http::response(['id' => '902'], 200),
|
||||
]);
|
||||
|
||||
$this->publisher->publish(($this->makePostPlatform)());
|
||||
|
||||
$expectedAlt = mb_substr($longAlt, 0, Platform::Discord->altTextMaxLength());
|
||||
|
||||
Http::assertSent(function ($request) use ($expectedAlt) {
|
||||
if (! str_contains($request->url(), '/messages')) {
|
||||
return false;
|
||||
}
|
||||
$payloadPart = collect($request->data())->firstWhere('name', 'payload_json');
|
||||
$payload = json_decode(data_get($payloadPart, 'contents'), true);
|
||||
|
||||
return data_get($payload, 'attachments.0.description') === $expectedAlt
|
||||
&& mb_strlen($expectedAlt) === Platform::Discord->altTextMaxLength();
|
||||
});
|
||||
});
|
||||
|
||||
test('omits the attachment description when the image has no alt text', function () {
|
||||
$this->post->update([
|
||||
'media' => [[
|
||||
'id' => 'm1',
|
||||
'path' => 'media/2026-01/pic.jpg',
|
||||
'url' => 'https://example.com/media/2026-01/pic.jpg',
|
||||
'mime_type' => 'image/jpeg',
|
||||
'original_filename' => 'pic.jpg',
|
||||
]],
|
||||
]);
|
||||
|
||||
$this->mock(MediaOptimizer::class)
|
||||
->shouldReceive('optimizeImage')
|
||||
->andReturnUsing(fn () => tap(tempnam(sys_get_temp_dir(), 'discord_test_'), fn ($f) => file_put_contents($f, str_repeat('x', 1024))));
|
||||
|
||||
Http::fake([
|
||||
config('trypost.platforms.discord.api').'/guilds/*/channels' => Http::response([['id' => '444555666', 'name' => 'general', 'type' => 0]], 200),
|
||||
config('trypost.platforms.discord.api').'/guilds/*/roles' => Http::response([['id' => '111222333', 'name' => '@everyone', 'permissions' => '3072']], 200),
|
||||
config('trypost.platforms.discord.api').'/guilds/*/members/*' => Http::response(['roles' => []], 200),
|
||||
'example.com/*' => Http::response(str_repeat('x', 1024), 200),
|
||||
config('trypost.platforms.discord.api').'/channels/*/messages' => Http::response(['id' => '903'], 200),
|
||||
]);
|
||||
|
||||
$this->publisher->publish(($this->makePostPlatform)());
|
||||
|
||||
Http::assertSent(function ($request) {
|
||||
if (! str_contains($request->url(), '/messages')) {
|
||||
return false;
|
||||
}
|
||||
$payloadPart = collect($request->data())->firstWhere('name', 'payload_json');
|
||||
$payload = json_decode(data_get($payloadPart, 'contents'), true);
|
||||
|
||||
return ! array_key_exists('description', data_get($payload, 'attachments.0'));
|
||||
});
|
||||
});
|
||||
|
||||
test('throws when no channel is selected', function () {
|
||||
expect(fn () => $this->publisher->publish(($this->makePostPlatform)(meta: [])))
|
||||
->toThrow(DiscordPublishException::class);
|
||||
|
|
|
|||
Loading…
Reference in a new issue