From e4895122c19d9039333abdc8ed52696704f57db0 Mon Sep 17 00:00:00 2001 From: Christopher Hertel Date: Sun, 23 Oct 2022 01:40:44 +0200 Subject: [PATCH] [Notifier] Add support for editing Telegram messages --- .../Bridge/Telegram/TelegramOptions.php | 10 +++ .../Bridge/Telegram/TelegramTransport.php | 6 +- .../Telegram/Tests/TelegramTransportTest.php | 74 ++++++++++++++++++- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramOptions.php b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramOptions.php index 335a7eccd697e..bbc2285b634aa 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramOptions.php +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramOptions.php @@ -99,4 +99,14 @@ public function replyMarkup(AbstractTelegramReplyMarkup $markup): static return $this; } + + /** + * @return $this + */ + public function edit(int $messageId): static + { + $this->options['message_id'] = $messageId; + + return $this; + } } diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransport.php b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransport.php index 773b09a2c0641..9a027b1ac2b32 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/TelegramTransport.php @@ -72,7 +72,6 @@ protected function doSend(MessageInterface $message): SentMessage throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" for options.', __CLASS__, TelegramOptions::class)); } - $endpoint = sprintf('https://%s/bot%s/sendMessage', $this->getEndpoint(), $this->token); $options = ($opts = $message->getOptions()) ? $opts->toArray() : []; if (!isset($options['chat_id'])) { $options['chat_id'] = $message->getRecipientId() ?: $this->chatChannel; @@ -85,6 +84,9 @@ protected function doSend(MessageInterface $message): SentMessage $options['text'] = preg_replace('/([_*\[\]()~`>#+\-=|{}.!])/', '\\\\$1', $message->getSubject()); } + $path = isset($options['message_id']) ? 'editMessageText' : 'sendMessage'; + $endpoint = sprintf('https://%s/bot%s/%s', $this->getEndpoint(), $this->token, $path); + $response = $this->client->request('POST', $endpoint, [ 'json' => array_filter($options), ]); @@ -98,7 +100,7 @@ protected function doSend(MessageInterface $message): SentMessage if (200 !== $statusCode) { $result = $response->toArray(false); - throw new TransportException('Unable to post the Telegram message: '.$result['description'].sprintf(' (code %s).', $result['error_code']), $response); + throw new TransportException('Unable to '.(isset($options['message_id']) ? 'edit' : 'post').' the Telegram message: '.$result['description'].sprintf(' (code %d).', $result['error_code']), $response); } $success = $response->toArray(false); diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php index 2c162a38eba9b..3231617c126b9 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php @@ -49,7 +49,7 @@ public function unsupportedMessagesProvider(): iterable public function testSendWithErrorResponseThrowsTransportException() { $this->expectException(TransportException::class); - $this->expectExceptionMessageMatches('/testDescription.+testErrorCode/'); + $this->expectExceptionMessageMatches('/post.+testDescription.+400/'); $response = $this->createMock(ResponseInterface::class); $response->expects($this->exactly(2)) @@ -57,7 +57,7 @@ public function testSendWithErrorResponseThrowsTransportException() ->willReturn(400); $response->expects($this->once()) ->method('getContent') - ->willReturn(json_encode(['description' => 'testDescription', 'error_code' => 'testErrorCode'])); + ->willReturn(json_encode(['description' => 'testDescription', 'error_code' => 400])); $client = new MockHttpClient(static function () use ($response): ResponseInterface { return $response; @@ -68,6 +68,28 @@ public function testSendWithErrorResponseThrowsTransportException() $transport->send(new ChatMessage('testMessage')); } + public function testSendWithErrorResponseThrowsTransportExceptionForEdit() + { + $this->expectException(TransportException::class); + $this->expectExceptionMessageMatches('/edit.+testDescription.+404/'); + + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(400); + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['description' => 'testDescription', 'error_code' => 404])); + + $client = new MockHttpClient(static function () use ($response): ResponseInterface { + return $response; + }); + + $transport = $this->createTransport($client, 'testChannel'); + + $transport->send(new ChatMessage('testMessage', (new TelegramOptions())->edit(123))); + } + public function testSendWithOptions() { $response = $this->createMock(ResponseInterface::class); @@ -110,6 +132,7 @@ public function testSendWithOptions() ]; $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertStringEndsWith('/sendMessage', $url); $this->assertSame($expectedBody, json_decode($options['body'], true)); return $response; @@ -123,6 +146,53 @@ public function testSendWithOptions() $this->assertEquals('telegram://api.telegram.org?channel=testChannel', $sentMessage->getTransport()); } + public function testSendWithOptionForEditMessage() + { + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + + $content = <<expects($this->once()) + ->method('getContent') + ->willReturn($content) + ; + + $client = new MockHttpClient(function (string $method, string $url) use ($response): ResponseInterface { + $this->assertStringEndsWith('/editMessageText', $url); + + return $response; + }); + + $transport = $this->createTransport($client, 'testChannel'); + $options = (new TelegramOptions())->edit(123); + + $transport->send(new ChatMessage('testMessage', $options)); + } + public function testSendWithChannelOverride() { $channelOverride = 'channelOverride';