1
0
Fork 0

Compare commits

...

6 Commits

7 changed files with 43 additions and 12 deletions

11
Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM debian:12-slim
RUN apt update && apt install golang -y --no-install-recommends && apt install ca-certificates -y
RUN mkdir /src && mkdir /conf
COPY . /src
RUN cd /src && go build
FROM debian:12-slim
COPY --from=0 /conf /conf
COPY --from=0 /src/alarm_bot /
WORKDIR /conf
CMD ["/alarm_bot"]

View File

@ -10,7 +10,7 @@ In other words - treat it as a toy, not as a tool that will save your life or va
## Running ## Running
``` ```
$ TELEGRAM_APITOKEN=YOUR_API_TOKEN ./alarm-bot $ ./alarm-bot
``` ```
Remember that `hswro-alarm-bot.yml` should be present in the current directory. Remember that `hswro-alarm-bot.yml` should be present in the current directory.
@ -32,6 +32,7 @@ allowed-indexes:
- 5678 - 5678
- 1337 - 1337
pool-interval: 5m pool-interval: 5m
telegram-api-key: "telegram api key"
arm-callback-urls: arm-callback-urls:
- "http://192.168.1.10/hello" - "http://192.168.1.10/hello"
- "http://example.com/api" - "http://example.com/api"
@ -51,6 +52,7 @@ matterbridge:
- `pool-interval` sets how often will the Satel device be asked for changes - `pool-interval` sets how often will the Satel device be asked for changes
- `satel-addr` sets the IP address of the Satel device - `satel-addr` sets the IP address of the Satel device
- `tg-chat-ids` sets which telegram groups will receive notifications about alarm state changes - `tg-chat-ids` sets which telegram groups will receive notifications about alarm state changes
- `telegram-api-key` sets the Bot API key for Telegram that was obtained from BotFather
### Matterbridge integration ### Matterbridge integration
@ -132,7 +134,6 @@ After=network.target
[Service] [Service]
Type=simple Type=simple
ExecStart=/path/to/alarm_bot ExecStart=/path/to/alarm_bot
Environment=TELEGRAM_APITOKEN=YOUR_API_TOKEN
DynamicUser=True DynamicUser=True
RuntimeDirectory=hswro-alarm-bot RuntimeDirectory=hswro-alarm-bot
StateDirectory=hswro-alarm-bot StateDirectory=hswro-alarm-bot
@ -149,7 +150,3 @@ MemoryMax=50M
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
## Debugging
Set the `OMIT_TG` environment variable to, well, omit sending anything over to Telegram and just see the logs instead.

View File

