8000 Fix BC with sending photo in Telegram by file_id · symfony/symfony@0ba9064 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ba9064

Browse files
committed
Fix BC with sending photo in Telegram by file_id
1 parent f1ac295 commit 0ba9064

File tree

4 files changed

+124
-24
lines changed

4 files changed

+124
-24
lines changed

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ With a Telegram message, you can use the `TelegramOptions` class to add
5454
[message options](https://core.telegram.org/bots/api).
5555

5656
```php
57-
use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\Button\InlineKeyboardButton;
58-
use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\InlineKeyboardMarkup;
5957
use Symfony\Component\Notifier\Bridge\Telegram\TelegramOptions;
6058
use Symfony\Component\Notifier\Message\ChatMessage;
6159

@@ -76,15 +74,32 @@ $chatMessage->options($telegramOptions);
7674
$chatter->send($chatMessage);
7775
```
7876

77+
[Telegram supports 3 ways](https://core.telegram.org/bots/api#sending-files) for passing photo:
78+
79+
* Pass image HTTP URL to Telegram
80+
```
81+
$telegramOptions = (new TelegramOptions())
82+
->photo('https://symfony.com/favicons/android-chrome-192x192.png');
83+
```
84+
* Pass Telegram file_id
85+
```
86+
$telegramOptions = (new TelegramOptions())
87+
->photo('ABCDEF');
88+
```
89+
* Post the file using multipart/form-data
90+
```
91+
$telegramOptions = (new TelegramOptions())
92+
->uploadPhoto('files/android-chrome-192x192.png');
93+
```
94+
95+
7996
Adding Location to a Message
8097
----------------------------
8198

8299
With a Telegram message, you can use the `TelegramOptions` class to add
83100
[message options](https://core.telegram.org/bots/api).
84101

85102
```php
86-
use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\Button\InlineKeyboardButton;
87-
use Symfony\Component\Notifier\Bridge\Telegram\Reply\Markup\InlineKeyboardMarkup;
88103
use Symfony\Component\Notifier\Bridge\Telegram\TelegramOptions;
89104
use Symfony\Component\Notifier\Message\ChatMessage;
90105

src/Symfony/Component/Notifier/Bridge/Telegram/TelegramOptions.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ public function photo(string $url): static
112112
return $this;
113113
}
114114

115+
/**
116+
* @return $this
117+
*/
118+
public function uploadPhoto(string $path): static
119+
{
120+
$this->options['upload_photo'] = $path;
121+
122+
return $this;
123+
}
124+
115125
/**
116126
* @return $this
117127
*/

src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransport.php

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,15 @@ protected function doSend(MessageInterface $message): SentMessage
7777
$options['text'] = preg_replace('/([_*\[\]()~`>#+\-=|{}.!])/', '\\\\$1', $message->getSubject());
7878
}
7979

80+
if (isset($options['upload_photo'])) {
81+
$options['photo'] = fopen($options['upload_photo'], 'r');
82+
$optionsContainer = 'body';
83+
unset($options['upload_photo']);
84+
}
85+
8086
if (isset($options['photo'])) {
8187
$options['caption'] = $options['text'];
8288
unset($options['text']);
83-
if ($this->isPhotoPrivate($options['photo'])) {
84-
$options['photo'] = fopen($options['photo'], 'r');
85-
$optionsContainer = 'body';
86-
}
8789
}
8890

8991
$endpoint = sprintf('https://%s/bot%s/%s', $this->getEndpoint(), $this->token, $this->getPath($options));
@@ -133,12 +135,4 @@ private function getAction(array $options): string
133135
default => 'post',
134136
};
135137
}
136-
137-
private function isPhotoPrivate(string $photo): bool
138-
{
139-
return match (parse_url($photo, \PHP_URL_SCHEME)) {
140-
'http', 'https' => false,
141-
default => true,
142-
};
143-
}
144138
}

src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ public function testSendWithMarkdownShouldEscapeSpecialCharacters()
331331
$transport->send(new ChatMessage('I contain special characters _ * [ ] ( ) ~ ` > # + - = | { } . ! to send.'));
332332
}
333333

