blive fundet Tjekket fandtes i forvejen, og svaret stod ét sted: nederst på indstillingssiden for beskeder. Det er en oplysning, man kun får, hvis man i forvejen havde mistanke om, at der var noget at se efter — og "der er kommet en rettelse af noget, du er ramt af" er ikke noget, man gætter sig til at kigge efter. Nu går den i klokken, i push og på mærket på ikonet, som alt andet, der er værd at vide. Og den fører hen, hvor knappen til at genstarte sidder, frem for ud af programmet. Én besked pr. version, ikke én pr. time. En påmindelse hver time om det samme er den slags besked, folk slår fra — og så er den næste, der betyder noget, også slået fra. Versionen, der er sagt til om, skrives først, når beskederne er sendt: den anden vej rundt ville en fejl midtvejs betyde, at halvdelen fik besked og resten aldrig gjorde. Kun administratorer, af samme grund som versionsfeltet allerede er det: en besked om, at serveren er bagud, er en besked om en andens arbejde, hvis man ikke selv kan gøre noget ved den. Og et tjek, operatøren har slået fra, bliver ikke til en besked ad bagvejen. VERDANDE_UPDATE_CHECK styrer det hele, som før. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92 lines
3.2 KiB
Go
92 lines
3.2 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/kristianwind/verdande/internal/store"
|
|
"github.com/kristianwind/verdande/internal/update"
|
|
)
|
|
|
|
// Besked til administratorerne, når der er kommet en ny version.
|
|
//
|
|
// Tjekket fandtes i forvejen, og svaret stod ét sted: nederst på en
|
|
// indstillingsside. Det er en oplysning, man kun får, hvis man i forvejen havde
|
|
// mistanke om, at der var noget at se efter — og "der er kommet en rettelse af
|
|
// noget, du er ramt af" er ikke noget, man gætter sig til at kigge efter.
|
|
//
|
|
// Kun til administratorer, af samme grund som versionsfeltet er det: en besked om,
|
|
// at serveren er bagud, er en besked om en andens arbejde, hvis man ikke selv kan
|
|
// gøre noget ved den. Og den fører hen, hvor knappen til at gøre det sidder.
|
|
|
|
const updateScope = "update"
|
|
|
|
// NotifyOfUpdates er timeslaget. Selve tjekket mellemlagrer sit svar i seks timer,
|
|
// så en time mellem opslagene her koster ikke noget — og en instans, der har været
|
|
// slukket, opdager det ved den første time, den er vågen.
|
|
func (s *Server) NotifyOfUpdates(ctx context.Context) error {
|
|
return s.notifyOfUpdate(ctx, s.updates.Status(ctx))
|
|
}
|
|
|
|
// notifyOfUpdate tager status som argument frem for at hente den, så den kan
|
|
// prøves uden at spørge GitHub om noget.
|
|
func (s *Server) notifyOfUpdate(ctx context.Context, status update.Status) error {
|
|
// Slået fra betyder slået fra. Et tjek, operatøren ikke har bedt om, må ikke
|
|
// blive til en besked ad bagvejen.
|
|
if status.Disabled || !status.Available || status.Latest == "" {
|
|
return nil
|
|
}
|
|
|
|
stored, err := s.db.InstanceSettings(ctx, updateScope)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Én besked pr. version, ikke én pr. dag. En påmindelse hver morgen om det
|
|
// samme er den slags besked, folk slår fra — og så er den næste, der betyder
|
|
// noget, også slået fra.
|
|
if last, _ := stored["notified_version"].(string); last == status.Latest {
|
|
return nil
|
|
}
|
|
|
|
users, err := s.db.ListUsers(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
title := updateTitle(status.Latest)
|
|
body := firstLineOf(status.Notes)
|
|
for _, u := range users {
|
|
if !u.IsAdmin {
|
|
continue
|
|
}
|
|
s.notifyDirect(ctx, &store.Notification{
|
|
UserID: u.ID, Kind: "update.available", Title: title, Body: body,
|
|
})
|
|
}
|
|
|
|
// Skrevet efter beskederne, og kun hvis de blev sendt. Skrevet først ville en
|
|
// fejl midtvejs betyde, at halvdelen fik besked og resten aldrig gjorde.
|
|
return s.db.SetInstanceSettings(ctx, updateScope, map[string]any{
|
|
"notified_version": status.Latest,
|
|
})
|
|
}
|
|
|
|
// updateTitle er skrevet på dansk, fordi den også bliver til en push-besked, og
|
|
// push har ingen ordbog at slå op i. Fladen skriver sin egen sætning ud fra
|
|
// `kind` — se KINDS i Notifications.svelte.
|
|
func updateTitle(version string) string {
|
|
return "verdande " + version + " er klar"
|
|
}
|
|
|
|
// firstLineOf er den første linje af udgivelsesnoterne, som beskedens krop.
|
|
//
|
|
// Hele teksten ville være en udgivelsesnote i en notifikation, og det er ikke det,
|
|
// en notifikation er til: den skal sige, at der er noget, og hvor man læser det.
|
|
func firstLineOf(notes string) string {
|
|
for _, line := range strings.Split(notes, "\n") {
|
|
if line = strings.TrimSpace(line); line != "" {
|
|
return firstWords(line, 30)
|
|
}
|
|
}
|
|
return ""
|
|
}
|