elevengo

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2020 License: MIT Imports: 16 Imported by: 4

README

ElevenGo

Version Reference License

A Golang API wrapper for 115 Cloud Storage Service.

Example

import "github.com/deadblue/elevengo"

// Create agent
agent = elevengo.Default()

// Import credentials to login
cr := &elevengo.Credential{
    UID: "",
    CID: "",
    SEID: "",
}
if err := agent.CredentialImport(cr); err != nil {
    panic(err)
}

// List files under root.
for cursor := elevengo.FileCursor(); cursor.HasMore(); cursor.Next() {
    if files, err := agent.FileList("0", cursor); err != nil {
        panic(err)
    } else {
        // TODO: deal with the files
    }
}

You can find more examples from reference.

Features

  • Login
    • Import credential from cookies
    • Login via QRCode
    • Get signed in user information
  • File
    • List
    • Search
    • Rename
    • Move
    • Copy
    • Delete
    • Mkdir
    • Stat
    • Storage Stat
    • Download
    • Upload
    • Video HLS
    • Image URL
  • Offline
    • List tasks
    • Create URL task(s)
    • Delete tasks
    • Clear tasks
  • Other
    • Captcha

TODO list

  • Implement download/upload method, with progress echo.
  • Move example codes out of comment.
  • Handle more upstream errors.
  • Caller can swtich upstream API between HTTP/HTTPS.

License

MIT

Documentation

Overview

"elevengo" is an API wrapper for 115 NetDisk service, it bases on 115 web APIs which captured from their web pages.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsFileExist

func IsFileExist(err error) bool

func IsFileNotExist

func IsFileNotExist(err error) bool

func IsOfflineCaptcha

func IsOfflineCaptcha(err error) bool

func IsOfflineExist

func IsOfflineExist(err error) bool

func IsQrcodeExpire

func IsQrcodeExpire(err error) bool

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent holds signed-in user's credentials, and provides methods to access upstream server's features, such as file management, offline download, etc.

func Default

func Default() *Agent

Create an Agent in default settings.

func New

func New(opts *Options) *Agent

Create a customized Agent.

func (*Agent) CaptchaKeyImage

func (a *Agent) CaptchaKeyImage(session *CaptchaSession, index int) ([]byte, error)

Get one CAPTCHA key image data.

You can call this method multiple times, it will return the same character in different font on every calling.

It is useful when you try to train your CAPTCHA solver.

func (*Agent) CaptchaStart

func (a *Agent) CaptchaStart() (session *CaptchaSession, err error)

Start a CAPTCHA session.

Example:

// Start CAPTCHA session
session, err := agent.CaptchaStart()
if err != nil {
	panic(err)
}
// TODO: Solve the CAPTCHA here.
// Submit CAPTCHA code
if err = agent.CaptchaSubmit(session, code); err != nil {
	panic(err)
}

func (*Agent) CaptchaSubmit

func (a *Agent) CaptchaSubmit(session *CaptchaSession, code string) (err error)

Submit the CAPTCHA code.

func (*Agent) CredentialExport added in v0.1.3

func (a *Agent) CredentialExport() (cr Credential, err error)

Export credentials from agent, caller can store it for future use.

func (*Agent) CredentialImport added in v0.1.3

func (a *Agent) CredentialImport(cr *Credential) (err error)

Import credentials into agent.

func (*Agent) Download added in v0.1.4

func (a *Agent) Download(pickcode string, w io.Writer) (size int64, err error)

Download downloads a file from cloud, writes its content into w. If w implements io.Closer, it will be closed by method.

This method DOSE NOT support multi-thread/resuming, if caller require those, use thirdparty tools/libraries instead.

To monitor the downloading progress, caller can wrap w by "github.com/deadblue/gostream/observe".

func (*Agent) DownloadCreateTicket added in v0.1.4

func (a *Agent) DownloadCreateTicket(pickcode string) (ticket DownloadTicket, err error)

DownloadCreateTicket creates ticket which contails all necessary information to download a file. Caller can use thirdparty tools/libraries to perform downloading, such as wget/curl/aria2.

