package main import ( "crypto/sha256" "fmt" "net/http" "strings" ) // An avatar is drawn from the name alone: fetching one tells somewhere else // who reads what, and an upload needs a parser. func avatarSVG(name string) []byte { sum := sha256.Sum256([]byte(name)) // Fixed saturation and lightness, so every one is readable. hue := int(sum[0]) * 360 / 256 var b strings.Builder fmt.Fprintf(&b, ``, name) fmt.Fprintf(&b, ``) fmt.Fprintf(&b, ``, hue) // Three columns mirrored into five. for x := range 3 { for y := range 5 { if sum[1+x*5+y]&1 == 0 { continue } fmt.Fprintf(&b, ``, x, y) if x < 2 { fmt.Fprintf(&b, ``, 4-x, y) } } } b.WriteString(``) return []byte(b.String()) } func (f *Forge) handleAvatar(w http.ResponseWriter, r *http.Request) { name := r.PathValue("name") if !accountNameRE.MatchString(name) { http.NotFound(w, r) return } w.Header().Set("Content-Type", "image/svg+xml") w.Header().Set("Cache-Control", "max-age=86400") w.Write(avatarSVG(name)) }