Skip to content

Commit cf015b8

Browse files
committed
feature symfony#59667 [Notifier] [Bluesky] Allow to attach website preview card (ppoulpe)
This PR was merged into the 7.3 branch. Discussion ---------- [Notifier] [Bluesky] Allow to attach website preview card | Q | A | ------------- | --- | Branch? | 7.3 <!-- see below --> | Bug fix? | no | New feature? | yes<!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Issues | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT <!-- Replace this notice by a description of your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too). - Features and deprecations must be submitted against the latest branch. - For new features, provide some code snippets to help understand usage. - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> This addition will allow us to add a preview card to a link: ![image](https://github.com/user-attachments/assets/c2d5a19c-95e1-4160-8677-8e5cb15af904) Commits ------- 15ded98 [Notifier] [Bluesky] Allow to attach website preview card
2 parents a7a32f7 + 15ded98 commit cf015b8

File tree

5 files changed

+97
-7
lines changed

5 files changed

+97
-7
lines changed

src/Symfony/Component/Notifier/Bridge/Bluesky/BlueskyOptions.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,16 @@ public function attachMedia(File $file, string $description = ''): static
4343

4444
return $this;
4545
}
46+
47+
public function attachCard(string $uri, File $thumb, string $title = '', string $description = ''): static
48+
{
49+
$this->options['external'] = [
50+
'uri' => $uri,
51+
'thumb' => $thumb,
52+
'title' => $title,
53+
'description' => $description,
54+
];
55+
56+
return $this;
57+
}
4658
}

src/Symfony/Component/Notifier/Bridge/Bluesky/BlueskyTransport.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,26 @@ protected function doSend(MessageInterface $message): SentMessage
9191
unset($options['attach']);
9292
}
9393