334-
public function testSendPhotoWithOptions()
334+
public function testSendPhotoByHttpUrlWithOptions()
335335
{
336336
$response = $this->createMock(ResponseInterface::class);
337337
$response->expects($this->exactly(2))
@@ -412,7 +412,88 @@ public function testSendPhotoWithOptions()
412412
$this->assertEquals('telegram://api.telegram.org?channel=testChannel', $sentMessage->getTransport());
413413
}
414414

415-
public function testSendLocalPhotoWithOptions()
415+
public function testSendPhotoByFileIdWithOptions()
416+
{
417+
$response = $this->createMock(ResponseInterface::class);
418+
$response->expects($this->exactly(2))
419+
->method('getStatusCode')
420+
->willReturn(200);
421+
422+
$content = <<<JSON
423+
{
424+
"ok": true,
425+
"result": {
426+
"message_id": 1,
427+
"from": {
428+
"id": 12345678,
429+
"is_bot": true,
430+
"first_name": "YourBot",
431+
"username": "YourBot"
432+
},
433+
"chat": {
434+
"id": 1234567890,
435+
"first_name": "John",
436+
"last_name": "Doe",
437+
"username": "JohnDoe",
438+
"type": "private"
439+
},
440+
"date": 1459958199,
441+
"photo": [
442+
{
443+
"file_id": "ABCDEF",
444+
"file_unique_id" : "ABCDEF1",
445+
"file_size": 1378,
446+
"width": 90,
447+
"height": 51
448+
},
449+
{
450+
"file_id": "ABCDEF",
451+
"file_unique_id" : "ABCDEF2",
452+
"file_size": 19987,
453+
"width": 320,
454+
"height": 180
455+
}
456+
],
457+
"caption": "Hello from Bot!"
458+
}
459+
}
460+
JSON;
461+
462+
$response->expects($this->once())
463+
->method('getContent')
464+
->willReturn($content)
465+
;
466+
467+
$expectedBody = [
468+
'photo' => 'ABCDEF',
469+
'has_spoiler' => true,
470+
'chat_id' => 'testChannel',
471+
'parse_mode' => 'MarkdownV2',
472+
'caption' => 'testMessage',
473+
];
474+
475+
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface {
476+
$this->assertStringEndsWith('/sendPhoto', $url);
477+
$this->assertSame($expectedBody, json_decode($options['body'], true));
478+
479+
return $response;
480+
});
481+
482+
$transport = self::createTransport($client, 'testChannel');
483+
484+
$messageOptions = new TelegramOptions();
485+
$messageOptions
486+
->photo('ABCDEF')
487+
->hasSpoiler(true)
488+
;
489+
490+
$sentMessage = $transport->send(new ChatMessage('testMessage', $messageOptions));
491+
492+
$this->assertEquals(1, $sentMessage->getMessageId());
493+
$this->assertEquals('telegram://api.telegram.org?channel=testChannel', $sentMessage->getTransport());
494+
}
495+
496+
public function testSendPhotoByUploadWithOptions()
416497
{
417498
$response = $this->createMock(ResponseInterface::class);
418499
$response->expects($this->exactly(2))
@@ -470,11 +551,6 @@ public function testSendLocalPhotoWithOptions()
470551

471552
$this->assertSame('Content-Length: 576', $options['normalized_headers']['content-length'][0]);
472553
$expectedBody = <<<BODY
473-
--{$matches['boundary']}
474-
Content-Disposition: form-data; name="photo"; filename="fixtures.png"
475-
Content-Type: image/png
476-
477-
%s
478554
--{$matches['boundary']}
479555
Content-Disposition: form-data; name="has_spoiler"
480556
@@ -488,6 +564,11 @@ public function testSendLocalPhotoWithOptions()
488564
489565
MarkdownV2
490566
--{$matches['boundary']}
567+
Content-Disposition: form-data; name="photo"; filename="fixtures.png"
568+
Content-Type: image/png
569+
570+
%s
571+
--{$matches['boundary']}
491572
Content-Disposition: form-data; name="caption"
492573
493574
testMessage
@@ -510,7 +591,7 @@ public function testSendLocalPhotoWithOptions()
510591

511592
$messageOptions = new TelegramOptions();
512593
$messageOptions
513-
->photo(__DIR__.'/fixtures.png')
594+
->uploadPhoto(__DIR__.'/fixtures.png')
514595
->hasSpoiler(true)
515596
;
516597

0 commit comments

Comments
 (0)
0