Example - Downlaod through curl:

// Create download ticket
ticket, err := agent.DownloadCreateTicket("pickcode")
if err != nil {
	log.Fatal(err)
}
// Download file via "curl"
cmd := exec.Command("/usr/bin/curl", ticket.Url)
for name, value := range ticket.Headers {
	cmd.Args = append(cmd.Args, "-H", fmt.Sprintf("%s: %s", name, value))
}
cmd.Args = append(cmd.Args, "-o", ticket.FileName)
if err = cmd.Run(); err != nil {
	log.Fatal(err)
}

func (*Agent) FileCopy

func (a *Agent) FileCopy(parentId string, fileIds ...string) (err error)

Copy files into specific directory.

func (*Agent) FileDelete

func (a *Agent) FileDelete(parentId string, fileIds ...string) (err error)

Delete files from a directory.

func (*Agent) FileList

func (a *Agent) FileList(parentId string, cursor Cursor) (files []*File, err error)

Get file list from specific directory.

The upstream API restricts the data count in response, so for a directory which contains a lot of files. you need pass a cursor to receive the cursor information, and use it to fetch remain files.

The cursor should be created by FileCursor(), and DO NOT pass it as nil even you try to get file list from a empty directory.

func (*Agent) FileMkdir

func (a *Agent) FileMkdir(parentId, name string) (directoryId string, err error)

Create a directory under a directory with specific name.

func (*Agent) FileMove

func (a *Agent) FileMove(parentId string, fileIds ...string) (err error)

Move files into specific directory.

func (*Agent) FileRename

func (a *Agent) FileRename(fileId, name string) (err error)

Rename file.

func (*Agent) FileSearch

func (a *Agent) FileSearch(rootId, keyword string, cursor Cursor) (files []*File, err error)

Recursively search files which's name contains the keyword and under the directory.

func (*Agent) FileStat

func (a *Agent) FileStat(fileId string) (info FileInfo, err error)

Get file information related to the file ID. Since the upstream response is cheap, this method cat not return more information.

func (*Agent) ImageUrl added in v0.1.4

func (a *Agent) ImageUrl(pickcode string) (link string, err error)

Get a image URL which can be embedded into web page.

func (*Agent) OfflineAdd

func (a *Agent) OfflineAdd(url ...string) (err error)

Add one or more offline tasks by URL.

func (*Agent) OfflineClear

func (a *Agent) OfflineClear(flag *OfflineClearFlag) (err error)

Clear specific type of offline tasks.

The "flag" parameter indicates which type of tasks will be clear, you can pass nil to clear the done tasks but keep the downloaded files.

func (*Agent) OfflineDelete

func (a *Agent) OfflineDelete(deleteFile bool, hash ...string) (err error)

Delete some offline tasks. if "deleteFile" is true, the downloaded files will be deleted.

func (*Agent) OfflineList

func (a *Agent) OfflineList(cursor Cursor) (tasks []*OfflineTask, err error)

Get some of offline tasks.

The upstream API returns at most 30 tasks for one request, caller need pass a cursor to receive the cursor information, and use it to get remain tasks.

The cursor should be created by OfflineCursor(), DO NOT pass it as nil.

func (*Agent) QrcodeLogin

func (a *Agent) QrcodeLogin(session *QrcodeSession) error

Login through QRcode. You SHOULD call this method ONLY when `QrcodeStatus.IsAllowed()` is true.

func (*Agent) QrcodeStart

func (a *Agent) QrcodeStart() (session *QrcodeSession, err error)

Start a QRcode login process.

Example:

session, err := agent.QrcodeStart()
if err != nil {
	panic(error)
}
// TODO: Show QRcode and prompt user to scan it on mobile app.
for {
	if status, err := agent.QrcodeStatus(session); err != nil {
		panic(err)
	} else {
		if status.IsAllowed() {
			err = agent.QrcodeLogin(session)
			break
		} else status.IsCanceled() {
			fmt.Println("User canceled this login!")
			break
		}
	}
}

func (*Agent) QrcodeStatus

func (a *Agent) QrcodeStatus(session *QrcodeSession) (status QrcodeStatus, err error)

