-
-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
This update introduces the ability to mount 115 share links. Currently, only listing and downloading are supported. Note that login and share link are required for this feature to work. Close #5384
- Loading branch information
1 parent
769281b
commit da1c7a4
Showing
6 changed files
with
261 additions
and
96 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package _115_share | ||
|
||
import ( | ||
"context" | ||
|
||
driver115 "github.com/SheltonZhu/115driver/pkg/driver" | ||
"github.com/alist-org/alist/v3/internal/driver" | ||
"github.com/alist-org/alist/v3/internal/errs" | ||
"github.com/alist-org/alist/v3/internal/model" | ||
"github.com/alist-org/alist/v3/pkg/utils" | ||
"golang.org/x/time/rate" | ||
) | ||
|
||
type Pan115Share struct { | ||
model.Storage | ||
Addition | ||
client *driver115.Pan115Client | ||
limiter *rate.Limiter | ||
} | ||
|
||
func (d *Pan115Share) Config() driver.Config { | ||
return config | ||
} | ||
|
||
func (d *Pan115Share) GetAddition() driver.Additional { | ||
return &d.Addition | ||
} | ||
|
||
func (d *Pan115Share) Init(ctx context.Context) error { | ||
if d.LimitRate > 0 { | ||
d.limiter = rate.NewLimiter(rate.Limit(d.LimitRate), 1) | ||
} | ||
|
||
return d.login() | ||
} | ||
|
||
func (d *Pan115Share) WaitLimit(ctx context.Context) error { | ||
if d.limiter != nil { | ||
return d.limiter.Wait(ctx) | ||
} | ||
return nil | ||
} | ||
|
||
func (d *Pan115Share) Drop(ctx context.Context) error { | ||
return nil | ||
} | ||
|
||
func (d *Pan115Share) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { | ||
if err := d.WaitLimit(ctx); err != nil { | ||
return nil, err | ||
} | ||
|
||
files := make([]driver115.ShareFile, 0) | ||
fileResp, err := d.client.GetShareSnap(d.ShareCode, d.ReceiveCode, dir.GetID(), driver115.QueryLimit(int(d.PageSize))) | ||
if err != nil { | ||
return nil, err | ||
} | ||
files = append(files, fileResp.Data.List...) | ||
total := fileResp.Data.Count | ||
count := len(fileResp.Data.List) | ||
for total > count { | ||
fileResp, err := d.client.GetShareSnap( | ||
d.ShareCode, d.ReceiveCode, dir.GetID(), | ||
driver115.QueryLimit(int(d.PageSize)), driver115.QueryOffset(count), | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
files = append(files, fileResp.Data.List...) | ||
count += len(fileResp.Data.List) | ||
} | ||
|
||
return utils.SliceConvert(files, transFunc) | ||
} | ||
|
||
func (d *Pan115Share) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { | ||
if err := d.WaitLimit(ctx); err != nil { | ||
return nil, err | ||
} | ||
downloadInfo, err := d.client.DownloadByShareCode(d.ShareCode, d.ReceiveCode, file.GetID()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &model.Link{URL: downloadInfo.URL.URL}, nil | ||
} | ||
|
||
func (d *Pan115Share) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *Pan115Share) Move(ctx context.Context, srcObj, dstDir model.Obj) error { | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *Pan115Share) Rename(ctx context.Context, srcObj model.Obj, newName string) error { | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *Pan115Share) Copy(ctx context.Context, srcObj, dstDir model.Obj) error { | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *Pan115Share) Remove(ctx context.Context, obj model.Obj) error { | ||
return errs.NotSupport | ||
} | ||
|
||
func (d *Pan115Share) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { | ||
return errs.NotSupport | ||
} | ||
|
||
var _ driver.Driver = (*Pan115Share)(nil) |
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,33 @@ | ||
package _115_share | ||
|
||
import ( | ||
"github.com/alist-org/alist/v3/internal/driver" | ||
"github.com/alist-org/alist/v3/internal/op" | ||
) | ||
|
||
type Addition struct { | ||
Cookie string `json:"cookie" type:"text" help:"one of QR code token and cookie required"` | ||
QRCodeToken string `json:"qrcode_token" type:"text" help:"one of QR code token and cookie required"` | ||
PageSize int64 `json:"page_size" type:"number" default:"20" help:"list api per page size of 115 driver"` | ||
LimitRate float64 `json:"limit_rate" type:"number" default:"2" help:"limit all api request rate (1r/[limit_rate]s)"` | ||
ShareCode string `json:"share_code" type:"text" required:"true" help:"share code of 115 share link"` | ||
ReceiveCode string `json:"receive_code" type:"text" required:"true" help:"receive code of 115 share link"` | ||
driver.RootID | ||
} | ||
|
||
var config = driver.Config{ | ||
Name: "115 Share", | ||
DefaultRoot: "", | ||
// OnlyProxy: true, | ||
// OnlyLocal: true, | ||
CheckStatus: false, | ||
Alert: "", | ||
NoOverwriteUpload: true, | ||
NoUpload: true, | ||
} | ||
|
||
func init() { | ||
op.RegisterDriver(func() driver.Driver { | ||
return &Pan115Share{} | ||
}) | ||
} |
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,111 @@ | ||
package _115_share | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"time" | ||
|
||
driver115 "github.com/SheltonZhu/115driver/pkg/driver" | ||
"github.com/alist-org/alist/v3/internal/model" | ||
"github.com/alist-org/alist/v3/pkg/utils" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
var _ model.Obj = (*FileObj)(nil) | ||
|
||
type FileObj struct { | ||
Size int64 | ||
Sha1 string | ||
Utm time.Time | ||
FileName string | ||
isDir bool | ||
FileID string | ||
} | ||
|
||
func (f *FileObj) CreateTime() time.Time { | ||
return f.Utm | ||
} | ||
|
||
func (f *FileObj) GetHash() utils.HashInfo { | ||
return utils.NewHashInfo(utils.SHA1, f.Sha1) | ||
} | ||
|
||
func (f *FileObj) GetSize() int64 { | ||
return f.Size | ||
} | ||
|
||
func (f *FileObj) GetName() string { | ||
return f.FileName | ||
} | ||
|
||
func (f *FileObj) ModTime() time.Time { | ||
return f.Utm | ||
} | ||
|
||
func (f *FileObj) IsDir() bool { | ||
return f.isDir | ||
} | ||
|
||
func (f *FileObj) GetID() string { | ||
return f.FileID | ||
} | ||
|
||
func (f *FileObj) GetPath() string { | ||
return "" | ||
} | ||
|
||
func transFunc(sf driver115.ShareFile) (model.Obj, error) { | ||
timeInt, err := strconv.ParseInt(sf.UpdateTime, 10, 64) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var ( | ||
utm = time.Unix(timeInt, 0) | ||
isDir = (sf.IsFile == 0) | ||
fileID = string(sf.FileID) | ||
) | ||
if isDir { | ||
fileID = string(sf.CategoryID) | ||
} | ||
return &FileObj{ | ||
Size: int64(sf.Size), | ||
Sha1: sf.Sha1, | ||
Utm: utm, | ||
FileName: string(sf.FileName), | ||
isDir: isDir, | ||
FileID: fileID, | ||
}, nil | ||
} | ||
|
||
var UserAgent = driver115.UA115Browser | ||
|
||
func (d *Pan115Share) login() error { | ||
var err error | ||
opts := []driver115.Option{ | ||
driver115.UA(UserAgent), | ||
} | ||
d.client = driver115.New(opts...) | ||
if _, err := d.client.GetShareSnap(d.ShareCode, d.ReceiveCode, ""); err != nil { | ||
return errors.Wrap(err, "failed to get share snap") | ||
} | ||
cr := &driver115.Credential{} | ||
if d.QRCodeToken != "" { | ||
s := &driver115.QRCodeSession{ | ||
UID: d.QRCodeToken, | ||
} | ||
if cr, err = d.client.QRCodeLogin(s); err != nil { | ||
return errors.Wrap(err, "failed to login by qrcode") | ||
} | ||
d.Cookie = fmt.Sprintf("UID=%s;CID=%s;SEID=%s", cr.UID, cr.CID, cr.SEID) | ||
d.QRCodeToken = "" | ||
} else if d.Cookie != "" { | ||
if err = cr.FromCookie(d.Cookie); err != nil { | ||
return errors.Wrap(err, "failed to login by cookies") | ||
} | ||
d.client.ImportCredential(cr) | ||
} else { | ||
return errors.New("missing cookie or qrcode account") | ||
} | ||
|
||
return d.client.LoginCheck() | ||
} |
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
Oops, something went wrong.