@ -44,6 +44,7 @@ type AppConfig struct {
AlarmCallbackUrls []string `yaml:"alarm-callback-urls"` AlarmCallbackUrls []string `yaml:"alarm-callback-urls"`
WriteMemoryProfile bool `yaml:"write-memory-profile"` WriteMemoryProfile bool `yaml:"write-memory-profile"`
Matterbridge []MatterbridgeConfig `yaml:"matterbridge"` Matterbridge []MatterbridgeConfig `yaml:"matterbridge"`
TelegramApiKey string `yaml:"telegram-api-key"`
} }
func (m *SatelChangeType) UnmarshalYAML(unmarshal func(interface{}) error) error { func (m *SatelChangeType) UnmarshalYAML(unmarshal func(interface{}) error) error {

View File

@ -32,6 +32,7 @@ disarm-callback-urls:
alarm-callback-urls: alarm-callback-urls:
- "test alarm callback url" - "test alarm callback url"
- "second test alarm callback url" - "second test alarm callback url"
telegram-api-key: "test api key"
matterbridge: matterbridge:
- uri: test_uri_1 - uri: test_uri_1
token: test_token_1 token: test_token_1
@ -56,6 +57,7 @@ func TestParseYamlConfig(t *testing.T) {
a.ElementsMatch([]string{"test arm callback url", "second test arm callback url"}, actualConfig.ArmCallbackUrls) a.ElementsMatch([]string{"test arm callback url", "second test arm callback url"}, actualConfig.ArmCallbackUrls)
a.ElementsMatch([]string{"test disarm callback url", "second test disarm callback url"}, actualConfig.DisarmCallbackUrls) a.ElementsMatch([]string{"test disarm callback url", "second test disarm callback url"}, actualConfig.DisarmCallbackUrls)
a.ElementsMatch([]string{"test alarm callback url", "second test alarm callback url"}, actualConfig.AlarmCallbackUrls) a.ElementsMatch([]string{"test alarm callback url", "second test alarm callback url"}, actualConfig.AlarmCallbackUrls)
a.Equal("test api key", actualConfig.TelegramApiKey)
a.Equal(actualConfig.Matterbridge[0].URI, "test_uri_1") a.Equal(actualConfig.Matterbridge[0].URI, "test_uri_1")
a.Equal(actualConfig.Matterbridge[0].Token, "test_token_1") a.Equal(actualConfig.Matterbridge[0].Token, "test_token_1")

14
main.go
View File

@ -61,11 +61,17 @@ func main() {
s := makeSatel(config.SatelAddr, config.PoolInterval.GetDuration()) s := makeSatel(config.SatelAddr, config.PoolInterval.GetDuration())
logger.Printf("Connected to Satel: %s", config.SatelAddr) logger.Printf("Connected to Satel: %s", config.SatelAddr)
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN")) var bot TelegramBotSender = nil
if err != nil { if len(config.TelegramApiKey) != 0 {
panic(err) b, err := tgbotapi.NewBotAPI(config.TelegramApiKey)
if err != nil {
panic(err)
}
logger.Print("Created Telegram Bot API client")
bot = b
} else {
bot = EmptySender{}
} }
logger.Print("Created Telegram Bot API client")
tgSender := TgSender{bot, s, log.New(os.Stderr, "TgFormatter", log.Lmicroseconds), config.ChatIds} tgSender := TgSender{bot, s, log.New(os.Stderr, "TgFormatter", log.Lmicroseconds), config.ChatIds}

View File

@ -8,12 +8,14 @@ import (
"log" "log"
"net/http" "net/http"
"sync" "sync"
"time"
"git.sr.ht/~michalr/go-satel" "git.sr.ht/~michalr/go-satel"
) )
const ( const (
NotificationPartitionIndex = 0 NotificationPartitionIndex = 0
httpTimeout = 1 * time.Second
) )
type Sender interface { type Sender interface {
@ -61,7 +63,10 @@ func doHttpNotification(url string, logger *log.Logger, wg *sync.WaitGroup) {
} }
req, err := http.NewRequest(http.MethodPost, url, nil) req, err := http.NewRequest(http.MethodPost, url, nil)
res, err := http.DefaultClient.Do(req) client := http.Client{
Timeout: httpTimeout,
}
res, err := client.Do(req)
if err != nil { if err != nil {
logger.Print("Could not POST ", url, ": ", err) logger.Print("Could not POST ", url, ": ", err)
return return
@ -139,7 +144,10 @@ func SendToMatterbridge(events <-chan GenericMessage, s SatelNameGetter, config
} }
req, err := http.NewRequest(http.MethodPost, matterbridgeConfig.URI, bytes.NewBuffer(body)) req, err := http.NewRequest(http.MethodPost, matterbridgeConfig.URI, bytes.NewBuffer(body))
req.Header["Authorization"] = []string{fmt.Sprint("Bearer ", matterbridgeConfig.Token)} req.Header["Authorization"] = []string{fmt.Sprint("Bearer ", matterbridgeConfig.Token)}
res, err := http.DefaultClient.Do(req) client := http.Client{
Timeout: httpTimeout,
}
res, err := client.Do(req)
if err != nil { if err != nil {
logger.Print("Could not POST ", matterbridgeConfig.URI, ": ", err) logger.Print("Could not POST ", matterbridgeConfig.URI, ": ", err)
return return

View File

@ -11,6 +11,12 @@ type TelegramBotSender interface {
Send(c tgbotapi.Chattable) (tgbotapi.Message, error) Send(c tgbotapi.Chattable) (tgbotapi.Message, error)
} }
type EmptySender struct{}
func (self EmptySender) Send(_ tgbotapi.Chattable) (tgbotapi.Message, error) {
return tgbotapi.Message{}, nil
}
type TgSender struct { type TgSender struct {
bot TelegramBotSender bot TelegramBotSender
s SatelNameGetter s SatelNameGetter