Get QRcode status.

The upstream API uses a long-pull request for 30 seconds, so this API will also block at most 30 seconds, be careful to use it in main goroutine.

The QRcode has 4 status: - Waiting - Scanned - Allowed - Canceled

The QRcode will expire in 5 mimutes, when it expired, an error will be return, caller can use IsQrcodeExipre() to check that.

func (*Agent) StorageStat

func (a *Agent) StorageStat() (info StorageInfo, err error)

Get storage size information.

func (*Agent) Upload added in v0.1.4

func (a *Agent) Upload(parentId string, info UploadInfo, r io.Reader) (file *File, err error)

Upload uploads data as a file to cloud, and returns the file metadata on successful. If r implements io.Closer, it will be closed by method.

Example:

// To upload a regular file
file, err := os.Open("/path/to/file")
if err != nil {
	panic(err)
}
info, err := file.Stat()
if err != nil {
	panic(err)
}
// Caller can use "github.com/deadblue/gostream/observe" to monitor the
// uploading progress, please see the example code in that package.
metadata, err := agent.Upload("0", info, file)
if err != nil {
	panic(err)
} else {
	log.Printf("Uploaded file: %#v", metadata)
}

func (*Agent) UploadCreateTicket added in v0.1.4

func (a *Agent) UploadCreateTicket(parentId string, info UploadInfo) (ticket UploadTicket, err error)

UploadCreateTicket creates a ticket which contails all necessary information to upload a file. Caller can use thirdpary tools/libraries to perform the upload.

Example - Upload through curl:

filename := "/path/to/file"
// Get file info
info, err := os.Stat(filename)
if err != nil {
	log.Fatal(err)
}
// Create ticket
ticket, err := agent.UploadCreateTicket(parentId, info)
if err != nil {
	log.Fatal(err)
}
// Create temp file to receive upload response
tmpFile, err := ioutil.TempFile(os.TempDir(), "115-upload-")
if err != nil {
	log.Fatal(err)
}
defer os.Remove(tmpFile.Name())
// Construct curl command
cmd := exec.Command("/path/to/curl", ticket.Endpoint, "-o", tmpFile.Name(), "-#")
for name, value := range ticket.Values {
	cmd.Args = append(cmd.Args, "-F", fmt.Sprintf("%s=%s", name, value))
}
// NOTICE: File field should be at the end of the form.
cmd.Args = append(cmd.Args, "-F", fmt.Sprintf("%s=@%s", ticket.FileField, filename))
// Run the command
if err = cmd.Run(); err != nil {
	log.Fatal(err)
}
// Parse upload response
response, _ := ioutil.ReadAll(tmpFile)
file, err := agent.UploadParseResult(response)
if err != nil {
	log.Fatel(f)
} else {
	log.Printf("Uploaded file: %#v", file)
}

func (*Agent) UploadParseResult added in v0.1.4

func (a *Agent) UploadParseResult(content []byte) (file *File, err error)

UploadParseResult parses the raw upload response body. If caller performs upload ticket through thirdpary tools/libraries, he can call the method to parse the upload result.

func (*Agent) User added in v0.1.2

func (a *Agent) User() (info UserInfo)

Get signed in user information.

func (*Agent) Version

func (a *Agent) Version() string

func (*Agent) VideoHlsContent

func (a *Agent) VideoHlsContent(pickcode string) (content []byte, err error)

Get HLS content of a video.

For video file, the upstream server support HLS streaming. Caller can use this method to get the HLS content, and play it through thirdparty tools, such as "mpv".

Example:

// Get HLS content for a video
hls, err := agent.VideoHlsContent("pickcode")
if err != nil {
	log.Fatal(err)
}
// Start mpv process with reading file from STDIN
cmd := exec.Command("/path/to/mpv", "-")
cmd.Stdin = bytes.NewReader(hls)
if err = cmd.Run(); err != nil {
	log.Fatal(err)
}

type CaptchaSession

type CaptchaSession struct {
	// CAPTCHA image data.
	CodeImage []byte

	// CAPTCHA keys image data.
	KeysImage []byte
	// contains filtered or unexported fields
}

