From 3943edd52af9ef7a23a04e07df039c64b148c915 Mon Sep 17 00:00:00 2001 From: Thies Mueller Date: Mon, 4 Nov 2024 16:50:20 +0100 Subject: [PATCH] initial commit --- .gitea/workflows/build.yml | 29 ++++++++++ .gitignore | 3 + README.MD | 29 ++++++++++ config.json.example | 5 ++ main.go | 116 +++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+) create mode 100644 .gitea/workflows/build.yml create mode 100644 .gitignore create mode 100644 config.json.example create mode 100644 main.go diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..504e56e --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,29 @@ +name: Build Go Project + +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: '1.23' + + - name: Build Go Project + run: | + go build -o errorlog-server main.go + + - name: Upload Artifact + uses: actions/upload-artifact@v2 + with: + name: errorlog-server + path: errorlog-server diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d2d02e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +config.json +.trunk +errorlog-server \ No newline at end of file diff --git a/README.MD b/README.MD index e69de29..69643f4 100644 --- a/README.MD +++ b/README.MD @@ -0,0 +1,29 @@ +# Errorlog Handler + +Simple go binary that binds to localhost:2342 and has 2 endpoints + +### /errorlog + +expects a json with "script" & "log". Puts that in a nice ntfy message. + +``` +{ + "script": "$scriptname", + "log": "$log_content" +} +``` + +### /success + +expects a PUT without anything. + +Send a "ran successfully" to the server + + +## HowTo + +- `config.json` expects server, access token & channel + +- Run it. + +- Profit diff --git a/config.json.example b/config.json.example new file mode 100644 index 0000000..e20aa11 --- /dev/null +++ b/config.json.example @@ -0,0 +1,5 @@ +{ + "ntfy_server": "https://ntfy.sh", + "access_token": "your_token", + "channel": "your_channel" +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..b06d943 --- /dev/null +++ b/main.go @@ -0,0 +1,116 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "strings" + "time" +) + +type Config struct { + NtfyServer string `json:"ntfy_server"` + AccessToken string `json:"access_token"` + Channel string `json:"channel"` +} + +type ErrorLog struct { + Script string `json:"script"` + Log string `json:"log"` +} + +func loadConfig(filename string) (Config, error) { + var config Config + data, err := ioutil.ReadFile(filename) + if err != nil { + return config, err + } + err = json.Unmarshal(data, &config) + return config, err +} + +func sendNotification(config Config, message string, title string, priority string) { + req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s", config.NtfyServer, config.Channel), nil) + if err != nil { + log.Println("Failed to create request:", err) + return + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", config.AccessToken)) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Title", title) + req.Header.Set("Priority", priority) + + req.Body = ioutil.NopCloser(strings.NewReader(message)) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Println("Failed to send notification:", err) + return + } + defer resp.Body.Close() + + log.Println("Notification sent. Status code:", resp.StatusCode) +} + +func errorHandler(w http.ResponseWriter, r *http.Request) { + // Notify that the error handler has started + timestamp := time.Now().Format(time.RFC3339) + config, err := loadConfig("config.json") + if err == nil { + startMessage := fmt.Sprintf("Error handler started at %s", timestamp) + sendNotification(config, startMessage, "Error Handler Notification", "high") + } else { + log.Println("Failed to load config for startup notification:", err) + } + + if r.Method != http.MethodPost { + http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed) + return + } + + var errorLog ErrorLog + err = json.NewDecoder(r.Body).Decode(&errorLog) + if err != nil { + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + sendNotification(config, fmt.Sprintf("Error in Script: **%s**\n\nLog:\n```\n%s\n```", errorLog.Script, errorLog.Log), "Error Notification", "high") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Notification sent for script: %s", errorLog.Script) +} + +func successHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed) + return + } + + timestamp := time.Now().Format(time.RFC3339) + config, err := loadConfig("config.json") + if err != nil { + log.Println("Failed to load config:", err) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } + + message := fmt.Sprintf("Script ran successfully at %s", timestamp) + sendNotification(config, message, "Success Notification", "low") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Success notification sent.") +} + +func main() { + http.HandleFunc("/errorlog", errorHandler) + http.HandleFunc("/success", successHandler) + + log.Println("Starting server on :2342...") + err := http.ListenAndServe(":2342", nil) + if err != nil { + log.Fatal("Server failed:", err) + } +}