libs5-go/metadata/extra.go

151 lines
4.1 KiB
Go

package metadata
import (
"encoding/json"
"errors"
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
"git.lumeweb.com/LumeWeb/libs5-go/types"
"github.com/vmihailenco/msgpack/v5"
)
type jsonData = map[string]interface{}
var names = map[types.MetadataExtension]string{
types.MetadataExtensionLicenses: "licenses",
types.MetadataExtensionDonationKeys: "donationKeys",
types.MetadataExtensionWikidataClaims: "wikidataClaims",
types.MetadataExtensionLanguages: "languages",
types.MetadataExtensionSourceUris: "sourceUris",
types.MetadataExtensionPreviousVersions: "previousVersions",
types.MetadataExtensionTimestamp: "timestamp",
types.MetadataExtensionOriginalTimestamp: "originalTimestamp",
types.MetadataExtensionTags: "tags",
types.MetadataExtensionCategories: "categories",
types.MetadataExtensionBasicMediaMetadata: "basicMediaMetadata",
types.MetadataExtensionViewTypes: "viewTypes",
types.MetadataExtensionBridge: "bridge",
types.MetadataExtensionRoutingHints: "routingHints",
}
var namesReverse = map[string]types.MetadataExtension{
"licenses": types.MetadataExtensionLicenses,
"donationKeys": types.MetadataExtensionDonationKeys,
"wikidataClaims": types.MetadataExtensionWikidataClaims,
"languages": types.MetadataExtensionLanguages,
"sourceUris": types.MetadataExtensionSourceUris,
"previousVersions": types.MetadataExtensionPreviousVersions,
"timestamp": types.MetadataExtensionTimestamp,
"originalTimestamp": types.MetadataExtensionOriginalTimestamp,
"tags": types.MetadataExtensionTags,
"categories": types.MetadataExtensionCategories,
"basicMediaMetadata": types.MetadataExtensionBasicMediaMetadata,
"viewTypes": types.MetadataExtensionViewTypes,
"bridge": types.MetadataExtensionBridge,
"routingHints": types.MetadataExtensionRoutingHints,
}
type ExtraMetadata struct {
Data map[int]interface{}
}
var _ SerializableMetadata = (*ExtraMetadata)(nil)
func NewExtraMetadata(data map[int]interface{}) *ExtraMetadata {
return &ExtraMetadata{
Data: data,
}
}
func (em ExtraMetadata) MarshalJSON() ([]byte, error) {
data, err := em.encode()
if err != nil {
return nil, err
}
return json.Marshal(data)
}
func (em *ExtraMetadata) UnmarshalJSON(data []byte) error {
// Intermediate representation of the expected JSON structure
jsonObject := make(map[string]interface{})
if err := json.Unmarshal(data, &jsonObject); err != nil {
return err
}
em.Data = make(map[int]interface{})
for name, value := range jsonObject {
if key, ok := namesReverse[name]; ok {
if key == types.MetadataExtensionUpdateCID {
// Convert string back to CID bytes
cid, err := encoding.Decode(value.(string))
if err != nil {
return err
}
em.Data[int(key)] = cid
} else {
em.Data[int(key)] = value
}
} else {
return errors.New("unknown key in JSON: " + name)
}
}
return nil
}
func (em *ExtraMetadata) DecodeMsgpack(dec *msgpack.Decoder) error {
mapLen, err := dec.DecodeMapLen()
if err != nil {
return err
}
for i := 0; i < mapLen; i++ {
key, err := dec.DecodeInt8()
if err != nil {
return err
}
value, err := dec.DecodeInterface()
if err != nil {
return err
}
em.Data[int(key)] = value
}
return nil
}
func (em ExtraMetadata) EncodeMsgpack(enc *msgpack.Encoder) error {
data, err := em.encode()
if err != nil {
return err
}
return enc.Encode(data)
}
func (em ExtraMetadata) encode() (jsonData, error) {
jsonObject := make(map[string]interface{})
for key, value := range em.Data {
name, ok := names[types.MetadataExtension(key)]
if ok {
if types.MetadataExtension(key) == types.MetadataExtensionUpdateCID {
cid, err := encoding.CIDFromBytes(value.([]byte))
var cidString string
if err == nil {
cidString, err = cid.ToString()
}
if err == nil {
jsonObject["updateCID"] = cidString
} else {
jsonObject["updateCID"] = ""
}
} else {
jsonObject[name] = value
}
}
}
return jsonObject, nil
}