CaptchaSession holds CAPTCHA images and session information during a CAPTCHA process.

There are 4 Chinese characters on "CodeImage" and 10 Chinese characters on "KeysImage" (5 columns by 2 rows). User should find the 4 characters on "CodeImage" from "KeysImage", the indexes of these characters is the CAPTCHA code.

The index bases on 0, starts from left top corner, increases from left to right, then from top to bottom.

For example:

Assume the code image is

+---------------+
| J | F | C | H |
+---------------+

and the keys image is

+-------------------+
| A | B | C | D | E |
+-------------------+
| F | G | H | I | J |
+-------------------+

Then the CAPTCHA code is "9527", you can call Agent.CaptchaSubmit() to submit it.

type Credential added in v0.1.3

type Credential struct {
	UID  string
	CID  string
	SEID string
}

Credential contains required information that the upstream server uses to authenticate a signed-in user.

In detail, three cookies are required: "UID", "CID", "SEID", caller can find them from browser cookie storage.

type Cursor

type Cursor interface {

	// Return true if the cursor has not been used or there is some data remain.
	HasMore() bool

	// Move cursor to the start of the remaining data.
	Next()

	// Return total amount of the data.
	Total() int
}

Due to the upstream API restriction, some list methods can not get the whole data in one request. Cursor is design for these methods, to get data page-by-page.

There are two types of cursors for different methods:

- File cursor: created by FileCursor(), used in Agent.FileList() and Agent.FileSearch().

- Offline cursor: created by OfflineCursor(), used in Agent.OfflineList().

A typical usage (call FileList for example):

// Assume "agent" is an Agent instance, and "parentId" is the directory ID
// where you want to get file list from.
for cursor := FileCursor(); cursor.HasMore(); cursor.Next() {
	if files, err := agent.FileList(parentId, cursor); err != nil {
		// handle error
		break
	} else {
		// deal with the files
	}
}

func FileCursor

func FileCursor() Cursor

Create a cursor for "Agent.FileList()" and "Agent.FileSearch()".

func OfflineCursor

func OfflineCursor() Cursor

Create a cursor for "Agent.OfflineList()".

type DirectoryInfo added in v0.1.2

type DirectoryInfo struct {
	// Directory ID.
	Id string
	// Directory Name.
	Name string
}

DirectoryInfo only used in FileInfo.

type DownloadTicket

type DownloadTicket struct {
	// Download URL.
	Url string
	// Request headers which SHOULD be sent with download URL.
	Headers map[string]string
	// File name.
	FileName string
	// File size in bytes.
	FileSize int64
}

DownloadTicket contains all required information to download a file.

type File

type File struct {
	// True means a file.
	IsFile bool
	// True means a directory.
	IsDirectory bool
	// Unique ID for the file.
	FileId string
	// Parent directory ID.
	ParentId string
	// File name.
	Name string
	// File size in bytes, 0 for directory.
	Size int64
	// Pick code, you can use this to create a download ticket.
	PickCode string
	// Sha1 hash value of the file, empty for directory.
	Sha1 string
	// Create time of the file.
	CreateTime time.Time
	// Update time of the file.
	UpdateTime time.Time
}

File describe a remote file or directory.

type FileInfo

type FileInfo struct {
	// True means a file.
	IsFile bool
	// True means a directory.
	IsDirectory bool
	// File name.
	Name string
	// Pick code for downloading.
	PickCode string
	// Sha1 hash value of the file, empty for directory.
	Sha1 string
	// Create time of the file.
	CreateTime time.Time
	// Update time of the file.
	UpdateTime time.Time
	// Parent directory list.
	Parents []*DirectoryInfo
}

FileInfo is returned by FileStat(), contains basic information of a file.

type OfflineClearFlag

type OfflineClearFlag struct {
	// contains filtered or unexported fields
}

Parameter for "Agent.OfflineClear()" method. Default value is to clear all done tasks without deleteing downloaded files.

func (*OfflineClearFlag) All

func (f *OfflineClearFlag) All(delete bool) *OfflineClearFlag

