kopia lustrzana https://codeberg.org/nmkj/audon
always convert original avatar to png to avoid recompression
rodzic
6adbf5de60
commit
e28f2edb2e
72
avatar.go
72
avatar.go
|
@ -22,42 +22,18 @@ import (
|
|||
"gopkg.in/gographics/imagick.v2/imagick"
|
||||
)
|
||||
|
||||
func (u *AudonUser) GetIndicator(ctx context.Context, fnew []byte, room *Room) ([]byte, error) {
|
||||
func (u *AudonUser) GetIndicator(ctx context.Context, fnew []byte, room *Room) ([]byte, []byte, error) {
|
||||
if u == nil {
|
||||
return nil, errors.New("nil user")
|
||||
return nil, nil, errors.New("nil user")
|
||||
}
|
||||
|
||||
mtype := mimetype.Detect(fnew)
|
||||
if !mimetype.EqualsAny(mtype.String(), "image/png", "image/jpeg", "image/webp", "image/gif") {
|
||||
return nil, errors.New("file type not supported")
|
||||
return nil, nil, errors.New("file type not supported")
|
||||
}
|
||||
|
||||
hash := sha256.Sum256(fnew)
|
||||
|
||||
var err error
|
||||
|
||||
// Check if user's original avatar exists
|
||||
saved := u.GetOriginalAvatarPath(hash, mtype)
|
||||
if _, err := os.Stat(saved); err != nil {
|
||||
if err := os.MkdirAll(filepath.Dir(saved), 0775); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Write user's avatar if the original version doesn't exist
|
||||
if err := os.WriteFile(saved, fnew, 0664); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
fname := filepath.Base(saved)
|
||||
coll := mainDB.Collection(COLLECTION_USER)
|
||||
if _, err = coll.UpdateOne(ctx,
|
||||
bson.D{{Key: "audon_id", Value: u.AudonID}},
|
||||
bson.D{
|
||||
{Key: "$set", Value: bson.D{{Key: "avatar", Value: fname}}},
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := bytes.NewReader(fnew)
|
||||
|
||||
var newImg image.Image
|
||||
|
@ -71,9 +47,45 @@ func (u *AudonUser) GetIndicator(ctx context.Context, fnew []byte, room *Room) (
|
|||
newImg, err = gif.Decode(buf)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
return u.createGIF(newImg, room.IsHost(u) || room.IsCoHost(u))
|
||||
|
||||
// encode to png to avoid recompression
|
||||
origBuf := new(bytes.Buffer)
|
||||
if err := png.Encode(origBuf, newImg); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
origPng := origBuf.Bytes()
|
||||
hash := sha256.Sum256(origPng)
|
||||
|
||||
// Check if user's original avatar exists
|
||||
filename := fmt.Sprintf("%x.png", hash)
|
||||
saved := u.getAvatarImagePath(filename)
|
||||
if _, err := os.Stat(saved); err != nil {
|
||||
if err := os.MkdirAll(filepath.Dir(saved), 0775); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Write user's avatar if the original version doesn't exist
|
||||
if err := os.WriteFile(saved, origPng, 0664); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
coll := mainDB.Collection(COLLECTION_USER)
|
||||
if _, err = coll.UpdateOne(ctx,
|
||||
bson.D{{Key: "audon_id", Value: u.AudonID}},
|
||||
bson.D{
|
||||
{Key: "$set", Value: bson.D{{Key: "avatar", Value: filename}}},
|
||||
}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
indicator, err := u.createGIF(newImg, room.IsHost(u) || room.IsCoHost(u))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return indicator, origPng, nil
|
||||
}
|
||||
|
||||
func (u *AudonUser) createGIF(avatar image.Image, blue bool) ([]byte, error) {
|
||||
|
@ -129,7 +141,7 @@ func (u *AudonUser) createGIF(avatar image.Image, blue bool) ([]byte, error) {
|
|||
return os.ReadFile(u.GetGIFAvatarPath())
|
||||
}
|
||||
|
||||
func (u *AudonUser) GetOriginalAvatarPath(hash [sha256.Size]byte, mtype *mimetype.MIME) string {
|
||||
func (u *AudonUser) getOriginalAvatarPath(hash [sha256.Size]byte, mtype *mimetype.MIME) string {
|
||||
filename := fmt.Sprintf("%x%s", hash, mtype.Extension())
|
||||
return u.getAvatarImagePath(filename)
|
||||
}
|
||||
|
|
7
room.go
7
room.go
|
@ -12,7 +12,6 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
@ -380,7 +379,7 @@ func joinRoomHandler(c echo.Context) (err error) {
|
|||
if user.AvatarFile != "" {
|
||||
orig, err := os.ReadFile(user.getAvatarImagePath(user.AvatarFile))
|
||||
if err == nil && orig != nil {
|
||||
resp.Original = fmt.Sprintf("data:%s;base64,%s", mimetype.Detect(orig), base64.StdEncoding.EncodeToString(orig))
|
||||
resp.Original = fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(orig))
|
||||
} else if orig == nil {
|
||||
user.AvatarFile = ""
|
||||
}
|
||||
|
@ -424,12 +423,12 @@ func joinRoomHandler(c echo.Context) (err error) {
|
|||
}
|
||||
|
||||
// Generate indicator GIF
|
||||
indicator, err := user.GetIndicator(c.Request().Context(), fnew, room)
|
||||
indicator, original, err := user.GetIndicator(c.Request().Context(), fnew, room)
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
resp.Original = fmt.Sprintf("data:%s;base64,%s", mimetype.Detect(fnew), base64.StdEncoding.EncodeToString(fnew))
|
||||
resp.Original = fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(original))
|
||||
resp.Indicator = fmt.Sprintf("data:image/gif;base64,%s", base64.StdEncoding.EncodeToString(indicator))
|
||||
} else if err != nil {
|
||||
c.Logger().Error(err)
|
||||
|
|
Ładowanie…
Reference in New Issue