131 lines
2.9 KiB
Go
131 lines
2.9 KiB
Go
package style
|
|
|
|
import (
|
|
"context"
|
|
"crypto/md5"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/lucasb-eyer/go-colorful"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var pixl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
|
|
|
|
type Key string
|
|
|
|
func (s Key) Key() interface{} {
|
|
return s
|
|
}
|
|
|
|
type Style struct {
|
|
Avatar,
|
|
Cover,
|
|
Background string
|
|
|
|
Palette []string
|
|
}
|
|
|
|
func GetStyle(ctx context.Context, email string) (*Style, error) {
|
|
log := log.Ctx(ctx)
|
|
|
|
avatarHost, styleHost, err := GetSRV(ctx, email)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
log.Info().Str("avatar", avatarHost).Str("style", styleHost).Msg("getStyle")
|
|
|
|
hash := md5.New()
|
|
email = strings.TrimSpace(strings.ToLower(email))
|
|
_, _ = hash.Write([]byte(email))
|
|
id := hash.Sum(nil)
|
|
|
|
style := &Style{}
|
|
|
|
style.Palette = GetPalette(fmt.Sprintf("#%x", id[:3]))
|
|
style.Avatar = fmt.Sprintf("https://%s/avatar/%x", avatarHost, id)
|
|
style.Cover = pixl
|
|
style.Background = pixl
|
|
|
|
if styleHost != "" {
|
|
style.Cover = fmt.Sprintf("https://%s/cover/%x", styleHost, id)
|
|
style.Background = fmt.Sprintf("https://%s/bg/%x", styleHost, id)
|
|
}
|
|
|
|
return style, err
|
|
}
|
|
|
|
func GetSRV(ctx context.Context, email string) (avatar string, style string, err error) {
|
|
|
|
// Defaults
|
|
style = ""
|
|
avatar = "www.libravatar.org"
|
|
|
|
parts := strings.SplitN(email, "@", 2)
|
|
if _, srv, err := net.DefaultResolver.LookupSRV(ctx, "style-sec", "tcp", parts[1]); err == nil {
|
|
if len(srv) > 0 {
|
|
style = strings.TrimSuffix(srv[0].Target, ".")
|
|
avatar = strings.TrimSuffix(srv[0].Target, ".")
|
|
|
|
return avatar, style, err
|
|
}
|
|
}
|
|
|
|
if _, srv, err := net.DefaultResolver.LookupSRV(ctx, "avatars-sec", "tcp", parts[1]); err == nil {
|
|
if len(srv) > 0 {
|
|
avatar = strings.TrimSuffix(srv[0].Target, ".")
|
|
|
|
return avatar, style, err
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// getPalette maes a complementary color palette. https://play.golang.org/p/nBXLUocGsU5
|
|
func GetPalette(hex string) []string {
|
|
reference, _ := colorful.Hex(hex)
|
|
reference = sat(lum(reference, 0, .5), 0, .5)
|
|
|
|
white := colorful.Color{R: 1, G: 1, B: 1}
|
|
black := colorful.Color{R: 0, G: 0, B: 0}
|
|
accentA := hue(reference, 60)
|
|
accentB := hue(reference, -60)
|
|
accentC := hue(reference, -180)
|
|
|
|
return append(
|
|
[]string{},
|
|
|
|
white.Hex(),
|
|
lum(reference, .4, .6).Hex(),
|
|
reference.Hex(),
|
|
lum(reference, .4, 0).Hex(),
|
|
black.Hex(),
|
|
|
|
lum(accentA, .4, .6).Hex(),
|
|
accentA.Hex(),
|
|
lum(accentA, .4, 0).Hex(),
|
|
|
|
lum(accentB, .4, .6).Hex(),
|
|
accentB.Hex(),
|
|
lum(accentB, .4, 0).Hex(),
|
|
|
|
lum(accentC, .4, .6).Hex(),
|
|
accentC.Hex(),
|
|
lum(accentC, .4, 0).Hex(),
|
|
)
|
|
}
|
|
func hue(in colorful.Color, H float64) colorful.Color {
|
|
h, s, l := in.Hsl()
|
|
return colorful.Hsl(h+H, s, l)
|
|
}
|
|
func sat(in colorful.Color, S, V float64) colorful.Color {
|
|
h, s, l := in.Hsl()
|
|
return colorful.Hsl(h, V+s*S, l)
|
|
}
|
|
func lum(in colorful.Color, L, V float64) colorful.Color {
|
|
h, s, l := in.Hsl()
|
|
return colorful.Hsl(h, s, V+l*L)
|
|
}
|