1
0
Fork 0
hswro-alarm-bot/filters.go

107 lines
2.3 KiB
Go

package main
import (
"encoding/gob"
"errors"
"io/fs"
"log"
"os"
"github.com/probakowski/go-satel"
)
func FilterByType(ev <-chan satel.Event, allowedTypes []satel.ChangeType) <-chan satel.Event {
returnChan := make(chan satel.Event)
go func() {
for e := range ev {
for _, allowedType := range allowedTypes {
if allowedType == e.Type {
returnChan <- e
continue
}
}
}
close(returnChan)
}()
return returnChan
}
type EventKey struct {
ChangeType satel.ChangeType
Index int
}
type EventValue struct{ Value bool }
type PersistenceRecord struct {
Key EventKey
Value EventValue
}
func persistMapOnDisk(lastSeen *map[EventKey]bool, persistenceFilePath string) {
f, err := os.OpenFile(persistenceFilePath, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
panic(err)
}
defer f.Close()
enc := gob.NewEncoder(f)
data := make([]PersistenceRecord, len(*lastSeen))
i := 0
for k, v := range *lastSeen {
data[i] = PersistenceRecord{Key: k, Value: EventValue{v}}
i += 1
}
err = enc.Encode(data)
if err != nil {
panic(err)
}
}
func readMapFromDisk(persistenceFilePath string, logger *log.Logger) map[EventKey]bool {
lastSeen := make(map[EventKey]bool)
f, err := os.OpenFile(persistenceFilePath, os.O_RDONLY|os.O_CREATE, 0600)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// File not existing is fine, we'll create one later
return lastSeen
}
panic(err)
}
defer f.Close()
dec := gob.NewDecoder(f)
data := make([]PersistenceRecord, 0)
err = dec.Decode(&data)
if err != nil {
logger.Println("LastSeenFilter: Error reading persistence file", persistenceFilePath, "from disk:", err, ". Discarding and starting over.")
return lastSeen
}
for _, readData := range data {
lastSeen[readData.Key] = readData.Value.Value
}
return lastSeen
}
func FilterByLastSeen(ev <-chan satel.Event, persistenceFilePath string, logger *log.Logger) <-chan satel.Event {
returnChan := make(chan satel.Event)
go func() {
lastSeen := readMapFromDisk(persistenceFilePath, logger)
for e := range ev {
val, ok := lastSeen[EventKey{e.Type, e.Index}]
if !ok || val != e.Value {
lastSeen[EventKey{e.Type, e.Index}] = e.Value
returnChan <- e
persistMapOnDisk(&lastSeen, persistenceFilePath)
}
}
close(returnChan)
}()
return returnChan
}