215 lines
6.1 KiB
Go
215 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Notification payload
|
|
type Notification struct {
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
func main() {
|
|
http.HandleFunc("/notify", notifyHandler)
|
|
http.HandleFunc("/ready", readinessHandler)
|
|
http.HandleFunc("/live", livenessHandler)
|
|
http.HandleFunc("/template/notify/", templateNotifyHandler)
|
|
log.Println("Starting server on :8080...")
|
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
|
}
|
|
|
|
func notifyHandler(w http.ResponseWriter, r *http.Request) {
|
|
log.Printf("Incoming %s request from %s to %s", r.Method, r.RemoteAddr, r.URL.Path)
|
|
if r.Method != http.MethodPost {
|
|
log.Printf("Method not allowed: %s", r.Method)
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
w.Write([]byte("Method not allowed"))
|
|
return
|
|
}
|
|
|
|
var notif Notification
|
|
if err := json.NewDecoder(r.Body).Decode(¬if); err != nil {
|
|
log.Printf("Invalid payload: %v", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Invalid payload"))
|
|
return
|
|
}
|
|
log.Printf("Received notification payload: Title='%s', Message='%s'", notif.Title, notif.Message)
|
|
|
|
// Call Discord notification function
|
|
if err := sendDiscordNotification(notif.Title, notif.Message); err != nil {
|
|
log.Printf("Failed to send Discord notification: %v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to send Discord notification"))
|
|
return
|
|
}
|
|
|
|
log.Printf("Notification sent successfully for Title='%s'", notif.Title)
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("Notification sent"))
|
|
}
|
|
|
|
// Readiness handler
|
|
func readinessHandler(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("Ready"))
|
|
}
|
|
|
|
// Liveness handler
|
|
func livenessHandler(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("Alive"))
|
|
}
|
|
|
|
func sendDiscordNotification(title, message string) error {
|
|
webhookURL := os.Getenv("WEBHOOK_URL")
|
|
if webhookURL == "" {
|
|
log.Printf("WEBHOOK_URL environment variable not set")
|
|
return fmt.Errorf("WEBHOOK_URL environment variable not set")
|
|
}
|
|
|
|
// Discord webhook payload
|
|
type discordPayload struct {
|
|
Content string `json:"content"`
|
|
}
|
|
|
|
content := "**" + title + "**\n" + message
|
|
payload := discordPayload{Content: content}
|
|
|
|
jsonData, err := json.Marshal(payload)
|
|
if err != nil {
|
|
log.Printf("Failed to marshal Discord payload: %v", err)
|
|
return err
|
|
}
|
|
|
|
log.Printf("Sending Discord notification: Title='%s', Message='%s'", title, message)
|
|
resp, err := http.Post(webhookURL, "application/json", bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
log.Printf("Error posting to Discord webhook: %v", err)
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
log.Printf("Discord webhook returned status: %s", resp.Status)
|
|
return fmt.Errorf("Discord webhook returned status: %s", resp.Status)
|
|
}
|
|
|
|
log.Printf("Discord notification sent successfully: Title='%s'", title)
|
|
return nil
|
|
}
|
|
|
|
func templateNotifyHandler(w http.ResponseWriter, r *http.Request) {
|
|
log.Printf("Incoming %s request from %s to %s", r.Method, r.RemoteAddr, r.URL.Path)
|
|
if r.Method != http.MethodPost {
|
|
log.Printf("Method not allowed: %s", r.Method)
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
w.Write([]byte("Method not allowed"))
|
|
return
|
|
}
|
|
|
|
templateName := r.URL.Path[len("/template/notify/"):] // Extract template name
|
|
if templateName == "" {
|
|
log.Printf("Template name not provided")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Template name not provided"))
|
|
return
|
|
}
|
|
|
|
templatePath := "template/" + templateName + ".tmpl"
|
|
templateData, err := ioutil.ReadFile(templatePath)
|
|
if err != nil {
|
|
log.Printf("Failed to read template: %v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to read template"))
|
|
return
|
|
}
|
|
|
|
tmpl, err := template.New(templateName).Funcs(template.FuncMap{
|
|
"formatSize": func(size float64) string {
|
|
if size > 1024 {
|
|
return fmt.Sprintf("%.2f GiB", size/1024)
|
|
}
|
|
return fmt.Sprintf("%.2f MiB", size)
|
|
},
|
|
"upper": strings.ToUpper,
|
|
"lower": strings.ToLower,
|
|
"title": strings.Title,
|
|
"now": func() string {
|
|
return fmt.Sprintf("%d", time.Now().Unix())
|
|
},
|
|
"formatTime": func(timestamp string) string {
|
|
if timestamp == "" {
|
|
return time.Now().Format("2006-01-02T15:04:05Z")
|
|
}
|
|
return timestamp
|
|
},
|
|
}).Parse(string(templateData))
|
|
if err != nil {
|
|
log.Printf("Failed to parse template: %v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to parse template"))
|
|
return
|
|
}
|
|
|
|
var rawPayload map[string]interface{}
|
|
if err := json.NewDecoder(r.Body).Decode(&rawPayload); err != nil {
|
|
log.Printf("Invalid payload: %v", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write([]byte("Invalid payload"))
|
|
return
|
|
}
|
|
|
|
// Normalize keys to lowercase for case-insensitive parsing
|
|
payload := make(map[string]interface{})
|
|
for key, value := range rawPayload {
|
|
payload[strings.ToLower(key)] = value
|
|
}
|
|
|
|
var filledTemplate bytes.Buffer
|
|
if err := tmpl.Execute(&filledTemplate, payload); err != nil {
|
|
log.Printf("Failed to execute template: %v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to execute template"))
|
|
return
|
|
}
|
|
|
|
webhookURL := os.Getenv("WEBHOOK_URL")
|
|
if webhookURL == "" {
|
|
log.Printf("WEBHOOK_URL environment variable not set")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("WEBHOOK_URL environment variable not set"))
|
|
return
|
|
}
|
|
|
|
resp, err := http.Post(webhookURL, "application/json", &filledTemplate)
|
|
if err != nil {
|
|
log.Printf("Error posting to Discord webhook: %v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to send notification"))
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
log.Printf("Discord webhook returned status: %s", resp.Status)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte("Failed to send notification"))
|
|
return
|
|
}
|
|
|
|
log.Printf("Notification sent successfully using template '%s'", templateName)
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("Notification sent"))
|
|
}
|