mirror of
https://github.com/rclone/rclone.git
synced 2025-12-06 00:03:32 +00:00
ulozto: implement the about functionality
This commit is contained in:
@@ -104,6 +104,19 @@ type File struct {
|
||||
} `json:"processing"`
|
||||
}
|
||||
|
||||
// FolderSize represents the API object describing the sizes of a files and subfolders of a folder.
|
||||
type FolderSize struct {
|
||||
FilesSize int64 `json:"files_size"`
|
||||
FilesCount int64 `json:"files_count"`
|
||||
FoldersCount int64 `json:"folders_count"`
|
||||
}
|
||||
|
||||
// FolderSizes describes the subfolder sizes of a single folder.
|
||||
type FolderSizes struct {
|
||||
Direct FolderSize `json:"direct"`
|
||||
Recursive FolderSize `json:"recursive"`
|
||||
}
|
||||
|
||||
// CreateFolderRequest represents the JSON API object
|
||||
// that's sent to the create folder API endpoint.
|
||||
type CreateFolderRequest struct {
|
||||
@@ -126,6 +139,9 @@ type ListFilesResponse struct {
|
||||
Items []File `json:"items"`
|
||||
}
|
||||
|
||||
// FolderSizesResponse represents the response from the folder-sizes endpoint.
|
||||
type FolderSizesResponse map[string]FolderSizes
|
||||
|
||||
// DeleteFoldersRequest represents the JSON API object
|
||||
// that's sent to the delete folders API endpoint.
|
||||
type DeleteFoldersRequest struct {
|
||||
|
||||
@@ -97,7 +97,8 @@ any root slug set.`,
|
||||
Advanced: true,
|
||||
Default: encoder.Display | encoder.EncodeInvalidUtf8 | encoder.EncodeBackSlash,
|
||||
},
|
||||
}})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Fs represents a remote uloz.to storage
|
||||
@@ -143,7 +144,6 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
||||
f.rest.SetHeader("X-Auth-Token", f.opt.AppToken)
|
||||
|
||||
auth, err := f.authenticate(ctx)
|
||||
|
||||
if err != nil {
|
||||
return f, err
|
||||
}
|
||||
@@ -178,6 +178,20 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
||||
return f, err
|
||||
}
|
||||
|
||||
// About implements the Abouter interface for Uloz.to.
|
||||
func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
|
||||
used, err := f.getUsedSize(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
usage := fs.Usage{
|
||||
Used: &used,
|
||||
}
|
||||
|
||||
return &usage, nil
|
||||
}
|
||||
|
||||
// errorHandler parses a non 2xx error response into an error
|
||||
func errorHandler(resp *http.Response) error {
|
||||
// Decode error response
|
||||
@@ -253,7 +267,6 @@ func (f *Fs) authenticate(ctx context.Context) (response *api.AuthenticateRespon
|
||||
httpResp, err := f.rest.CallJSON(ctx, &opts, &authRequest, &response)
|
||||
return f.shouldRetry(ctx, httpResp, err, false)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,6 +276,32 @@ func (f *Fs) authenticate(ctx context.Context) (response *api.AuthenticateRespon
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (f *Fs) getUsedSize(ctx context.Context) (int64, error) {
|
||||
rootID, err := f.dirCache.RootID(ctx, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
opts := rest.Opts{
|
||||
Method: "GET",
|
||||
Path: fmt.Sprintf("/v6/user/%s/folder/%s/folder-sizes", f.opt.Username, rootID),
|
||||
Parameters: url.Values{
|
||||
"recursive": []string{"true"},
|
||||
},
|
||||
}
|
||||
|
||||
folderSizes := api.FolderSizesResponse{}
|
||||
|
||||
err = f.pacer.Call(func() (bool, error) {
|
||||
resp, err := f.rest.CallJSON(ctx, &opts, nil, &folderSizes)
|
||||
return f.shouldRetry(ctx, resp, err, true)
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return folderSizes[rootID].Recursive.FilesSize, nil
|
||||
}
|
||||
|
||||
// UploadSession represents a single Uloz.to upload session.
|
||||
//
|
||||
// Uloz.to supports uploading multiple files at once and committing them atomically. This functionality isn't being used
|
||||
@@ -310,7 +349,6 @@ func (session *UploadSession) renewUploadSession(ctx context.Context) error {
|
||||
httpResp, err := session.Filesystem.rest.CallJSON(ctx, &opts, &createUploadURLReq, &response)
|
||||
return session.Filesystem.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -324,14 +362,12 @@ func (session *UploadSession) renewUploadSession(ctx context.Context) error {
|
||||
|
||||
func (f *Fs) uploadUnchecked(ctx context.Context, name, parentSlug string, info fs.ObjectInfo, payload io.Reader) (fs.Object, error) {
|
||||
session, err := f.createUploadSession(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hashes := hash.NewHashSet(hash.MD5, hash.SHA256)
|
||||
hasher, err := hash.NewMultiHasherTypes(hashes)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -360,7 +396,6 @@ func (f *Fs) uploadUnchecked(ctx context.Context, name, parentSlug string, info
|
||||
httpResp, err := f.cdn.CallJSON(ctx, &opts, nil, &uploadResponse)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -386,7 +421,6 @@ func (f *Fs) uploadUnchecked(ctx context.Context, name, parentSlug string, info
|
||||
}
|
||||
|
||||
encodedMetadata, err := metadata.encode()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -412,7 +446,6 @@ func (f *Fs) uploadUnchecked(ctx context.Context, name, parentSlug string, info
|
||||
httpResp, err := session.Filesystem.rest.CallJSON(ctx, &opts, &updateReq, &updateResponse)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -438,7 +471,6 @@ func (f *Fs) uploadUnchecked(ctx context.Context, name, parentSlug string, info
|
||||
httpResp, err := session.Filesystem.rest.CallJSON(ctx, &opts, &commitRequest, &commitResponse)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -468,7 +500,6 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
|
||||
// Uloz.to allows to have multiple files of the same name in the same folder.
|
||||
func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
|
||||
filename, folderSlug, err := f.dirCache.FindPath(ctx, src.Remote(), true)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -484,7 +515,6 @@ func (f *Fs) Mkdir(ctx context.Context, dir string) (err error) {
|
||||
|
||||
func (f *Fs) isDirEmpty(ctx context.Context, slug string) (empty bool, err error) {
|
||||
folders, err := f.fetchListFolderPage(ctx, slug, "", 1, 0)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -494,7 +524,6 @@ func (f *Fs) isDirEmpty(ctx context.Context, slug string) (empty bool, err error
|
||||
}
|
||||
|
||||
files, err := f.fetchListFilePage(ctx, slug, "", 1, 0)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -509,13 +538,11 @@ func (f *Fs) isDirEmpty(ctx context.Context, slug string) (empty bool, err error
|
||||
// Rmdir implements the mandatory method fs.Fs.Rmdir.
|
||||
func (f *Fs) Rmdir(ctx context.Context, dir string) error {
|
||||
slug, err := f.dirCache.FindDir(ctx, dir, false)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
empty, err := f.isDirEmpty(ctx, slug)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -534,7 +561,6 @@ func (f *Fs) Rmdir(ctx context.Context, dir string) error {
|
||||
httpResp, err := f.rest.CallJSON(ctx, &opts, req, nil)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -558,7 +584,6 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object,
|
||||
}
|
||||
|
||||
filename, folderSlug, err := f.dirCache.FindPath(ctx, remote, true)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -600,7 +625,6 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
|
||||
httpResp, err := f.rest.CallJSON(ctx, &opts, &req, nil)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -741,7 +765,6 @@ func (o *Object) updateFileProperties(ctx context.Context, req any) (err error)
|
||||
httpResp, err := o.fs.rest.CallJSON(ctx, &opts, &req, &resp)
|
||||
return o.fs.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -870,7 +893,6 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
|
||||
remote: o.Remote(),
|
||||
}
|
||||
newo, err := o.fs.PutUnchecked(ctx, in, info, options...)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -914,7 +936,6 @@ func (o *Object) ModTime(ctx context.Context) time.Time {
|
||||
|
||||
// The time the object was last modified on the server - a handwavy guess, but we don't have any better
|
||||
return o.remoteFsMtime
|
||||
|
||||
}
|
||||
|
||||
// Fs implements the mandatory method fs.Object.Fs
|
||||
@@ -1053,7 +1074,6 @@ func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.Fi
|
||||
}
|
||||
|
||||
files, err := f.listFiles(ctx, folderSlug, filename)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1065,7 +1085,6 @@ func (f *Fs) readMetaDataForPath(ctx context.Context, path string) (info *api.Fi
|
||||
}
|
||||
|
||||
folders, err := f.listFolders(ctx, folderSlug, filename)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1136,8 +1155,8 @@ func (f *Fs) fetchListFolderPage(
|
||||
folderSlug string,
|
||||
searchQuery string,
|
||||
limit int,
|
||||
offset int) (folders []api.Folder, err error) {
|
||||
|
||||
offset int,
|
||||
) (folders []api.Folder, err error) {
|
||||
opts := rest.Opts{
|
||||
Method: "GET",
|
||||
Path: "/v9/user/" + f.opt.Username + "/folder/" + folderSlug + "/folder-list",
|
||||
@@ -1160,7 +1179,6 @@ func (f *Fs) fetchListFolderPage(
|
||||
httpResp, err := f.rest.CallJSON(ctx, &opts, nil, &respBody)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1175,8 +1193,8 @@ func (f *Fs) fetchListFolderPage(
|
||||
func (f *Fs) listFolders(
|
||||
ctx context.Context,
|
||||
folderSlug string,
|
||||
searchQuery string) (folders []api.Folder, err error) {
|
||||
|
||||
searchQuery string,
|
||||
) (folders []api.Folder, err error) {
|
||||
targetPageSize := f.opt.ListPageSize
|
||||
lastPageSize := targetPageSize
|
||||
offset := 0
|
||||
@@ -1204,8 +1222,8 @@ func (f *Fs) fetchListFilePage(
|
||||
folderSlug string,
|
||||
searchQuery string,
|
||||
limit int,
|
||||
offset int) (folders []api.File, err error) {
|
||||
|
||||
offset int,
|
||||
) (folders []api.File, err error) {
|
||||
opts := rest.Opts{
|
||||
Method: "GET",
|
||||
Path: "/v8/user/" + f.opt.Username + "/folder/" + folderSlug + "/file-list",
|
||||
@@ -1227,7 +1245,6 @@ func (f *Fs) fetchListFilePage(
|
||||
httpResp, err := f.rest.CallJSON(ctx, &opts, nil, &respBody)
|
||||
return f.shouldRetry(ctx, httpResp, err, true)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't list files: %w", err)
|
||||
}
|
||||
@@ -1242,8 +1259,8 @@ func (f *Fs) fetchListFilePage(
|
||||
func (f *Fs) listFiles(
|
||||
ctx context.Context,
|
||||
folderSlug string,
|
||||
searchQuery string) (folders []api.File, err error) {
|
||||
|
||||
searchQuery string,
|
||||
) (folders []api.File, err error) {
|
||||
targetPageSize := f.opt.ListPageSize
|
||||
lastPageSize := targetPageSize
|
||||
offset := 0
|
||||
|
||||
Reference in New Issue
Block a user