Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added LINE Notify integration #158

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Noti can send notifications on a number of services.
| Twilio | ✔ | ✔ | ✔ |
| GChat | ✔ | ✔ | ✔ |
| Chanify | ✔ | ✔ | ✔ |
| LINENotify | ✔ | ✔ | ✔ |

Check the [screenshots] directory to see what the notifications look like on different platforms.

Expand Down
20 changes: 20 additions & 0 deletions docs/noti.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Noti can send notifications on a number of services.
| Twilio | ✔ | ✔ | ✔ |
| GChat | ✔ | ✔ | ✔ |
| ntfy | ✔ | ✔ | ✔ |
| LINENotify | ✔ | ✔ | ✔ |


## Installation
Expand Down Expand Up @@ -127,6 +128,10 @@ curl -L $(curl -s https://api.github.com/repos/variadico/noti/releases/latest |
Trigger a ntfy notification. This requires `ntfy.topic` be set. Optionally,
`ntfy.url` can also be set to use a different ntfy server.

--linenotify
Trigger a LINE Notify notification. This requires `linenotify.token` to be set. Optionally,
`linenotify.notificationDisabled` can be set to disable the notification.

-w , --pwatch
Monitor a process by PID and trigger a notification when the pid
disappears.
Expand Down Expand Up @@ -182,6 +187,8 @@ curl -L $(curl -s https://api.github.com/repos/variadico/noti/releases/latest |
* `NOTI_CHANIFY_SOUND`
* `NOTI_CHANIFY_PRIORITY`
* `NOTI_CHANIFY_INTERUPTIONLEVEL`
* `NOTI_LINENOTIFY_TOKEN`
* `NOTI_LINENOTIFY_NOTIFICATION_DISABLED`


## Files
Expand Down Expand Up @@ -354,6 +361,13 @@ url
topic
Topic ID to send messages to

LINENOTIFY

token
A token of LINE Notify. You can get it from https://notify-bot.line.me/my/

notificationDisabled
Whether to disable the notification. Default is false.
```

## Examples
Expand Down Expand Up @@ -434,6 +448,9 @@ chanify:
ntfy:
url: https://my.ntfy.url.com
topic: 'xxxxxxxxxxxxxxxx'
linenotify:
token: 'xxxxxxxxxxxxxxxx'
notificationDisabled: false
```

## Setting up cloud accounts
Expand Down Expand Up @@ -503,6 +520,9 @@ Configure a Google Spaces webhook (see [setting up webhooks](https://developers.
Open up Chanify on your device, pick a channel and create a token. You have an option of token with best-by date or token with no expiration. Set the token as `chanify.channelURL` with the default host `api.chanify.net`. Your `chanify.channelURL` should look like this: `https://api.chanify.net/v1/sender/<TOKEN>`
To create token's expiration click on the ![Shield button](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAcCAYAAACdz7SqAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAHaADAAQAAAABAAAAHAAAAADjGz/hAAADAklEQVRIDeVVTShEURT+5keJkgXSFJlSFhSRNNlYkGLBLDVFWVIaYaMkpSibWdhZMQ2JjYWIMpOiJguUn2k2itUsSKKmEcc9J2+aN97MvEnZOPV6752/75x77/muBQCp50/F+qdo32D/B9Sez/LW1NSgq6sLjY2NeHx8RCgUwsnJCRKJRD5pYFHeWQ9SVVUVenp65Kmrq5PkT09PKCkpgd1ux+vrKyYnJwX8/f3dFLghaGFhIfr6+uB2u9HU1CSJYrEYDg4OsLe3h/PzcwHt7u5Gb28v2tra8PLygv39fWxubuL6+jonOHeqewKBAEUiETo+Pqbp6Wlqbm4mi8Wi80mN8Xg8tLa2Rjc3N3R7e0sdHR0Zfb/j9ICs5EC/309WqzVXsM7OxXGx4+PjOn1qgfxtODKqKzw/P+Pz81P5ZBdVGJxOpzjxXrNwfDbJ6/QaJRocHJTTe3d3Z2Q21P0KlEfI6/WipaVFkptZGXY0XF7D8tKUvKyLi4uylB8fH2nW7L+mQPv7+8HzmirDw8MyTj6fL6nmQsxITi+e2bm5OaiRQFlZmeSsra3F2NgYzs7OsLq6agZH55MRVKs6Ho9DzSoqKyuxvLyMoqIiLCwsgNmH9an7qMUQ8cRkFsODxNSmdcWhu7u7cDgcmJiYwM7Ojiz1zMwMHh4edJnLy8vl/+3tTadP/zHsNBqNoqGhQbrTAlZWVrC+vi6ATPRbW1uaKfnu7OyUb47PJT/YQ/GuMIvaL1J7mrQzFTLrpOpUcrG3t7fT1dUVHR4eUkFBQTJGs6e9f9IgJ19aWhLg7e1tqq6uzppkaGhIAC8uLkhde1l9v8F/grLBZrPR1NSU8PDl5SWNjIwYdlhfXy/FBYNBUltiBpB9jEE1fWtrK6nrTBIfHR2RusoksTpoND8/LzfL7OwsFRcXmwUkZmZBZvRMwpf1wMAARkdHUVpaivv7e1RUVIBn+PT0FEwU+YrpCrkbRQoUDodpY2ODXC6X6VhVVNLXVKf5dpHL33BOcwX91v5/QL8AnJm6qDdN5A0AAAAASUVORK5CYII=) Shield button

### LINE Notify
Log into [LINE Notify dashboard](https://notify-bot.line.me/my/). Next, click on "Generate token". The text that appears will be what you'll set `linenotify.token` in noti.

## Reporting bugs

Report bugs on GitHub at https://github.com/variadico/noti/issues.
Expand Down
9 changes: 9 additions & 0 deletions internal/command/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/variadico/noti/service/chanify"
"github.com/variadico/noti/service/gchat"
"github.com/variadico/noti/service/keybase"
"github.com/variadico/noti/service/linenotify"
"github.com/variadico/noti/service/mattermost"
"github.com/variadico/noti/service/ntfy"
"github.com/variadico/noti/service/pushbullet"
Expand Down Expand Up @@ -190,3 +191,11 @@ func getNtfy(title, message string, v *viper.Viper) notification {
Client: httpClient,
}
}

func getLINENotify(title, message string, v *viper.Viper) notification {
return &linenotify.Notification{
Token: v.GetString("linenotify.token"),
Message: fmt.Sprintf("%s\n%s", title, message),
NotificationDisabled: v.GetBool("linenotify.notificationDisabled"),
}
}
13 changes: 13 additions & 0 deletions internal/command/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ var baseDefaults = map[string]interface{}{

"ntfy.url": "https://ntfy.sh/",
"ntfy.topic": "",

"liennotify.token": "",
"linenotify.notificationDisabled": false,
}

func setNotiDefaults(v *viper.Viper) {
Expand Down Expand Up @@ -157,6 +160,9 @@ var keyEnvBindings = map[string]string{

"ntfy.url": "NOTI_NTFY_URL",
"ntfy.topic": "NOTI_NTFY_TOPIC",

"linenotify.token": "NOTI_LINENOTIFY_TOKEN",
"linenotify.notificationDisabled": "NOTI_LINENOTIFY_NOTIFICATION_DISABLED",
}

var keyEnvBindingsDeprecated = map[string]string{
Expand Down Expand Up @@ -282,6 +288,7 @@ func enabledFromSlice(defaults []string) map[string]bool {
"twilio": false,
"chanify": false,
"ntfy": false,
"linenotify": false,
}

for _, name := range defaults {
Expand Down Expand Up @@ -313,6 +320,7 @@ func hasServiceFlags(flags *pflag.FlagSet) bool {
"twilio": false,
"chanify": false,
"ntfy": false,
"linenotify": false,
}

flags.Visit(func(f *pflag.Flag) {
Expand Down Expand Up @@ -347,6 +355,7 @@ func enabledFromFlags(flags *pflag.FlagSet) map[string]bool {
"twilio": false,
"chanify": false,
"ntfy": false,
"linenotify": false,
}

// Visit flags that have been set.
Expand Down Expand Up @@ -459,5 +468,9 @@ func getNotifications(v *viper.Viper, services map[string]struct{}) []notificati
notis = append(notis, getNtfy(title, message, v))
}

if _, ok := services["linenotify"]; ok {
notis = append(notis, getLINENotify(title, message, v))
}

return notis
}
1 change: 1 addition & 0 deletions internal/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func InitFlags(flags *pflag.FlagSet) {
flags.BoolP("zulip", "z", false, "Trigger a Zulip notification")
flags.Bool("twilio", false, "Trigger a twilio SMS notification")
flags.Bool("ntfy", false, "Trigger a Ntfy notification")
flags.Bool("linenotify", false, "Trigger a LINE Notify notification")

flags.IntP("pwatch", "w", -1, "Monitor a process by PID and trigger a notification when the pid disappears.")
flags.StringP("file", "f", "", "Path to noti.yaml configuration file.")
Expand Down
65 changes: 65 additions & 0 deletions service/linenotify/linenotify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package linenotify

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
)

var API = "https://notify-api.line.me/api/notify"

type apiResponse struct {
Status int `json:"status"`
Message string `json:"message"`
}

type Notification struct {
// Token is the user's authentication token.
Token string
// Message is the notification's message.
Message string
// Wheteher to disable notification.
NotificationDisabled bool
}

func (n *Notification) Send() error {
if n.Token == "" {
return errors.New("missing token")
}

if n.Message == "" {
return errors.New("missing message")
}

vals := make(url.Values)
vals.Set("message", n.Message)
vals.Set("notificationDisabled", fmt.Sprintf("%t", n.NotificationDisabled))
valsReader := bytes.NewBufferString(vals.Encode())

client := &http.Client{}
req, err := http.NewRequest("POST", API, valsReader)
if err != nil {
return err
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", n.Token))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

var r apiResponse
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return err
}

if r.Status != 200 {
return errors.New(r.Message)
}

return nil
}
52 changes: 52 additions & 0 deletions service/linenotify/linenotify_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package linenotify

import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)

func TestLINENotifySend(t *testing.T) {
n := Notification{
Token: "token",
Message: "Testing notification",
NotificationDisabled: false,
}

var mockResp apiResponse
var hitServer bool

ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
hitServer = true

if r.Method != "POST" {
t.Error("HTTP method should be POST.")
}

if n.Token == "" {
t.Error("missing token")
}

if n.Message == "" {
t.Error("missing message")
}

if err := json.NewEncoder(rw).Encode(mockResp); err != nil {
t.Error(err)
}
}))
defer ts.Close()

API = ts.URL

// successful
mockResp.Status = 200
if err := n.Send(); err != nil {
t.Error(err)
}

if !hitServer {
t.Error("didn't reach server")
}
}