forked from rclone/rclone
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new backend: hidrive - fixes rclone#1069
- Loading branch information
Showing
17 changed files
with
3,450 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package api | ||
|
||
import ( | ||
"encoding/json" | ||
"net/url" | ||
"path" | ||
"strings" | ||
"time" | ||
) | ||
|
||
// Some presets for different amounts of information that can be requested for fields; | ||
// it is recommended to only request the information that is actually needed. | ||
var ( | ||
HiDriveObjectNoMetadataFields = []string{"name", "type"} | ||
HiDriveObjectWithMetadataFields = append(HiDriveObjectNoMetadataFields, "id", "size", "mtime", "chash") | ||
HiDriveObjectWithDirectoryMetadataFields = append(HiDriveObjectWithMetadataFields, "nmembers") | ||
DirectoryContentFields = []string{"nmembers"} | ||
) | ||
|
||
// QueryParameters represents the parameters passed to an API-call. | ||
type QueryParameters struct { | ||
url.Values | ||
} | ||
|
||
// NewQueryParameters initializes an instance of QueryParameters and | ||
// returns a pointer to it. | ||
func NewQueryParameters() *QueryParameters { | ||
return &QueryParameters{url.Values{}} | ||
} | ||
|
||
// SetFileInDirectory sets the appropriate parameters | ||
// to specify a path to a file in a directory. | ||
// This is used by requests that work with paths for files that do not exist yet. | ||
// (For example when creating a file). | ||
// Most requests use the format produced by SetPath(...). | ||
func (p *QueryParameters) SetFileInDirectory(filePath string) { | ||
directory, file := path.Split(path.Clean(filePath)) | ||
p.Set("dir", path.Clean(directory)) | ||
p.Set("name", file) | ||
// NOTE: It would be possible to switch to pid-based requests | ||
// by modifying this function. | ||
} | ||
|
||
// SetPath sets the appropriate parameters to access the given path. | ||
func (p *QueryParameters) SetPath(objectPath string) { | ||
p.Set("path", path.Clean(objectPath)) | ||
// NOTE: It would be possible to switch to pid-based requests | ||
// by modifying this function. | ||
} | ||
|
||
// SetTime sets the key to the time-value. It replaces any existing values. | ||
func (p *QueryParameters) SetTime(key string, value time.Time) error { | ||
valueAPI := Time(value) | ||
valueBytes, err := json.Marshal(&valueAPI) | ||
if err != nil { | ||
return err | ||
} | ||
p.Set(key, string(valueBytes)) | ||
return nil | ||
} | ||
|
||
// AddList adds the given values as a list | ||
// with each value separated by the separator. | ||
// It appends to any existing values associated with key. | ||
func (p *QueryParameters) AddList(key string, separator string, values ...string) { | ||
original := p.Get(key) | ||
p.Set(key, strings.Join(values, separator)) | ||
if original != "" { | ||
p.Set(key, original+separator+p.Get(key)) | ||
} | ||
} | ||
|
||
// AddFields sets the appropriate parameter to access the given fields. | ||
// The given fields will be appended to any other existing fields. | ||
func (p *QueryParameters) AddFields(prefix string, fields ...string) { | ||
modifiedFields := make([]string, len(fields)) | ||
for i, field := range fields { | ||
modifiedFields[i] = prefix + field | ||
} | ||
p.AddList("fields", ",", modifiedFields...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Package api has type definitions and code related to API-calls for the HiDrive-API. | ||
package api | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/url" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
// Time represents date and time information for the API. | ||
type Time time.Time | ||
|
||
// MarshalJSON turns Time into JSON (in Unix-time/UTC). | ||
func (t *Time) MarshalJSON() ([]byte, error) { | ||
secs := time.Time(*t).Unix() | ||
return []byte(strconv.FormatInt(secs, 10)), nil | ||
} | ||
|
||
// UnmarshalJSON turns JSON into Time. | ||
func (t *Time) UnmarshalJSON(data []byte) error { | ||
secs, err := strconv.ParseInt(string(data), 10, 64) | ||
if err != nil { | ||
return err | ||
} | ||
*t = Time(time.Unix(secs, 0)) | ||
return nil | ||
} | ||
|
||
// Error is returned from the API when things go wrong. | ||
type Error struct { | ||
Code json.Number `json:"code"` | ||
ContextInfo json.RawMessage | ||
Message string `json:"msg"` | ||
} | ||
|
||
// Error returns a string for the error and satisfies the error interface. | ||
func (e *Error) Error() string { | ||
out := fmt.Sprintf("Error %q", e.Code.String()) | ||
if e.Message != "" { | ||
out += ": " + e.Message | ||
} | ||
if e.ContextInfo != nil { | ||
out += fmt.Sprintf(" (%+v)", e.ContextInfo) | ||
} | ||
return out | ||
} | ||
|
||
// Check Error satisfies the error interface. | ||
var _ error = (*Error)(nil) | ||
|
||
// possible types for HiDriveObject | ||
const ( | ||
HiDriveObjectTypeDirectory = "dir" | ||
HiDriveObjectTypeFile = "file" | ||
HiDriveObjectTypeSymlink = "symlink" | ||
) | ||
|
||
// HiDriveObject describes a folder, a symlink or a file. | ||
// Depending on the type and content, not all fields are present. | ||
type HiDriveObject struct { | ||
Type string `json:"type"` | ||
ID string `json:"id"` | ||
ParentID string `json:"parent_id"` | ||
Name string `json:"name"` | ||
Path string `json:"path"` | ||
Size int64 `json:"size"` | ||
MemberCount int64 `json:"nmembers"` | ||
ModifiedAt Time `json:"mtime"` | ||
ChangedAt Time `json:"ctime"` | ||
MetaHash string `json:"mhash"` | ||
MetaOnlyHash string `json:"mohash"` | ||
NameHash string `json:"nhash"` | ||
ContentHash string `json:"chash"` | ||
IsTeamfolder bool `json:"teamfolder"` | ||
Readable bool `json:"readable"` | ||
Writable bool `json:"writable"` | ||
Shareable bool `json:"shareable"` | ||
MIMEType string `json:"mime_type"` | ||
} | ||
|
||
// ModTime returns the modification time of the HiDriveObject. | ||
func (i *HiDriveObject) ModTime() time.Time { | ||
t := time.Time(i.ModifiedAt) | ||
if t.IsZero() { | ||
t = time.Time(i.ChangedAt) | ||
} | ||
return t | ||
} | ||
|
||
// UnmarshalJSON turns JSON into HiDriveObject and | ||
// introduces specific default-values where necessary. | ||
func (i *HiDriveObject) UnmarshalJSON(data []byte) error { | ||
type objectAlias HiDriveObject | ||
defaultObject := objectAlias{ | ||
Size: -1, | ||
MemberCount: -1, | ||
} | ||
|
||
err := json.Unmarshal(data, &defaultObject) | ||
if err != nil { | ||
return err | ||
} | ||
name, err := url.PathUnescape(defaultObject.Name) | ||
if err == nil { | ||
defaultObject.Name = name | ||
} | ||
|
||
*i = HiDriveObject(defaultObject) | ||
return nil | ||
} | ||
|
||
// DirectoryContent describes the content of a directory. | ||
type DirectoryContent struct { | ||
TotalCount int64 `json:"nmembers"` | ||
Entries []HiDriveObject `json:"members"` | ||
} | ||
|
||
// UnmarshalJSON turns JSON into DirectoryContent and | ||
// introduces specific default-values where necessary. | ||
func (d *DirectoryContent) UnmarshalJSON(data []byte) error { | ||
type directoryContentAlias DirectoryContent | ||
defaultDirectoryContent := directoryContentAlias{ | ||
TotalCount: -1, | ||
} | ||
|
||
err := json.Unmarshal(data, &defaultDirectoryContent) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
*d = DirectoryContent(defaultDirectoryContent) | ||
return nil | ||
} |
Oops, something went wrong.