initial commit
This commit is contained in:
commit
bd4106b69f
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
Listen for [Gotify](https://gotify.net/) push notifications and displays a notification on the dektop via dbus.
|
||||
|
||||
# Usage
|
||||
```bash
|
||||
gotify-dektop <hostname> <token>
|
||||
```
|
8
go.mod
Normal file
8
go.mod
Normal file
@ -0,0 +1,8 @@
|
||||
module git.kapelle.org/niklas/gotify-desktop
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/godbus/dbus v4.1.0+incompatible
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
)
|
4
go.sum
Normal file
4
go.sum
Normal file
@ -0,0 +1,4 @@
|
||||
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
198
main.go
Normal file
198
main.go
Normal file
@ -0,0 +1,198 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type messageType struct {
|
||||
ID int `json:"id"`
|
||||
AppID int `json:"appid"`
|
||||
Message string `json:"message"`
|
||||
Title string `json:"title"`
|
||||
Priority int `json:"priority"`
|
||||
// Date time.Time `json:"date"` // Ignore that for now
|
||||
}
|
||||
|
||||
type applicationType struct {
|
||||
Description string `json:"description"`
|
||||
ID int `json:"id"`
|
||||
Image string `json:"image"`
|
||||
Name string `json:"name"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func listenToPushEvents(url string, c chan messageType) {
|
||||
defer close(c)
|
||||
connection, _, err := websocket.DefaultDialer.Dial(url, nil)
|
||||
if err != nil {
|
||||
log.Printf("Dial error: %s", err.Error())
|
||||
}
|
||||
defer connection.Close()
|
||||
|
||||
for {
|
||||
var result messageType
|
||||
err := connection.ReadJSON(&result)
|
||||
if err != nil {
|
||||
log.Printf("Connection error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Message: %s %s\n", result.Title, result.Message)
|
||||
c <- result
|
||||
}
|
||||
}
|
||||
|
||||
func sendNotification(dbusConn *dbus.Conn, message messageType, hostname, token string) error {
|
||||
|
||||
image := getAppImage(hostname, token, message.AppID)
|
||||
|
||||
// https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html#urgency-levels
|
||||
var urgencyByte int
|
||||
|
||||
if message.Priority <= 3 {
|
||||
urgencyByte = 0
|
||||
} else if message.Priority <= 7 {
|
||||
urgencyByte = 1
|
||||
} else {
|
||||
urgencyByte = 2
|
||||
}
|
||||
|
||||
obj := dbusConn.Object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
|
||||
call := obj.Call("org.freedesktop.Notifications.Notify", 0, "gotify", uint32(0), "", message.Title, message.Message, []string{},
|
||||
map[string]dbus.Variant{"urgency": dbus.MakeVariant(byte(urgencyByte)), "image-path": dbus.MakeVariant(image)}, int32(-1))
|
||||
|
||||
return call.Err
|
||||
}
|
||||
|
||||
func getAppImage(hostname, token string, appID int) string {
|
||||
|
||||
cacheDir := getImageDir()
|
||||
image := path.Join(cacheDir, fmt.Sprint(appID))
|
||||
|
||||
// Check if you need to download the image
|
||||
_, err := os.Stat(image)
|
||||
if os.IsNotExist(err) {
|
||||
// File does not exist
|
||||
err := downloadAppImage(hostname, token, cacheDir, appID)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
func getImageDir() string {
|
||||
cacheDir := os.Getenv("XDG_CACHE_HOME")
|
||||
|
||||
if cacheDir == "" {
|
||||
cacheDir = path.Join(os.Getenv("HOME"), ".cache/gotify-desktop")
|
||||
} else {
|
||||
cacheDir = path.Join(cacheDir, "gotify-desktop")
|
||||
}
|
||||
|
||||
return cacheDir
|
||||
}
|
||||
|
||||
func downloadAppImage(hostname string, token string, cacheDir string, appID int) error {
|
||||
u, err := getAppImageURL(hostname, token, appID)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
os.MkdirAll(cacheDir, 0755) // rwx r-x r-x
|
||||
|
||||
resp, err := http.Get(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
out, err := os.Create(path.Join(cacheDir, fmt.Sprint(appID)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func getAppImageURL(hostname string, token string, appID int) (string, error) {
|
||||
u := url.URL{Scheme: "https", Host: hostname, Path: "/application"}
|
||||
param := url.Values{}
|
||||
param.Add("token", token)
|
||||
|
||||
resp, err := http.Get(u.String() + "?" + param.Encode())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var result []applicationType
|
||||
json.Unmarshal(body, &result)
|
||||
|
||||
for i := 0; i < len(result); i++ {
|
||||
if result[i].ID == appID {
|
||||
u := url.URL{Scheme: "https", Host: hostname, Path: result[i].Image}
|
||||
|
||||
return u.String() + "?" + param.Encode(), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("")
|
||||
}
|
||||
|
||||
func parseArgs() (string, string) {
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("Usage: gotify-dektop <hostname> <token>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return os.Args[1], os.Args[2]
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
hostname, token := parseArgs()
|
||||
|
||||
u := url.URL{Scheme: "wss", Host: hostname, Path: "/stream"}
|
||||
|
||||
param := url.Values{}
|
||||
param.Add("token", token)
|
||||
|
||||
dbusConn, err := dbus.ConnectSessionBus()
|
||||
if err != nil {
|
||||
log.Printf("Dbus error: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for {
|
||||
push := make(chan messageType)
|
||||
go listenToPushEvents(u.String()+"?"+param.Encode(), push)
|
||||
|
||||
for pushMessage := range push {
|
||||
go sendNotification(dbusConn, pushMessage, hostname, token)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user