2024-02-10 23:13:31 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-12-27 11:28:51 +00:00
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2024-02-19 18:52:40 +00:00
|
|
|
"html/template"
|
2024-02-11 21:48:05 +00:00
|
|
|
"log"
|
2024-03-06 17:45:12 +00:00
|
|
|
"net/http"
|
2024-02-10 23:13:31 +00:00
|
|
|
"sync"
|
2024-03-06 17:45:12 +00:00
|
|
|
|
|
|
|
"git.sr.ht/~michalr/go-satel"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
NotificationPartitionIndex = 0
|
2024-02-10 23:13:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Sender interface {
|
2024-02-19 18:52:40 +00:00
|
|
|
Send(msg GenericMessage, tpl *template.Template) error
|
2024-02-10 23:13:31 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 10:51:41 +00:00
|
|
|
type Sleeper interface {
|
|
|
|
Sleep(ch chan<- interface{})
|
|
|
|
}
|
|
|
|
|
2024-02-18 00:44:10 +00:00
|
|
|
func Consume(events <-chan GenericMessage) {
|
|
|
|
go func() {
|
|
|
|
for range events {
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2024-02-19 18:52:40 +00:00
|
|
|
func SendToTg(events <-chan GenericMessage, s Sender, wg *sync.WaitGroup, logger *log.Logger, tpl *template.Template) <-chan GenericMessage {
|
2024-02-18 00:44:10 +00:00
|
|
|
returnEvents := make(chan GenericMessage)
|
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-02-18 00:44:10 +00:00
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
2025-01-02 12:40:25 +00:00
|
|
|
defer close(returnEvents)
|
|
|
|
|
2024-02-18 00:44:10 +00:00
|
|
|
for e := range events {
|
|
|
|
returnEvents <- e
|
2024-02-19 18:52:40 +00:00
|
|
|
err := s.Send(e, tpl)
|
2024-02-18 00:44:10 +00:00
|
|
|
if err != nil {
|
|
|
|
// TODO: handle it better
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return returnEvents
|
|
|
|
}
|
2024-03-06 17:45:12 +00:00
|
|
|
|
|
|
|
func doHttpNotification(url string, logger *log.Logger, wg *sync.WaitGroup) {
|
|
|
|
wg.Add(1)
|
|
|
|
defer wg.Done()
|
2024-03-24 08:32:03 +00:00
|
|
|
|
2024-03-06 17:45:12 +00:00
|
|
|
if len(url) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, url, nil)
|
|
|
|
|
|
|
|
res, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
logger.Print("Could not POST ", url, ": ", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Print("Notified via HTTP with result ", res.StatusCode)
|
|
|
|
}
|
|
|
|
|
2024-03-24 08:32:03 +00:00
|
|
|
func notifyAllHttp(urls []string, logger *log.Logger, wg *sync.WaitGroup) {
|
|
|
|
for _, uri := range urls {
|
|
|
|
go doHttpNotification(uri, logger, wg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NotifyViaHTTP(events <-chan GenericMessage, config AppConfig, wg *sync.WaitGroup, logger *log.Logger) <-chan GenericMessage {
|
2024-03-10 09:52:27 +00:00
|
|
|
returnEvents := make(chan GenericMessage)
|
|
|
|
|
2025-01-02 12:40:25 +00:00
|
|
|
wg.Add(1)
|
2024-03-06 17:45:12 +00:00
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
2025-01-02 12:40:25 +00:00
|
|
|
defer close(returnEvents)
|
|
|
|
|
2024-03-06 17:45:12 +00:00
|
|
|
for e := range events {
|
2024-03-10 09:52:27 +00:00
|
|
|
returnEvents <- e
|
2024-03-24 08:32:03 +00:00
|
|
|
inner_arm:
|
|
|
|
for _, basicElement := range e.Messages {
|
|
|
|
if (basicElement.Index == NotificationPartitionIndex) && (basicElement.Type == satel.ArmedPartition) {
|
|
|
|
if basicElement.Value == ArmedPartition_Armed {
|
2024-03-24 15:54:33 +00:00
|
|
|
notifyAllHttp(config.ArmCallbackUrls, logger, wg)
|
2024-03-24 08:32:03 +00:00
|
|
|
} else {
|
2024-03-24 15:54:33 +00:00
|
|
|
notifyAllHttp(config.DisarmCallbackUrls, logger, wg)
|
2024-03-06 21:31:08 +00:00
|
|
|
}
|
2024-03-24 08:32:03 +00:00
|
|
|
break inner_arm
|
2024-03-06 21:31:08 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-24 08:32:03 +00:00
|
|
|
inner_alarm:
|
|
|
|
for _, basicElement := range e.Messages {
|
|
|
|
if basicElement.Type == satel.PartitionAlarm {
|
|
|
|
if basicElement.Value == PartitionAlarm_Alarm {
|
2024-03-24 15:54:33 +00:00
|
|
|
notifyAllHttp(config.AlarmCallbackUrls, logger, wg)
|
2024-03-24 08:32:03 +00:00
|
|
|
break inner_alarm
|
2024-03-06 17:45:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-24 08:32:03 +00:00
|
|
|
|
2024-03-06 17:45:12 +00:00
|
|
|
}
|
|
|
|
}()
|
2024-03-10 09:52:27 +00:00
|
|
|
|
|
|
|
return returnEvents
|
2024-03-06 17:45:12 +00:00
|
|
|
}
|
2024-12-27 11:28:51 +00:00
|
|
|
|
|
|
|
type MatterbridgeMessage struct {
|
|
|
|
Text string `json:"text"`
|
|
|
|
Username string `json:"username"`
|
|
|
|
Gateway string `json:"gateway"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func SendToMatterbridge(events <-chan GenericMessage, s SatelNameGetter, config AppConfig, wg *sync.WaitGroup, logger *log.Logger, tpl *template.Template) <-chan GenericMessage {
|
|
|
|
returnEvents := make(chan GenericMessage)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
wg.Add(1)
|
|
|
|
defer wg.Done()
|
|
|
|
for e := range events {
|
|
|
|
returnEvents <- e
|
|
|
|
body, err := json.Marshal(MatterbridgeMessage{
|
|
|
|
Text: e.Format(tpl, s, logger),
|
|
|
|
Username: config.Matterbridge.Username,
|
|
|
|
Gateway: config.Matterbridge.Gateway,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatal("Could not marshal a JSON message: ", err)
|
|
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, config.Matterbridge.URI, bytes.NewBuffer(body))
|
|
|
|
req.Header["Authorization"] = []string{fmt.Sprint("Bearer ", config.Matterbridge.Token)}
|
|
|
|
res, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
logger.Print("Could not POST ", config.Matterbridge.URI, ": ", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Print("Notified via Matterbridge with result ", res.StatusCode)
|
|
|
|
}
|
|
|
|
close(returnEvents)
|
|
|
|
}()
|
|
|
|
|
|
|
|
return returnEvents
|
|
|
|
}
|