diff --git a/drivers/alist_v3/driver.go b/drivers/alist_v3/driver.go index 75208408..e2deabac 100644 --- a/drivers/alist_v3/driver.go +++ b/drivers/alist_v3/driver.go @@ -94,8 +94,10 @@ func (d *AListV3) List(ctx context.Context, dir model.Obj, args model.ListArgs) Object: model.Object{ Name: f.Name, Modified: f.Modified, + Ctime: f.Created, Size: f.Size, IsFolder: f.IsDir, + HashInfo: utils.FromString(f.HashInfo), }, Thumbnail: model.Thumbnail{Thumbnail: f.Thumb}, } diff --git a/drivers/alist_v3/types.go b/drivers/alist_v3/types.go index 77801254..e517307f 100644 --- a/drivers/alist_v3/types.go +++ b/drivers/alist_v3/types.go @@ -18,9 +18,11 @@ type ObjResp struct { Size int64 `json:"size"` IsDir bool `json:"is_dir"` Modified time.Time `json:"modified"` + Created time.Time `json:"created"` Sign string `json:"sign"` Thumb string `json:"thumb"` Type int `json:"type"` + HashInfo string `json:"hashinfo"` } type FsListResp struct { diff --git a/drivers/aliyundrive_share/types.go b/drivers/aliyundrive_share/types.go index 97b6b7cf..bb9be800 100644 --- a/drivers/aliyundrive_share/types.go +++ b/drivers/aliyundrive_share/types.go @@ -44,6 +44,7 @@ func fileToObj(f File) *model.ObjThumb { Name: f.Name, Size: f.Size, Modified: f.UpdatedAt, + Ctime: f.CreatedAt, IsFolder: f.Type == "folder", }, Thumbnail: model.Thumbnail{Thumbnail: f.Thumbnail}, diff --git a/drivers/local/driver.go b/drivers/local/driver.go index 6dc05f59..04604366 100644 --- a/drivers/local/driver.go +++ b/drivers/local/driver.go @@ -12,6 +12,7 @@ import ( "path/filepath" "strconv" "strings" + "time" "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/driver" @@ -103,7 +104,7 @@ func (d *Local) FileInfoToObj(f fs.FileInfo, reqPath string, fullPath string) mo if !isFolder { size = f.Size() } - ctime := f.ModTime() + var ctime time.Time t, err := times.Stat(stdpath.Join(fullPath, f.Name())) if err == nil { if t.HasBirthTime() { @@ -155,10 +156,18 @@ func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) { if isFolder { size = 0 } + var ctime time.Time + t, err := times.Stat(path) + if err == nil { + if t.HasBirthTime() { + ctime = t.BirthTime() + } + } file := model.Object{ Path: path, Name: f.Name(), Modified: f.ModTime(), + Ctime: ctime, Size: size, IsFolder: isFolder, } diff --git a/pkg/utils/hash.go b/pkg/utils/hash.go index cd1a4b0a..ae025a7e 100644 --- a/pkg/utils/hash.go +++ b/pkg/utils/hash.go @@ -4,12 +4,14 @@ import ( "crypto/md5" "crypto/sha1" "crypto/sha256" + "encoding" "encoding/hex" + "encoding/json" "errors" "github.com/alist-org/alist/v3/internal/errs" + log "github.com/sirupsen/logrus" "hash" "io" - "strings" ) func GetMD5EncodeStr(data string) string { @@ -30,6 +32,23 @@ type HashType struct { NewFunc func() hash.Hash } +func (ht *HashType) MarshalJSON() ([]byte, error) { + return []byte(`"` + ht.Name + `"`), nil +} + +func (ht *HashType) MarshalText() (text []byte, err error) { + return []byte(ht.Name), nil +} + +var ( + _ json.Marshaler = (*HashType)(nil) + //_ json.Unmarshaler = (*HashType)(nil) + + // read/write from/to json keys + _ encoding.TextMarshaler = (*HashType)(nil) + //_ encoding.TextUnmarshaler = (*HashType)(nil) +) + var ( name2hash = map[string]*HashType{} alias2hash = map[string]*HashType{} @@ -158,23 +177,39 @@ func (m *MultiHasher) Size() int64 { // A HashInfo contains hash string for one or more hashType type HashInfo struct { - h map[*HashType]string + h map[*HashType]string `json:"hashInfo"` } func NewHashInfo(ht *HashType, str string) HashInfo { m := make(map[*HashType]string) - m[ht] = str + if ht != nil { + m[ht] = str + } return HashInfo{h: m} } func (hi HashInfo) String() string { - var tmp []string - for ht, str := range hi.h { - if len(str) > 0 { - tmp = append(tmp, ht.Name+":"+str) + result, err := json.Marshal(hi.h) + if err != nil { + return "" + } + return string(result) +} +func FromString(str string) HashInfo { + hi := NewHashInfo(nil, "") + var tmp map[string]string + err := json.Unmarshal([]byte(str), &tmp) + if err != nil { + log.Warnf("failed to unmarsh HashInfo from string=%s", str) + } else { + for k, v := range tmp { + if name2hash[k] != nil && len(v) > 0 { + hi.h[name2hash[k]] = v + } } } - return strings.Join(tmp, "\n") + + return hi } func (hi HashInfo) GetHash(ht *HashType) string { return hi.h[ht] diff --git a/pkg/utils/hash_test.go b/pkg/utils/hash_test.go index 64ff9cfd..55713c1a 100644 --- a/pkg/utils/hash_test.go +++ b/pkg/utils/hash_test.go @@ -58,7 +58,10 @@ func TestMultiHasher(t *testing.T) { } expect := hashInfo.GetHash(nil) require.True(t, len(expect) == 0, "unknown type should return empty string") - Log.Info(hashInfo.String()) + str := hashInfo.String() + Log.Info("str=" + str) + newHi := FromString(str) + assert.Equal(t, newHi.h, hashInfo.h) } } diff --git a/server/handles/fsread.go b/server/handles/fsread.go index cd376723..2457a2af 100644 --- a/server/handles/fsread.go +++ b/server/handles/fsread.go @@ -204,6 +204,8 @@ func toObjsResp(objs []model.Obj, parent string, encrypt bool) []ObjResp { Size: obj.GetSize(), IsDir: obj.IsDir(), Modified: obj.ModTime(), + Created: obj.CreateTime(), + HashInfo: obj.GetHash().String(), Sign: common.Sign(obj, parent, encrypt), Thumb: thumb, Type: utils.GetObjType(obj.GetName(), obj.IsDir()),