Feat: add character card support
This commit is contained in:
107
pngmeta/metareader.go
Normal file
107
pngmeta/metareader.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package pngmeta
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"elefant/models"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
embType = "tEXt"
|
||||
)
|
||||
|
||||
type PngEmbed struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (c PngEmbed) GetDecodedValue() (*models.CharCardSpec, error) {
|
||||
data, err := base64.StdEncoding.DecodeString(c.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
card := &models.CharCardSpec{}
|
||||
if err := json.Unmarshal(data, &card); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return card, nil
|
||||
}
|
||||
|
||||
func extractChar(fname string) (*PngEmbed, error) {
|
||||
data, err := os.ReadFile(fname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reader := bytes.NewReader(data)
|
||||
pr, err := NewPNGStepReader(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
step, err := pr.Next()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if step.Type() != embType {
|
||||
if _, err := io.Copy(io.Discard, step); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
buf, err := io.ReadAll(step)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataInstep := string(buf)
|
||||
values := strings.Split(dataInstep, "\x00")
|
||||
if len(values) == 2 {
|
||||
return &PngEmbed{Key: values[0], Value: values[1]}, nil
|
||||
}
|
||||
}
|
||||
if err := step.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, errors.New("failed to find embedded char in png: " + fname)
|
||||
}
|
||||
|
||||
func ReadCard(fname, uname string) (*models.CharCard, error) {
|
||||
pe, err := extractChar(fname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
charSpec, err := pe.GetDecodedValue()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return charSpec.Simplify(uname, fname), nil
|
||||
}
|
||||
|
||||
func ReadDirCards(dirname, uname string) ([]*models.CharCard, error) {
|
||||
files, err := os.ReadDir(dirname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := []*models.CharCard{}
|
||||
for _, f := range files {
|
||||
if !strings.HasSuffix(f.Name(), ".png") {
|
||||
continue
|
||||
}
|
||||
fpath := path.Join(dirname, f.Name())
|
||||
cc, err := ReadCard(fpath, uname)
|
||||
if err != nil {
|
||||
// log err
|
||||
return nil, err
|
||||
// continue
|
||||
}
|
||||
resp = append(resp, cc)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
Reference in New Issue
Block a user