Skip to content

Commit

Permalink
fix: add aliyun download service.
Browse files Browse the repository at this point in the history
  • Loading branch information
syhily committed Nov 15, 2022
1 parent 069b683 commit b767b4f
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 2 deletions.
9 changes: 8 additions & 1 deletion internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"time"

"github.com/go-resty/resty/v2"

"github.com/bookstairs/bookhunter/internal/log"
)

var (
Expand Down Expand Up @@ -144,13 +146,18 @@ func New(c *Config) (*Client, error) {
SetRetryCount(3).
SetRetryWaitTime(3*time.Second).
SetRetryMaxWaitTime(10*time.Second).
SetRedirectPolicy(c.redirectPolicy()...).
SetAllowGetMethodPayload(true).
SetTimeout(1*time.Minute).
SetContentLength(true).
SetDebug(log.EnableDebug).
SetDisableWarn(true).
SetHeader("User-Agent", c.userAgent()).
SetBaseURL(c.baseURL())

if len(c.redirectPolicy()) > 0 {
client.SetRedirectPolicy(c.redirectPolicy()...)
}

// Setting the cookiejar
cookieJar, err := c.newCookieJar()
if err != nil {
Expand Down
23 changes: 23 additions & 0 deletions internal/driver/aliyun.go
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
package driver

import (
"io"

"github.com/bookstairs/bookhunter/internal/client"
"github.com/bookstairs/bookhunter/internal/driver/aliyun"
)

func newAliyunDriver(c *client.Config) (Driver, error) {
return &aliyunDriver{}, nil
}

type aliyunDriver struct {
Aliyun *aliyun.Aliyun
}

func (a *aliyunDriver) Resolve(shareLink string, passcode string) []Share {
panic("TODO implement me")
}

func (a *aliyunDriver) Download(share Share) io.ReadCloser {
panic("TODO implement me")
}
75 changes: 75 additions & 0 deletions internal/driver/aliyun/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package aliyun

import (
"errors"
"net/http"
"time"

"github.com/go-resty/resty/v2"

"github.com/bookstairs/bookhunter/internal/client"
)

var (
// Token will be refreshed before this time.
acceleratedExpirationDuration = 10 * time.Minute
)

type Aliyun struct {
client *client.Client
tokenCache *TokenResp
refreshToken string
}

// New will create a aliyun download service.
func New(c *client.Config, refreshToken string) (*Aliyun, error) {
if refreshToken == "" {
return nil, errors.New("refreshToken is required")
}

cl, err := client.New(&client.Config{
HTTPS: true,
Host: "api.aliyundrive.com",
UserAgent: c.UserAgent,
Proxy: c.Proxy,
ConfigRoot: c.ConfigRoot,
})
if err != nil {
return nil, err
}

// Set extra middleware for cleaning up the header.
cl.SetPreRequestHook(removeContentType)

return &Aliyun{client: cl, refreshToken: refreshToken}, nil
}

// removeContentType is used to remove the useless content type by setting.
func removeContentType(_ *resty.Client, req *http.Request) error {
if req.Header.Get("x-empty-content-type") != "" {
req.Header.Del("x-empty-content-type")
req.Header.Set("content-type", "")
}

return nil
}

// Try to get the cached auth token.
func (ali *Aliyun) cachedToken() *TokenResp {
tokenResp := ali.tokenCache
if tokenResp != nil {
if time.Now().Add(acceleratedExpirationDuration).Before(tokenResp.ExpireTime) {
return tokenResp
} else {
// Expire the cached token.
ali.tokenCache = nil
}
}
return nil
}

// cacheToken will save the token into cache.
func (ali *Aliyun) cacheToken(resp *TokenResp) {
ali.refreshToken = resp.RefreshToken
ali.tokenCache = resp
}
143 changes: 143 additions & 0 deletions internal/driver/aliyun/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package aliyun

import "time"

type ErrorResp struct {
Code string `json:"code"`
Message string `json:"message"`
}

type TokenReq struct {
GrantType string `json:"grant_type"`
RefreshToken string `json:"refresh_token"`
}

type TokenResp struct {
DefaultSboxDriveID string `json:"default_sbox_drive_id"`
Role string `json:"role"`
DeviceID string `json:"device_id"`
UserName string `json:"user_name"`
NeedLink bool `json:"need_link"`
ExpireTime time.Time `json:"expire_time"`
PinSetup bool `json:"pin_setup"`
NeedRpVerify bool `json:"need_rp_verify"`
Avatar string `json:"avatar"`
TokenType string `json:"token_type"`
AccessToken string `json:"access_token"`
DefaultDriveID string `json:"default_drive_id"`
DomainID string `json:"domain_id"`
RefreshToken string `json:"refresh_token"`
IsFirstLogin bool `json:"is_first_login"`
UserID string `json:"user_id"`
NickName string `json:"nick_name"`
State string `json:"state"`
ExpiresIn int `json:"expires_in"`
Status string `json:"status"`
}

type ShareInfoReq struct {
ShareID string `json:"share_id"`
}

type ShareInfoResp struct {
Avatar string `json:"avatar"`
CreatorID string `json:"creator_id"`
CreatorName string `json:"creator_name"`
CreatorPhone string `json:"creator_phone"`
Expiration string `json:"expiration"`
UpdatedAt string `json:"updated_at"`
ShareName string `json:"share_name"`
FileCount int `json:"file_count"`
FileInfos []ShareItemInfo `json:"file_infos"`
Vip string `json:"vip"`
DisplayName string `json:"display_name"`
IsFollowingCreator bool `json:"is_following_creator"`
}

type ShareItemInfo struct {
Category string `json:"category"`
FileExtension string `json:"file_extension"`
FileID string `json:"file_id"`
Thumbnail string `json:"thumbnail"`
FileType string `json:"type"`
}

type ShareLinkDownloadURLReq struct {
ShareID string `json:"share_id"`
FileID string `json:"file_id"`
ExpireSec int `json:"expire_sec"`
}

type ShareLinkDownloadURLResp struct {
DownloadURL string `json:"download_url"`
URL string `json:"url"`
Thumbnail string `json:"thumbnail"`
}

type ShareTokenReq struct {
ShareID string `json:"share_id"`
SharePwd string `json:"share_pwd"`
}

type ShareTokenResp struct {
ShareToken string `json:"share_token"`
ExpireTime string `json:"expire_time"`
ExpiresIn int `json:"expires_in"`
}

type ShareFileListReq struct {
ShareID string `json:"share_id"`
Starred bool `json:"starred"`
All bool `json:"all"`
Category string `json:"category"`
Fields string `json:"fields"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
Limit int `json:"limit"`
Marker string `json:"marker"`
OrderBy string `json:"order_by"`
OrderDirection string `json:"order_direction"`
ParentFileID string `json:"parent_file_id"`
Status string `json:"status"`
FileType string `json:"type"`
URLExpireSec int `json:"url_expire_sec"`
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}

type ShareFileListResp struct {
Items []*ShareFile `json:"items"`
NextMarker string `json:"next_marker"`
}

type ShareFile struct {
ShareID string `json:"share_id"`
Name string `json:"name"`
Size int `json:"size"`
Creator string `json:"creator"`
Description string `json:"description"`
Category string `json:"category"`
DownloadURL int `json:"download_url"`
URL int `json:"url"`
FileExtension string `json:"file_extension"`
FileID string `json:"file_id"`
Thumbnail string `json:"thumbnail"`
ParentFileID string `json:"parent_file_id"`
FileType string `json:"type"`
UpdatedAt string `json:"updated_at"`
CreatedAt string `json:"created_at"`
Selected string `json:"selected"`
MimeExtension string `json:"mime_extension"`
MimeType string `json:"mime_type"`
PunishFlag int `json:"punish_flag"`
ActionList []string `json:"action_list"`
DriveID string `json:"drive_id"`
DomainID string `json:"domain_id"`
RevisionID string `json:"revision_id"`
}

// listShareFilesParam is used in file list query context.
type listShareFilesParam struct {
shareToken string
shareID string
parentFileID string
marker string
}

0 comments on commit b767b4f

Please sign in to comment.