libs5-go/metadata/extra.go

184 lines
4.7 KiB
Go

package metadata
import (
"encoding/json"
"fmt"
"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{}
}
type keyValue struct {
Key interface{}
Value 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 {
em.Data = make(map[int]interface{})
jsonObject := make(map[int]interface{})
if err := json.Unmarshal(data, &jsonObject); err != nil {
return err
}
for name, value := range jsonObject {
err := em.decodeItem(keyValue{Key: name, Value: value})
if err != nil {
return err
}
}
return nil
}
func (em *ExtraMetadata) decodeItem(pair keyValue) error {
var metadataKey int
// Determine the type of the key and convert it if necessary
switch k := pair.Key.(type) {
case string:
if val, ok := namesReverse[k]; ok {
metadataKey = int(val)
} else {
return fmt.Errorf("unknown key in JSON: %s", k)
}
case int8:
metadataKey = int(k)
default:
return fmt.Errorf("unsupported key type")
}
if metadataKey == int(types.MetadataExtensionUpdateCID) {
// Convert string to CID bytes for MetadataExtensionUpdateCID
cid, err := encoding.CIDFromString(pair.Value.(string))
if err != nil {
return err
}
em.Data[metadataKey] = cid
} else {
em.Data[metadataKey] = pair.Value
}
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
}
var value interface{}
if key == int8(types.MetadataExtensionUpdateCID) {
value, err = dec.DecodeString()
} else {
value, err = dec.DecodeInterface()
}
if err != nil {
return err
}
err = em.decodeItem(keyValue{Key: key, Value: value})
if err != nil {
return err
}
}
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
}