diff --git a/backend/icloud/api/client.go b/backend/icloud/api/client.go index 095a7196a3775..32f9d37053f50 100644 --- a/backend/icloud/api/client.go +++ b/backend/icloud/api/client.go @@ -5,9 +5,9 @@ import ( "bytes" "context" "encoding/json" - "net/http" "fmt" - "strings" + "net/http" + "strings" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/fshttp" @@ -135,10 +135,10 @@ func IntoReader(values any) (*bytes.Reader, error) { return bytes.NewReader(m), nil } -// Sometimes icloud returns a 200 but the request status is unkown +// RequestError holds info on a result state, icloud can return a 200 but the result is unknown type RequestError struct { - Status string - Text string + Status string + Text string } // Error satisfy the error interface. @@ -148,8 +148,8 @@ func (e *RequestError) Error() string { func newRequestError(Status string, Text string) *RequestError { return &RequestError{ - Status: strings.ToLower(Status), - Text: Text, + Status: strings.ToLower(Status), + Text: Text, } } diff --git a/backend/icloud/api/drive.go b/backend/icloud/api/drive.go index 5f793d2c7de8a..c079456c89637 100644 --- a/backend/icloud/api/drive.go +++ b/backend/icloud/api/drive.go @@ -85,8 +85,8 @@ func (d *DriveService) GetItemsByDriveID(ctx context.Context, ids []string, incl } //if items[0].Status != statusOk { - // err = newRequestErrorf(items[0].Status, "unkown inner status for: %s %s", opts.Method, resp.Request.URL) - //return nil, resp, fmt.Errorf("%s %s failed, status %s", opts.Method, resp.Request.URL, items[0].Status) + // err = newRequestErrorf(items[0].Status, "unknown inner status for: %s %s", opts.Method, resp.Request.URL) + //return nil, resp, fmt.Errorf("%s %s failed, status %s", opts.Method, resp.Request.URL, items[0].Status) //} return items, resp, err @@ -203,7 +203,7 @@ func (d *DriveService) GetItemsInFolder(ctx context.Context, id string, limit in return items.Items, resp, err } -// GetDownloadURL retrieves the download URL for a file in the DriveService. +// GetDownloadURLByDriveID retrieves the download URL for a file in the DriveService. func (d *DriveService) GetDownloadURLByDriveID(ctx context.Context, id string) (string, *http.Response, error) { _, zone, docid := DeconstructDriveID(id) values := url.Values{} @@ -304,7 +304,7 @@ func (d *DriveService) MoveItemToTrashByID(ctx context.Context, drivewsid, etag return d.MoveItemToTrashByID(ctx, drivewsid, item.Items[0].Etag, false) } - err = newRequestError(item.Items[0].Status, "unknown request status") + err = newRequestError(item.Items[0].Status, "unknown request status") //return nil, resp, fmt.Errorf("%s %s failed, inner_status %s", opts.Method, resp.Request.URL, item.Items[0].Status) } @@ -378,12 +378,12 @@ func (d *DriveService) CreateNewFolderByDriveID(ctx context.Context, drivewsid, } var fResp *CreateFoldersResponse resp, err := d.icloud.Request(ctx, opts, nil, &fResp) - if err != nil { + if err != nil { return nil, resp, err } status := fResp.Folders[0].Status if status != statusOk { - err = newRequestError(status, "unknown request status") + err = newRequestError(status, "unknown request status") } return fResp.Folders[0], resp, err @@ -431,7 +431,7 @@ func (d *DriveService) RenameItemByDriveID(ctx context.Context, id, etag, name s if force && status == "ETAG_CONFLICT" { return d.RenameItemByDriveID(ctx, id, items.Items[0].Etag, name, false) } - err = newRequestErrorf(status, "unkown inner status for: %s %s", opts.Method, resp.Request.URL) + err = newRequestErrorf(status, "unknown inner status for: %s %s", opts.Method, resp.Request.URL) } return items.Items[0], resp, err @@ -483,7 +483,7 @@ func (d *DriveService) MoveItemByDriveID(ctx context.Context, id, etag, dstID st if force && status == "ETAG_CONFLICT" { return d.MoveItemByDriveID(ctx, id, items.Items[0].Etag, dstID, false) } - err = newRequestErrorf(status, "unkown inner status for: %s %s", opts.Method, resp.Request.URL) + err = newRequestErrorf(status, "unknown inner status for: %s %s", opts.Method, resp.Request.URL) } return items.Items[0], resp, err @@ -522,8 +522,8 @@ func (d *DriveService) CreateUpload(ctx context.Context, size int64, name string // api requires a mime type passed in mimeType = "text/plain" } - - // first we need to request an upload url + + // first we need to request an upload url values := map[string]any{ "filename": name, "type": "FILE", @@ -540,14 +540,14 @@ func (d *DriveService) CreateUpload(ctx context.Context, size int64, name string } var responseInfo []*UploadResponse resp, err := d.icloud.Request(ctx, opts, nil, &responseInfo) - if err != nil { + if err != nil { return nil, resp, err } - return responseInfo[0], resp, err + return responseInfo[0], resp, err } // Upload uploads a file to the given url -func (d *DriveService) Upload(ctx context.Context, in io.Reader, size int64, name, uploadUrl string) (*SingleFileResponse, *http.Response, error) { +func (d *DriveService) Upload(ctx context.Context, in io.Reader, size int64, name, uploadURL string) (*SingleFileResponse, *http.Response, error) { // detect MIME type by looking at the filename only mimeType := mime.TypeByExtension(filepath.Ext(name)) if mimeType == "" { @@ -558,7 +558,7 @@ func (d *DriveService) Upload(ctx context.Context, in io.Reader, size int64, nam opts := rest.Opts{ Method: "POST", ExtraHeaders: d.icloud.Session.GetHeaders(map[string]string{}), - RootURL: uploadUrl, + RootURL: uploadURL, Body: in, ContentLength: &size, ContentType: mimeType, @@ -570,7 +570,7 @@ func (d *DriveService) Upload(ctx context.Context, in io.Reader, size int64, nam if err != nil { return nil, resp, err } - return singleFileResponse, resp, err + return singleFileResponse, resp, err } // UpdateFile updates a file in the DriveService. @@ -831,7 +831,7 @@ type SingleFileInfo struct { Receipt string `json:"receipt"` } -// UploadUrlResponse is the response of an upload request. +// UploadResponse is the response of an upload request. type UploadResponse struct { URL string `json:"url"` DocumentID string `json:"document_id"` diff --git a/backend/icloud/api/session.go b/backend/icloud/api/session.go index 21b02984e53c6..30ce938bdf1b8 100644 --- a/backend/icloud/api/session.go +++ b/backend/icloud/api/session.go @@ -43,10 +43,10 @@ func (s *Session) Request(ctx context.Context, opts rest.Opts, request interface resp, err := s.srv.CallJSON(ctx, &opts, &request, &response) if err != nil { - //fs.PrettyPrint(opts, "opts", fs.LogLevelDebug) - //fs.PrettyPrint(resp, "resp", fs.LogLevelDebug) - return resp, err - //return resp, fmt.Errorf("%s %s failed, status %d, err: %s", opts.Method, resp.Request.URL, resp.StatusCode, err) + //fs.PrettyPrint(opts, "opts", fs.LogLevelDebug) + //fs.PrettyPrint(resp, "resp", fs.LogLevelDebug) + return resp, err + //return resp, fmt.Errorf("%s %s failed, status %d, err: %s", opts.Method, resp.Request.URL, resp.StatusCode, err) } if val := resp.Header.Get("X-Apple-ID-Account-Country"); val != "" { diff --git a/backend/icloud/icloud.go b/backend/icloud/icloud.go index c2e9ae1e98897..b86a441e295d9 100644 --- a/backend/icloud/icloud.go +++ b/backend/icloud/icloud.go @@ -63,7 +63,7 @@ func init() { // Password is not required, it will be left blank for 2FA Name: configPassword, Help: "Password.", - Required: true, + Required: true, IsPassword: true, Sensitive: true, }, { @@ -73,24 +73,24 @@ func init() { Required: false, Sensitive: true, Hide: fs.OptionHideBoth, - }, - { - Name: configCookies, - Help: "cookies (internal use only)", - Required: false, - Advanced: false, - Sensitive: true, - Hide: fs.OptionHideBoth, - }, - { - Name: config.ConfigEncoding, - Help: config.ConfigEncodingHelp, - Advanced: true, - Default: (encoder.Display | - //encoder.EncodeDot | - encoder.EncodeBackSlash | - encoder.EncodeInvalidUtf8), - }}, + }, + { + Name: configCookies, + Help: "cookies (internal use only)", + Required: false, + Advanced: false, + Sensitive: true, + Hide: fs.OptionHideBoth, + }, + { + Name: config.ConfigEncoding, + Help: config.ConfigEncodingHelp, + Advanced: true, + Default: (encoder.Display | + //encoder.EncodeDot | + encoder.EncodeBackSlash | + encoder.EncodeInvalidUtf8), + }}, }) } @@ -113,7 +113,7 @@ type Fs struct { features *fs.Features // optional features dirCache *dircache.DirCache // Map of directory path to directory id icloud *api.Client - service *api.DriveService + service *api.DriveService pacer *fs.Pacer // pacer for API calls } @@ -125,7 +125,7 @@ type Object struct { modTime time.Time // modification time of the object createdTime time.Time // creation time of the object id string // item ID of the object - docId string // document ID of the object + docID string // document ID of the object itemID string // item ID of the object etag string downloadURL string @@ -317,7 +317,7 @@ func (f *Fs) listAll(ctx context.Context, dirID string) (items []*api.DriveItem, item.Extension = f.opt.Enc.ToStandardName(item.Extension) items = append(items, item) } - //fs.PrettyPrint(items, "ERR", fs.LogLevelInfo) + //fs.PrettyPrint(items, "ERR", fs.LogLevelInfo) return items, nil } @@ -391,8 +391,8 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object, var resp *http.Response var info *api.DriveItemRaw - - // make a copy + + // make a copy if err = f.pacer.Call(func() (bool, error) { info, resp, err = f.service.CopyDocByItemID(ctx, srcObj.id) return retryResultUnknown(ctx, resp, err) @@ -421,7 +421,7 @@ func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object, } // build request - // cant use normal rename as file needs to be "activated" first + // cant use normal rename as file needs to be "activated" first r := api.NewUpdateFileInfo() r.DocumentID = doc.DocumentID @@ -582,30 +582,30 @@ func (f *Fs) String() string { func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (string, error) { var item *api.DriveItem var err error - var found bool + var found bool var resp *http.Response if err = f.pacer.Call(func() (bool, error) { id, _ := f.parseNormalizedID(pathID) item, resp, err = f.service.CreateNewFolderByItemID(ctx, id, f.opt.Enc.FromStandardName(leaf)) - - // check if it went oke - if requestError, ok := err.(*api.RequestError); ok { - if requestError.Status == "unknown" { - fs.Debugf(requestError, " checking if dir is created with seperate call.") - time.Sleep(1 * time.Second) // sleep to give icloud time to clear up its mind + + // check if it went oke + if requestError, ok := err.(*api.RequestError); ok { + if requestError.Status == "unknown" { + fs.Debugf(requestError, " checking if dir is created with separate call.") + time.Sleep(1 * time.Second) // sleep to give icloud time to clear up its mind item, found, err = f.findLeafItem(ctx, pathID, leaf) if err != nil { return false, err } if !found { - // lets assume it failed and retry - return true, err + // lets assume it failed and retry + return true, err } - - // success, clear err - err = nil - } + + // success, clear err + err = nil + } } return ignoreResultUnknown(ctx, resp, err) @@ -625,7 +625,7 @@ func (f *Fs) CreateDir(ctx context.Context, pathID, leaf string) (string, error) // // If destination exists then return fs.ErrorDirExists func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string) error { - srcFs, ok := src.(*Fs) + srcFs, ok := src.(*Fs) if !ok { fs.Debugf(srcFs, "Can't move directory - not same remote type") return fs.ErrorCantDirMove @@ -653,7 +653,7 @@ func (f *Fs) move(ctx context.Context, ID, srcDirectoryID, srcLeaf, srcEtag, dst var resp *http.Response var item *api.DriveItem var err error - //fmt.Println("MOVE") + //fmt.Println("MOVE") // move if srcDirectoryID != dstDirectoryID { if err = f.pacer.Call(func() (bool, error) { @@ -663,12 +663,12 @@ func (f *Fs) move(ctx context.Context, ID, srcDirectoryID, srcLeaf, srcEtag, dst }); err != nil { return nil, err } - ID = item.Itemid - srcEtag = item.Etag - } + ID = item.Itemid + srcEtag = item.Etag + } - // rename - if srcLeaf != dstLeaf { + // rename + if srcLeaf != dstLeaf { if err = f.pacer.Call(func() (bool, error) { id, _ := f.parseNormalizedID(ID) item, resp, err = f.service.RenameItemByItemID(ctx, id, srcEtag, dstLeaf, true) @@ -683,7 +683,7 @@ func (f *Fs) move(ctx context.Context, ID, srcDirectoryID, srcLeaf, srcEtag, dst // Move moves the src object to the specified remote. func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object, error) { - srcObj, ok := src.(*Object) + srcObj, ok := src.(*Object) if !ok { fs.Debugf(src, "Can't move - not same remote type") return nil, fs.ErrorCantMove @@ -699,8 +699,7 @@ func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object, return nil, err } - //fmt.Println("MOVE", srcObj.Remote(), srcLeaf, remote, dstLeaf, f.root) - + //fmt.Println("MOVE", srcObj.Remote(), srcLeaf, remote, dstLeaf, f.root) item, err := f.move(ctx, srcObj.id, srcDirectoryID, srcLeaf, srcObj.etag, dstDirectoryID, dstLeaf) if err != nil { @@ -741,7 +740,7 @@ func ReadCookies(raw string) []*http.Cookie { } var retryErrorCodes = []int{ - 400, // icloud is a mess, sometimes returns 400 on a perfectly fine request. So just retry + 400, // icloud is a mess, sometimes returns 400 on a perfectly fine request. So just retry 408, // Request Timeout 409, // Conflict, retry could fix it. 429, // Rate exceeded. @@ -753,8 +752,8 @@ var retryErrorCodes = []int{ func shouldRetry(ctx context.Context, resp *http.Response, err error) (bool, error) { //PrettyPrint - //fs.PrettyPrint(resp, "resp", fs.LogLevelDebug) - if fserrors.ContextError(ctx, &err) { + //fs.PrettyPrint(resp, "resp", fs.LogLevelDebug) + if fserrors.ContextError(ctx, &err) { return false, err } @@ -763,26 +762,26 @@ func shouldRetry(ctx context.Context, resp *http.Response, err error) (bool, err func ignoreResultUnknown(ctx context.Context, resp *http.Response, err error) (bool, error) { if requestError, ok := err.(*api.RequestError); ok { - if requestError.Status == "unknown" { - fs.Debugf(requestError, " ignoring.") - //time.Sleep(1 * time.Second) - return false, nil - } - //fs.Debugf(requestError, "Response returned not ok state.") - } - return shouldRetry(ctx, resp, err) + if requestError.Status == "unknown" { + fs.Debugf(requestError, " ignoring.") + //time.Sleep(1 * time.Second) + return false, nil + } + //fs.Debugf(requestError, "Response returned not ok state.") + } + return shouldRetry(ctx, resp, err) } func retryResultUnknown(ctx context.Context, resp *http.Response, err error) (bool, error) { if requestError, ok := err.(*api.RequestError); ok { - if requestError.Status == "unknown" { - fs.Debugf(requestError, " retrying.") - //time.Sleep(1 * time.Second) - return true, err - } - //fs.Debugf(requestError, "Response returned not ok state.") - } - return shouldRetry(ctx, resp, err) + if requestError.Status == "unknown" { + fs.Debugf(requestError, " retrying.") + //time.Sleep(1 * time.Second) + return true, err + } + //fs.Debugf(requestError, "Response returned not ok state.") + } + return shouldRetry(ctx, resp, err) } // NewFs constructs an Fs from the path, container:path @@ -820,8 +819,8 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e opt.AppleID, opt.Password, opt.TrustToken, - //nil, - //nil, + //nil, + //nil, cookies, callback, ) @@ -846,7 +845,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e }).Fill(ctx, f) rootID := f.rootID - f.service, _ = icloud.DriveService() + f.service, _ = icloud.DriveService() f.dirCache = dircache.New( root, /* root folder path */ @@ -946,7 +945,7 @@ func (f *Fs) readMetaData(ctx context.Context, path string) (item *api.DriveItem } if !found { - //fmt.Println("nout found", path, ID, leaf) + //fmt.Println("nout found", path, ID, leaf) return nil, fs.ErrorObjectNotFound } @@ -1004,7 +1003,7 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo var doc *api.Document var url string // Cant get the download url on a item to work, so do it the hard way. - if o.docId == "" { + if o.docID == "" { doc, resp, err = o.fs.service.GetDocByItemID(ctx, o.id) url, _, err = o.fs.service.GetDownloadURLByDriveID(ctx, doc.DriveID()) } @@ -1087,28 +1086,28 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op // Move current file to trash if o.id != "" { err = o.Remove(ctx) - if err != nil { - return err - } + if err != nil { + return err + } } - name := o.fs.opt.Enc.FromStandardName(leaf) - var resp *http.Response + name := o.fs.opt.Enc.FromStandardName(leaf) + var resp *http.Response - // create a bew document - var upload_info *api.UploadResponse + // create a bew document + var uploadInfo *api.UploadResponse if err = o.fs.pacer.Call(func() (bool, error) { - upload_info, resp, err = o.fs.service.CreateUpload(ctx, size, name) - return ignoreResultUnknown(ctx, resp, err) + uploadInfo, resp, err = o.fs.service.CreateUpload(ctx, size, name) + return ignoreResultUnknown(ctx, resp, err) }); err != nil { return err } - // upload content + // upload content var upload *api.SingleFileResponse if err = o.fs.pacer.Call(func() (bool, error) { - upload, resp, err = o.fs.service.Upload(ctx, in, size, name, upload_info.URL) - return ignoreResultUnknown(ctx, resp, err) + upload, resp, err = o.fs.service.Upload(ctx, in, size, name, uploadInfo.URL) + return ignoreResultUnknown(ctx, resp, err) }); err != nil { return err } @@ -1116,13 +1115,13 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op var doc *api.Document if err = o.fs.pacer.Call(func() (bool, error) { doc, resp, err = o.fs.service.GetDocByItemID(ctx, dirID) - return ignoreResultUnknown(ctx, resp, err) + return ignoreResultUnknown(ctx, resp, err) }); err != nil { return err } r := api.NewUpdateFileInfo() - r.DocumentID = upload_info.DocumentID + r.DocumentID = uploadInfo.DocumentID r.Path.Path = name r.Path.StartingDocumentID = doc.DocumentID r.Data.Receipt = upload.SingleFile.Receipt @@ -1133,11 +1132,11 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op r.Mtime = modTime.Unix() * 1000 r.Btime = modTime.Unix() * 1000 - // update metadata + // update metadata var item *api.DriveItem if err = o.fs.pacer.Call(func() (bool, error) { item, resp, err = o.fs.service.UpdateFile(ctx, &r) - return ignoreResultUnknown(ctx, resp, err) + return ignoreResultUnknown(ctx, resp, err) }); err != nil { return err }