jottacloud: add link sharing support

This commit is contained in:
albertony 2018-09-04 21:02:35 +02:00 committed by Nick Craig-Wood
parent a823d518ac
commit d51501938a
5 changed files with 87 additions and 25 deletions

View file

@ -236,6 +236,7 @@ type JottaFile struct {
XMLName xml.Name XMLName xml.Name
Name string `xml:"name,attr"` Name string `xml:"name,attr"`
Deleted Flag `xml:"deleted,attr"` Deleted Flag `xml:"deleted,attr"`
PublicSharePath string `xml:"publicSharePath"`
State string `xml:"currentRevision>state"` State string `xml:"currentRevision>state"`
CreatedAt Time `xml:"currentRevision>created"` CreatedAt Time `xml:"currentRevision>created"`
ModifiedAt Time `xml:"currentRevision>modified"` ModifiedAt Time `xml:"currentRevision>modified"`

View file

@ -40,6 +40,7 @@ const (
defaultMountpoint = "Sync" defaultMountpoint = "Sync"
rootURL = "https://www.jottacloud.com/jfs/" rootURL = "https://www.jottacloud.com/jfs/"
apiURL = "https://api.jottacloud.com" apiURL = "https://api.jottacloud.com"
shareURL = "https://www.jottacloud.com/"
cachePrefix = "rclone-jcmd5-" cachePrefix = "rclone-jcmd5-"
) )
@ -77,6 +78,11 @@ func init() {
Help: "Delete files permanently rather than putting them into the trash.", Help: "Delete files permanently rather than putting them into the trash.",
Default: false, Default: false,
Advanced: true, Advanced: true,
}, {
Name: "unlink",
Help: "Remove existing public link to file/folder with link command rather than creating.",
Default: false,
Advanced: true,
}}, }},
}) })
} }
@ -88,6 +94,7 @@ type Options struct {
Mountpoint string `config:"mountpoint"` Mountpoint string `config:"mountpoint"`
MD5MemoryThreshold fs.SizeSuffix `config:"md5_memory_limit"` MD5MemoryThreshold fs.SizeSuffix `config:"md5_memory_limit"`
HardDelete bool `config:"hard_delete"` HardDelete bool `config:"hard_delete"`
Unlink bool `config:"unlink"`
} }
// Fs represents a remote jottacloud // Fs represents a remote jottacloud
@ -614,7 +621,7 @@ func (f *Fs) purgeCheck(dir string, check bool) (err error) {
return shouldRetry(resp, err) return shouldRetry(resp, err)
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "rmdir failed") return errors.Wrap(err, "couldn't purge directory")
} }
// TODO: Parse response? // TODO: Parse response?
@ -687,7 +694,7 @@ func (f *Fs) Copy(src fs.Object, remote string) (fs.Object, error) {
info, err := f.copyOrMove("cp", srcObj.filePath(), remote) info, err := f.copyOrMove("cp", srcObj.filePath(), remote)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "copy failed") return nil, errors.Wrap(err, "couldn't copy file")
} }
return f.newObjectWithInfo(remote, info) return f.newObjectWithInfo(remote, info)
@ -717,7 +724,7 @@ func (f *Fs) Move(src fs.Object, remote string) (fs.Object, error) {
info, err := f.copyOrMove("mv", srcObj.filePath(), remote) info, err := f.copyOrMove("mv", srcObj.filePath(), remote)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "move failed") return nil, errors.Wrap(err, "couldn't move file")
} }
return f.newObjectWithInfo(remote, info) return f.newObjectWithInfo(remote, info)
@ -761,11 +768,57 @@ func (f *Fs) DirMove(src fs.Fs, srcRemote, dstRemote string) error {
_, err = f.copyOrMove("mvDir", path.Join(f.endpointURL, replaceReservedChars(srcPath))+"/", dstRemote) _, err = f.copyOrMove("mvDir", path.Join(f.endpointURL, replaceReservedChars(srcPath))+"/", dstRemote)
if err != nil { if err != nil {
return errors.Wrap(err, "moveDir failed") return errors.Wrap(err, "couldn't move directory")
} }
return nil return nil
} }
// PublicLink generates a public link to the remote path (usually readable by anyone)
func (f *Fs) PublicLink(remote string) (link string, err error) {
opts := rest.Opts{
Method: "GET",
Path: f.filePath(remote),
Parameters: url.Values{},
}
if f.opt.Unlink {
opts.Parameters.Set("mode", "disableShare")
} else {
opts.Parameters.Set("mode", "enableShare")
}
var resp *http.Response
var result api.JottaFile
err = f.pacer.Call(func() (bool, error) {
resp, err = f.srv.CallXML(&opts, nil, &result)
return shouldRetry(resp, err)
})
if apiErr, ok := err.(*api.Error); ok {
// does not exist
if apiErr.StatusCode == http.StatusNotFound {
return "", fs.ErrorObjectNotFound
}
}
if err != nil {
if f.opt.Unlink {
return "", errors.Wrap(err, "couldn't remove public link")
}
return "", errors.Wrap(err, "couldn't create public link")
}
if f.opt.Unlink {
if result.PublicSharePath != "" {
return "", errors.Errorf("couldn't remove public link - %q", result.PublicSharePath)
}
return "", nil
}
if result.PublicSharePath == "" {
return "", errors.New("couldn't create public link - no link path received")
}
link = path.Join(shareURL, result.PublicSharePath)
return link, nil
}
// About gets quota information // About gets quota information
func (f *Fs) About() (*fs.Usage, error) { func (f *Fs) About() (*fs.Usage, error) {
info, err := f.getAccountInfo() info, err := f.getAccountInfo()
@ -1045,6 +1098,7 @@ var (
_ fs.Mover = (*Fs)(nil) _ fs.Mover = (*Fs)(nil)
_ fs.DirMover = (*Fs)(nil) _ fs.DirMover = (*Fs)(nil)
_ fs.ListRer = (*Fs)(nil) _ fs.ListRer = (*Fs)(nil)
_ fs.PublicLinker = (*Fs)(nil)
_ fs.Abouter = (*Fs)(nil) _ fs.Abouter = (*Fs)(nil)
_ fs.Object = (*Object)(nil) _ fs.Object = (*Object)(nil)
_ fs.MimeTyper = (*Object)(nil) _ fs.MimeTyper = (*Object)(nil)

View file

@ -34,7 +34,9 @@ without account.
if err != nil { if err != nil {
return err return err
} }
if link != "" {
fmt.Println(link) fmt.Println(link)
}
return nil return nil
}) })
}, },

