Skip to content

Commit

Permalink
feat(avatar): avatar set is customizable
Browse files Browse the repository at this point in the history
  • Loading branch information
ncarlier committed Apr 30, 2022
1 parent 3f4bdd3 commit bc4f1bb
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 29 deletions.
24 changes: 6 additions & 18 deletions pkg/api/avatar.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,30 @@ import (
)

const (
DefaultAvatarSet = "cat"
MaxAge = 864000
MaxAge = 864000
)

func newAvatarGenerator(provider string) (*avatar.Generator, error) {
u, err := url.Parse(provider)
if err != nil {
return nil, err
}
defaultSet := u.Query().Get("default")
switch u.Scheme {
case "file":
return avatar.NewGenerator(u.Host + u.Path)
return avatar.NewGenerator(u.Host+u.Path, defaultSet)
case "https":
return nil, nil
}
return nil, fmt.Errorf("invalid avatar provider: %s", provider)
}

func getAvatarSet(provider string) string {
u, err := url.Parse(provider)
if err != nil {
return DefaultAvatarSet
}
set := u.Query().Get("set")
if set == "" {
return DefaultAvatarSet
}
return set
}

func avatarHandler(conf *config.Config) http.Handler {
generator, err := newAvatarGenerator(conf.Integration.AvatarProvider)
if err != nil {
log.Fatal().Err(err).Msg("unable to create avatar generator")
}
log.Info().Str("component", "api").Str("provider", conf.Integration.AvatarProvider).Msg("using Avatar provider")
avatarSet := getAvatarSet(conf.Integration.AvatarProvider)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
seed := strings.TrimPrefix(r.URL.Path, "/avatar/")
if seed == "" {
Expand All @@ -61,8 +48,9 @@ func avatarHandler(conf *config.Config) http.Handler {
http.Redirect(w, r, redirect, http.StatusTemporaryRedirect)
return
}
log.Debug().Str("seed", seed).Msg("generating avatar image")
img, err := generator.Generate(avatarSet, seed)
set := r.URL.Query().Get("set")
log.Debug().Str("seed", seed).Str("set", set).Msg("generating avatar image")
img, err := generator.Generate(seed, set)
if err != nil {
log.Error().Err(err).Str("seed", seed).Msg("unable to generate avatar image")
http.Error(w, "unable to generate avatar image", http.StatusInternalServerError)
Expand Down
37 changes: 27 additions & 10 deletions pkg/avatar/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,22 @@ type Avatars map[string]*Avatar

// Generator instance
type Generator struct {
avatars Avatars
directory string
avatars Avatars
directory string
defaultSet string
}

// Generate avatar
func (g *Generator) Generate(name, seed string) (*bytes.Buffer, error) {
// get avatar
avatar, ok := g.avatars[name]
func (g *Generator) Generate(seed, set string) (*bytes.Buffer, error) {
if set == "" {
set = g.defaultSet
}
// get avatar set
avatar, ok := g.avatars[set]
if !ok {
return nil, fmt.Errorf("avatar %s doesn't exists", name)
// avatar set doesn't exists, using default
set = g.defaultSet
avatar = g.avatars[set]
}

// init random seed
Expand All @@ -66,7 +72,7 @@ func (g *Generator) Generate(name, seed string) (*bytes.Buffer, error) {

// build avatar image
for _, part := range specs {
imgSrc := filepath.Join(g.directory, name, fmt.Sprintf("%s_%d.png", part.Name, part.Nb))
imgSrc := filepath.Join(g.directory, set, fmt.Sprintf("%s_%d.png", part.Name, part.Nb))
if _, err := os.Stat(imgSrc); err == nil {
img, _ = blendWithImageFile(img, imgSrc)
}
Expand All @@ -80,7 +86,7 @@ func (g *Generator) Generate(name, seed string) (*bytes.Buffer, error) {
}

// NewServer creates new server instance
func NewGenerator(dir string) (*Generator, error) {
func NewGenerator(dir string, defaultSet string) (*Generator, error) {
if _, err := os.Stat(dir); err != nil {
return nil, err
}
Expand All @@ -90,19 +96,30 @@ func NewGenerator(dir string) (*Generator, error) {
return nil, err
}

defaultSetExists := false
for _, file := range files {
if file.IsDir() {
avatar, e := readAvatarDir(filepath.Join(dir, file.Name()))
if e != nil {
return nil, err
}
if defaultSet == "" {
defaultSet = file.Name()
}
if file.Name() == defaultSet {
defaultSetExists = true
}
avatars[file.Name()] = avatar
}
}
if !defaultSetExists {
return nil, fmt.Errorf("avatar default set not found: %s", defaultSet)
}

return &Generator{
avatars: avatars,
directory: dir,
avatars: avatars,
directory: dir,
defaultSet: defaultSet,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/readflow.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ image_proxy_url = "${READFLOW_IMAGE_PROXY_URL}"
# If using a remote provider, {seed} is a placehoder for the avatar seed.
# Default: "https://robohash.org/{seed}?set=set4&size=48x48"
# Examples:
# - file:///var/opt/avatars
# - file:///var/opt/avatars?default=cat
# - https://seccdn.libravatar.org/avatar/{seed}?d=mp&s=48
avatar_provider = "${READFLOW_AVATAR_PROVIDER}"

Expand Down

0 comments on commit bc4f1bb

Please sign in to comment.