diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..cd8eb86e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+; This file is for unifying the coding style for different editors and IDEs.
+; More information at http://editorconfig.org
+
+root = true
+
+[*]
+charset = utf-8
+indent_size = 4
+indent_style = space
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..b2638710
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+# Path-based git attributes
+# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
+
+# Ignore all test and documentation with "export-ignore".
+/.gitattributes export-ignore
+/.gitignore export-ignore
+/.travis.yml export-ignore
+/phpunit.xml.dist export-ignore
+/.scrutinizer.yml export-ignore
+/tests export-ignore
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 00000000..99d4daf7
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,32 @@
+name: PHPUnit tests
+
+on:
+ - push
+ - pull_request
+
+jobs:
+ tests:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: true
+ matrix:
+ php: [8.1, 8.2, 8.3]
+
+ name: Tests on PHP ${{ matrix.php }} - ${{ matrix.stability }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: composer:v2
+ coverage: pcov
+
+ - name: Install dependencies
+ run: composer update --prefer-source --no-interaction --no-progress
+
+ - name: Execute tests
+ run: vendor/bin/phpunit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..0044b968
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+/.phpunit.cache
+/build
+/vendor
+composer.phar
+composer.lock
+.DS_Store
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 00000000..d748664b
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $PROJECT_DIR$/composer.json
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1726217638481
+
+
+ 1726217638481
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
new file mode 100644
index 00000000..fc4b6f4f
--- /dev/null
+++ b/.scrutinizer.yml
@@ -0,0 +1,18 @@
+checks:
+ php:
+ remove_extra_empty_lines: true
+ remove_php_closing_tag: true
+ remove_trailing_whitespace: true
+ fix_use_statements:
+ remove_unused: true
+ preserve_multiple: false
+ preserve_blanklines: true
+ order_alphabetically: true
+ fix_php_opening_tag: true
+ fix_linefeed: true
+ fix_line_ending: true
+ fix_identation_4spaces: true
+ fix_doc_comments: true
+
+tools:
+ external_code_coverage: true
diff --git a/.styleci.yml b/.styleci.yml
new file mode 100644
index 00000000..0285f179
--- /dev/null
+++ b/.styleci.yml
@@ -0,0 +1 @@
+preset: laravel
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100755
index 00000000..fd83ef6c
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Changelog
+
+All notable changes to `:package_name` will be documented in this file
+
+## 1.0.0 - 201X-XX-XX
+
+- initial release
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100755
index 00000000..4da74e3f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,55 @@
+# Contributing
+
+Contributions are **welcome** and will be fully **credited**.
+
+Please read and understand the contribution guide before creating an issue or pull request.
+
+## Etiquette
+
+This project is open source, and as such, the maintainers give their free time to build and maintain the source code
+held within. They make the code freely available in the hope that it will be of use to other developers. It would be
+extremely unfair for them to suffer abuse or anger for their hard work.
+
+Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
+world that developers are civilized and selfless people.
+
+It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
+quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.
+
+## Viability
+
+When requesting or submitting new features, first consider whether it might be useful to others. Open
+source projects are used by many developers, who may have entirely different needs to your own. Think about
+whether or not your feature is likely to be used by other users of the project.
+
+## Procedure
+
+Before filing an issue:
+
+- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
+- Check to make sure your feature suggestion isn't already present within the project.
+- Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
+- Check the pull requests tab to ensure that the feature isn't already in progress.
+
+Before submitting a pull request:
+
+- Check the codebase to ensure that your feature doesn't already exist.
+- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
+
+## Requirements
+
+If the project maintainer has any additional requirements, you will find them listed here.
+
+- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
+
+- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
+
+- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
+
+- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
+
+- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
+
+- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
+
+**Happy coding**!
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 00000000..8bc4a36c
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+# The MIT License (MIT)
+
+Copyright (c) :author_name <:author_email>
+
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+> THE SOFTWARE.
diff --git a/README.md b/README.md
index fa8362b7..fca25217 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,102 @@
-# New Notification Channels
+# LINE Laravel Notifications Channel
-### Suggesting a new channel
-Have a suggestion or working on a new channel? Please create a new issue for that service.
+[](https://packagist.org/packages/laravel-notification-channels/line)
+[](LICENSE.md)
+[](https://travis-ci.org/laravel-notification-channels/line)
+[](https://styleci.io/repos/241828511)
+[](https://scrutinizer-ci.com/g/laravel-notification-channels/line)
+[](https://scrutinizer-ci.com/g/laravel-notification-channels/line/?branch=master)
+[](https://packagist.org/packages/laravel-notification-channels/line)
-### I'm working on a new channel
-Please create an issue for it if it does not already exist, then PR you code for review.
+## Introduction
-## Workflow for new channels
+This package makes it easy to send notifications using [LINE](https://line.me/) with Laravel 5.6+.
-1) Head over to the [skeleton repo](https://github.com/laravel-notification-channels/skeleton) download a ZIP copy. This is important, to ensure you start from a fresh commit history.
-2) Use find/replace to replace all of the placeholders with the correct values (package name, author name, email, etc).
-3) Implement to logic for the channel & add tests.
-4) Fork this repo, add it as a remote and push your new channel to a branch.
-5) Submit a new PR against this repo for review.
+## Contents
-Take a look at our [FAQ](http://laravel-notification-channels.com/) to see our small list of rules, to provide top-notch notification channels.
+- [LINE Laravel Notifications Channel](#line-laravel-notifications-channel)
+ - [Introduction](#introduction)
+ - [Contents](#contents)
+ - [Installation](#installation)
+ - [Setting up the LINE service](#setting-up-the-line-service)
+ - [Usage](#usage)
+ - [Available methods](#available-methods)
+ - [Security](#security)
+ - [Contributing](#contributing)
+ - [Credits](#credits)
+ - [License](#license)
+
+## Installation
+
+You can install the package via composer:
+
+```shell script
+$ composer require laravel-notification-channels/line
+```
+
+### Setting up the LINE service
+
+In order to send message to LINE channels, you need to obtain [Messaging API overview](https://developers.line.biz/en/docs/messaging-api/overview/).
+
+Add your LINE Message API Token to your `config/services.php`:
+
+```php
+// config/services.php
+...
+'line_message_api' => [
+ 'token' => env('LINE_MESSAGE_TOKEN', 'YOUR MESSAGE TOKEN HERE'),
+],
+...
+```
+
+## Usage
+
+You can use the channel in your `via()` method inside the notification:
+
+```php
+use Illuminate\Notifications\Notification;
+use NotificationChannels\Line\LineMessage;
+use NotificationChannels\Line\LineWebhookChannel;
+
+class TaskCompleted extends Notification
+{
+ public function via($notifiable): array
+ {
+ return [
+ 'line',
+ ];
+ }
+
+ public function toLine($notifiable): LineMessage
+ {
+ return LineMessage::create('Test message')
+ ->to('line_user_id')
+ ->from('message_api_token'); // optional if set in config
+ }
+}
+```
+
+### Available methods
+
+`from()`: Sets the sender's access token.
+
+`to()`: Specifies the line user id to send the notification to.
+
+`content()`: Sets a content of the notification message. Only support plain text for now.
+
+## Security
+
+If you discover any security related issues, please email s950329@hotmail.com instead of using the issue tracker.
+
+## Contributing
+
+Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
+
+## Credits
+
+- [Leo Chien](https://github.com/s950329)
+- [All Contributors](../../contributors)
+
+## License
+
+The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..4f21d975
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,49 @@
+{
+ "name": "laravel-notification-channels/line",
+ "description": "LINE Notifications Channel for Laravel",
+ "homepage": "https://github.com/laravel-notification-channels/line",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Leo Chien",
+ "email": "s950329@hotmail.com",
+ "homepage": "https://google.com",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=8.1",
+ "illuminate/notifications": "~10.0 || ~11.0",
+ "illuminate/support": "~10.0 || ~11.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^10.0"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true,
+ "autoload": {
+ "psr-4": {
+ "NotificationChannels\\Line\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "NotificationChannels\\Line\\Test\\": "tests"
+ }
+ },
+ "scripts": {
+ "test": "phpunit",
+ "test:coverage": "phpunit --coverage-text --coverage-clover=coverage.clover"
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "laravel": {
+ "providers": [
+ "NotificationChannels\\Line\\LineServiceProvider"
+ ]
+ }
+ }
+}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 00000000..f574e107
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ tests
+
+
+
+
+
+
+
+ src/
+
+
+
diff --git a/src/Exceptions/CouldNotSendNotification.php b/src/Exceptions/CouldNotSendNotification.php
new file mode 100644
index 00000000..680485d5
--- /dev/null
+++ b/src/Exceptions/CouldNotSendNotification.php
@@ -0,0 +1,41 @@
+getResponse()->getBody();
+ $code = $exception->getResponse()->getStatusCode();
+
+ return new static("LINE responded with an error `{$code} - {$message}`");
+ }
+
+ /**
+ * Thrown when we're unable to communicate with LINE.
+ *
+ * @param \Exception $exception
+ * @return static
+ */
+ public static function couldNotCommunicateWithLine(\Exception $exception): self
+ {
+ return new static("The communication with LINE failed. Reason: {$exception->getMessage()}");
+ }
+
+ /**
+ * Thrown when there's no bot token provided.
+ */
+ public static function lineMessageTokenNotProvided(string $message): self
+ {
+ return new self($message);
+ }
+}
diff --git a/src/Line.php b/src/Line.php
new file mode 100644
index 00000000..6ccd40b7
--- /dev/null
+++ b/src/Line.php
@@ -0,0 +1,112 @@
+http = $http;
+ $this->token = $token;
+ }
+
+ /**
+ * Returns Line token.
+ */
+ public function getToken(): string
+ {
+ return $this->token;
+ }
+
+ public function setToken(string $token): self
+ {
+ $this->token = $token;
+
+ return $this;
+ }
+
+ /**
+ * Send text message.
+ *
+ *
+ * $params = [
+ * 'chat_id' => '',
+ * 'text' => '',
+ * 'parse_mode' => '',
+ * 'disable_web_page_preview' => '',
+ * 'disable_notification' => '',
+ * 'reply_to_message_id' => '',
+ * 'reply_markup' => '',
+ * ];
+ *
+ *
+ * @see https://core.telegram.org/bots/api#sendmessage
+ *
+ * @throws CouldNotSendNotification
+ */
+ public function sendMessage(string $to, array $params): ?ResponseInterface
+ {
+ return $this->sendRequest($to, $params);
+ }
+
+ /**
+ * Perform a simple post request.
+ */
+ private function post(string $url, array $options): void
+ {
+ $this->http->post($url, $options);
+ }
+
+ /**
+ * Send an API request and return response.
+ *
+ *
+ * @throws CouldNotSendNotification
+ */
+ protected function sendRequest(string $to, array $params): ?ResponseInterface
+ {
+ if (blank($this->token)) {
+ throw CouldNotSendNotification::lineMessageTokenNotProvided('You must provide your line message token to make any API requests.');
+ }
+
+ $url = 'https://api.line.me/v2/bot/message/push';
+
+ try {
+ return $this->post($url, [
+ 'json' => array_merge($params, [
+ 'to' => $to,
+ ]),
+ 'headers' => [
+ 'Authorization' => 'Bearer '.$this->token,
+ ],
+ ]);
+ } catch (ClientException $exception) {
+ throw CouldNotSendNotification::lineRespondedWithAnError($exception);
+ } catch (\Exception $exception) {
+ throw CouldNotSendNotification::couldNotCommunicateWithLine($exception);
+ }
+ }
+}
diff --git a/src/LineChannel.php b/src/LineChannel.php
new file mode 100644
index 00000000..c50d26e4
--- /dev/null
+++ b/src/LineChannel.php
@@ -0,0 +1,63 @@
+line = $line;
+ }
+
+ /**
+ * Send the given notification.
+ *
+ * @param mixed $notifiable
+ * @param \Illuminate\Notifications\Notification $notification
+ *
+ * @throws \NotificationChannels\Line\Exceptions\CouldNotSendNotification
+ */
+ public function send($notifiable, Notification $notification)
+ {
+ /** @var \NotificationChannels\Line\LineMessage $message */
+ $message = $notification->toLine($notifiable);
+
+ $to = $message->getTo() ?: $notifiable->routeNotificationFor('line');
+ if ($to === null) {
+ return null;
+ }
+
+ if ($message->getFrom()) {
+ $this->line->setToken($message->getFrom());
+ }
+
+ try {
+ $response = $this->sendMessage($to, $message);
+ } catch (ClientException $exception) {
+ throw CouldNotSendNotification::lineRespondedWithAnError($exception);
+ } catch (Exception $exception) {
+ throw CouldNotSendNotification::couldNotCommunicateWithLine($exception);
+ }
+
+ return $response instanceof Response ? json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR) : $response;
+ }
+
+ /**
+ * @param string $to
+ * @param \NotificationChannels\LINE\LINEMessage $message
+ * @return void
+ */
+ private function sendMessage(string $to, LineMessage $message): void
+ {
+ $this->line->sendMessage($to, $message->toArray());
+ }
+}
diff --git a/src/LineMessage.php b/src/LineMessage.php
new file mode 100644
index 00000000..38c26cff
--- /dev/null
+++ b/src/LineMessage.php
@@ -0,0 +1,90 @@
+content($content);
+ }
+
+ public function getTo(): ?string
+ {
+ return $this->to;
+ }
+
+ public function to(string $to): self
+ {
+ $this->to = $to;
+
+ return $this;
+ }
+
+ public function getFrom(): ?string
+ {
+ return $this->from;
+ }
+
+ /**
+ * Set the sender's access token.
+ *
+ * @return $this
+ */
+ public function from(string $accessToken): self
+ {
+ $this->from = $accessToken;
+
+ return $this;
+ }
+
+ /**
+ * Set the content of the Line message.
+ * Supports GitHub flavoured markdown.
+ *
+ * @return $this
+ */
+ public function content(string $content): self
+ {
+ $this->content = $content;
+
+ return $this;
+ }
+
+ /**
+ * Get an array representation of the LineMessage.
+ */
+ public function toArray(): array
+ {
+ return array_filter([
+ 'messages' => [
+ [
+ 'type' => 'text',
+ 'text' => $this->content,
+ ],
+ ],
+ ]);
+ }
+}
diff --git a/src/LineServiceProvider.php b/src/LineServiceProvider.php
new file mode 100644
index 00000000..4101331a
--- /dev/null
+++ b/src/LineServiceProvider.php
@@ -0,0 +1,26 @@
+app->bind(Line::class, static fn () => new Line(
+ app(HttpClient::class),
+ config('services.line_message_api.token'),
+ ));
+
+ Notification::resolved(static function (ChannelManager $service) {
+ $service->extend('line', static fn ($app) => $app->make(LineChannel::class));
+ });
+ }
+}
diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php
new file mode 100644
index 00000000..b57b0836
--- /dev/null
+++ b/tests/ExampleTest.php
@@ -0,0 +1,14 @@
+assertTrue(true);
+ }
+}