View file

@ -149,6 +149,11 @@ Controls whether files are sent to the trash or deleted
permanently. Defaults to false, namely sending files to the trash. permanently. Defaults to false, namely sending files to the trash.
Use `--jottacloud-hard-delete=true` to delete files permanently instead. Use `--jottacloud-hard-delete=true` to delete files permanently instead.
#### --jottacloud-unlink ####
Set to true to make the link command remove existing public link to file/folder.
Default is false, meaning link command will create or retrieve public link.
### Troubleshooting ### ### Troubleshooting ###
Jottacloud exhibits some inconsistent behaviours regarding deleted files and folders which may cause Copy, Move and DirMove operations to previously deleted paths to fail. Emptying the trash should help in such cases. Jottacloud exhibits some inconsistent behaviours regarding deleted files and folders which may cause Copy, Move and DirMove operations to previously deleted paths to fail. Emptying the trash should help in such cases.

View file

@ -138,7 +138,7 @@ operations more efficient.
| Google Drive | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | Google Drive | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| HTTP | No | No | No | No | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | | HTTP | No | No | No | No | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
| Hubic | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | Hubic | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes |
| Jottacloud | Yes | Yes | Yes | Yes | No | Yes | No | No | No | | Jottacloud | Yes | Yes | Yes | Yes | No | Yes | No | Yes | No |
| Mega | Yes | No | Yes | Yes | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | Mega | Yes | No | Yes | Yes | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes |
| Microsoft Azure Blob Storage | Yes | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No | | Microsoft Azure Blob Storage | Yes | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
| Microsoft OneDrive | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes | | Microsoft OneDrive | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | Yes |