diff --git a/internal/shiftnotifier/formatting.go b/internal/shiftnotifier/formatting.go
new file mode 100644
index 0000000..912835e
--- /dev/null
+++ b/internal/shiftnotifier/formatting.go
@@ -0,0 +1,140 @@
+package shiftnotifier
+
+import (
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func (service *service) diffToMessage(diffs *shiftDiffs) (string, string) {
+ msg := strings.Builder{}
+ msgHTML := strings.Builder{}
+
+ defaultTZ, err := time.LoadLocation("Europe/Berlin")
+ if err != nil {
+ defaultTZ = time.Local
+ }
+
+ timeStr := diffs.ReferenceTime.
+ Add(service.config.NotifyBeforeShiftStart).
+ In(defaultTZ).
+ Format("Mon, 15:04")
+
+ // Title.
+ msg.WriteString("TROLL CHANGES FOR ")
+ msg.WriteString(timeStr)
+ msg.WriteString("\n\n")
+
+ msgHTML.WriteString("
Troll Changes for ")
+ msgHTML.WriteString(timeStr)
+ msgHTML.WriteString("
\n")
+
+ // Sort by mapkey to have deterministic order.
+ locations := make([]string, 0, len(diffs.DiffsInLocations))
+ for k := range diffs.DiffsInLocations {
+ locations = append(locations, k)
+ }
+ sort.Strings(locations)
+
+ for _, loc := range locations {
+ // Location.
+ msg.WriteString("📍 ")
+ msg.WriteString(loc)
+ msg.WriteString("\n")
+
+ msgHTML.WriteString("📍 ")
+ msgHTML.WriteString(loc)
+ msgHTML.WriteString("
\n")
+
+ // Troll lists.
+ msg.WriteString("Arriving Trolls 🔜:\n")
+ msgHTML.WriteString("Arriving Trolls 🔜:
\n")
+ usersToList(diffs.DiffsInLocations[loc].UsersArriving, &msg, &msgHTML)
+
+ msg.WriteString("Staying Trolls 🔄:\n")
+ msgHTML.WriteString("Staying Trolls 🔄:
\n")
+ usersToList(diffs.DiffsInLocations[loc].UsersWorking, &msg, &msgHTML)
+
+ msg.WriteString("Leaving Trolls 🔚:\n")
+ msgHTML.WriteString("Leaving Trolls 🔚:
\n")
+ usersToList(diffs.DiffsInLocations[loc].UsersLeaving, &msg, &msgHTML)
+
+ // Summary.
+ msg.WriteString("\nExpecting ")
+ msg.WriteString(strconv.Itoa(int(diffs.DiffsInLocations[loc].ExpectedUsers)))
+ msg.WriteString(" trolls total\n")
+ msgHTML.WriteString("
\nExpecting ")
+ msgHTML.WriteString(strconv.Itoa(int(diffs.DiffsInLocations[loc].ExpectedUsers)))
+ msgHTML.WriteString(" trolls total
\n")
+
+ if len(diffs.DiffsInLocations[loc].OpenUsers) > 0 {
+ msg.WriteString("🚨 Open positions:\n")
+ for shiftType, amount := range diffs.DiffsInLocations[loc].OpenUsers {
+ msg.WriteString("- ")
+ msg.WriteString(strconv.Itoa(int(amount)))
+ msg.WriteString("x ")
+ msg.WriteString(shiftType)
+ msg.WriteString("\n")
+ }
+
+ msgHTML.WriteString("🚨 Open positions:
\n")
+ for shiftType, amount := range diffs.DiffsInLocations[loc].OpenUsers {
+ msgHTML.WriteString("- ")
+ msgHTML.WriteString(strconv.Itoa(int(amount)))
+ msgHTML.WriteString("x ")
+ msgHTML.WriteString(shiftType)
+ msgHTML.WriteString("
\n")
+ }
+ }
+
+ msg.WriteString("\n")
+ msgHTML.WriteString("
\n")
+ }
+
+ return msg.String(), msgHTML.String()
+}
+
+func usersToList(users []shiftUser, msg *strings.Builder, msgHTML *strings.Builder) {
+ if len(users) == 0 {
+ msg.WriteString(" _none_\n")
+ msgHTML.WriteString(" none
\n")
+ return
+ }
+
+ for _, user := range users {
+ msg.WriteString(" - ")
+ msg.WriteString(user.Nickname)
+ msg.WriteString(" (")
+ msg.WriteString(user.ShiftName)
+ msg.WriteString(shiftNameToEmoji(user.ShiftName))
+ msg.WriteString(")\n")
+
+ msgHTML.WriteString(" - ")
+ msgHTML.WriteString(user.Nickname)
+ msgHTML.WriteString(" (")
+ msgHTML.WriteString(user.ShiftName)
+ msgHTML.WriteString(shiftNameToEmoji(user.ShiftName))
+ msgHTML.WriteString(")
\n")
+ }
+}
+
+func shiftNameToEmoji(shiftName string) string {
+ shiftName = strings.TrimSpace(strings.ToLower(shiftName))
+ switch {
+ case strings.Contains(shiftName, "orga"):
+ return " 👑"
+ case strings.Contains(shiftName, "tschunk"):
+ return " 🥃"
+ case strings.Contains(shiftName, "kaffee"):
+ return " 🍫"
+ case strings.Contains(shiftName, "runner"):
+ return " 🏃♀️"
+ case strings.Contains(shiftName, "bottle"):
+ return " ♻️"
+ case strings.Contains(shiftName, "bar-theke"):
+ return " 💶"
+ default:
+ return ""
+ }
+}
diff --git a/internal/shiftnotifier/service.go b/internal/shiftnotifier/service.go
index 2b2bf64..092d6a1 100644
--- a/internal/shiftnotifier/service.go
+++ b/internal/shiftnotifier/service.go
@@ -2,13 +2,9 @@ package shiftnotifier
import (
"context"
- "encoding/json"
- "errors"
"log/slog"
"net/http"
"os"
- "sort"
- "strconv"
"strings"
"sync"
"time"
@@ -64,56 +60,6 @@ func New(config *Config, angelAPI angelapi.Service, messenger matrixmessenger.Me
return s
}
-func (service *service) serveJSONData(w http.ResponseWriter, r *http.Request) {
- err := service.requireToken(r)
- if err != nil {
- w.WriteHeader(http.StatusUnauthorized)
- _, _ = w.Write([]byte("unauthorized"))
- return
- }
-
- data, err := json.Marshal(service.latestDiffs)
- if err != nil {
- slog.Error("failed marshaling data", "error", err.Error())
- w.WriteHeader(http.StatusInternalServerError)
- _, _ = w.Write([]byte("internal server error"))
- return
- }
- _, _ = w.Write(data)
-}
-
-func (service *service) serveHumanData(w http.ResponseWriter, r *http.Request) {
- err := service.requireToken(r)
- if err != nil {
- w.WriteHeader(http.StatusUnauthorized)
- _, _ = w.Write([]byte("unauthorized"))
- return
- }
-
- if service.latestDiffs == nil {
- _, _ = w.Write([]byte("no data"))
- return
- }
-
- _, html := service.diffToMessage(service.latestDiffs)
-
- if refreshSeconds := r.URL.Query().Get("refresh_seconds"); refreshSeconds != "" {
- html = `` + html
- }
-
- html = `
-
- ` + html + ""
-
- _, _ = w.Write([]byte(html))
-}
-
func (service *service) Start() error {
go func(config Config) {
err := http.ListenAndServe(config.ListenAddr, nil)
@@ -392,121 +338,3 @@ func (service *service) cleanUpDiffs(diffs map[string]shiftDiff) map[string]shif
return newDiffs
}
-
-func (service *service) diffToMessage(diffs *shiftDiffs) (string, string) {
- msg := strings.Builder{}
- msgHTML := strings.Builder{}
-
- defaultTZ, err := time.LoadLocation("Europe/Berlin")
- if err != nil {
- defaultTZ = time.Local
- }
-
- timeStr := diffs.ReferenceTime.
- Add(service.config.NotifyBeforeShiftStart).
- In(defaultTZ).
- Format("Mon, 15:04")
-
- // Title.
- msg.WriteString("TROLL CHANGES FOR ")
- msg.WriteString(timeStr)
- msg.WriteString("\n\n")
-
- msgHTML.WriteString("Troll Changes for ")
- msgHTML.WriteString(timeStr)
- msgHTML.WriteString("
\n")
-
- // Sort by mapkey to have deterministic order.
- locations := make([]string, 0, len(diffs.DiffsInLocations))
- for k := range diffs.DiffsInLocations {
- locations = append(locations, k)
- }
- sort.Strings(locations)
-
- for _, loc := range locations {
- // Location.
- msg.WriteString("📍 ")
- msg.WriteString(loc)
- msg.WriteString("\n")
-
- msgHTML.WriteString("📍 ")
- msgHTML.WriteString(loc)
- msgHTML.WriteString("
\n")
-
- // Troll lists.
- msg.WriteString("Arriving Trolls 🔜:\n")
- msgHTML.WriteString("Arriving Trolls 🔜:
\n")
- usersToList(diffs.DiffsInLocations[loc].UsersArriving, &msg, &msgHTML)
-
- msg.WriteString("Staying Trolls 🔄:\n")
- msgHTML.WriteString("Staying Trolls 🔄:
\n")
- usersToList(diffs.DiffsInLocations[loc].UsersWorking, &msg, &msgHTML)
-
- msg.WriteString("Leaving Trolls 🔚:\n")
- msgHTML.WriteString("Leaving Trolls 🔚:
\n")
- usersToList(diffs.DiffsInLocations[loc].UsersLeaving, &msg, &msgHTML)
-
- // Summary.
- msg.WriteString("\nExpecting ")
- msg.WriteString(strconv.Itoa(int(diffs.DiffsInLocations[loc].ExpectedUsers)))
- msg.WriteString(" trolls total\n")
- msgHTML.WriteString("
\nExpecting ")
- msgHTML.WriteString(strconv.Itoa(int(diffs.DiffsInLocations[loc].ExpectedUsers)))
- msgHTML.WriteString(" trolls total
\n")
-
- if len(diffs.DiffsInLocations[loc].OpenUsers) > 0 {
- msg.WriteString("🚨 Open positions:\n")
- for shiftType, amount := range diffs.DiffsInLocations[loc].OpenUsers {
- msg.WriteString("- ")
- msg.WriteString(strconv.Itoa(int(amount)))
- msg.WriteString("x ")
- msg.WriteString(shiftType)
- msg.WriteString("\n")
- }
-
- msgHTML.WriteString("🚨 Open positions:
\n")
- for shiftType, amount := range diffs.DiffsInLocations[loc].OpenUsers {
- msgHTML.WriteString("- ")
- msgHTML.WriteString(strconv.Itoa(int(amount)))
- msgHTML.WriteString("x ")
- msgHTML.WriteString(shiftType)
- msgHTML.WriteString("
\n")
- }
- }
-
- msg.WriteString("\n")
- msgHTML.WriteString("
\n")
- }
-
- return msg.String(), msgHTML.String()
-}
-
-func usersToList(users []shiftUser, msg *strings.Builder, msgHTML *strings.Builder) {
- if len(users) == 0 {
- msg.WriteString(" _none_\n")
- msgHTML.WriteString(" none
\n")
- return
- }
-
- for _, user := range users {
- msg.WriteString(" - ")
- msg.WriteString(user.Nickname)
- msg.WriteString(" (")
- msg.WriteString(user.ShiftName)
- msg.WriteString(")\n")
-
- msgHTML.WriteString(" - ")
- msgHTML.WriteString(user.Nickname)
- msgHTML.WriteString(" (")
- msgHTML.WriteString(user.ShiftName)
- msgHTML.WriteString(")
\n")
- }
-}
-
-func (service *service) requireToken(r *http.Request) error {
- t := r.URL.Query().Get("token")
- if strings.TrimSpace(t) != service.config.Token {
- return errors.New("invalid auth")
- }
- return nil
-}
diff --git a/internal/shiftnotifier/webview.go b/internal/shiftnotifier/webview.go
new file mode 100644
index 0000000..daf1487
--- /dev/null
+++ b/internal/shiftnotifier/webview.go
@@ -0,0 +1,67 @@
+package shiftnotifier
+
+import (
+ "encoding/json"
+ "errors"
+ "log/slog"
+ "net/http"
+ "strings"
+)
+
+func (service *service) requireToken(r *http.Request) error {
+ t := r.URL.Query().Get("token")
+ if strings.TrimSpace(t) != service.config.Token {
+ return errors.New("invalid auth")
+ }
+ return nil
+}
+
+func (service *service) serveJSONData(w http.ResponseWriter, r *http.Request) {
+ err := service.requireToken(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ _, _ = w.Write([]byte("unauthorized"))
+ return
+ }
+
+ data, err := json.Marshal(service.latestDiffs)
+ if err != nil {
+ slog.Error("failed marshaling data", "error", err.Error())
+ w.WriteHeader(http.StatusInternalServerError)
+ _, _ = w.Write([]byte("internal server error"))
+ return
+ }
+ _, _ = w.Write(data)
+}
+
+func (service *service) serveHumanData(w http.ResponseWriter, r *http.Request) {
+ err := service.requireToken(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ _, _ = w.Write([]byte("unauthorized"))
+ return
+ }
+
+ if service.latestDiffs == nil {
+ _, _ = w.Write([]byte("no data"))
+ return
+ }
+
+ _, html := service.diffToMessage(service.latestDiffs)
+
+ if refreshSeconds := r.URL.Query().Get("refresh_seconds"); refreshSeconds != "" {
+ html = `` + html
+ }
+
+ html = `
+
+ ` + html + ""
+
+ _, _ = w.Write([]byte(html))
+}