From 7a2e0d1caf957fff63437dc49efa0f60fb4fb4ca Mon Sep 17 00:00:00 2001 From: Lucas Schumacher Date: Wed, 25 Oct 2023 16:05:05 -0400 Subject: [PATCH] first commit --- .gitignore | 1 + LICENSE | 22 +++++ PKGBUILD | 39 ++++++++ README.md | 2 + go.mod | 3 + main.go | 196 +++++++++++++++++++++++++++++++++++++++++ telegramAlert.env | 2 + telegramAlert.service | 14 +++ telegramAlert.sysusers | 1 + 9 files changed, 280 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 PKGBUILD create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go create mode 100644 telegramAlert.env create mode 100644 telegramAlert.service create mode 100644 telegramAlert.sysusers diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ccf61c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pkg.tar.zst diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c9a5ac7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2023 Lucas Schumacher + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..a5d7ed5 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,39 @@ +# simple PKGBUILD for packaging locally +pkgname=telegramAlert +pkgver=0.0.0 +pkgrel=0 +pkgdesc="Server that listens for alerts and forwards them to a telegram user" +arch=(x86_64 i686 armv5 armv6h armv7h aarch64) +license=("MIT") +backup=( + etc/$pkgname/$pkgname.env #Don't overwrite config file +) +depends=() +makedepends=("go") +source=( + 'main.go' + 'go.mod' + 'telegramAlert.env' + 'telegramAlert.service' + 'telegramAlert.sysusers' + 'LICENSE' +) +sha256sums=( + 'f2d19e3b2ed8244d2f539a4d9485961b5ed0fb14a29c3094387cc97124e5b571' #main.go + '6d215015f4084363c15c7710b406f7981d759913b88a22060e8c8ad95a3eb18a' #go.mod + '8ab2d17885a3dee972db1e74d9371cb9b35cc47fbb8c2d25968a46f3dc351002' #telegramAlert.env + '6aedcf80266e272b54cf8385bf4fa9f125ab8aadc92ad1775207e55521226c7b' #telegramAlert.service + '13db81008358f744fe84ca20a1f27e46dd11614ff847976a3aa2c95672cf2e02' #telegramAlert.sysusers + '5dd6c227cb4a3821fd8d0ddea2b84ceb50f370b121f5e9fbd0986325948aaa78' #LICENSE +) + +build() { + go build -trimpath +} +package() { + install -D -m555 "$pkgname" "$pkgdir/usr/bin/$pkgname" + install -D -m644 "$pkgname.service" "$pkgdir/usr/lib/systemd/system/$pkgname.service" + install -D -m644 "$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf" + install -D -m600 "$pkgname.env" "$pkgdir/etc/$pkgname/$pkgname.env" + install -D -m644 "LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..7640109 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# telegramAlert +Telegram bot that forwards InfluxDB Alerts to a telegream user account diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..915030d --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module telegramAlert + +go 1.20 diff --git a/main.go b/main.go new file mode 100644 index 0000000..52714b3 --- /dev/null +++ b/main.go @@ -0,0 +1,196 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "os" +) + +var KEY string = os.Getenv("TELEGRAM_TOKEN") +var UID string = os.Getenv("TELEGRAM_USERID") +var VERBOSE bool = os.Getenv("VERBOSE") != "" +var BASE_URL string = "https://api.telegram.org/bot" + KEY + +type InfluxAlert struct { + CheckID string `json:"_check_id"` + CheckName string `json:"_check_name"` + Level string `json:"_level"` + Measurement string `json:"_measurement"` + Message string `json:"_message"` + NotificationEndpointID string `json:"_notification_endpoint_id"` + NotificationEndpointName string `json:"_notification_endpoint_name"` + NotificationRuleID string `json:"_notification_rule_id"` + NotificationRuleName string `json:"_notification_rule_name"` + SourceMeasurement string `json:"_source_measurement"` + SourceTimestamp float64 `json:"_source_timestamp"` + Start string `json:"_start"` + StatusTimestamp float64 `json:"_status_timestamp"` + Stop string `json:"_stop"` + Time string `json:"_time"` + Type string `json:"_type"` + Version float64 `json:"_version"` +} +type TelegramMessage struct { + ChatID string `json:"chat_id"` + Text string `json:"text"` +} + +func handler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + dat, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Error reading request", http.StatusInternalServerError) + return + } + incoming := InfluxAlert{} + err = json.Unmarshal(dat, &incoming) + if err != nil { + fmt.Println("Got Error unmarshaling") + fmt.Printf("Error: %T\n", err) + fmt.Println(err) + //http.Error + return + } + w.WriteHeader(http.StatusOK) + w.Write(nil) + if VERBOSE { + fmt.Println(string(dat)) + // parsed, err := json.MarshalIndent(incoming, "", " ") + // if err == nil { + // fmt.Println(string(parsed)) + // } + } + fmt.Print(incoming.Time + ": ") + fmt.Println(incoming.Message) + + // KEY := os.Getenv("TELEGRAM_TOKEN") + // if KEY == "" { + // fmt.Println("Error: Can not send message - no bot token set") + // return + // } + // UID := os.Getenv("TELEGRAM_USERID") + // if UID == "" { + // fmt.Println("Error: Can not send message - no recepient user id set") + // return + // } + + URL := BASE_URL + "/sendMessage" + message := TelegramMessage{UID, incoming.Message} + outgoing, err := json.Marshal(message) + if err != nil { + fmt.Println("Error marshaling telegram json") + return + } + + //http.Post(URL, "application/json", json.Marshal(outgoing)) + req, err := http.NewRequest(http.MethodPost, URL, bytes.NewBuffer(outgoing)) + //defer resp.Body.Close(); + if err != nil { + fmt.Println("Error making request to telegram") + fmt.Printf("%T: ", err) + fmt.Println(err) + return + } + req.Header.Add("Content-Type", "application/json") + res, err := http.DefaultClient.Do(req) + if err != nil { + fmt.Println("Error posting message to telegram") + fmt.Printf("%T: ", err) + fmt.Println(err) + return + } + defer res.Body.Close() + resBody, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error getting response from telegram") + fmt.Printf("%T: ", err) + fmt.Println(err) + return + } + // fmt.Print(res.StatusCode) + + print := false + resdata := map[string]interface{}{} + json.Unmarshal(resBody, &resdata) + if resdata["ok"] != true { + fmt.Println("Error telegram responded with error") + print = true + return + } + + if VERBOSE || print { + pretty, err := json.MarshalIndent(resdata, "", " ") + if err != nil { + return + } + fmt.Println(string(pretty)) + } +} +func main() { + //TODO check if uid is valid + // Test KEY + if KEY == "" { + fmt.Println("Error: Can not send message - no bot token set") + return + } + if UID == "" { + fmt.Println("Error: Can not send message - no recepient user id set") + return + } + resp, err := http.Get(BASE_URL + "/getMe") + if err != nil { + fmt.Println("Error could not validate bot token") + fmt.Printf("%T: ", err) + fmt.Println(err) + return + } + defer resp.Body.Close() + + me := map[string]interface{}{} + data, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Println("Error could not validate bot token") + fmt.Printf("%T: ", err) + fmt.Println(err) + return + } + + json.Unmarshal(data, &me) + if me["ok"] != true { + fmt.Println("Error could not validate bot token") + //fmt.Printf("%T\n", me["ok"]) + pretty, err := json.MarshalIndent(me, "", " ") + if err != nil { + return + } + fmt.Println(string(pretty)) + return + } + fmt.Println("Validated bot token") + + if VERBOSE { + pretty, err := json.MarshalIndent(me, "", " ") + if err != nil { + return + } + fmt.Println(string(pretty)) + } + + http.HandleFunc("/", handler) + fmt.Println("server started at localhost:8080") + err = http.ListenAndServe(":8080", nil) + + if err != nil { + fmt.Println("!!! ERROR !!!") + fmt.Printf("%T: ", err) + fmt.Println(err) + panic(err) + } +} diff --git a/telegramAlert.env b/telegramAlert.env new file mode 100644 index 0000000..eca2529 --- /dev/null +++ b/telegramAlert.env @@ -0,0 +1,2 @@ +TELEGRAM_TOKEN= +TELEGRAM_USERID= diff --git a/telegramAlert.service b/telegramAlert.service new file mode 100644 index 0000000..d45db12 --- /dev/null +++ b/telegramAlert.service @@ -0,0 +1,14 @@ +[Unit] +Description=telegramAlert +After=network.target + +[Service] +User=tgalert +#Group=your_groupname +ExecStart=/usr/bin/telegramAlert +EnvironmentFile=-/etc/telegramAlert/telegramAlert.env +# Other settings as needed + +[Install] +WantedBy=multi-user.target + diff --git a/telegramAlert.sysusers b/telegramAlert.sysusers new file mode 100644 index 0000000..d439b76 --- /dev/null +++ b/telegramAlert.sysusers @@ -0,0 +1 @@ +u tgalert - "telegramAlert daemon" /var/lib/telegramAlert