Skip to content

Commit 37ec351

Browse files
pan93412OskarStark
andcommitted
[Notifier] Add LINE Bot bridge
Co-authored-by: Oskar Stark <oskarstark@googlemail.com>
1 parent d83167d commit 37ec351

File tree

17 files changed

+428
-0
lines changed

17 files changed

+428
-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 $channelAccessToken,
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+
"https://{$this->getEndpoint()}/v2/bot/message/push",
48+
[
49+
'headers' => [
50+
'Authorization' => "Bearer $this->channelAccessToken",
51+
],
52+
'json' => [
53+
'to' => $this->receiver,
54+
'messages' => [
55+
[
56+
'type' => 'text',
57+
'text' => $message->getSubject(),
58+
],
59+
],
60+
],
61+
],
62+
);
63+
64+
try {
65+
$statusCode = $response->getStatusCode();
66+
} catch (\Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface $e) {
67+
throw new TransportException('Could not reach the remote LINE server.', $response, 0, $e);
68+
}
69+
70+
if (200 !== $statusCode) {
71+
$originalContent = $message->getSubject();
72+
73+
$result = $response->toArray(false) ?: ['message' => ''];
74+
$errorMessage = trim($result['message']);
75+
76+
throw new TransportException("Unable to post the LINE message: \"$originalContent\" ($statusCode: \"$errorMessage\").", $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 "linebot://{$this->getEndpoint()}?receiver=$this->receiver";
90+
}
91+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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\UnsupportedSchemeException;
15+
use Symfony\Component\Notifier\Transport\AbstractTransportFactory;
16+
use Symfony\Component\Notifier\Transport\Dsn;
17+
18+
/**
19+
@author Yi-Jyun Pan <me@pan93.com>
20+
*/
21+
final class LineBotTransportFactory extends AbstractTransportFactory
22+
{
23+
private const SCHEME = 'linebot';
24+
25+
protected function getSupportedSchemes(): array
26+
{
27+
return [self::SCHEME];
28+
}
29+
30+
public function create(Dsn $dsn): LineBotTransport
31+
{
32+
if (self::SCHEME !== $dsn->getScheme()) {
33+
throw new UnsupportedSchemeException($dsn, self::SCHEME, $this->getSupportedSchemes());
34+
}
35+
36+
$accessToken = $dsn->getUser();
37+
$receiver = $dsn->getRequiredOption('receiver');
38+
$host = 'default' === $dsn->getHost() ? null : $dsn->getHost();
39+
$port = $dsn->getPort();
40+
41+
return (new LineBotTransport($accessToken, $receiver, $this->client, $this->dispatcher))->setHost($host)->setPort($port);
42+
}
43+
}

0 commit comments

Comments
 (0)