Clear all tasks, delete the downloaded files if "delete" is true.

func (*OfflineClearFlag) Done

func (f *OfflineClearFlag) Done(delete bool) *OfflineClearFlag

Clear done tasks, delete the downloaded files if "delete" is true.

func (*OfflineClearFlag) Failed

func (f *OfflineClearFlag) Failed() *OfflineClearFlag

Clear failed tasks.

func (*OfflineClearFlag) Running

func (f *OfflineClearFlag) Running() *OfflineClearFlag

Clean running tasks.

type OfflineTask

type OfflineTask struct {
	// Unique hash of the task.
	InfoHash string
	// Task name.
	Name string
	// Task URL.
	Url string
	// Task status.
	Status OfflineTaskStatus
	// Download percent of the task, 0 to 100.
	Percent float64
	// File ID of the downloaded file on remote server.
	FileId string
}

OfflineTask describe a remote download task.

type OfflineTaskStatus

type OfflineTaskStatus int

Describe status of an offline task.

func (OfflineTaskStatus) IsDone

func (s OfflineTaskStatus) IsDone() bool

Return true if the task has been done.

func (OfflineTaskStatus) IsFailed

func (s OfflineTaskStatus) IsFailed() bool

Return true if the task has been failed.

func (OfflineTaskStatus) IsRunning

func (s OfflineTaskStatus) IsRunning() bool

Return true if the task is still running.

type Options added in v0.1.3

type Options struct {

	// Name of the agent, will be used in "User-Agent" request header.
	// Caller can customize it, while it does not affect any features.
	Name string

	// Logger for printing debug message.
	// Set to nil to disable the debug message.
	// Caller can implement one or simply use plugin.StdLogger.
	Logger plugin.Logger
}

Options for customize Agent.

type QrcodeSession

type QrcodeSession struct {
	// The raw data of QR code, caller should use thridparty tools/libraries
	// to convert it into QR code matrix or image.
	Content string
	// contains filtered or unexported fields
}

QrcodeSession holds the information during a QRcode login process.

type QrcodeStatus

type QrcodeStatus int

QrcodeStatus is returned by `Agent.QrcodeStatus()`. You can call `QrcodeStatus.IsXXX()` method to check the status, or directly check its value.

func (QrcodeStatus) IsAllowed

func (qs QrcodeStatus) IsAllowed() bool

Return true if user allowed this login process, you can call "Agent.QrcodeLogin()" after then.

func (QrcodeStatus) IsCanceled

func (qs QrcodeStatus) IsCanceled() bool

Return true if user canceled this login process.

func (QrcodeStatus) IsScanned

func (qs QrcodeStatus) IsScanned() bool

Return true if user has scanned the QRcode, but still not allow or cancel this login.

func (QrcodeStatus) IsWaiting

func (qs QrcodeStatus) IsWaiting() bool

Return true if user still does not scan the QRcode.

type StorageInfo

type StorageInfo struct {
	// Total size in bytes.
	Size int64
	// Used size in bytes.
	Used int64
	// Avail size in bytes.
	Avail int64
}

Storage information.

type UploadInfo

type UploadInfo interface {
	// Name of the upload file.
	Name() string
	// Size in bytes of the upload file.
	Size() int64
}

UploadInfo contains all required information to create an upload ticket.

To upload a regular file, caller can use os.FileInfo as UploadInfo, see "Agent.UploadCreateTicket" doc for detail.

To upload a memory data as file, caller should implement it himself.

type UploadTicket

type UploadTicket struct {
	// Remote URL which will receive the file content.
	Endpoint string
	// Field name for the upload file.
	FileField string
	// Other parameters that should be sent with the file.
	Values map[string]string
}

UploadTicket contains all required information to upload a file.

type UserInfo added in v0.1.2

type UserInfo struct {
	Id   int
	Name string
}

Basic information of the signed-in user.

Directories

Path Synopsis
internal
types
This package contains all internal types that you needn't care about.
This package contains all internal types that you needn't care about.
"plugin" package declare some interfaces that developer can implement himself.
"plugin" package declare some interfaces that developer can implement himself.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL