Files
kefu/im/backend/internal/testusers/assets.go
T
2026-09-03 08:38:17 +08:00

58 lines
1.4 KiB
Go

package testusers
import (
"bytes"
"fmt"
"image/png"
"os"
"path/filepath"
)
// CopyAvatars validates all sources and destination collisions before copying.
// Existing identical assets are reused. Existing different files are not replaced.
func CopyAvatars(sourceDir, mediaDir string) error {
if sourceDir == "" || mediaDir == "" {
return fmt.Errorf("both avatar source and media directories are required")
}
assets := make(map[string][]byte)
for _, name := range Avatars() {
data, err := os.ReadFile(filepath.Join(sourceDir, name))
if err != nil {
return err
}
cfg, err := png.DecodeConfig(bytes.NewReader(data))
if err != nil || cfg.Width < 256 || cfg.Height < 256 {
return fmt.Errorf("invalid or undersized PNG avatar: %s", name)
}
existing, err := os.ReadFile(filepath.Join(mediaDir, name))
if err == nil {
if !bytes.Equal(existing, data) {
return fmt.Errorf("refusing to overwrite different existing avatar: %s", name)
}
continue
}
if !os.IsNotExist(err) {
return err
}
assets[name] = data
}
if err := os.MkdirAll(mediaDir, 0755); err != nil {
return err
}
for name, data := range assets {
file, err := os.OpenFile(filepath.Join(mediaDir, name), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
if err != nil {
return err
}
_, writeErr := file.Write(data)
closeErr := file.Close()
if writeErr != nil {
return writeErr
}
if closeErr != nil {
return closeErr
}
}
return nil
}