mirror of
https://github.com/rclone/rclone.git
synced 2024-11-29 03:45:25 +01:00
vendor: add github.com/putdotio/go-putio for putio client
This commit is contained in:
parent
8159658e67
commit
566aa0fca7
1
go.mod
1
go.mod
@ -38,6 +38,7 @@ require (
|
|||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/pkg/sftp v1.10.1-0.20190523025818-e98a7bef6829
|
github.com/pkg/sftp v1.10.1-0.20190523025818-e98a7bef6829
|
||||||
|
github.com/putdotio/go-putio v0.0.0-20190731220109-37c0795af843
|
||||||
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46
|
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46
|
||||||
github.com/sevlyar/go-daemon v0.1.5
|
github.com/sevlyar/go-daemon v0.1.5
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
2
go.sum
2
go.sum
@ -151,6 +151,8 @@ github.com/pkg/sftp v1.10.1-0.20190523025818-e98a7bef6829 h1:I+1BDgqX1nXLUL5Uio2
|
|||||||
github.com/pkg/sftp v1.10.1-0.20190523025818-e98a7bef6829/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
|
github.com/pkg/sftp v1.10.1-0.20190523025818-e98a7bef6829/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/putdotio/go-putio v0.0.0-20190731220109-37c0795af843 h1:Hf9Zw1N+0gQolpRwWOwisCombJ/9anLxUwFkLMQL22c=
|
||||||
|
github.com/putdotio/go-putio v0.0.0-20190731220109-37c0795af843/go.mod h1:EWtDL88jJLLWZzywr0QaPO+mGP8gFpvl8dcox8qTk3Y=
|
||||||
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46 h1:w2CpS5muK+jyydnmlkqpAhzKmHmMBzBkfYUDjQNS1Dk=
|
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46 h1:w2CpS5muK+jyydnmlkqpAhzKmHmMBzBkfYUDjQNS1Dk=
|
||||||
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46/go.mod h1:U2bmx0hDj8EyDdcxmD5t3XHDnBFnyNNc22n1R4008eM=
|
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46/go.mod h1:U2bmx0hDj8EyDdcxmD5t3XHDnBFnyNNc22n1R4008eM=
|
||||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||||
|
22
vendor/github.com/putdotio/go-putio/LICENSE
generated
vendored
Normal file
22
vendor/github.com/putdotio/go-putio/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 H. İbrahim Güngör
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
42
vendor/github.com/putdotio/go-putio/putio/account.go
generated
vendored
Normal file
42
vendor/github.com/putdotio/go-putio/putio/account.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// AccountService is the service to gather information about user account.
|
||||||
|
type AccountService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info retrieves user account information.
|
||||||
|
func (a *AccountService) Info(ctx context.Context) (AccountInfo, error) {
|
||||||
|
req, err := a.client.NewRequest(ctx, "GET", "/v2/account/info", nil)
|
||||||
|
if err != nil {
|
||||||
|
return AccountInfo{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Info AccountInfo
|
||||||
|
}
|
||||||
|
_, err = a.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return AccountInfo{}, err
|
||||||
|
}
|
||||||
|
return r.Info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings retrieves user preferences.
|
||||||
|
func (a *AccountService) Settings(ctx context.Context) (Settings, error) {
|
||||||
|
req, err := a.client.NewRequest(ctx, "GET", "/v2/account/settings", nil)
|
||||||
|
if err != nil {
|
||||||
|
return Settings{}, nil
|
||||||
|
}
|
||||||
|
var r struct {
|
||||||
|
Settings Settings
|
||||||
|
}
|
||||||
|
_, err = a.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return Settings{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Settings, nil
|
||||||
|
}
|
180
vendor/github.com/putdotio/go-putio/putio/client.go
generated
vendored
Normal file
180
vendor/github.com/putdotio/go-putio/putio/client.go
generated
vendored
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultUserAgent = "go-putio"
|
||||||
|
defaultMediaType = "application/json"
|
||||||
|
defaultBaseURL = "https://api.put.io"
|
||||||
|
defaultUploadURL = "https://upload.put.io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client manages communication with Put.io v2 API.
|
||||||
|
type Client struct {
|
||||||
|
// HTTP client used to communicate with Put.io API
|
||||||
|
client *http.Client
|
||||||
|
|
||||||
|
// Base URL for API requests
|
||||||
|
BaseURL *url.URL
|
||||||
|
|
||||||
|
// base url for upload requests
|
||||||
|
uploadURL *url.URL
|
||||||
|
|
||||||
|
// User agent for client
|
||||||
|
UserAgent string
|
||||||
|
|
||||||
|
// ExtraHeaders are passed to the API server on every request.
|
||||||
|
ExtraHeaders http.Header
|
||||||
|
|
||||||
|
// Services used for communicating with the API
|
||||||
|
Account *AccountService
|
||||||
|
Files *FilesService
|
||||||
|
Transfers *TransfersService
|
||||||
|
Zips *ZipsService
|
||||||
|
Friends *FriendsService
|
||||||
|
Events *EventsService
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns a new Put.io API client, using the htttpClient, which must
|
||||||
|
// be a new Oauth2 enabled http.Client. If httpClient is not defined, default
|
||||||
|
// HTTP client is used.
|
||||||
|
func NewClient(httpClient *http.Client) *Client {
|
||||||
|
if httpClient == nil {
|
||||||
|
httpClient = http.DefaultClient
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL, _ := url.Parse(defaultBaseURL)
|
||||||
|
uploadURL, _ := url.Parse(defaultUploadURL)
|
||||||
|
c := &Client{
|
||||||
|
client: httpClient,
|
||||||
|
BaseURL: baseURL,
|
||||||
|
uploadURL: uploadURL,
|
||||||
|
UserAgent: defaultUserAgent,
|
||||||
|
ExtraHeaders: make(http.Header),
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Account = &AccountService{client: c}
|
||||||
|
c.Files = &FilesService{client: c}
|
||||||
|
c.Transfers = &TransfersService{client: c}
|
||||||
|
c.Zips = &ZipsService{client: c}
|
||||||
|
c.Friends = &FriendsService{client: c}
|
||||||
|
c.Events = &EventsService{client: c}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) ValidateToken(ctx context.Context) (userID *int64, err error) {
|
||||||
|
req, err := c.NewRequest(ctx, "GET", "/v2/oauth2/validate", nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var r struct {
|
||||||
|
UserID *int64 `json:"user_id"`
|
||||||
|
}
|
||||||
|
_, err = c.Do(req, &r)
|
||||||
|
return r.UserID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest creates an API request. A relative URL can be provided via
|
||||||
|
// relURL, which will be resolved to the BaseURL of the Client.
|
||||||
|
func (c *Client) NewRequest(ctx context.Context, method, relURL string, body io.Reader) (*http.Request, error) {
|
||||||
|
rel, err := url.Parse(relURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var u *url.URL
|
||||||
|
// XXX: workaroud for upload endpoint. upload method has a different base url,
|
||||||
|
// so we've a special case for testing purposes.
|
||||||
|
if relURL == "/v2/files/upload" {
|
||||||
|
u = c.uploadURL.ResolveReference(rel)
|
||||||
|
} else {
|
||||||
|
u = c.BaseURL.ResolveReference(rel)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(method, u.String(), body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
req.Header.Set("Accept", defaultMediaType)
|
||||||
|
req.Header.Set("User-Agent", c.UserAgent)
|
||||||
|
|
||||||
|
// merge headers with extra headers
|
||||||
|
for header, values := range c.ExtraHeaders {
|
||||||
|
for _, value := range values {
|
||||||
|
req.Header.Add(header, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do sends an API request and returns the API response. The API response is
|
||||||
|
// JSON decoded and stored in the value pointed to by v, or returned as an
|
||||||
|
// error if an API error has occurred. Response body is closed at all cases except
|
||||||
|
// v is nil. If v is nil, response body is not closed and the body can be used
|
||||||
|
// for streaming.
|
||||||
|
func (c *Client) Do(r *http.Request, v interface{}) (*http.Response, error) {
|
||||||
|
resp, err := c.client.Do(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = checkResponse(resp)
|
||||||
|
if err != nil {
|
||||||
|
// close the body at all times if there is an http error
|
||||||
|
resp.Body.Close()
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == nil {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the body for all cases from here
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(v)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkResponse is the entrypoint to reading the API response. If the response
|
||||||
|
// status code is not in success range, it will try to return a structured
|
||||||
|
// error.
|
||||||
|
func checkResponse(r *http.Response) error {
|
||||||
|
status := r.StatusCode
|
||||||
|
switch {
|
||||||
|
case status >= 200 && status <= 399:
|
||||||
|
return nil
|
||||||
|
case status >= 400 && status <= 599:
|
||||||
|
// server returns json
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected status code: %d", status)
|
||||||
|
}
|
||||||
|
errorResponse := &ErrorResponse{Response: r}
|
||||||
|
data, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("body read error: %s. status: %v. Details: %v:", err, status, string(data[:250]))
|
||||||
|
}
|
||||||
|
if len(data) > 0 {
|
||||||
|
err = json.Unmarshal(data, errorResponse)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("json decod error: %s. status: %v. Details: %v:", err, status, string(data[:250]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorResponse
|
||||||
|
}
|
11
vendor/github.com/putdotio/go-putio/putio/doc.go
generated
vendored
Normal file
11
vendor/github.com/putdotio/go-putio/putio/doc.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Package putio is the Put.io API v2 client for Go.
|
||||||
|
//
|
||||||
|
// The go-putio package does not directly handle authentication. Instead, when
|
||||||
|
// creating a new client, pass an http.Client that can handle authentication for
|
||||||
|
// you. The easiest and recommended way to do this is using the golang.org/x/oauth2
|
||||||
|
// library, but you can always use any other library that provides an http.Client.
|
||||||
|
//
|
||||||
|
// Note that when using an authenticated Client, all calls made by the client will
|
||||||
|
// include the specified OAuth token. Therefore, authenticated clients should
|
||||||
|
// almost never be shared between different users.
|
||||||
|
package putio
|
25
vendor/github.com/putdotio/go-putio/putio/error.go
generated
vendored
Normal file
25
vendor/github.com/putdotio/go-putio/putio/error.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrorResponse reports the error caused by an API request.
|
||||||
|
type ErrorResponse struct {
|
||||||
|
Response *http.Response `json:"-"`
|
||||||
|
|
||||||
|
Message string `json:"error_message"`
|
||||||
|
Type string `json:"error_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ErrorResponse) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Type: %v Message: %q. Original error: %v %v: %v",
|
||||||
|
e.Type,
|
||||||
|
e.Message,
|
||||||
|
e.Response.Request.Method,
|
||||||
|
e.Response.Request.URL,
|
||||||
|
e.Response.Status,
|
||||||
|
)
|
||||||
|
}
|
44
vendor/github.com/putdotio/go-putio/putio/events.go
generated
vendored
Normal file
44
vendor/github.com/putdotio/go-putio/putio/events.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// EventsService is the service to gather information about user's events.
|
||||||
|
type EventsService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: events list returns inconsistent data structures.
|
||||||
|
|
||||||
|
// List gets list of dashboard events. It includes downloads and share events.
|
||||||
|
func (e *EventsService) List(ctx context.Context) ([]Event, error) {
|
||||||
|
req, err := e.client.NewRequest(ctx, "GET", "/v2/events/list", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Events []Event
|
||||||
|
}
|
||||||
|
_, err = e.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return r.Events, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Clears all all dashboard events.
|
||||||
|
func (e *EventsService) Delete(ctx context.Context) error {
|
||||||
|
req, err := e.client.NewRequest(ctx, "POST", "/v2/events/delete", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = e.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
429
vendor/github.com/putdotio/go-putio/putio/files.go
generated
vendored
Normal file
429
vendor/github.com/putdotio/go-putio/putio/files.go
generated
vendored
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FilesService is a general service to gather information about user files,
|
||||||
|
// such as listing, searching, creating new ones, or just fetching a single
|
||||||
|
// file.
|
||||||
|
type FilesService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get fetches file metadata for given file ID.
|
||||||
|
func (f *FilesService) Get(ctx context.Context, id int64) (File, error) {
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/"+itoa(id), nil)
|
||||||
|
if err != nil {
|
||||||
|
return File{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
File File `json:"file"`
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return File{}, err
|
||||||
|
}
|
||||||
|
return r.File, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// List fetches children for given directory ID.
|
||||||
|
func (f *FilesService) List(ctx context.Context, id int64) (children []File, parent File, err error) {
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/list?parent_id="+itoa(id)+"&per_page=1000", nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var r struct {
|
||||||
|
Files []File `json:"files"`
|
||||||
|
Parent File `json:"parent"`
|
||||||
|
Cursor string `json:"cursor"`
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
children = append(children, r.Files...)
|
||||||
|
parent = r.Parent
|
||||||
|
for r.Cursor != "" {
|
||||||
|
body := strings.NewReader(`{"cursor": "` + r.Cursor + `"}`)
|
||||||
|
req, err = f.client.NewRequest(ctx, "POST", "/v2/files/list/continue", body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Set("content-type", "application/json")
|
||||||
|
r.Files = nil
|
||||||
|
r.Cursor = ""
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
children = append(children, r.Files...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// URL returns a URL of the file for downloading or streaming.
|
||||||
|
func (f *FilesService) URL(ctx context.Context, id int64, useTunnel bool) (string, error) {
|
||||||
|
notunnel := "notunnel=1"
|
||||||
|
if useTunnel {
|
||||||
|
notunnel = "notunnel=0"
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/"+itoa(id)+"/url?"+notunnel, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.URL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFolder creates a new folder under parent.
|
||||||
|
func (f *FilesService) CreateFolder(ctx context.Context, name string, parent int64) (File, error) {
|
||||||
|
if name == "" {
|
||||||
|
return File{}, fmt.Errorf("empty folder name")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("name", name)
|
||||||
|
params.Set("parent_id", itoa(parent))
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/create-folder", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return File{}, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
File File `json:"file"`
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return File{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.File, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes given files.
|
||||||
|
func (f *FilesService) Delete(ctx context.Context, files ...int64) error {
|
||||||
|
if len(files) == 0 {
|
||||||
|
return fmt.Errorf("no file id is given")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
for _, id := range files {
|
||||||
|
ids = append(ids, itoa(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("file_ids", strings.Join(ids, ","))
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/delete", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename change the name of the file to newname.
|
||||||
|
func (f *FilesService) Rename(ctx context.Context, id int64, newname string) error {
|
||||||
|
if newname == "" {
|
||||||
|
return fmt.Errorf("new filename cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("file_id", itoa(id))
|
||||||
|
params.Set("name", newname)
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/rename", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move moves files to the given destination.
|
||||||
|
func (f *FilesService) Move(ctx context.Context, parent int64, files ...int64) error {
|
||||||
|
if len(files) == 0 {
|
||||||
|
return fmt.Errorf("no files given")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
for _, file := range files {
|
||||||
|
ids = append(ids, itoa(file))
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("file_ids", strings.Join(ids, ","))
|
||||||
|
params.Set("parent_id", itoa(parent))
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/move", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload reads from given io.Reader and uploads the file contents to Put.io
|
||||||
|
// servers under directory given by parent. If parent is negative, user's
|
||||||
|
// prefered folder is used.
|
||||||
|
//
|
||||||
|
// If the uploaded file is a torrent file, Put.io will interpret it as a
|
||||||
|
// transfer and Transfer field will be present to represent the status of the
|
||||||
|
// tranfer. Likewise, if the uploaded file is a regular file, Transfer field
|
||||||
|
// would be nil and the uploaded file will be represented by the File field.
|
||||||
|
//
|
||||||
|
// This method reads the file contents into the memory, so it should be used for
|
||||||
|
// <150MB files.
|
||||||
|
func (f *FilesService) Upload(ctx context.Context, r io.Reader, filename string, parent int64) (Upload, error) {
|
||||||
|
if filename == "" {
|
||||||
|
return Upload{}, fmt.Errorf("filename cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
mw := multipart.NewWriter(&buf)
|
||||||
|
|
||||||
|
// negative parent means use user's prefered download folder.
|
||||||
|
if parent >= 0 {
|
||||||
|
err := mw.WriteField("parent_id", itoa(parent))
|
||||||
|
if err != nil {
|
||||||
|
return Upload{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
formfile, err := mw.CreateFormFile("file", filename)
|
||||||
|
if err != nil {
|
||||||
|
return Upload{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(formfile, r)
|
||||||
|
if err != nil {
|
||||||
|
return Upload{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mw.Close()
|
||||||
|
if err != nil {
|
||||||
|
return Upload{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/upload", &buf)
|
||||||
|
if err != nil {
|
||||||
|
return Upload{}, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", mw.FormDataContentType())
|
||||||
|
|
||||||
|
var response struct {
|
||||||
|
Upload
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &response)
|
||||||
|
if err != nil {
|
||||||
|
return Upload{}, err
|
||||||
|
}
|
||||||
|
return response.Upload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search makes a search request with the given query. Servers return 50
|
||||||
|
// results at a time. The URL for the next 50 results are in Next field. If
|
||||||
|
// page is -1, all results are returned.
|
||||||
|
func (f *FilesService) Search(ctx context.Context, query string, page int64) (Search, error) {
|
||||||
|
if page == 0 || page < -1 {
|
||||||
|
return Search{}, fmt.Errorf("invalid page number")
|
||||||
|
}
|
||||||
|
if query == "" {
|
||||||
|
return Search{}, fmt.Errorf("no query given")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/search/"+query+"/page/"+itoa(page), nil)
|
||||||
|
if err != nil {
|
||||||
|
return Search{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r Search
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return Search{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared returns list of shared files and share information.
|
||||||
|
func (f *FilesService) shared(ctx context.Context) ([]share, error) {
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/shared", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Shared []share
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Shared, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SharedWith returns list of users the given file is shared with.
|
||||||
|
func (f *FilesService) sharedWith(ctx context.Context, id int64) ([]share, error) {
|
||||||
|
// FIXME: shared-with returns different json structure than /shared/
|
||||||
|
// endpoint. so it's not an exported method until a common structure is
|
||||||
|
// decided
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/"+itoa(id)+"/shared-with", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Shared []share `json:"shared-with"`
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Shared, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtitles lists available subtitles for the given file for user's prefered
|
||||||
|
// subtitle language.
|
||||||
|
func (f *FilesService) Subtitles(ctx context.Context, id int64) ([]Subtitle, error) {
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/"+itoa(id)+"/subtitles", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Subtitles []Subtitle
|
||||||
|
Default string
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Subtitles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadSubtitle sends the contents of the subtitle file. If the key is empty string,
|
||||||
|
// `default` key is used. This key is used to search for a subtitle in the
|
||||||
|
// following order and returns the first match:
|
||||||
|
// - A subtitle file that has identical parent folder and name with the video.
|
||||||
|
// - Subtitle file extracted from video if the format is MKV.
|
||||||
|
// - First match from OpenSubtitles.org.
|
||||||
|
func (f *FilesService) DownloadSubtitle(ctx context.Context, id int64, key string, format string) (io.ReadCloser, error) {
|
||||||
|
if key == "" {
|
||||||
|
key = "default"
|
||||||
|
}
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/"+itoa(id)+"/subtitles/"+key, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := f.client.Do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HLSPlaylist serves a HLS playlist for a video file. Use “all” as
|
||||||
|
// subtitleKey to get available subtitles for user’s preferred languages.
|
||||||
|
func (f *FilesService) HLSPlaylist(ctx context.Context, id int64, subtitleKey string) (io.ReadCloser, error) {
|
||||||
|
if subtitleKey == "" {
|
||||||
|
return nil, fmt.Errorf("empty subtitle key is given")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/files/"+itoa(id)+"/hls/media.m3u8?subtitle_key"+subtitleKey, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := f.client.Do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetVideoPosition sets default video position for a video file.
|
||||||
|
func (f *FilesService) SetVideoPosition(ctx context.Context, id int64, t int) error {
|
||||||
|
if t < 0 {
|
||||||
|
return fmt.Errorf("time cannot be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("time", strconv.Itoa(t))
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/"+itoa(id)+"/start-from", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteVideoPosition deletes video position for a video file.
|
||||||
|
func (f *FilesService) DeleteVideoPosition(ctx context.Context, id int64) error {
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/files/"+itoa(id)+"/start-from/delete", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func itoa(i int64) string {
|
||||||
|
return strconv.FormatInt(i, 10)
|
||||||
|
}
|
124
vendor/github.com/putdotio/go-putio/putio/friends.go
generated
vendored
Normal file
124
vendor/github.com/putdotio/go-putio/putio/friends.go
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FriendsService is the service to operate on user friends.
|
||||||
|
type FriendsService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// List lists users friends.
|
||||||
|
func (f *FriendsService) List(ctx context.Context) ([]Friend, error) {
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/friends/list", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Friends []Friend
|
||||||
|
Total int
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Friends, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitingRequests lists user's pending friend requests.
|
||||||
|
func (f *FriendsService) WaitingRequests(ctx context.Context) ([]Friend, error) {
|
||||||
|
req, err := f.client.NewRequest(ctx, "GET", "/v2/friends/waiting-requests", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Friends []Friend
|
||||||
|
}
|
||||||
|
_, err = f.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Friends, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request sends a friend request to the given username.
|
||||||
|
func (f *FriendsService) Request(ctx context.Context, username string) error {
|
||||||
|
if username == "" {
|
||||||
|
return fmt.Errorf("empty username")
|
||||||
|
}
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/friends/"+username+"/request", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Approve approves a friend request from the given username.
|
||||||
|
func (f *FriendsService) Approve(ctx context.Context, username string) error {
|
||||||
|
if username == "" {
|
||||||
|
return fmt.Errorf("empty username")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/friends/"+username+"/approve", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deny denies a friend request from the given username.
|
||||||
|
func (f *FriendsService) Deny(ctx context.Context, username string) error {
|
||||||
|
if username == "" {
|
||||||
|
return fmt.Errorf("empty username")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/friends/"+username+"/deny", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfriend removed friend from user's friend list.
|
||||||
|
func (f *FriendsService) Unfriend(ctx context.Context, username string) error {
|
||||||
|
if username == "" {
|
||||||
|
return fmt.Errorf("empty username")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := f.client.NewRequest(ctx, "POST", "/v2/friends/"+username+"/unfriend", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = f.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
33
vendor/github.com/putdotio/go-putio/putio/time.go
generated
vendored
Normal file
33
vendor/github.com/putdotio/go-putio/putio/time.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Time is a wrapper around time.Time that can be unmarshalled from a JSON
|
||||||
|
// string formatted as "2016-04-19T15:44:42". All methods of time.Time can be
|
||||||
|
// called on Time.
|
||||||
|
type Time struct {
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Time) String() string {
|
||||||
|
return t.Time.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
|
func (t *Time) UnmarshalJSON(data []byte) error {
|
||||||
|
// put.io API has inconsistent time layouts for different endpoints, such
|
||||||
|
// as /files and /events
|
||||||
|
var timeLayouts = []string{`"2006-01-02T15:04:05"`, `"2006-01-02 15:04:05"`}
|
||||||
|
|
||||||
|
s := string(data)
|
||||||
|
var err error
|
||||||
|
var tm time.Time
|
||||||
|
for _, layout := range timeLayouts {
|
||||||
|
tm, err = time.ParseInLocation(layout, s, time.UTC)
|
||||||
|
if err == nil {
|
||||||
|
t.Time = tm
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
154
vendor/github.com/putdotio/go-putio/putio/transfers.go
generated
vendored
Normal file
154
vendor/github.com/putdotio/go-putio/putio/transfers.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TransfersService is the service to operate on torrent transfers, such as
|
||||||
|
// adding a torrent or magnet link, retrying a current one etc.
|
||||||
|
type TransfersService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// List lists all active transfers. If a transfer is completed, it will not be
|
||||||
|
// available in response.
|
||||||
|
func (t *TransfersService) List(ctx context.Context) ([]Transfer, error) {
|
||||||
|
req, err := t.client.NewRequest(ctx, "GET", "/v2/transfers/list", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Transfers []Transfer
|
||||||
|
}
|
||||||
|
_, err = t.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Transfers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add creates a new transfer. A valid torrent or a magnet URL is expected.
|
||||||
|
// Parent is the folder where the new transfer is downloaded to. If a negative
|
||||||
|
// value is given, user's preferred download folder is used. CallbackURL is
|
||||||
|
// used to send a POST request after the transfer is finished downloading.
|
||||||
|
func (t *TransfersService) Add(ctx context.Context, urlStr string, parent int64, callbackURL string) (Transfer, error) {
|
||||||
|
if urlStr == "" {
|
||||||
|
return Transfer{}, fmt.Errorf("empty URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("url", urlStr)
|
||||||
|
// negative values indicate user's preferred download folder. don't include
|
||||||
|
// it in the request
|
||||||
|
if parent >= 0 {
|
||||||
|
params.Set("save_parent_id", itoa(parent))
|
||||||
|
}
|
||||||
|
if callbackURL != "" {
|
||||||
|
params.Set("callback_url", callbackURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := t.client.NewRequest(ctx, "POST", "/v2/transfers/add", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return Transfer{}, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Transfer Transfer
|
||||||
|
}
|
||||||
|
_, err = t.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return Transfer{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Transfer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the given transfer's properties.
|
||||||
|
func (t *TransfersService) Get(ctx context.Context, id int64) (Transfer, error) {
|
||||||
|
req, err := t.client.NewRequest(ctx, "GET", "/v2/transfers/"+itoa(id), nil)
|
||||||
|
if err != nil {
|
||||||
|
return Transfer{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Transfer Transfer
|
||||||
|
}
|
||||||
|
_, err = t.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return Transfer{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Transfer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retry retries previously failed transfer.
|
||||||
|
func (t *TransfersService) Retry(ctx context.Context, id int64) (Transfer, error) {
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("id", itoa(id))
|
||||||
|
|
||||||
|
req, err := t.client.NewRequest(ctx, "POST", "/v2/transfers/retry", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return Transfer{}, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Transfer Transfer
|
||||||
|
}
|
||||||
|
_, err = t.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return Transfer{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Transfer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel deletes given transfers.
|
||||||
|
func (t *TransfersService) Cancel(ctx context.Context, ids ...int64) error {
|
||||||
|
if len(ids) == 0 {
|
||||||
|
return fmt.Errorf("no id given")
|
||||||
|
}
|
||||||
|
|
||||||
|
var transfers []string
|
||||||
|
for _, id := range ids {
|
||||||
|
transfers = append(transfers, itoa(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("transfer_ids", strings.Join(transfers, ","))
|
||||||
|
|
||||||
|
req, err := t.client.NewRequest(ctx, "POST", "/v2/transfers/cancel", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = t.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean removes completed transfers from the transfer list.
|
||||||
|
func (t *TransfersService) Clean(ctx context.Context) error {
|
||||||
|
req, err := t.client.NewRequest(ctx, "POST", "/v2/transfers/clean", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
_, err = t.client.Do(req, &struct{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
166
vendor/github.com/putdotio/go-putio/putio/types.go
generated
vendored
Normal file
166
vendor/github.com/putdotio/go-putio/putio/types.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// File represents a Put.io file.
|
||||||
|
type File struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
ContentType string `json:"content_type"`
|
||||||
|
CreatedAt *Time `json:"created_at"`
|
||||||
|
UpdatedAt *Time `json:"updated_at"`
|
||||||
|
FirstAccessedAt *Time `json:"first_accessed_at"`
|
||||||
|
ParentID int64 `json:"parent_id"`
|
||||||
|
Screenshot string `json:"screenshot"`
|
||||||
|
OpensubtitlesHash string `json:"opensubtitles_hash"`
|
||||||
|
IsMP4Available bool `json:"is_mp4_available"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
CRC32 string `json:"crc32"`
|
||||||
|
IsShared bool `json:"is_shared"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) String() string {
|
||||||
|
return fmt.Sprintf("<ID: %v Name: %q Size: %v>", f.ID, f.Name, f.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDir reports whether the file is a directory.
|
||||||
|
func (f *File) IsDir() bool {
|
||||||
|
return f.ContentType == "application/x-directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload represents a Put.io upload. If the uploaded file is a torrent file,
|
||||||
|
// Transfer field will represent the status of the transfer.
|
||||||
|
type Upload struct {
|
||||||
|
File *File `json:"file"`
|
||||||
|
Transfer *Transfer `json:"transfer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search represents a search response.
|
||||||
|
type Search struct {
|
||||||
|
Files []File `json:"files"`
|
||||||
|
Next string `json:"next"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer represents a Put.io transfer state.
|
||||||
|
type Transfer struct {
|
||||||
|
Availability int `json:"availability"`
|
||||||
|
CallbackURL string `json:"callback_url"`
|
||||||
|
CreatedAt *Time `json:"created_at"`
|
||||||
|
CreatedTorrent bool `json:"created_torrent"`
|
||||||
|
ClientIP string `json:"client_ip"`
|
||||||
|
|
||||||
|
// FIXME: API returns either string or float non-deterministically.
|
||||||
|
// CurrentRatio float32 `json:"current_ratio"`
|
||||||
|
|
||||||
|
DownloadSpeed int `json:"down_speed"`
|
||||||
|
Downloaded int64 `json:"downloaded"`
|
||||||
|
DownloadID int64 `json:"download_id"`
|
||||||
|
ErrorMessage string `json:"error_message"`
|
||||||
|
EstimatedTime int64 `json:"estimated_time"`
|
||||||
|
Extract bool `json:"extract"`
|
||||||
|
FileID int64 `json:"file_id"`
|
||||||
|
FinishedAt *Time `json:"finished_at"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
IsPrivate bool `json:"is_private"`
|
||||||
|
MagnetURI string `json:"magneturi"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
PeersConnected int `json:"peers_connected"`
|
||||||
|
PeersGettingFromUs int `json:"peers_getting_from_us"`
|
||||||
|
PeersSendingToUs int `json:"peers_sending_to_us"`
|
||||||
|
PercentDone int `json:"percent_done"`
|
||||||
|
SaveParentID int64 `json:"save_parent_id"`
|
||||||
|
SecondsSeeding int `json:"seconds_seeding"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
StatusMessage string `json:"status_message"`
|
||||||
|
SubscriptionID int `json:"subscription_id"`
|
||||||
|
TorrentLink string `json:"torrent_link"`
|
||||||
|
TrackerMessage string `json:"tracker_message"`
|
||||||
|
Trackers string `json:"tracker"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
UploadSpeed int `json:"up_speed"`
|
||||||
|
Uploaded int64 `json:"uploaded"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountInfo represents user's account information.
|
||||||
|
type AccountInfo struct {
|
||||||
|
AccountActive bool `json:"account_active"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
DaysUntilFilesDeletion int `json:"days_until_files_deletion"`
|
||||||
|
DefaultSubtitleLanguage string `json:"default_subtitle_language"`
|
||||||
|
Disk struct {
|
||||||
|
Avail int64 `json:"avail"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
Used int64 `json:"used"`
|
||||||
|
} `json:"disk"`
|
||||||
|
HasVoucher bool `json:"has_voucher"`
|
||||||
|
Mail string `json:"mail"`
|
||||||
|
PlanExpirationDate string `json:"plan_expiration_date"`
|
||||||
|
Settings Settings `json:"settings"`
|
||||||
|
SimultaneousDownloadLimit int `json:"simultaneous_download_limit"`
|
||||||
|
SubtitleLanguages []string `json:"subtitle_languages"`
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings represents user's personal settings.
|
||||||
|
type Settings struct {
|
||||||
|
CallbackURL string `json:"callback_url"`
|
||||||
|
DefaultDownloadFolder int64 `json:"default_download_folder"`
|
||||||
|
DefaultSubtitleLanguage string `json:"default_subtitle_language"`
|
||||||
|
DownloadFolderUnset bool `json:"download_folder_unset"`
|
||||||
|
IsInvisible bool `json:"is_invisible"`
|
||||||
|
Nextepisode bool `json:"nextepisode"`
|
||||||
|
PrivateDownloadHostIP interface{} `json:"private_download_host_ip"`
|
||||||
|
PushoverToken string `json:"pushover_token"`
|
||||||
|
Routing string `json:"routing"`
|
||||||
|
Sorting string `json:"sorting"`
|
||||||
|
SSLEnabled bool `json:"ssl_enabled"`
|
||||||
|
StartFrom bool `json:"start_from"`
|
||||||
|
SubtitleLanguages []string `json:"subtitle_languages"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Friend represents Put.io user's friend.
|
||||||
|
type Friend struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zip represents Put.io zip file.
|
||||||
|
type Zip struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
CreatedAt *Time `json:"created_at"`
|
||||||
|
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtitle represents a subtitle.
|
||||||
|
type Subtitle struct {
|
||||||
|
Key string
|
||||||
|
Language string
|
||||||
|
Name string
|
||||||
|
Source string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event represents a Put.io event. It could be a transfer or a shared file.
|
||||||
|
type Event struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
FileID int64 `json:"file_id"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
TransferName string `json:"transfer_name"`
|
||||||
|
TransferSize int64 `json:"transfer_size"`
|
||||||
|
CreatedAt *Time `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type share struct {
|
||||||
|
FileID int64 `json:"file_id"`
|
||||||
|
Filename string `json:"file_name"`
|
||||||
|
// Number of friends the file is shared with
|
||||||
|
SharedWith int64 `json:"shared_with"`
|
||||||
|
}
|
80
vendor/github.com/putdotio/go-putio/putio/zips.go
generated
vendored
Normal file
80
vendor/github.com/putdotio/go-putio/putio/zips.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package putio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ZipsService is the service manage zip streams.
|
||||||
|
type ZipsService struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gives detailed information about the given zip file id.
|
||||||
|
func (z *ZipsService) Get(ctx context.Context, id int64) (Zip, error) {
|
||||||
|
req, err := z.client.NewRequest(ctx, "GET", "/v2/zips/"+itoa(id), nil)
|
||||||
|
if err != nil {
|
||||||
|
return Zip{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r Zip
|
||||||
|
_, err = z.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return Zip{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// List lists active zip files.
|
||||||
|
func (z *ZipsService) List(ctx context.Context) ([]Zip, error) {
|
||||||
|
req, err := z.client.NewRequest(ctx, "GET", "/v2/zips/list", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Zips []Zip
|
||||||
|
}
|
||||||
|
_, err = z.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Zips, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates zip files for given file IDs. If the operation is successful,
|
||||||
|
// a zip ID will be returned to keep track of zip process.
|
||||||
|
func (z *ZipsService) Create(ctx context.Context, fileIDs ...int64) (int64, error) {
|
||||||
|
if len(fileIDs) == 0 {
|
||||||
|
return 0, fmt.Errorf("no file id given")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
for _, id := range fileIDs {
|
||||||
|
ids = append(ids, itoa(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
params := url.Values{}
|
||||||
|
params.Set("file_ids", strings.Join(ids, ","))
|
||||||
|
|
||||||
|
req, err := z.client.NewRequest(ctx, "POST", "/v2/zips/create", strings.NewReader(params.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
ID int64 `json:"zip_id"`
|
||||||
|
}
|
||||||
|
_, err = z.client.Do(req, &r)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.ID, nil
|
||||||
|
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -143,6 +143,8 @@ github.com/pkg/errors
|
|||||||
github.com/pkg/sftp
|
github.com/pkg/sftp
|
||||||
# github.com/pmezard/go-difflib v1.0.0
|
# github.com/pmezard/go-difflib v1.0.0
|
||||||
github.com/pmezard/go-difflib/difflib
|
github.com/pmezard/go-difflib/difflib
|
||||||
|
# github.com/putdotio/go-putio v0.0.0-20190731220109-37c0795af843
|
||||||
|
github.com/putdotio/go-putio/putio
|
||||||
# github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46
|
# github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46
|
||||||
github.com/rfjakob/eme
|
github.com/rfjakob/eme
|
||||||
# github.com/russross/blackfriday v1.5.2
|
# github.com/russross/blackfriday v1.5.2
|
||||||
|
Loading…
Reference in New Issue
Block a user