Some checks failed
Check scripts syntax / check-scripts-syntax (push) Successful in 3s
Test automated-nfs-backup / test-automated-nfs-backup (push) Successful in 4s
Haven Notify Build and Deploy / Build Haven Notify Image (pull_request) Has been cancelled
Haven Notify Build and Deploy / Build Haven Notify Image (PR) (pull_request) Has been cancelled
Haven Notify Build and Deploy / Deploy Haven Notify (internal) (pull_request) Has been cancelled
Haven Notify Build and Deploy / Test Haven Notify (pull_request) Has been cancelled
136 lines
3.2 KiB
Go
136 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"embed"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/fs"
|
|
"strconv"
|
|
"text/template"
|
|
)
|
|
|
|
//go:embed template/*.tmpl
|
|
var templatesFS embed.FS
|
|
|
|
type templateRenderer struct {
|
|
templates map[string]*template.Template
|
|
}
|
|
|
|
type templateExtra struct {
|
|
Name string
|
|
Value string
|
|
}
|
|
|
|
type backupTemplateData struct {
|
|
Title string
|
|
Asset string
|
|
BackupSizeInMB float64
|
|
Extra []templateExtra
|
|
}
|
|
|
|
type updateTemplateData struct {
|
|
Host string
|
|
Asset string
|
|
Time float64
|
|
}
|
|
|
|
type errorTemplateData struct {
|
|
Caller string
|
|
Message string
|
|
Critical bool
|
|
Extra []templateExtra
|
|
}
|
|
|
|
func newTemplateRenderer() (*templateRenderer, error) {
|
|
return newTemplateRendererFromFS(templatesFS)
|
|
}
|
|
|
|
func newTemplateRendererFromFS(templateFS fs.FS) (*templateRenderer, error) {
|
|
functions := template.FuncMap{
|
|
"formatSize": formatSize,
|
|
"formatSeconds": formatSeconds,
|
|
"json": jsonLiteral,
|
|
}
|
|
templates := make(map[string]*template.Template, 3)
|
|
for _, name := range []string{"backup", "update", "error"} {
|
|
contents, err := fs.ReadFile(templateFS, "template/"+name+".tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
parsed, err := template.New(name).Funcs(functions).Parse(string(contents))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
templates[name] = parsed
|
|
}
|
|
return &templateRenderer{templates: templates}, nil
|
|
}
|
|
|
|
func (r *templateRenderer) renderBackup(request backupRequest) (discordPayload, error) {
|
|
return r.render("backup", backupTemplateData{
|
|
Title: *request.Title,
|
|
Asset: *request.Asset,
|
|
BackupSizeInMB: *request.BackupSizeInMB,
|
|
Extra: templateExtras(request.Extra),
|
|
})
|
|
}
|
|
|
|
func (r *templateRenderer) renderUpdate(request updateRequest) (discordPayload, error) {
|
|
return r.render("update", updateTemplateData{
|
|
Host: *request.Host,
|
|
Asset: *request.Asset,
|
|
Time: *request.Time,
|
|
})
|
|
}
|
|
|
|
func (r *templateRenderer) renderError(request errorRequest) (discordPayload, error) {
|
|
return r.render("error", errorTemplateData{
|
|
Caller: *request.Caller,
|
|
Message: *request.Message,
|
|
Critical: *request.Critical,
|
|
Extra: templateExtras(request.Extra),
|
|
})
|
|
}
|
|
|
|
func (r *templateRenderer) render(name string, data any) (discordPayload, error) {
|
|
parsed, ok := r.templates[name]
|
|
if !ok {
|
|
return discordPayload{}, fmt.Errorf("unknown template %q", name)
|
|
}
|
|
var rendered bytes.Buffer
|
|
if err := parsed.Execute(&rendered, data); err != nil {
|
|
return discordPayload{}, err
|
|
}
|
|
var payload discordPayload
|
|
if err := json.Unmarshal(rendered.Bytes(), &payload); err != nil {
|
|
return discordPayload{}, fmt.Errorf("template produced invalid JSON: %w", err)
|
|
}
|
|
normalizeDiscordPayload(&payload)
|
|
return payload, nil
|
|
}
|
|
|
|
func templateExtras(extra extraRequests) []templateExtra {
|
|
result := make([]templateExtra, 0, len(extra))
|
|
for _, field := range extra {
|
|
result = append(result, templateExtra{Name: *field.Name, Value: *field.Value})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func jsonLiteral(value any) (string, error) {
|
|
encoded, err := json.Marshal(value)
|
|
return string(encoded), err
|
|
}
|
|
|
|
func formatSize(size float64) string {
|
|
if size >= 1024 {
|
|
return fmt.Sprintf("%.2f GiB", size/1024)
|
|
}
|
|
return fmt.Sprintf("%.2f MiB", size)
|
|
}
|
|
|
|
func formatSeconds(seconds float64) string {
|
|
return strconv.FormatFloat(seconds, 'f', -1, 64) + " seconds"
|
|
}
|