Skip to content

Commit cb16097

Browse files
committed
feature symfony#58527 [Notifier] Add LINE Bot bridge (pan93412)
This PR was squashed before being merged into the 7.2 branch. Discussion ---------- [Notifier] Add LINE Bot bridge | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | Fix symfony#58474 | License | MIT It should be worked as what LINE Notify used to do: <img src="https://github.com/user-attachments/assets/80783c1b-c0af-42fb-9f08-ca60de9e0cdb" width="40%" alt="LINE Bot demo"> Commits ------- 4f4742e [Notifier] Add LINE Bot bridge
2 parents 661bda1 + 4f4742e commit cb16097

File tree

17 files changed

+441
-0
lines changed

17 files changed

+441
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,6 +2839,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
28392839
NotifierBridge\JoliNotif\JoliNotifTransportFactory::class => 'notifier.transport_factory.joli-notif',
28402840
NotifierBridge\KazInfoTeh\KazInfoTehTransportFactory::class => 'notifier.transport_factory.kaz-info-teh',
28412841
NotifierBridge\LightSms\LightSmsTransportFactory::class => 'notifier.transport_factory.light-sms',
2842+
NotifierBridge\LineBot\LineBotTransportFactory::class => 'notifier.transport_factory.line-bot',
28422843
NotifierBridge\LineNotify\LineNotifyTransportFactory::class => 'notifier.transport_factory.line-notify',
28432844
NotifierBridge\LinkedIn\LinkedInTransportFactory::class => 'notifier.transport_factory.linked-in',
28442845
NotifierBridge\Lox24\Lox24TransportFactory::class => 'notifier.transport_factory.lox24',

src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
'fake-chat' => Bridge\FakeChat\FakeChatTransportFactory::class,
3333
'firebase' => Bridge\Firebase\FirebaseTransportFactory::class,
3434
'google-chat' => Bridge\GoogleChat\GoogleChatTransportFactory::class,
35+
'line-bot' => Bridge\LineBot\LineBotTransportFactory::class,
3536
'line-notify' => Bridge\LineNotify\LineNotifyTransportFactory::class,
3637
'linked-in' => Bridge\LinkedIn\LinkedInTransportFactory::class,
3738
'mastodon' => Bridge\Mastodon\MastodonTransportFactory::class,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/Tests export-ignore
2+
/phpunit.xml.dist export-ignore
3+
/.git* export-ignore

src/Symfony/Component/Notifier/Bridge/LineBot/.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Symfony/Component/Notifier/Bridge/LineBot/.github/workflows/close-pull-request.yml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CHANGELOG
2+
=========
3+
4+
7.2
5+
---
6+
7+
* Add LINE Bot bridge
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2024-present Fabien Potencier
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Notifier\Bridge\LineBot;
13+
14+
use Symfony\Component\Notifier\Exception\TransportException;
15+
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
16+
use Symfony\Component\Notifier\Message\ChatMessage;
17+
use Symfony\Component\Notifier\Message\MessageInterface;
18+
use Symfony\Component\Notifier\Message\SentMessage;
19+
use Symfony\Component\Notifier\Transport\AbstractTransport;
20+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
21+
use Symfony\Contracts\HttpClient\HttpClientInterface;
22+
23+
/**
24+
* @author Yi-Jyun Pan <me@pan93.com>
25+
*/
26+
final class LineBotTransport extends AbstractTransport
27+
{
28+
protected const HOST = 'api.line.me';
29+
30+
public function __construct(
31+
#[\SensitiveParameter] private readonly string $accessToken,
32+
private readonly string $receiver,
33+
?HttpClientInterface $client = null,
34+
?EventDispatcherInterface $dispatcher = null,
35+
) {
36+
parent::__construct($client, $dispatcher);
37+
}
38+
39+
protected function doSend(MessageInterface $message): SentMessage
40+
{
41+
if (!$message instanceof ChatMessage) {
42+
throw new UnsupportedMessageTypeException(__CLASS__, ChatMessage::class, $message);
43+
}
44+
45+
$response = $this->client->request(
46+
'POST',
47+
\sprintf('https://%s/v2/bot/message/push', $this->getEndpoint()),
48+
[
49+
'auth_bearer' => $this->accessToken,
50+
'json' => [
51+
'to' => $this->receiver,
52+
'messages' => [
53+
[
54+
'type' => 'text',
55+
'text' => $message->getSubject(),
56+
],
57+
],
58+
],
59+
],
60+
);
61+
62+
try {
63+
$statusCode = $response->getStatusCode();
64+
} catch (\Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface $e) {
65+
throw new TransportException('Could not reach the remote LINE server.', $response, 0, $e);
66+
}
67+
68+
if (200 !== $statusCode) {
69+
$originalContent = $message->getSubject();
70+
71+
$result = $response->toArray(false) ?: ['message' => ''];
72+
if (!isset($result['message']) || !\is_string($result['message'])) {
73+
$result['message'] = '';
74+
}
75+
76+
throw new TransportException(\sprintf('Unable to post the LINE message: "%s" (%d: "%s").', $originalContent, $statusCode, trim($result['message'])), $response);
77+
}
78+
79+
return new SentMessage($message, (string) $this);
80+
}
81+
82+
public function supports(MessageInterface $message): bool
83+
{
84+
return $message instanceof ChatMessage;
85+
}
86+
87+
public function __toString(): string
88+
{
89+
return \sprintf('linebot://%s?receiver=%s', $this->getEndpoint(), $this->receiver);
90+
}
91+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Notifier\Bridge\LineBot;
13+
14+
use Symfony\Component\Notifier\Exception\InvalidArgumentException;
15+
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
16+
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
17+
use Symfony\Component\Notifier\Transport\Dsn;
18+
19+
/**
20+
* @author Yi-Jyun Pan <me@pan93.com>
21+
*/
22+
final class LineBotTransportFactory extends AbstractTransportFactory
23+
{
24+
private const SCHEME = 'linebot';
25+
26+
protected function getSupportedSchemes(): array
27+
{
28+
return [self::SCHEME];
29+
}
30+
31+
public function create(Dsn $dsn): LineBotTransport
32+
{
33+
if (self::SCHEME !== $dsn->getScheme()) {
34+
throw new UnsupportedSchemeException($dsn, self::SCHEME, $this->getSupportedSchemes());
35+
}
36+
37+
$accessToken = $this->getUser($dsn);
38+
$receiver = $dsn->getRequiredOption('receiver');
39+
if (!\is_string($receiver)) {
40+
throw new InvalidArgumentException('The "receiver" option must be a string.');
41+
}
42+
43+
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
44+
$port = $dsn->getPort();
45+
46+
return (new LineBotTransport($accessToken, $receiver, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
47+
}
48+
}

0 commit comments

Comments
 (0)