Add support for import/export of profile icon
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/vincent-petithory/dataurl"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/safing/portbase/database"
|
||||
"github.com/safing/portbase/database/record"
|
||||
)
|
||||
|
||||
// Icon describes an icon.
|
||||
@@ -58,3 +65,68 @@ func sortAndCompactIcons(icons []Icon) []Icon {
|
||||
|
||||
return icons
|
||||
}
|
||||
|
||||
// GetIconAsDataURL returns the icon data as a data URL.
|
||||
func (icon *Icon) GetIconAsDataURL() (bloburl string, err error) {
|
||||
switch icon.Type {
|
||||
case IconTypeFile:
|
||||
return "", errors.New("getting icon from file is not supported")
|
||||
|
||||
case IconTypeDatabase:
|
||||
if !strings.HasPrefix(icon.Value, "cache:icons/") {
|
||||
return "", errors.New("invalid icon db key")
|
||||
}
|
||||
r, err := iconDB.Get(icon.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
dbIcon, err := EnsureIconInDatabase(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return dbIcon.IconData, nil
|
||||
|
||||
case IconTypeAPI:
|
||||
data, err := GetProfileIcon(icon.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return dataurl.EncodeBytes(data), nil
|
||||
|
||||
default:
|
||||
return "", errors.New("unknown icon type")
|
||||
}
|
||||
}
|
||||
|
||||
var iconDB = database.NewInterface(&database.Options{
|
||||
Local: true,
|
||||
Internal: true,
|
||||
})
|
||||
|
||||
type IconInDatabase struct {
|
||||
sync.Mutex
|
||||
record.Base
|
||||
|
||||
IconData string `json:"iconData,omitempty"` // DataURL
|
||||
}
|
||||
|
||||
// EnsureIconInDatabase ensures that the given record is a *IconInDatabase, and returns it.
|
||||
func EnsureIconInDatabase(r record.Record) (*IconInDatabase, error) {
|
||||
// unwrap
|
||||
if r.IsWrapped() {
|
||||
// only allocate a new struct, if we need it
|
||||
newIcon := &IconInDatabase{}
|
||||
err := record.Unwrap(r, newIcon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newIcon, nil
|
||||
}
|
||||
|
||||
// or adjust type
|
||||
newIcon, ok := r.(*IconInDatabase)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("record not of type *IconInDatabase, but %T", r)
|
||||
}
|
||||
return newIcon, nil
|
||||
}
|
||||
|
||||
@@ -17,6 +17,11 @@ var profileIconStoragePath = ""
|
||||
|
||||
// GetProfileIcon returns the profile icon with the given ID and extension.
|
||||
func GetProfileIcon(name string) (data []byte, err error) {
|
||||
// Check if enabled.
|
||||
if profileIconStoragePath == "" {
|
||||
return nil, errors.New("api icon storage not configured")
|
||||
}
|
||||
|
||||
// Build storage path.
|
||||
iconPath := filepath.Clean(
|
||||
filepath.Join(profileIconStoragePath, name),
|
||||
|
||||
Reference in New Issue
Block a user