94+
if (isset($options['external'])) {
95+
$uploadedMedia = $this->uploadMedia([
96+
[
97+
'file' => $options['external']['thumb'],
98+
'description' => $options['external']['description'],
99+
],
100+
]);
101+
102+
$options['record']['embed'] = [
103+
'$type' => 'app.bsky.embed.external',
104+
'external' => [
105+
'uri' => $options['external']['uri'],
106+
'title' => $options['external']['title'],
107+
'description' => $options['external']['description'],
108+
'thumb' => $uploadedMedia[array_key_first($uploadedMedia)]['image'],
109+
],
110+
];
111+
unset($options['external']);
112+
}
113+
94114
$response = $this->client->request('POST', \sprintf('https://%s/xrpc/com.atproto.repo.createRecord', $this->getEndpoint()), [
95115
'auth_bearer' => $this->authSession['accessJwt'] ?? null,
96116
'json' => $options,

src/Symfony/Component/Notifier/Bridge/Bluesky/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add option to attach a website preview card
8+
49
7.2
510
---
611

src/Symfony/Component/Notifier/Bridge/Bluesky/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@ DSN example
1010
BLUESKY_DSN=bluesky://nyholm.bsky.social:[email protected]
1111
```
1212

13+
Adding Options to a Message
14+
---------------------------
15+
16+
Use a `BlueskyOptions` object to add options to the message:
17+
18+
```php
19+
use Symfony\Component\Notifier\Bridge\Bluesky\BlueskyOptions;
20+
use Symfony\Component\Notifier\Message\ChatMessage;
21+
22+
$message = new ChatMessage('My message');
23+
24+
// Add website preview card to the message
25+
$options = (new BlueskyOptions())
26+
->attachCard('https://example.com', new File('image.jpg'))
27+
// You can also add media to the message
28+
//->attachMedia(new File($command->fileName), 'description')
29+
;
30+
31+
// Add the custom options to the Bluesky message and send the message
32+
$message->options($options);
33+
34+
$chatter->send($message);
35+
```
36+
1337
Resources
1438
---------
1539

src/Symfony/Component/Notifier/Bridge/Bluesky/Tests/BlueskyTransportTest.php

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,12 @@ public function testParseFacetsUrlWithTrickyRegex()
274274
$this->assertEquals($expected, $this->parseFacets($input));
275275
}
276276

277-
public function testWithMedia()
277+
/**
278+
* @dataProvider sendMessageWithEmbedDataProvider
279+
*/
280+
public function testWithEmbed(BlueskyOptions $blueskyOptions, string $expectedJsonResponse)
278281
{
279-
$transport = $this->createTransport(new MockHttpClient((function () {
282+
$transport = $this->createTransport(new MockHttpClient((function () use ($expectedJsonResponse) {
280283
yield function (string $method, string $url, array $options) {
281284
$this->assertSame('POST', $method);
282285
$this->assertSame('https://bsky.social/xrpc/com.atproto.server.createSession', $url);
@@ -299,23 +302,49 @@ public function testWithMedia()
299302
]]);
300303
};
301304

302-
yield function (string $method, string $url, array $options) {
305+
yield function (string $method, string $url, array $options) use ($expectedJsonResponse) {
303306
$this->assertSame('POST', $method);
304307
$this->assertSame('https://bsky.social/xrpc/com.atproto.repo.createRecord', $url);
305308
$this->assertArrayHasKey('authorization', $options['normalized_headers']);
306-
$this->assertSame('{"repo":null,"collection":"app.bsky.feed.post","record":{"$type":"app.bsky.feed.post","text":"Hello World!","createdAt":"2024-04-28T08:40:17.000000Z","embed":{"$type":"app.bsky.embed.images","images":[{"alt":"A fixture","image":{"$type":"blob","ref":{"$link":"bafkreibabalobzn6cd366ukcsjycp4yymjymgfxcv6xczmlgpemzkz3cfa"},"mimeType":"image\/png","size":760898}}]}}}', $options['body']);
309+
$this->assertSame($expectedJsonResponse, $options['body']);
307310

308311
return new JsonMockResponse(['cid' => '103254962155278888']);
309312
};
310313
})()));
311314

312-
$options = (new BlueskyOptions())
313-
->attachMedia(new File(__DIR__.'/fixtures.gif'), 'A fixture');
314-
$result = $transport->send(new ChatMessage('Hello World!', $options));
315+
$result = $transport->send(new ChatMessage('Hello World!', $blueskyOptions));
315316

316317
$this->assertSame('103254962155278888', $result->getMessageId());
317318
}
318319

320+
public function sendMessageWithEmbedDataProvider(): iterable
321+
{
322+
yield 'With media' => [
323+
'options' => (new BlueskyOptions())->attachMedia(new File(__DIR__.'/fixtures.gif'), 'A fixture'),
324+
'expectedResponse' => '{"repo":null,"collection":"app.bsky.feed.post","record":{"$type":"app.bsky.feed.post","text":"Hello World!","createdAt":"2024-04-28T08:40:17.000000Z","embed":{"$type":"app.bsky.embed.images","images":[{"alt":"A fixture","image":{"$type":"blob","ref":{"$link":"bafkreibabalobzn6cd366ukcsjycp4yymjymgfxcv6xczmlgpemzkz3cfa"},"mimeType":"image\/png","size":760898}}]}}}',
325+
];
326+
327+
yield 'With website preview card and all optionnal informations' => [
328+
'options' => (new BlueskyOptions())
329+
->attachCard(
330+
'https://example.com',
331+
new File(__DIR__.'/fixtures.gif'),
332+
'Fork me im famous',
333+
'Click here to go to website!'
334+
),
335+
'expectedResponse' => '{"repo":null,"collection":"app.bsky.feed.post","record":{"$type":"app.bsky.feed.post","text":"Hello World!","createdAt":"2024-04-28T08:40:17.000000Z","embed":{"$type":"app.bsky.embed.external","external":{"uri":"https:\/\/example.com","title":"Fork me im famous","description":"Click here to go to website!","thumb":{"$type":"blob","ref":{"$link":"bafkreibabalobzn6cd366ukcsjycp4yymjymgfxcv6xczmlgpemzkz3cfa"},"mimeType":"image\/png","size":760898}}}}}',
336+
];
337+
338+
yield 'With website preview card and minimal information' => [
339+
'options' => (new BlueskyOptions())
340+
->attachCard(
341+
'https://example.com',
342+
new File(__DIR__.'/fixtures.gif')
343+
),
344+
'expectedResponse' => '{"repo":null,"collection":"app.bsky.feed.post","record":{"$type":"app.bsky.feed.post","text":"Hello World!","createdAt":"2024-04-28T08:40:17.000000Z","embed":{"$type":"app.bsky.embed.external","external":{"uri":"https:\/\/example.com","title":"","description":"","thumb":{"$type":"blob","ref":{"$link":"bafkreibabalobzn6cd366ukcsjycp4yymjymgfxcv6xczmlgpemzkz3cfa"},"mimeType":"image\/png","size":760898}}}}}',
345+
];
346+
}
347+
319348
/**
320349
* A small helper function to test BlueskyTransport::parseFacets().
321350
*/

0 commit comments

Comments
 (0)