feat: wip directory metadata
This commit is contained in:
parent
eed785e1eb
commit
c2ed126ab8
|
@ -0,0 +1,92 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/serialize"
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/types"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type DirectoryMetadata struct {
|
||||
Details DirectoryMetadataDetails `json:"details"`
|
||||
Directories map[string]DirectoryReference `json:"directories"`
|
||||
Files map[string]FileReference `json:"files"`
|
||||
ExtraMetadata ExtraMetadata `json:"extraMetadata"`
|
||||
BaseMetadata
|
||||
}
|
||||
|
||||
var _ SerializableMetadata = (*DirectoryMetadata)(nil)
|
||||
|
||||
func NewDirectoryMetadata(details DirectoryMetadataDetails, directories map[string]DirectoryReference, files map[string]FileReference, extraMetadata ExtraMetadata) *DirectoryMetadata {
|
||||
dirMetadata := &DirectoryMetadata{
|
||||
Details: details,
|
||||
Directories: directories,
|
||||
Files: files,
|
||||
ExtraMetadata: extraMetadata,
|
||||
}
|
||||
|
||||
dirMetadata.Type = "directory"
|
||||
return dirMetadata
|
||||
}
|
||||
func (dm *DirectoryMetadata) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
err := serialize.InitMarshaller(types.MetadataTypeDirectory, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
items := make([]interface{}, 4)
|
||||
|
||||
items[0] = dm.Details
|
||||
items[1] = dm.Directories
|
||||
items[2] = dm.Files
|
||||
items[3] = dm.ExtraMetadata.Data
|
||||
|
||||
return enc.Encode(items)
|
||||
}
|
||||
|
||||
func (dm *DirectoryMetadata) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||
err := serialize.InitUnmarshaller(types.MetadataTypeDirectory, dec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val, err := dec.DecodeArrayLen()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if val != 4 {
|
||||
return errors.New(" Corrupted metadata")
|
||||
}
|
||||
|
||||
for i := 0; i < val; i++ {
|
||||
switch i {
|
||||
case 0:
|
||||
err = dec.Decode(&dm.Details)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case 1:
|
||||
err = dec.Decode(&dm.Directories)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case 2:
|
||||
err = dec.Decode(&dm.Files)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case 3:
|
||||
intMap, err := decodeIntMap(dec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dm.ExtraMetadata.Data = intMap
|
||||
}
|
||||
}
|
||||
|
||||
dm.Type = "directory"
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package metadata
|
||||
|
||||
import "github.com/vmihailenco/msgpack/v5"
|
||||
|
||||
type DirectoryMetadataDetails struct {
|
||||
Data map[int]interface{}
|
||||
}
|
||||
|
||||
func NewDirectoryMetadataDetails(data map[int]interface{}) *DirectoryMetadataDetails {
|
||||
return &DirectoryMetadataDetails{
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (dmd *DirectoryMetadataDetails) IsShared() bool {
|
||||
_, exists := dmd.Data[3]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (dmd *DirectoryMetadataDetails) IsSharedReadOnly() bool {
|
||||
value, exists := dmd.Data[3].([]interface{})
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
return len(value) > 1 && value[1] == true
|
||||
}
|
||||
|
||||
func (dmd *DirectoryMetadataDetails) IsSharedReadWrite() bool {
|
||||
value, exists := dmd.Data[3].([]interface{})
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
return len(value) > 2 && value[2] == true
|
||||
}
|
||||
|
||||
func (dmd *DirectoryMetadataDetails) SetShared(value bool, write bool) {
|
||||
if dmd.Data == nil {
|
||||
dmd.Data = make(map[int]interface{})
|
||||
}
|
||||
sharedValue, exists := dmd.Data[3].([]interface{})
|
||||
if !exists {
|
||||
sharedValue = make([]interface{}, 3)
|
||||
dmd.Data[3] = sharedValue
|
||||
}
|
||||
if write {
|
||||
sharedValue[2] = value
|
||||
} else {
|
||||
sharedValue[1] = value
|
||||
}
|
||||
}
|
||||
func (dmd *DirectoryMetadataDetails) 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
|
||||
}
|
||||
dmd.Data[int(key)] = value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dmd DirectoryMetadataDetails) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
return enc.Encode(dmd.Data)
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package metadata
|
||||
|
||||
import "github.com/vmihailenco/msgpack/v5"
|
||||
|
||||
var _ SerializableMetadata = (*DirectoryReference)(nil)
|
||||
|
||||
type DirectoryReference struct {
|
||||
Created uint64 `json:"created"`
|
||||
Name string `json:"name"`
|
||||
EncryptedWriteKey Base64UrlBinary `json:"encryptedWriteKey,string"`
|
||||
PublicKey Base64UrlBinary `json:"publicKey,string"`
|
||||
EncryptionKey Base64UrlBinary `json:"encryptionKey,string"`
|
||||
Ext map[string]interface{} `json:"ext"`
|
||||
URI string `json:"uri"`
|
||||
Key string `json:"key"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
func NewDirectoryReference(created uint64, name string, encryptedWriteKey, publicKey, encryptionKey []byte, ext map[string]interface{}) *DirectoryReference {
|
||||
return &DirectoryReference{
|
||||
Created: created,
|
||||
Name: name,
|
||||
EncryptedWriteKey: encryptedWriteKey,
|
||||
PublicKey: publicKey,
|
||||
EncryptionKey: encryptionKey,
|
||||
Ext: ext,
|
||||
URI: "",
|
||||
Key: "",
|
||||
Size: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (dr *DirectoryReference) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
data := map[int]interface{}{
|
||||
1: dr.Name,
|
||||
2: dr.Created,
|
||||
3: dr.PublicKey,
|
||||
4: dr.EncryptedWriteKey,
|
||||
}
|
||||
|
||||
if dr.EncryptionKey != nil {
|
||||
data[5] = dr.EncryptionKey
|
||||
}
|
||||
|
||||
if dr.Ext != nil {
|
||||
data[6] = dr.Ext
|
||||
}
|
||||
|
||||
return enc.Encode(data)
|
||||
}
|
||||
|
||||
func (dr *DirectoryReference) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||
var (
|
||||
err error
|
||||
l int
|
||||
)
|
||||
if l, err = dec.DecodeMapLen(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
key, err := dec.DecodeInt8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
value, err := dec.DecodeInterface()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch key {
|
||||
case int8(1):
|
||||
dr.Name = value.(string)
|
||||
case int8(2):
|
||||
dr.Created = value.(uint64)
|
||||
case int8(3):
|
||||
dr.PublicKey = value.([]byte)
|
||||
case int8(4):
|
||||
dr.EncryptedWriteKey = value.([]byte)
|
||||
case int8(5):
|
||||
dr.EncryptionKey = value.([]byte)
|
||||
case int8(6):
|
||||
dr.Ext = value.(map[string]interface{})
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,514 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
|
||||
cmp "github.com/LumeWeb/go-cmp"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func readFile(filename string) []byte {
|
||||
filePath := filepath.Join("testdata", filename)
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func getDirectoryMeta() *DirectoryMetadata {
|
||||
data := readFile("directory.json")
|
||||
|
||||
var dir DirectoryMetadata
|
||||
|
||||
err := json.Unmarshal(data, &dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &dir
|
||||
}
|
||||
|
||||
func TestDirectoryMetadata_DecodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Details DirectoryMetadataDetails
|
||||
Directories map[string]DirectoryReference
|
||||
Files map[string]FileReference
|
||||
ExtraMetadata ExtraMetadata
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Decode",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
jsonDm := getDirectoryMeta()
|
||||
dm := &DirectoryMetadata{}
|
||||
|
||||
if err := msgpack.Unmarshal(readFile("directory.bin"), dm); (err != nil) != tt.wantErr {
|
||||
t.Errorf("DecodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
fmt.Println(cmp.Diff(jsonDm, dm))
|
||||
if !cmp.Equal(jsonDm, dm) {
|
||||
t.Errorf("DecodeMsgpack() error = %v, wantErr %v", "msgpack does not match json", tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirectoryMetadata_EncodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Details DirectoryMetadataDetails
|
||||
Directories map[string]DirectoryReference
|
||||
Files map[string]FileReference
|
||||
ExtraMetadata ExtraMetadata
|
||||
}
|
||||
type args struct {
|
||||
enc *msgpack.Encoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dm := &DirectoryMetadata{
|
||||
Details: tt.fields.Details,
|
||||
Directories: tt.fields.Directories,
|
||||
Files: tt.fields.Files,
|
||||
ExtraMetadata: tt.fields.ExtraMetadata,
|
||||
}
|
||||
if err := dm.EncodeMsgpack(tt.args.enc); (err != nil) != tt.wantErr {
|
||||
t.Errorf("EncodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirectoryReference_DecodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Created uint64
|
||||
Name string
|
||||
EncryptedWriteKey []byte
|
||||
PublicKey []byte
|
||||
EncryptionKey []byte
|
||||
Ext map[string]interface{}
|
||||
URI string
|
||||
Key string
|
||||
Size int64
|
||||
}
|
||||
type args struct {
|
||||
dec *msgpack.Decoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dr := &DirectoryReference{
|
||||
Created: tt.fields.Created,
|
||||
Name: tt.fields.Name,
|
||||
EncryptedWriteKey: tt.fields.EncryptedWriteKey,
|
||||
PublicKey: tt.fields.PublicKey,
|
||||
EncryptionKey: tt.fields.EncryptionKey,
|
||||
Ext: tt.fields.Ext,
|
||||
URI: tt.fields.URI,
|
||||
Key: tt.fields.Key,
|
||||
Size: tt.fields.Size,
|
||||
}
|
||||
if err := dr.DecodeMsgpack(tt.args.dec); (err != nil) != tt.wantErr {
|
||||
t.Errorf("DecodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirectoryReference_EncodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Created uint64
|
||||
Name string
|
||||
EncryptedWriteKey []byte
|
||||
PublicKey []byte
|
||||
EncryptionKey []byte
|
||||
Ext map[string]interface{}
|
||||
URI string
|
||||
Key string
|
||||
Size int64
|
||||
}
|
||||
type args struct {
|
||||
enc *msgpack.Encoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dr := &DirectoryReference{
|
||||
Created: tt.fields.Created,
|
||||
Name: tt.fields.Name,
|
||||
EncryptedWriteKey: tt.fields.EncryptedWriteKey,
|
||||
PublicKey: tt.fields.PublicKey,
|
||||
EncryptionKey: tt.fields.EncryptionKey,
|
||||
Ext: tt.fields.Ext,
|
||||
URI: tt.fields.URI,
|
||||
Key: tt.fields.Key,
|
||||
Size: tt.fields.Size,
|
||||
}
|
||||
if err := dr.EncodeMsgpack(tt.args.enc); (err != nil) != tt.wantErr {
|
||||
t.Errorf("EncodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileReference_DecodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Name string
|
||||
Created int
|
||||
Version int
|
||||
File *FileVersion
|
||||
Ext map[string]interface{}
|
||||
History map[int]*FileVersion
|
||||
MimeType string
|
||||
URI string
|
||||
Key string
|
||||
}
|
||||
type args struct {
|
||||
dec *msgpack.Decoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fr := &FileReference{
|
||||
Name: tt.fields.Name,
|
||||
Created: tt.fields.Created,
|
||||
Version: tt.fields.Version,
|
||||
File: tt.fields.File,
|
||||
Ext: tt.fields.Ext,
|
||||
History: tt.fields.History,
|
||||
MimeType: tt.fields.MimeType,
|
||||
URI: tt.fields.URI,
|
||||
Key: tt.fields.Key,
|
||||
}
|
||||
if err := fr.DecodeMsgpack(tt.args.dec); (err != nil) != tt.wantErr {
|
||||
t.Errorf("DecodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileReference_EncodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Name string
|
||||
Created int
|
||||
Version int
|
||||
File *FileVersion
|
||||
Ext map[string]interface{}
|
||||
History map[int]*FileVersion
|
||||
MimeType string
|
||||
URI string
|
||||
Key string
|
||||
}
|
||||
type args struct {
|
||||
enc *msgpack.Encoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fr := &FileReference{
|
||||
Name: tt.fields.Name,
|
||||
Created: tt.fields.Created,
|
||||
Version: tt.fields.Version,
|
||||
File: tt.fields.File,
|
||||
Ext: tt.fields.Ext,
|
||||
History: tt.fields.History,
|
||||
MimeType: tt.fields.MimeType,
|
||||
URI: tt.fields.URI,
|
||||
Key: tt.fields.Key,
|
||||
}
|
||||
if err := fr.EncodeMsgpack(tt.args.enc); (err != nil) != tt.wantErr {
|
||||
t.Errorf("EncodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileReference_Modified(t *testing.T) {
|
||||
type fields struct {
|
||||
Name string
|
||||
Created int
|
||||
Version int
|
||||
File *FileVersion
|
||||
Ext map[string]interface{}
|
||||
History map[int]*FileVersion
|
||||
MimeType string
|
||||
URI string
|
||||
Key string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want int
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fr := &FileReference{
|
||||
Name: tt.fields.Name,
|
||||
Created: tt.fields.Created,
|
||||
Version: tt.fields.Version,
|
||||
File: tt.fields.File,
|
||||
Ext: tt.fields.Ext,
|
||||
History: tt.fields.History,
|
||||
MimeType: tt.fields.MimeType,
|
||||
URI: tt.fields.URI,
|
||||
Key: tt.fields.Key,
|
||||
}
|
||||
if got := fr.Modified(); got != tt.want {
|
||||
t.Errorf("Modified() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileVersionThumbnail_DecodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
ImageType string
|
||||
AspectRatio float64
|
||||
CID *encoding.EncryptedCID
|
||||
Thumbhash []byte
|
||||
}
|
||||
type args struct {
|
||||
dec *msgpack.Decoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fvt := &FileVersionThumbnail{
|
||||
ImageType: tt.fields.ImageType,
|
||||
AspectRatio: tt.fields.AspectRatio,
|
||||
CID: tt.fields.CID,
|
||||
Thumbhash: tt.fields.Thumbhash,
|
||||
}
|
||||
if err := fvt.DecodeMsgpack(tt.args.dec); (err != nil) != tt.wantErr {
|
||||
t.Errorf("DecodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileVersionThumbnail_Encode(t *testing.T) {
|
||||
type fields struct {
|
||||
ImageType string
|
||||
AspectRatio float64
|
||||
CID *encoding.EncryptedCID
|
||||
Thumbhash []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want map[int]interface{}
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fvt := &FileVersionThumbnail{
|
||||
ImageType: tt.fields.ImageType,
|
||||
AspectRatio: tt.fields.AspectRatio,
|
||||
CID: tt.fields.CID,
|
||||
Thumbhash: tt.fields.Thumbhash,
|
||||
}
|
||||
if got := fvt.Encode(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Encode() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileVersionThumbnail_EncodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
ImageType string
|
||||
AspectRatio float64
|
||||
CID *encoding.EncryptedCID
|
||||
Thumbhash []byte
|
||||
}
|
||||
type args struct {
|
||||
enc *msgpack.Encoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fvt := &FileVersionThumbnail{
|
||||
ImageType: tt.fields.ImageType,
|
||||
AspectRatio: tt.fields.AspectRatio,
|
||||
CID: tt.fields.CID,
|
||||
Thumbhash: tt.fields.Thumbhash,
|
||||
}
|
||||
if err := fvt.EncodeMsgpack(tt.args.enc); (err != nil) != tt.wantErr {
|
||||
t.Errorf("EncodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileVersion_CID(t *testing.T) {
|
||||
type fields struct {
|
||||
Ts int
|
||||
EncryptedCID *encoding.EncryptedCID
|
||||
PlaintextCID *encoding.CID
|
||||
Thumbnail *FileVersionThumbnail
|
||||
Hashes []*encoding.Multihash
|
||||
Ext map[string]interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want *encoding.CID
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fv := &FileVersion{
|
||||
Ts: tt.fields.Ts,
|
||||
EncryptedCID: tt.fields.EncryptedCID,
|
||||
PlaintextCID: tt.fields.PlaintextCID,
|
||||
Thumbnail: tt.fields.Thumbnail,
|
||||
Hashes: tt.fields.Hashes,
|
||||
Ext: tt.fields.Ext,
|
||||
}
|
||||
if got := fv.CID(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("CID() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileVersion_DecodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Ts int
|
||||
EncryptedCID *encoding.EncryptedCID
|
||||
PlaintextCID *encoding.CID
|
||||
Thumbnail *FileVersionThumbnail
|
||||
Hashes []*encoding.Multihash
|
||||
Ext map[string]interface{}
|
||||
}
|
||||
type args struct {
|
||||
dec *msgpack.Decoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fv := &FileVersion{
|
||||
Ts: tt.fields.Ts,
|
||||
EncryptedCID: tt.fields.EncryptedCID,
|
||||
PlaintextCID: tt.fields.PlaintextCID,
|
||||
Thumbnail: tt.fields.Thumbnail,
|
||||
Hashes: tt.fields.Hashes,
|
||||
Ext: tt.fields.Ext,
|
||||
}
|
||||
if err := fv.DecodeMsgpack(tt.args.dec); (err != nil) != tt.wantErr {
|
||||
t.Errorf("DecodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileVersion_EncodeMsgpack(t *testing.T) {
|
||||
type fields struct {
|
||||
Ts int
|
||||
EncryptedCID *encoding.EncryptedCID
|
||||
PlaintextCID *encoding.CID
|
||||
Thumbnail *FileVersionThumbnail
|
||||
Hashes []*encoding.Multihash
|
||||
Ext map[string]interface{}
|
||||
}
|
||||
type args struct {
|
||||
enc *msgpack.Encoder
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fv := &FileVersion{
|
||||
Ts: tt.fields.Ts,
|
||||
EncryptedCID: tt.fields.EncryptedCID,
|
||||
PlaintextCID: tt.fields.PlaintextCID,
|
||||
Thumbnail: tt.fields.Thumbnail,
|
||||
Hashes: tt.fields.Hashes,
|
||||
Ext: tt.fields.Ext,
|
||||
}
|
||||
if err := fv.EncodeMsgpack(tt.args.enc); (err != nil) != tt.wantErr {
|
||||
t.Errorf("EncodeMsgpack() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/types"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type ExtraMetadata struct {
|
||||
Data map[int]interface{}
|
||||
}
|
||||
|
||||
func NewExtraMetadata(data map[int]interface{}) *ExtraMetadata {
|
||||
return &ExtraMetadata{
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (em *ExtraMetadata) ToJSON() map[string]interface{} {
|
||||
jsonObject := make(map[string]interface{})
|
||||
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",
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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 {
|
||||
return enc.Encode(em.Data)
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package metadata
|
||||
|
||||
import "github.com/vmihailenco/msgpack/v5"
|
||||
|
||||
var _ SerializableMetadata = (*FileReference)(nil)
|
||||
|
||||
type FileReference struct {
|
||||
Name string `json:"name"`
|
||||
Created int `json:"created"`
|
||||
Version int `json:"version"`
|
||||
File *FileVersion `json:"file"`
|
||||
Ext map[string]interface{} `json:"ext"`
|
||||
History map[int]*FileVersion `json:"history"`
|
||||
MimeType string `json:"mimeType"`
|
||||
URI string `json:"uri"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
func NewFileReference(name string, created, version int, file *FileVersion, ext map[string]interface{}, history map[int]*FileVersion, mimeType string) *FileReference {
|
||||
return &FileReference{
|
||||
Name: name,
|
||||
Created: created,
|
||||
Version: version,
|
||||
File: file,
|
||||
Ext: ext,
|
||||
History: history,
|
||||
MimeType: mimeType,
|
||||
URI: "",
|
||||
Key: "",
|
||||
}
|
||||
}
|
||||
|
||||
func (fr *FileReference) Modified() int {
|
||||
return fr.File.Ts
|
||||
}
|
||||
|
||||
func (fr *FileReference) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
data := map[int]interface{}{
|
||||
1: fr.Name,
|
||||
2: fr.Created,
|
||||
4: fr.File,
|
||||
5: fr.Version,
|
||||
}
|
||||
|
||||
if fr.MimeType != "" {
|
||||
data[6] = fr.MimeType
|
||||
}
|
||||
|
||||
if fr.Ext != nil {
|
||||
data[7] = fr.Ext
|
||||
}
|
||||
|
||||
if fr.History != nil {
|
||||
historyData := make(map[int]interface{})
|
||||
for key, value := range fr.History {
|
||||
historyData[key] = value
|
||||
}
|
||||
data[8] = historyData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (fr *FileReference) 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
|
||||
}
|
||||
|
||||
switch key {
|
||||
case int8(1):
|
||||
err := dec.Decode(&fr.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(2):
|
||||
err := dec.Decode(&fr.Created)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(4):
|
||||
err := dec.Decode(&fr.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(5):
|
||||
val, err := dec.DecodeInt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fr.Version = val
|
||||
case int8(6):
|
||||
err := dec.Decode(&fr.MimeType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(7):
|
||||
err := dec.Decode(&fr.Ext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(8):
|
||||
historyDataLen, err := dec.DecodeMapLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fr.History = make(map[int]*FileVersion, historyDataLen)
|
||||
for range fr.History {
|
||||
k, err := dec.DecodeInt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var fileVersion FileVersion
|
||||
err = dec.Decode(&fileVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fr.History[k] = &fileVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type FileVersion struct {
|
||||
Ts int `json:"ts"`
|
||||
EncryptedCID *encoding.EncryptedCID `json:"encryptedCID,string"`
|
||||
PlaintextCID *encoding.CID `json:"plaintextCID,string"`
|
||||
Thumbnail *FileVersionThumbnail `json:"thumbnail"`
|
||||
Hashes []*encoding.Multihash `json:"hashes"`
|
||||
Ext map[string]interface{} `json:"ext"`
|
||||
}
|
||||
|
||||
func NewFileVersion(ts int, encryptedCID *encoding.EncryptedCID, plaintextCID *encoding.CID, thumbnail *FileVersionThumbnail, hashes []*encoding.Multihash, ext map[string]interface{}) *FileVersion {
|
||||
return &FileVersion{
|
||||
Ts: ts,
|
||||
EncryptedCID: encryptedCID,
|
||||
PlaintextCID: plaintextCID,
|
||||
Thumbnail: thumbnail,
|
||||
Hashes: hashes,
|
||||
Ext: ext,
|
||||
}
|
||||
}
|
||||
|
||||
func (fv *FileVersion) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
data := map[int]interface{}{
|
||||
8: fv.Ts,
|
||||
}
|
||||
|
||||
if fv.EncryptedCID != nil {
|
||||
data[1] = fv.EncryptedCID.ToBytes()
|
||||
}
|
||||
|
||||
if fv.PlaintextCID != nil {
|
||||
data[2] = fv.PlaintextCID.ToBytes()
|
||||
}
|
||||
|
||||
if len(fv.Hashes) > 0 {
|
||||
hashesData := make([][]byte, len(fv.Hashes))
|
||||
for i, hash := range fv.Hashes {
|
||||
hashesData[i] = hash.FullBytes
|
||||
}
|
||||
data[9] = hashesData
|
||||
}
|
||||
|
||||
if fv.Thumbnail != nil {
|
||||
data[10] = fv.Thumbnail.Encode()
|
||||
}
|
||||
|
||||
return enc.Encode(data)
|
||||
}
|
||||
|
||||
func (fv *FileVersion) 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
|
||||
}
|
||||
switch key {
|
||||
|
||||
case int8(1):
|
||||
err := dec.Decode(&fv.EncryptedCID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case int8(2):
|
||||
err := dec.Decode(&fv.PlaintextCID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(8):
|
||||
err := dec.Decode(&fv.Ts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(9):
|
||||
hashesData, err := dec.DecodeSlice()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fv.Hashes = make([]*encoding.Multihash, len(hashesData))
|
||||
for i, hashData := range hashesData {
|
||||
hashBytes := hashData.([]byte)
|
||||
fv.Hashes[i] = encoding.NewMultihash(hashBytes)
|
||||
}
|
||||
|
||||
case int8(10):
|
||||
err := dec.Decode(&fv.Thumbnail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fv *FileVersion) CID() *encoding.CID {
|
||||
if fv.PlaintextCID != nil {
|
||||
return fv.PlaintextCID
|
||||
}
|
||||
return &fv.EncryptedCID.OriginalCID
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type FileVersionThumbnail struct {
|
||||
ImageType string
|
||||
AspectRatio float64
|
||||
CID *encoding.EncryptedCID
|
||||
Thumbhash []byte
|
||||
}
|
||||
|
||||
func NewFileVersionThumbnail(imageType string, aspectRatio float64, cid *encoding.EncryptedCID, thumbhash []byte) *FileVersionThumbnail {
|
||||
return &FileVersionThumbnail{
|
||||
ImageType: imageType,
|
||||
AspectRatio: aspectRatio,
|
||||
CID: cid,
|
||||
Thumbhash: thumbhash,
|
||||
}
|
||||
}
|
||||
|
||||
func (fvt *FileVersionThumbnail) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||
data := map[int]interface{}{
|
||||
2: fvt.AspectRatio,
|
||||
3: fvt.CID.ToBytes(),
|
||||
}
|
||||
|
||||
if fvt.ImageType != "" {
|
||||
data[1] = fvt.ImageType
|
||||
}
|
||||
|
||||
if fvt.Thumbhash != nil {
|
||||
data[4] = fvt.Thumbhash
|
||||
}
|
||||
|
||||
return enc.Encode(data)
|
||||
}
|
||||
func (fvt *FileVersionThumbnail) 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
|
||||
}
|
||||
switch key {
|
||||
case int8(1):
|
||||
err := dec.Decode(&fvt.ImageType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(2):
|
||||
err := dec.Decode(&fvt.AspectRatio)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case int8(3):
|
||||
val, err := dec.DecodeBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fvt.CID, err = encoding.EncryptedCIDFromBytes(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case int8(4):
|
||||
err := dec.Decode(&fvt.Thumbhash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (fvt *FileVersionThumbnail) Encode() map[int]interface{} {
|
||||
data := map[int]interface{}{
|
||||
2: fvt.AspectRatio,
|
||||
3: fvt.CID.ToBytes(),
|
||||
}
|
||||
|
||||
if fvt.ImageType != "" {
|
||||
data[1] = fvt.ImageType
|
||||
}
|
||||
|
||||
if fvt.Thumbhash != nil {
|
||||
data[4] = fvt.Thumbhash
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package metadata
|
||||
|
||||
import "github.com/vmihailenco/msgpack/v5"
|
||||
|
||||
type Metadata interface {
|
||||
}
|
||||
type SerializableMetadata interface {
|
||||
msgpack.CustomEncoder
|
||||
msgpack.CustomDecoder
|
||||
}
|
||||
|
||||
type BaseMetadata struct {
|
||||
Type string `json:"type"`
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type Base64UrlBinary []byte
|
||||
|
||||
func (b *Base64UrlBinary) UnmarshalJSON(data []byte) error {
|
||||
strData := string(data)
|
||||
if len(strData) >= 2 && strData[0] == '"' && strData[len(strData)-1] == '"' {
|
||||
strData = strData[1 : len(strData)-1]
|
||||
}
|
||||
|
||||
if strData == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
decodedData, err := base64.RawURLEncoding.DecodeString(strData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*b = (decodedData)
|
||||
return nil
|
||||
}
|
||||
func (b Base64UrlBinary) MarshalJSON() ([]byte, error) {
|
||||
return []byte(base64.RawURLEncoding.EncodeToString(b)), nil
|
||||
|
||||
}
|
||||
|
||||
func decodeIntMap(dec *msgpack.Decoder) (map[int]interface{}, error) {
|
||||
mapLen, err := dec.DecodeMapLen()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make(map[int]interface{}, mapLen)
|
||||
|
||||
for i := 0; i < mapLen; i++ {
|
||||
key, err := dec.DecodeInt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err := dec.DecodeInterface()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data[key] = value
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,193 @@
|
|||
{
|
||||
"type": "directory",
|
||||
"details": {},
|
||||
"directories": {
|
||||
"arch": {
|
||||
"name": "arch",
|
||||
"created": 1704127624979,
|
||||
"publicKey": "7Vd1kAf0LoYmKKQ9-C8Znl0npyjK2M4-ciiNWShOTpbD",
|
||||
"encryptedWriteKey": "",
|
||||
"encryptionKey": null,
|
||||
"ext": null
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
"archlinux-bootstrap-x86_64.tar.gz": {
|
||||
"name": "archlinux-bootstrap-x86_64.tar.gz",
|
||||
"created": 1704127689514,
|
||||
"modified": 1704127689514,
|
||||
"version": 0,
|
||||
"mimeType": null,
|
||||
"file": {
|
||||
"ts": 1704127689514,
|
||||
"encryptedCID": null,
|
||||
"cid": "z6e5xDpewiueHz6n9HJz21uGmTDvvctawujzYSeu9773k8s9RkG8a",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-bootstrap-x86_64.tar.gz.sig": {
|
||||
"name": "archlinux-bootstrap-x86_64.tar.gz.sig",
|
||||
"created": 1704127698951,
|
||||
"modified": 1704127698951,
|
||||
"version": 0,
|
||||
"mimeType": "application/pgp-signature",
|
||||
"file": {
|
||||
"ts": 1704127698951,
|
||||
"encryptedCID": null,
|
||||
"cid": "z4odYNo3uQhHhypXze7ThLAKrnSGsJ3cRf1bYsvnt65Mqi9gp",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-x86_64.iso": {
|
||||
"name": "archlinux-x86_64.iso",
|
||||
"created": 1704127623412,
|
||||
"modified": 1704127623412,
|
||||
"version": 0,
|
||||
"mimeType": "application/x-iso9660-image",
|
||||
"file": {
|
||||
"ts": 1704127623412,
|
||||
"encryptedCID": null,
|
||||
"cid": "z6e5sRB3BeynWLyrzRPLWFetUS7PNDZWZHURnFAyikcRyGTnxjMwC",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-x86_64.iso.sig": {
|
||||
"name": "archlinux-x86_64.iso.sig",
|
||||
"created": 1704127698648,
|
||||
"modified": 1704127698648,
|
||||
"version": 0,
|
||||
"mimeType": "application/pgp-signature",
|
||||
"file": {
|
||||
"ts": 1704127698648,
|
||||
"encryptedCID": null,
|
||||
"cid": "z4odLKvhW8QPH4dLNqVzU1Zq6nj1MBdU6HYpJmThdzag4RJma",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-2024.01.01-x86_64.iso": {
|
||||
"name": "archlinux-2024.01.01-x86_64.iso",
|
||||
"created": 1704127623412,
|
||||
"modified": 1704127623412,
|
||||
"version": 0,
|
||||
"mimeType": "application/x-iso9660-image",
|
||||
"file": {
|
||||
"ts": 1704127623412,
|
||||
"encryptedCID": null,
|
||||
"cid": "z6e5sRB3BeynWLyrzRPLWFetUS7PNDZWZHURnFAyikcRyGTnxjMwC",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-2024.01.01-x86_64.iso.sig": {
|
||||
"name": "archlinux-2024.01.01-x86_64.iso.sig",
|
||||
"created": 1704127698648,
|
||||
"modified": 1704127698648,
|
||||
"version": 0,
|
||||
"mimeType": "application/pgp-signature",
|
||||
"file": {
|
||||
"ts": 1704127698648,
|
||||
"encryptedCID": null,
|
||||
"cid": "z4odLKvhW8QPH4dLNqVzU1Zq6nj1MBdU6HYpJmThdzag4RJma",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-2024.01.01-x86_64.iso.torrent": {
|
||||
"name": "archlinux-2024.01.01-x86_64.iso.torrent",
|
||||
"created": 1704127703578,
|
||||
"modified": 1704127703578,
|
||||
"version": 0,
|
||||
"mimeType": "application/x-bittorrent",
|
||||
"file": {
|
||||
"ts": 1704127703578,
|
||||
"encryptedCID": null,
|
||||
"cid": "zHnmSZc3qDZMGfhNaZ6iVjkbxeVzMonKtAnTmBtRSwXy7RLYQK",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-bootstrap-2024.01.01-x86_64.tar.gz": {
|
||||
"name": "archlinux-bootstrap-2024.01.01-x86_64.tar.gz",
|
||||
"created": 1704127689514,
|
||||
"modified": 1704127689514,
|
||||
"version": 0,
|
||||
"mimeType": null,
|
||||
"file": {
|
||||
"ts": 1704127689514,
|
||||
"encryptedCID": null,
|
||||
"cid": "z6e5xDpewiueHz6n9HJz21uGmTDvvctawujzYSeu9773k8s9RkG8a",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"archlinux-bootstrap-2024.01.01-x86_64.tar.gz.sig": {
|
||||
"name": "archlinux-bootstrap-2024.01.01-x86_64.tar.gz.sig",
|
||||
"created": 1704127698951,
|
||||
"modified": 1704127698951,
|
||||
"version": 0,
|
||||
"mimeType": "application/pgp-signature",
|
||||
"file": {
|
||||
"ts": 1704127698951,
|
||||
"encryptedCID": null,
|
||||
"cid": "z4odYNo3uQhHhypXze7ThLAKrnSGsJ3cRf1bYsvnt65Mqi9gp",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"b2sums.txt": {
|
||||
"name": "b2sums.txt",
|
||||
"created": 1704127703594,
|
||||
"modified": 1704127703594,
|
||||
"version": 0,
|
||||
"mimeType": "text/plain",
|
||||
"file": {
|
||||
"ts": 1704127703594,
|
||||
"encryptedCID": null,
|
||||
"cid": "zHnoyywarEZHWrSMZjL55nXeMAPsYi1mhXQs7ZmWqkpSg5Auz1",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
},
|
||||
"sha256sums.txt": {
|
||||
"name": "sha256sums.txt",
|
||||
"created": 1704127703591,
|
||||
"modified": 1704127703591,
|
||||
"version": 0,
|
||||
"mimeType": "text/plain",
|
||||
"file": {
|
||||
"ts": 1704127703591,
|
||||
"encryptedCID": null,
|
||||
"cid": "zHnnZGvqwnoN2AE342zhrxGWnuJpv79esruhY259TkXYyqmPB6",
|
||||
"hashes": null,
|
||||
"thumbnail": null
|
||||
},
|
||||
"ext": null,
|
||||
"history": null
|
||||
}
|
||||
},
|
||||
"extraMetadata": {}
|
||||
}
|
Loading…
Reference in New Issue