Compare commits
75 Commits
Author | SHA1 | Date | |
---|---|---|---|
4a0e47dbac | |||
510d266da8 | |||
35dfb36884 | |||
b88f4d2ba6 | |||
50318da879 | |||
575487a0e2 | |||
69d3ccaed2 | |||
170859a112 | |||
7fdcb106a5 | |||
14d4ddb752 | |||
428e59a844 | |||
1c8d895fc0 | |||
fbf3fb825b | |||
16e07ae016 | |||
d1b9db38c7 | |||
395f0fc5f3 | |||
143e4cd077 | |||
f777a2fab4 | |||
dad3012ec3 | |||
d45209edb2 | |||
e89489453d | |||
ed6c8194a7 | |||
83fe17c6ec | |||
c00dcc8f39 | |||
e118f4a3b9 | |||
5e28d0f96a | |||
3af23f6792 | |||
3a41b929c9 | |||
105f22969c | |||
e4a88a7c13 | |||
b0255040c6 | |||
f1e842e12a | |||
d756cf3e9f | |||
146619134d | |||
372030071e | |||
62a06fa0f9 | |||
e2bcca2fbd | |||
4568af9542 | |||
b50d486a63 | |||
0ae3fc608b | |||
6024e8d832 | |||
f38f4f401b | |||
3b2ae85009 | |||
faf4150d1e | |||
fb64f00640 | |||
3d336b328a | |||
f9cf29e0b6 | |||
cbd038f30f | |||
2aeb75a779 | |||
2f8eaf6bea | |||
fb7a5dec1b | |||
e61bac039a | |||
b3be9ef428 | |||
5a6b600ace | |||
e58ca686e3 | |||
6f4b1ba4b3 | |||
cdc45630ae | |||
7947ff1ae4 | |||
33bae52fa1 | |||
3ee45c69a7 | |||
179d285564 | |||
a2e8e96c71 | |||
5043815d48 | |||
1640f06e13 | |||
62ea93837c | |||
446f82888c | |||
6f1aeb47fd | |||
1f7c1b4f43 | |||
3fa0217c4b | |||
2dd30f2b77 | |||
6e23c8b4c0 | |||
72aa63adce | |||
e65e8be59e | |||
7aa4dfb240 | |||
bd324233a0 |
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -54,4 +54,3 @@ body:
|
||||
description: |
|
||||
Please copy and paste any relevant log output.
|
||||
请复制粘贴错误日志,或者截图
|
||||
render: shell
|
15
.gitignore
vendored
15
.gitignore
vendored
@ -20,11 +20,12 @@ output/
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
bin/*
|
||||
/bin/*
|
||||
*.json
|
||||
data/
|
||||
log/
|
||||
lang/
|
||||
daemon/
|
||||
public/dist/*
|
||||
!public/dist/README.md
|
||||
/build
|
||||
/data/
|
||||
/log/
|
||||
/lang/
|
||||
/daemon/
|
||||
/public/dist/*
|
||||
/!public/dist/README.md
|
||||
|
@ -10,6 +10,9 @@ LABEL MAINTAINER="i@nn.ci"
|
||||
VOLUME /opt/alist/data/
|
||||
WORKDIR /opt/alist/
|
||||
COPY --from=builder /app/bin/alist ./
|
||||
RUN apk add ca-certificates
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN apk add ca-certificates bash su-exec; \
|
||||
chmod +x /entrypoint.sh
|
||||
ENV PUID=0 PGID=0 UMASK=022
|
||||
EXPOSE 5244
|
||||
CMD [ "./alist", "server", "--no-prefix" ]
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
|
@ -9,7 +9,7 @@
|
||||
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild">
|
||||
<img src="https://img.shields.io/github/workflow/status/Xhofe/alist/build" alt="Build status" />
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
|
||||
</a>
|
||||
<a href="https://github.com/Xhofe/alist/releases">
|
||||
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
|
||||
|
@ -9,7 +9,7 @@
|
||||
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild">
|
||||
<img src="https://img.shields.io/github/workflow/status/Xhofe/alist/build" alt="Build status" />
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
|
||||
</a>
|
||||
<a href="https://github.com/Xhofe/alist/releases">
|
||||
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
|
||||
|
10
cmd/admin.go
10
cmd/admin.go
@ -4,19 +4,19 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/db"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// passwordCmd represents the password command
|
||||
var passwordCmd = &cobra.Command{
|
||||
// PasswordCmd represents the password command
|
||||
var PasswordCmd = &cobra.Command{
|
||||
Use: "admin",
|
||||
Aliases: []string{"password"},
|
||||
Short: "Show admin user's info",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
Init()
|
||||
admin, err := db.GetAdmin()
|
||||
admin, err := op.GetAdmin()
|
||||
if err != nil {
|
||||
utils.Log.Errorf("failed get admin user: %+v", err)
|
||||
} else {
|
||||
@ -26,7 +26,7 @@ var passwordCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(passwordCmd)
|
||||
RootCmd.AddCommand(PasswordCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
@ -4,22 +4,22 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/db"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// cancel2FACmd represents the delete2fa command
|
||||
var cancel2FACmd = &cobra.Command{
|
||||
// Cancel2FACmd represents the delete2fa command
|
||||
var Cancel2FACmd = &cobra.Command{
|
||||
Use: "cancel2fa",
|
||||
Short: "Delete 2FA of admin user",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
Init()
|
||||
admin, err := db.GetAdmin()
|
||||
admin, err := op.GetAdmin()
|
||||
if err != nil {
|
||||
utils.Log.Errorf("failed to get admin user: %+v", err)
|
||||
} else {
|
||||
err := db.Cancel2FAByUser(admin)
|
||||
err := op.Cancel2FAByUser(admin)
|
||||
if err != nil {
|
||||
utils.Log.Errorf("failed to cancel 2FA: %+v", err)
|
||||
}
|
||||
@ -28,7 +28,7 @@ var cancel2FACmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(cancel2FACmd)
|
||||
RootCmd.AddCommand(Cancel2FACmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
@ -15,8 +15,8 @@ func Init() {
|
||||
bootstrap.InitConfig()
|
||||
bootstrap.Log()
|
||||
bootstrap.InitDB()
|
||||
bootstrap.InitIndex()
|
||||
data.InitData()
|
||||
bootstrap.InitIndex()
|
||||
}
|
||||
|
||||
var pid = -1
|
||||
|
@ -123,8 +123,8 @@ func generateSettingsJson() {
|
||||
//utils.WriteJsonToFile("lang/settings.json", settingsLang)
|
||||
}
|
||||
|
||||
// langCmd represents the lang command
|
||||
var langCmd = &cobra.Command{
|
||||
// LangCmd represents the lang command
|
||||
var LangCmd = &cobra.Command{
|
||||
Use: "lang",
|
||||
Short: "Generate language json file",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@ -138,7 +138,7 @@ var langCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(langCmd)
|
||||
RootCmd.AddCommand(LangCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// restartCmd represents the restart command
|
||||
var restartCmd = &cobra.Command{
|
||||
// RestartCmd represents the restart command
|
||||
var RestartCmd = &cobra.Command{
|
||||
Use: "restart",
|
||||
Short: "Restart alist server by daemon/pid file",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@ -18,7 +18,7 @@ var restartCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(restartCmd)
|
||||
RootCmd.AddCommand(RestartCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
14
cmd/root.go
14
cmd/root.go
@ -8,7 +8,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "alist",
|
||||
Short: "A file list program that supports multiple storage.",
|
||||
Long: `A file list program that supports multiple storage,
|
||||
@ -17,16 +17,16 @@ Complete documentation is available at https://alist.nn.ci/`,
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&flags.DataDir, "data", "data", "config file")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.Debug, "debug", false, "start with debug mode")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.NoPrefix, "no-prefix", false, "disable env prefix")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.Dev, "dev", false, "start with dev mode")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.ForceBinDir, "force-bin-dir", false, "Force to use the directory where the binary file is located as data directory")
|
||||
RootCmd.PersistentFlags().StringVar(&flags.DataDir, "data", "data", "config file")
|
||||
RootCmd.PersistentFlags().BoolVar(&flags.Debug, "debug", false, "start with debug mode")
|
||||
RootCmd.PersistentFlags().BoolVar(&flags.NoPrefix, "no-prefix", false, "disable env prefix")
|
||||
RootCmd.PersistentFlags().BoolVar(&flags.Dev, "dev", false, "start with dev mode")
|
||||
RootCmd.PersistentFlags().BoolVar(&flags.ForceBinDir, "force-bin-dir", false, "Force to use the directory where the binary file is located as data directory")
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// serverCmd represents the server command
|
||||
var serverCmd = &cobra.Command{
|
||||
// ServerCmd represents the server command
|
||||
var ServerCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Start the server at the specified address",
|
||||
Long: `Start the server at the specified address
|
||||
@ -76,7 +76,7 @@ the address is defined in config file`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverCmd)
|
||||
RootCmd.AddCommand(ServerCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
@ -95,5 +95,5 @@ func OutAlistInit() {
|
||||
cmd *cobra.Command
|
||||
args []string
|
||||
)
|
||||
serverCmd.Run(cmd, args)
|
||||
ServerCmd.Run(cmd, args)
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// startCmd represents the start command
|
||||
var startCmd = &cobra.Command{
|
||||
// StartCmd represents the start command
|
||||
var StartCmd = &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Silent start alist server with `--force-bin-dir`",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@ -57,7 +57,7 @@ func start() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(startCmd)
|
||||
RootCmd.AddCommand(StartCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// stopCmd represents the stop command
|
||||
var stopCmd = &cobra.Command{
|
||||
// StopCmd represents the stop command
|
||||
var StopCmd = &cobra.Command{
|
||||
Use: "stop",
|
||||
Short: "Stop alist server by daemon/pid file",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@ -44,7 +44,7 @@ func stop() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(stopCmd)
|
||||
RootCmd.AddCommand(StopCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||
|
||||
*/
|
||||
package cmd
|
||||
|
||||
@ -12,8 +11,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command
|
||||
var versionCmd = &cobra.Command{
|
||||
// VersionCmd represents the version command
|
||||
var VersionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Show current version of AList",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@ -30,7 +29,7 @@ WebVersion: %s
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
RootCmd.AddCommand(VersionCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
|
14
docker-compose.yml
Normal file
14
docker-compose.yml
Normal file
@ -0,0 +1,14 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
alist:
|
||||
restart: always
|
||||
volumes:
|
||||
- '/etc/alist:/opt/alist/data'
|
||||
ports:
|
||||
- '5244:5244'
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- UMASK=022
|
||||
container_name: alist
|
||||
image: 'xhofe/alist:latest'
|
@ -22,15 +22,10 @@ func (d *Pan115) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Pan115) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Pan115) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Pan115) Init(ctx context.Context) error {
|
||||
return d.login()
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
Cookie string `json:"cookie"`
|
||||
Cookie string `json:"cookie"`
|
||||
QRCodeToken string `json:"qrcode_token"`
|
||||
driver.RootID
|
||||
}
|
||||
@ -18,10 +18,8 @@ var config = driver.Config{
|
||||
OnlyLocal: true,
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Pan115{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Pan115{}
|
||||
})
|
||||
}
|
||||
|
@ -37,15 +37,10 @@ func (d *Pan123) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Pan123) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Pan123) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Pan123) Init(ctx context.Context) error {
|
||||
return d.login()
|
||||
}
|
||||
|
||||
@ -63,11 +58,6 @@ func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *Pan123) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
if f, ok := file.(File); ok {
|
||||
//var resp DownResp
|
||||
@ -231,7 +221,7 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
}
|
||||
var resp UploadResp
|
||||
_, err := d.request("https://www.123pan.com/a/api/file/upload_request", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -255,14 +245,14 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
Key: &resp.Data.Key,
|
||||
Body: uploadFile,
|
||||
}
|
||||
_, err = uploader.Upload(input)
|
||||
_, err = uploader.UploadWithContext(ctx, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.request("https://www.123pan.com/api/file/upload_complete", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(base.Json{
|
||||
"fileId": resp.Data.FileId,
|
||||
})
|
||||
}).SetContext(ctx)
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "0",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Pan123{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Pan123{}
|
||||
})
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
)
|
||||
|
||||
//type BaseResp struct {
|
||||
@ -40,7 +39,7 @@ func (f File) GetSize() int64 {
|
||||
}
|
||||
|
||||
func (f File) GetName() string {
|
||||
return utils.MappingName(f.FileName)
|
||||
return f.FileName
|
||||
}
|
||||
|
||||
func (f File) ModTime() time.Time {
|
||||
|
@ -27,16 +27,11 @@ func (d *Yun139) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Yun139) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Yun139) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.post("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Json{
|
||||
func (d *Yun139) Init(ctx context.Context) error {
|
||||
_, err := d.post("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Json{
|
||||
"qryUserExternInfoReq": base.Json{
|
||||
"commonAccountInfo": base.Json{
|
||||
"account": d.Account,
|
||||
@ -59,11 +54,6 @@ func (d *Yun139) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
|
||||
}
|
||||
}
|
||||
|
||||
//func (d *Yun139) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *Yun139) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
u, err := d.getLink(file.GetID())
|
||||
if err != nil {
|
||||
@ -275,10 +265,13 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var Default int64 = 10485760
|
||||
var Default int64 = 104857600
|
||||
part := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
||||
var start int64 = 0
|
||||
for i := 0; i < part; i++ {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
byteSize := stream.GetSize() - start
|
||||
if byteSize > Default {
|
||||
byteSize = Default
|
||||
@ -292,6 +285,7 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
headers := map[string]string{
|
||||
"Accept": "*/*",
|
||||
"Content-Type": "text/plain;name=" + unicode(stream.GetName()),
|
||||
|
@ -19,7 +19,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Yun139{}
|
||||
})
|
||||
}
|
||||
|
@ -26,15 +26,10 @@ func (d *Cloud189) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Cloud189) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Cloud189) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Cloud189) Init(ctx context.Context) error {
|
||||
d.client = resty.New().
|
||||
SetTimeout(base.DefaultTimeout).
|
||||
SetRetryCount(3).
|
||||
@ -51,11 +46,6 @@ func (d *Cloud189) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
||||
return d.getFiles(dir.GetID())
|
||||
}
|
||||
|
||||
//func (d *Cloud189) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *Cloud189) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
var resp DownResp
|
||||
u := "https://cloud.189.cn/api/portal/getFileInfo.action"
|
||||
@ -204,7 +194,7 @@ func (d *Cloud189) Remove(ctx context.Context, obj model.Obj) error {
|
||||
}
|
||||
|
||||
func (d *Cloud189) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
return d.newUpload(dstDir, stream, up)
|
||||
return d.newUpload(ctx, dstDir, stream, up)
|
||||
}
|
||||
|
||||
var _ driver.Driver = (*Cloud189)(nil)
|
||||
|
@ -18,7 +18,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Cloud189{}
|
||||
})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package _189
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
@ -306,7 +307,7 @@ func (d *Cloud189) uploadRequest(uri string, form map[string]string, resp interf
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (d *Cloud189) newUpload(dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
|
||||
func (d *Cloud189) newUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
|
||||
sessionKey, err := d.getSessionKey()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -335,6 +336,9 @@ func (d *Cloud189) newUpload(dstDir model.Obj, file model.FileStreamer, up drive
|
||||
md5s := make([]string, 0)
|
||||
md5Sum := md5.New()
|
||||
for i = 1; i <= count; i++ {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
byteSize = file.GetSize() - finish
|
||||
if DEFAULT < byteSize {
|
||||
byteSize = DEFAULT
|
||||
@ -364,12 +368,15 @@ func (d *Cloud189) newUpload(dstDir model.Obj, file model.FileStreamer, up drive
|
||||
log.Debugf("uploadData: %+v", uploadData)
|
||||
requestURL := uploadData.RequestURL
|
||||
uploadHeaders := strings.Split(decodeURIComponent(uploadData.RequestHeader), "&")
|
||||
req, _ := http.NewRequest(http.MethodPut, requestURL, bytes.NewReader(byteData))
|
||||
req, err := http.NewRequest(http.MethodPut, requestURL, bytes.NewReader(byteData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
for _, v := range uploadHeaders {
|
||||
i := strings.Index(v, "=")
|
||||
req.Header.Set(v[0:i], v[i+1:])
|
||||
}
|
||||
|
||||
r, err := base.HttpClient.Do(req)
|
||||
log.Debugf("%+v %+v", r, r.Request.Header)
|
||||
r.Body.Close()
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type Yun189PC struct {
|
||||
type Cloud189PC struct {
|
||||
model.Storage
|
||||
Addition
|
||||
|
||||
@ -26,20 +26,15 @@ type Yun189PC struct {
|
||||
tokenInfo *AppSessionResp
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Config() driver.Config {
|
||||
func (y *Cloud189PC) Config() driver.Config {
|
||||
return config
|
||||
}
|
||||
|
||||
func (y *Yun189PC) GetAddition() driver.Additional {
|
||||
return y.Addition
|
||||
func (y *Cloud189PC) GetAddition() driver.Additional {
|
||||
return &y.Addition
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Init(ctx context.Context, storage model.Storage) (err error) {
|
||||
y.Storage = storage
|
||||
if err = utils.Json.UnmarshalFromString(y.Storage.Addition, &y.Addition); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Cloud189PC) Init(ctx context.Context) (err error) {
|
||||
// 处理个人云和家庭云参数
|
||||
if y.isFamily() && y.RootFolderID == "-11" {
|
||||
y.RootFolderID = ""
|
||||
@ -78,15 +73,15 @@ func (y *Yun189PC) Init(ctx context.Context, storage model.Storage) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Drop(ctx context.Context) error {
|
||||
func (y *Cloud189PC) Drop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (y *Yun189PC) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
func (y *Cloud189PC) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
return y.getFiles(ctx, dir.GetID())
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
func (y *Cloud189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
var downloadUrl struct {
|
||||
URL string `json:"fileDownloadUrl"`
|
||||
}
|
||||
@ -145,7 +140,7 @@ func (y *Yun189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs
|
||||
return like, nil
|
||||
}
|
||||
|
||||
func (y *Yun189PC) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
func (y *Cloud189PC) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
fullUrl := API_URL
|
||||
if y.isFamily() {
|
||||
fullUrl += "/family/file"
|
||||
@ -172,7 +167,7 @@ func (y *Yun189PC) MakeDir(ctx context.Context, parentDir model.Obj, dirName str
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
func (y *Cloud189PC) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
req.SetFormData(map[string]string{
|
||||
@ -196,7 +191,7 @@ func (y *Yun189PC) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
func (y *Cloud189PC) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
queryParam := make(map[string]string)
|
||||
fullUrl := API_URL
|
||||
method := http.MethodPost
|
||||
@ -221,7 +216,7 @@ func (y *Yun189PC) Rename(ctx context.Context, srcObj model.Obj, newName string)
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
func (y *Cloud189PC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
req.SetFormData(map[string]string{
|
||||
@ -246,7 +241,7 @@ func (y *Yun189PC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Remove(ctx context.Context, obj model.Obj) error {
|
||||
func (y *Cloud189PC) Remove(ctx context.Context, obj model.Obj) error {
|
||||
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
req.SetFormData(map[string]string{
|
||||
@ -270,7 +265,7 @@ func (y *Yun189PC) Remove(ctx context.Context, obj model.Obj) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Yun189PC) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
func (y *Cloud189PC) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
if y.RapidUpload {
|
||||
return y.FastUpload(ctx, dstDir, stream, up)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
return &Yun189PC{}
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Cloud189PC{}
|
||||
})
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
)
|
||||
|
||||
// 居然有四种返回方式
|
||||
@ -136,7 +134,7 @@ type Cloud189File struct {
|
||||
}
|
||||
|
||||
func (c *Cloud189File) GetSize() int64 { return c.Size }
|
||||
func (c *Cloud189File) GetName() string { return utils.MappingName(c.Name) }
|
||||
func (c *Cloud189File) GetName() string { return c.Name }
|
||||
func (c *Cloud189File) ModTime() time.Time {
|
||||
if c.parseTime == nil {
|
||||
c.parseTime = MustParseTime(c.LastOpTime)
|
||||
@ -168,7 +166,7 @@ type Cloud189Folder struct {
|
||||
}
|
||||
|
||||
func (c *Cloud189Folder) GetSize() int64 { return 0 }
|
||||
func (c *Cloud189Folder) GetName() string { return utils.MappingName(c.Name) }
|
||||
func (c *Cloud189Folder) GetName() string { return c.Name }
|
||||
func (c *Cloud189Folder) ModTime() time.Time {
|
||||
if c.parseTime == nil {
|
||||
c.parseTime = MustParseTime(c.LastOpTime)
|
||||
|
@ -47,7 +47,7 @@ const (
|
||||
CHANNEL_ID = "web_cloud.189.cn"
|
||||
)
|
||||
|
||||
func (y *Yun189PC) request(url, method string, callback base.ReqCallback, params Params, resp interface{}) ([]byte, error) {
|
||||
func (y *Cloud189PC) request(url, method string, callback base.ReqCallback, params Params, resp interface{}) ([]byte, error) {
|
||||
dateOfGmt := getHttpDateStr()
|
||||
sessionKey := y.tokenInfo.SessionKey
|
||||
sessionSecret := y.tokenInfo.SessionSecret
|
||||
@ -124,15 +124,15 @@ func (y *Yun189PC) request(url, method string, callback base.ReqCallback, params
|
||||
}
|
||||
}
|
||||
|
||||
func (y *Yun189PC) get(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
func (y *Cloud189PC) get(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
return y.request(url, http.MethodGet, callback, nil, resp)
|
||||
}
|
||||
|
||||
func (y *Yun189PC) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
func (y *Cloud189PC) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
return y.request(url, http.MethodPost, callback, nil, resp)
|
||||
}
|
||||
|
||||
func (y *Yun189PC) getFiles(ctx context.Context, fileId string) ([]model.Obj, error) {
|
||||
func (y *Cloud189PC) getFiles(ctx context.Context, fileId string) ([]model.Obj, error) {
|
||||
fullUrl := API_URL
|
||||
if y.isFamily() {
|
||||
fullUrl += "/family/file"
|
||||
@ -184,7 +184,7 @@ func (y *Yun189PC) getFiles(ctx context.Context, fileId string) ([]model.Obj, er
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (y *Yun189PC) login() (err error) {
|
||||
func (y *Cloud189PC) login() (err error) {
|
||||
// 初始化登陆所需参数
|
||||
if y.loginParam == nil || !y.NoUseOcr {
|
||||
if err = y.initLoginParam(); err != nil {
|
||||
@ -264,7 +264,7 @@ func (y *Yun189PC) login() (err error) {
|
||||
/* 初始化登陆需要的参数
|
||||
* 如果遇到验证码返回错误
|
||||
*/
|
||||
func (y *Yun189PC) initLoginParam() error {
|
||||
func (y *Cloud189PC) initLoginParam() error {
|
||||
// 清除cookie
|
||||
jar, _ := cookiejar.New(nil)
|
||||
y.client.SetCookieJar(jar)
|
||||
@ -335,7 +335,7 @@ func (y *Yun189PC) initLoginParam() error {
|
||||
}
|
||||
|
||||
// 刷新会话
|
||||
func (y *Yun189PC) refreshSession() (err error) {
|
||||
func (y *Cloud189PC) refreshSession() (err error) {
|
||||
var erron RespErr
|
||||
var userSessionResp UserSessionResp
|
||||
_, err = y.client.R().
|
||||
@ -381,7 +381,7 @@ func (y *Yun189PC) refreshSession() (err error) {
|
||||
}
|
||||
|
||||
// 普通上传
|
||||
func (y *Yun189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
||||
func (y *Cloud189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
||||
const DEFAULT int64 = 10485760
|
||||
var count = int64(math.Ceil(float64(file.GetSize()) / float64(DEFAULT)))
|
||||
|
||||
@ -418,10 +418,8 @@ func (y *Yun189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file mode
|
||||
silceMd5Hexs := make([]string, 0, count)
|
||||
byteData := bytes.NewBuffer(make([]byte, DEFAULT))
|
||||
for i := int64(1); i <= count; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
// 读取块
|
||||
@ -491,7 +489,7 @@ func (y *Yun189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file mode
|
||||
}
|
||||
|
||||
// 快传
|
||||
func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
||||
func (y *Cloud189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
||||
// 需要获取完整文件md5,必须支持 io.Seek
|
||||
tempFile, err := utils.CreateTempFile(file.GetReadCloser())
|
||||
if err != nil {
|
||||
@ -511,10 +509,8 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
||||
silceMd5Hexs := make([]string, 0, count)
|
||||
silceMd5Base64s := make([]string, 0, count)
|
||||
for i := 1; i <= count; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
silceMd5.Reset()
|
||||
@ -616,11 +612,11 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
||||
return err
|
||||
}
|
||||
|
||||
func (y *Yun189PC) isFamily() bool {
|
||||
func (y *Cloud189PC) isFamily() bool {
|
||||
return y.Type == "family"
|
||||
}
|
||||
|
||||
func (y *Yun189PC) isLogin() bool {
|
||||
func (y *Cloud189PC) isLogin() bool {
|
||||
if y.tokenInfo == nil {
|
||||
return false
|
||||
}
|
||||
@ -629,7 +625,7 @@ func (y *Yun189PC) isLogin() bool {
|
||||
}
|
||||
|
||||
// 获取家庭云所有用户信息
|
||||
func (y *Yun189PC) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
||||
func (y *Cloud189PC) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
||||
var resp FamilyInfoListResp
|
||||
_, err := y.get(API_URL+"/family/manage/getFamilyList.action", nil, &resp)
|
||||
if err != nil {
|
||||
@ -639,7 +635,7 @@ func (y *Yun189PC) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
||||
}
|
||||
|
||||
// 抽取家庭云ID
|
||||
func (y *Yun189PC) getFamilyID() (string, error) {
|
||||
func (y *Cloud189PC) getFamilyID() (string, error) {
|
||||
infos, err := y.getFamilyInfoList()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"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"
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
)
|
||||
|
||||
@ -21,21 +20,16 @@ func (d *AListV2) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *AListV2) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *AListV2) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *AListV2) Init(ctx context.Context) error {
|
||||
if len(d.Addition.Address) > 0 && string(d.Addition.Address[len(d.Addition.Address)-1]) == "/" {
|
||||
d.Addition.Address = d.Addition.Address[0 : len(d.Addition.Address)-1]
|
||||
}
|
||||
// TODO login / refresh token
|
||||
//op.MustSaveDriverStorage(d)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *AListV2) Drop(ctx context.Context) error {
|
||||
@ -73,11 +67,6 @@ func (d *AListV2) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
||||
return files, nil
|
||||
}
|
||||
|
||||
//func (d *AList) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *AListV2) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
url := d.Address + "/api/public/path"
|
||||
var resp common.Resp[PathResp]
|
||||
|
@ -20,7 +20,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &AListV2{}
|
||||
})
|
||||
}
|
||||
|
@ -2,12 +2,14 @@ package alist_v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"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"
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
)
|
||||
|
||||
@ -21,21 +23,14 @@ func (d *AListV3) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *AListV3) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *AListV3) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(d.Addition.Address) > 0 && string(d.Addition.Address[len(d.Addition.Address)-1]) == "/" {
|
||||
d.Addition.Address = d.Addition.Address[0 : len(d.Addition.Address)-1]
|
||||
}
|
||||
func (d *AListV3) Init(ctx context.Context) error {
|
||||
d.Addition.Address = strings.TrimSuffix(d.Addition.Address, "/")
|
||||
// TODO login / refresh token
|
||||
//op.MustSaveDriverStorage(d)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *AListV3) Drop(ctx context.Context) error {
|
||||
@ -76,11 +71,6 @@ func (d *AListV3) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
||||
return files, nil
|
||||
}
|
||||
|
||||
//func (d *AList) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *AListV3) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
url := d.Address + "/api/fs/get"
|
||||
var resp common.Resp[FsGetResp]
|
||||
@ -100,27 +90,86 @@ func (d *AListV3) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
||||
}
|
||||
|
||||
func (d *AListV3) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
return errs.NotImplement
|
||||
url := d.Address + "/api/fs/mkdir"
|
||||
var resp common.Resp[interface{}]
|
||||
_, err := base.RestyClient.R().
|
||||
SetResult(&resp).
|
||||
SetHeader("Authorization", d.AccessToken).
|
||||
SetBody(MkdirOrLinkReq{
|
||||
Path: path.Join(parentDir.GetPath(), dirName),
|
||||
}).Post(url)
|
||||
return checkResp(resp, err)
|
||||
}
|
||||
|
||||
func (d *AListV3) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
return errs.NotImplement
|
||||
url := d.Address + "/api/fs/move"
|
||||
var resp common.Resp[interface{}]
|
||||
_, err := base.RestyClient.R().
|
||||
SetResult(&resp).
|
||||
SetHeader("Authorization", d.AccessToken).
|
||||
SetBody(MoveCopyReq{
|
||||
SrcDir: srcObj.GetPath(),
|
||||
DstDir: dstDir.GetPath(),
|
||||
Names: []string{srcObj.GetName()},
|
||||
}).Post(url)
|
||||
return checkResp(resp, err)
|
||||
}
|
||||
|
||||
func (d *AListV3) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
return errs.NotImplement
|
||||
url := d.Address + "/api/fs/rename"
|
||||
var resp common.Resp[interface{}]
|
||||
_, err := base.RestyClient.R().
|
||||
SetResult(&resp).
|
||||
SetHeader("Authorization", d.AccessToken).
|
||||
SetBody(RenameReq{
|
||||
Path: srcObj.GetPath(),
|
||||
Name: newName,
|
||||
}).Post(url)
|
||||
return checkResp(resp, err)
|
||||
}
|
||||
|
||||
func (d *AListV3) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
return errs.NotImplement
|
||||
url := d.Address + "/api/fs/copy"
|
||||
var resp common.Resp[interface{}]
|
||||
_, err := base.RestyClient.R().
|
||||
SetResult(&resp).
|
||||
SetHeader("Authorization", d.AccessToken).
|
||||
SetBody(MoveCopyReq{
|
||||
SrcDir: srcObj.GetPath(),
|
||||
DstDir: dstDir.GetPath(),
|
||||
Names: []string{srcObj.GetName()},
|
||||
}).Post(url)
|
||||
return checkResp(resp, err)
|
||||
}
|
||||
|
||||
func (d *AListV3) Remove(ctx context.Context, obj model.Obj) error {
|
||||
return errs.NotImplement
|
||||
url := d.Address + "/api/fs/remove"
|
||||
var resp common.Resp[interface{}]
|
||||
_, err := base.RestyClient.R().
|
||||
SetResult(&resp).
|
||||
SetHeader("Authorization", d.AccessToken).
|
||||
SetBody(RemoveReq{
|
||||
Dir: obj.GetPath(),
|
||||
Names: []string{obj.GetName()},
|
||||
}).Post(url)
|
||||
return checkResp(resp, err)
|
||||
}
|
||||
|
||||
func (d *AListV3) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
return errs.NotImplement
|
||||
url := d.Address + "/api/fs/put"
|
||||
var resp common.Resp[interface{}]
|
||||
fileBytes, err := io.ReadAll(stream.GetReadCloser())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
_, err = base.RestyClient.R().SetContext(ctx).
|
||||
SetResult(&resp).
|
||||
SetHeader("Authorization", d.AccessToken).
|
||||
SetHeader("File-Path", path.Join(dstDir.GetPath(), stream.GetName())).
|
||||
SetHeader("Password", d.Password).
|
||||
SetHeader("Content-Length", strconv.FormatInt(stream.GetSize(), 10)).
|
||||
SetBody(fileBytes).Put(url)
|
||||
return checkResp(resp, err)
|
||||
}
|
||||
|
||||
//func (d *AList) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
|
||||
|
@ -15,12 +15,11 @@ type Addition struct {
|
||||
var config = driver.Config{
|
||||
Name: "AList V3",
|
||||
LocalSort: true,
|
||||
NoUpload: true,
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &AListV3{}
|
||||
})
|
||||
}
|
||||
|
@ -43,3 +43,23 @@ type FsGetResp struct {
|
||||
Provider string `json:"provider"`
|
||||
Related []ObjResp `json:"related"`
|
||||
}
|
||||
|
||||
type MkdirOrLinkReq struct {
|
||||
Path string `json:"path" form:"path"`
|
||||
}
|
||||
|
||||
type MoveCopyReq struct {
|
||||
SrcDir string `json:"src_dir"`
|
||||
DstDir string `json:"dst_dir"`
|
||||
Names []string `json:"names"`
|
||||
}
|
||||
|
||||
type RenameReq struct {
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type RemoveReq struct {
|
||||
Dir string `json:"dir"`
|
||||
Names []string `json:"names"`
|
||||
}
|
||||
|
@ -1 +1,17 @@
|
||||
package alist_v3
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
)
|
||||
|
||||
func checkResp(resp common.Resp[interface{}], err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Message == "success" {
|
||||
return nil
|
||||
}
|
||||
return errors.New(resp.Message)
|
||||
}
|
||||
|
@ -38,18 +38,13 @@ func (d *AliDrive) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *AliDrive) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *AliDrive) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *AliDrive) Init(ctx context.Context) error {
|
||||
// TODO login / refresh token
|
||||
//op.MustSaveDriverStorage(d)
|
||||
err = d.refreshToken()
|
||||
err := d.refreshToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -86,11 +81,6 @@ func (d *AliDrive) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *AliDrive) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // TODO this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *AliDrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
data := base.Json{
|
||||
"drive_id": d.DriveId,
|
||||
@ -258,10 +248,14 @@ func (d *AliDrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileS
|
||||
}
|
||||
|
||||
for i, partInfo := range resp.PartInfoList {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
req, err := http.NewRequest("PUT", partInfo.UploadUrl, io.LimitReader(file, DEFAULT))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
res, err := base.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -18,10 +18,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "root",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &AliDrive{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &AliDrive{}
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"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/cron"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
@ -29,16 +28,11 @@ func (d *AliyundriveShare) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.refreshToken()
|
||||
func (d *AliyundriveShare) Init(ctx context.Context) error {
|
||||
err := d.refreshToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -73,11 +67,6 @@ func (d *AliyundriveShare) List(ctx context.Context, dir model.Obj, args model.L
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *AliyundriveShare) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *AliyundriveShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
data := base.Json{
|
||||
"drive_id": d.DriveId,
|
||||
@ -123,34 +112,4 @@ func (d *AliyundriveShare) Link(ctx context.Context, file model.Obj, args model.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
// TODO create folder
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
// TODO move obj
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
// TODO rename obj
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
// TODO copy obj
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) Remove(ctx context.Context, obj model.Obj) error {
|
||||
// TODO remove obj
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
func (d *AliyundriveShare) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
// TODO upload file
|
||||
return errs.NotSupport
|
||||
}
|
||||
|
||||
var _ driver.Driver = (*AliyundriveShare)(nil)
|
||||
|
@ -23,7 +23,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &AliyundriveShare{}
|
||||
})
|
||||
}
|
||||
|
@ -21,11 +21,13 @@ import (
|
||||
_ "github.com/alist-org/alist/v3/drivers/mega"
|
||||
_ "github.com/alist-org/alist/v3/drivers/onedrive"
|
||||
_ "github.com/alist-org/alist/v3/drivers/pikpak"
|
||||
_ "github.com/alist-org/alist/v3/drivers/pikpak_share"
|
||||
_ "github.com/alist-org/alist/v3/drivers/quark"
|
||||
_ "github.com/alist-org/alist/v3/drivers/s3"
|
||||
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
||||
_ "github.com/alist-org/alist/v3/drivers/smb"
|
||||
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
||||
_ "github.com/alist-org/alist/v3/drivers/terabox"
|
||||
_ "github.com/alist-org/alist/v3/drivers/thunder"
|
||||
_ "github.com/alist-org/alist/v3/drivers/uss"
|
||||
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
||||
|
@ -31,15 +31,10 @@ func (d *BaiduNetdisk) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *BaiduNetdisk) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *BaiduNetdisk) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *BaiduNetdisk) Init(ctx context.Context) error {
|
||||
return d.refreshToken()
|
||||
}
|
||||
|
||||
@ -57,11 +52,6 @@ func (d *BaiduNetdisk) List(ctx context.Context, dir model.Obj, args model.ListA
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *BaiduNetdisk) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *BaiduNetdisk) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
if d.DownloadAPI == "crack" {
|
||||
return d.linkCrack(file, args)
|
||||
@ -98,12 +88,11 @@ func (d *BaiduNetdisk) Rename(ctx context.Context, srcObj model.Obj, newName str
|
||||
}
|
||||
|
||||
func (d *BaiduNetdisk) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
dest, newname := stdpath.Split(dstDir.GetPath())
|
||||
data := []base.Json{
|
||||
{
|
||||
"path": srcObj.GetPath(),
|
||||
"dest": dest,
|
||||
"newname": newname,
|
||||
"dest": dstDir.GetPath(),
|
||||
"newname": srcObj.GetName(),
|
||||
},
|
||||
}
|
||||
_, err := d.manage("copy", data)
|
||||
@ -175,7 +164,8 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
||||
return err
|
||||
}
|
||||
}
|
||||
path := encodeURIComponent(stdpath.Join(dstDir.GetPath(), stream.GetName()))
|
||||
rawPath := stdpath.Join(dstDir.GetPath(), stream.GetName())
|
||||
path := encodeURIComponent(rawPath)
|
||||
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
||||
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s&content-md5=%s&slice-md5=%s",
|
||||
path, stream.GetSize(),
|
||||
@ -202,6 +192,9 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
||||
}
|
||||
left = stream.GetSize()
|
||||
for i, partseq := range precreateResp.BlockList {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
byteSize := Default
|
||||
var byteData []byte
|
||||
if left < Default {
|
||||
@ -217,7 +210,11 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
||||
}
|
||||
u := "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2"
|
||||
params["partseq"] = strconv.Itoa(partseq)
|
||||
res, err := base.RestyClient.R().SetQueryParams(params).SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).Post(u)
|
||||
res, err := base.RestyClient.R().
|
||||
SetContext(ctx).
|
||||
SetQueryParams(params).
|
||||
SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).
|
||||
Post(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -226,7 +223,7 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
||||
up(i * 100 / len(precreateResp.BlockList))
|
||||
}
|
||||
}
|
||||
_, err = d.create(path, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||
_, err = d.create(rawPath, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &BaiduNetdisk{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &BaiduNetdisk{}
|
||||
})
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ func (d *BaiduNetdisk) create(path string, size int64, isdir int, uploadid, bloc
|
||||
params := map[string]string{
|
||||
"method": "create",
|
||||
}
|
||||
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", path, size, isdir)
|
||||
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", encodeURIComponent(path), size, isdir)
|
||||
if uploadid != "" {
|
||||
data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
|
||||
}
|
||||
|
@ -29,15 +29,10 @@ func (d *BaiduPhoto) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *BaiduPhoto) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *BaiduPhoto) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *BaiduPhoto) Init(ctx context.Context) error {
|
||||
return d.refreshToken()
|
||||
}
|
||||
|
||||
@ -245,6 +240,9 @@ func (d *BaiduPhoto) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
uploadParams["partseq"] = fmt.Sprint(i)
|
||||
_, err = d.Post("https://c3.pcs.baidu.com/rest/2.0/pcs/superfile2", func(r *resty.Request) {
|
||||
r.SetContext(ctx)
|
||||
|
@ -24,7 +24,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &BaiduPhoto{}
|
||||
})
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ package baiduphoto
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
)
|
||||
|
||||
type TokenErrResp struct {
|
||||
@ -102,7 +100,7 @@ type (
|
||||
)
|
||||
|
||||
func (a *Album) GetSize() int64 { return 0 }
|
||||
func (a *Album) GetName() string { return utils.MappingName(a.Title) }
|
||||
func (a *Album) GetName() string { return a.Title }
|
||||
func (a *Album) ModTime() time.Time {
|
||||
if a.parseTime == nil {
|
||||
a.parseTime = toTime(a.Mtime)
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"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"
|
||||
"github.com/jlaffaye/ftp"
|
||||
)
|
||||
|
||||
@ -22,15 +21,10 @@ func (d *FTP) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *FTP) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *FTP) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *FTP) Init(ctx context.Context) error {
|
||||
return d.login()
|
||||
}
|
||||
|
||||
@ -66,11 +60,6 @@ func (d *FTP) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]m
|
||||
return res, nil
|
||||
}
|
||||
|
||||
//func (d *FTP) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *FTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
if err := d.login(); err != nil {
|
||||
return nil, err
|
||||
@ -124,6 +113,7 @@ func (d *FTP) Put(ctx context.Context, dstDir model.Obj, stream model.FileStream
|
||||
if err := d.login(); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: support cancel
|
||||
return d.conn.Stor(stdpath.Join(dstDir.GetPath(), stream.GetName()), stream)
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &FTP{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &FTP{}
|
||||
})
|
||||
}
|
||||
|
@ -4,14 +4,12 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
stdpath "path"
|
||||
"strconv"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"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/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
@ -27,15 +25,10 @@ func (d *GoogleDrive) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *GoogleDrive) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *GoogleDrive) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *GoogleDrive) Init(ctx context.Context) error {
|
||||
if d.ChunkSize == 0 {
|
||||
d.ChunkSize = 5
|
||||
}
|
||||
@ -56,11 +49,6 @@ func (d *GoogleDrive) List(ctx context.Context, dir model.Obj, args model.ListAr
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *GoogleDrive) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *GoogleDrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
url := fmt.Sprintf("https://www.googleapis.com/drive/v3/files/%s?includeItemsFromAllDrives=true&supportsAllDrives=true", file.GetID())
|
||||
_, err := d.request(url, http.MethodGet, nil, nil)
|
||||
@ -122,8 +110,7 @@ func (d *GoogleDrive) Remove(ctx context.Context, obj model.Obj) error {
|
||||
}
|
||||
|
||||
func (d *GoogleDrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
obj, _ := op.Get(ctx, d, stdpath.Join(dstDir.GetPath(), stream.GetName()))
|
||||
|
||||
obj := stream.GetOld()
|
||||
var (
|
||||
e Error
|
||||
url string
|
||||
@ -147,7 +134,7 @@ func (d *GoogleDrive) Put(ctx context.Context, dstDir model.Obj, stream model.Fi
|
||||
"X-Upload-Content-Type": stream.GetMimetype(),
|
||||
"X-Upload-Content-Length": strconv.FormatInt(stream.GetSize(), 10),
|
||||
}).
|
||||
SetError(&e).SetBody(data)
|
||||
SetError(&e).SetBody(data).SetContext(ctx)
|
||||
if obj != nil {
|
||||
res, err = req.Patch(url)
|
||||
} else {
|
||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "root",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &GoogleDrive{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &GoogleDrive{}
|
||||
})
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -104,6 +105,9 @@ func (d *GoogleDrive) chunkUpload(ctx context.Context, stream model.FileStreamer
|
||||
var defaultChunkSize = d.ChunkSize * 1024 * 1024
|
||||
var finish int64 = 0
|
||||
for finish < stream.GetSize() {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
chunkSize := stream.GetSize() - finish
|
||||
if chunkSize > defaultChunkSize {
|
||||
chunkSize = defaultChunkSize
|
||||
@ -112,7 +116,7 @@ func (d *GoogleDrive) chunkUpload(ctx context.Context, stream model.FileStreamer
|
||||
req.SetHeaders(map[string]string{
|
||||
"Content-Length": strconv.FormatInt(chunkSize, 10),
|
||||
"Content-Range": fmt.Sprintf("bytes %d-%d/%d", finish, finish+chunkSize-1, stream.GetSize()),
|
||||
}).SetBody(io.LimitReader(stream.GetReadCloser(), chunkSize))
|
||||
}).SetBody(io.LimitReader(stream.GetReadCloser(), chunkSize)).SetContext(ctx)
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -26,15 +26,10 @@ func (d *GooglePhoto) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *GooglePhoto) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *GooglePhoto) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *GooglePhoto) Init(ctx context.Context) error {
|
||||
return d.refreshToken()
|
||||
}
|
||||
|
||||
@ -52,11 +47,6 @@ func (d *GooglePhoto) List(ctx context.Context, dir model.Obj, args model.ListAr
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *GooglePhoto) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *GooglePhoto) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
f, err := d.getMedia(file.GetID())
|
||||
if err != nil {
|
||||
@ -134,7 +124,7 @@ func (d *GooglePhoto) Put(ctx context.Context, dstDir model.Obj, stream model.Fi
|
||||
}
|
||||
|
||||
resp, err := d.request(postUrl, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(stream.GetReadCloser())
|
||||
req.SetBody(stream.GetReadCloser()).SetContext(ctx)
|
||||
}, nil, postHeaders)
|
||||
|
||||
if err != nil {
|
||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
||||
LocalSort: true,
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &GooglePhoto{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &GooglePhoto{}
|
||||
})
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"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"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
@ -25,15 +24,10 @@ func (d *LanZou) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *LanZou) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *LanZou) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *LanZou) Init(ctx context.Context) error {
|
||||
if d.IsCookie() {
|
||||
if d.RootFolderID == "" {
|
||||
d.RootFolderID = "-1"
|
||||
@ -163,7 +157,7 @@ func (d *LanZou) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
"id": "WU_FILE_0",
|
||||
"name": stream.GetName(),
|
||||
"folder_id": dstDir.GetID(),
|
||||
}).SetFileReader("upload_file", stream.GetName(), stream)
|
||||
}).SetFileReader("upload_file", stream.GetName(), stream).SetContext(ctx)
|
||||
}, nil, true)
|
||||
return err
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &LanZou{}
|
||||
})
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/conf"
|
||||
"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/internal/sign"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
"github.com/disintegration/imaging"
|
||||
@ -33,24 +33,18 @@ func (d *Local) Config() driver.Config {
|
||||
return config
|
||||
}
|
||||
|
||||
func (d *Local) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Local) Init(ctx context.Context) error {
|
||||
if !utils.Exists(d.GetRootPath()) {
|
||||
err = fmt.Errorf("root folder %s not exists", d.GetRootPath())
|
||||
} else {
|
||||
if !filepath.IsAbs(d.GetRootPath()) {
|
||||
abs, err := filepath.Abs(d.GetRootPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.SetRootPath(abs)
|
||||
}
|
||||
return fmt.Errorf("root folder %s not exists", d.GetRootPath())
|
||||
}
|
||||
return err
|
||||
if !filepath.IsAbs(d.GetRootPath()) {
|
||||
abs, err := filepath.Abs(d.GetRootPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Addition.RootFolderPath = abs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Local) Drop(ctx context.Context) error {
|
||||
@ -58,7 +52,7 @@ func (d *Local) Drop(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (d *Local) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
@ -76,15 +70,16 @@ func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
||||
if d.Thumbnail && utils.GetFileType(f.Name()) == conf.IMAGE {
|
||||
thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
|
||||
thumb = utils.EncodePath(thumb, true)
|
||||
thumb += "?type=thumb"
|
||||
thumb += "?type=thumb&sign=" + sign.Sign(stdpath.Join(args.ReqPath, f.Name()))
|
||||
}
|
||||
isFolder := f.IsDir() || isSymlinkDir(f, fullPath)
|
||||
size := f.Size()
|
||||
if isFolder {
|
||||
size = 0
|
||||
var size int64
|
||||
if !isFolder {
|
||||
size = f.Size()
|
||||
}
|
||||
file := model.ObjThumb{
|
||||
Object: model.Object{
|
||||
Path: filepath.Join(dir.GetPath(), f.Name()),
|
||||
Name: f.Name(),
|
||||
Modified: f.ModTime(),
|
||||
Size: size,
|
||||
@ -99,29 +94,6 @@ func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
f, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "cannot find the file") {
|
||||
return nil, errs.ObjectNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
isFolder := f.IsDir() || isSymlinkDir(f, path)
|
||||
size := f.Size()
|
||||
if isFolder {
|
||||
size = 0
|
||||
}
|
||||
file := model.Object{
|
||||
Path: path,
|
||||
Name: f.Name(),
|
||||
Modified: f.ModTime(),
|
||||
Size: size,
|
||||
IsFolder: isFolder,
|
||||
}
|
||||
return &file, nil
|
||||
}
|
||||
|
||||
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
fullPath := file.GetPath()
|
||||
var link model.Link
|
||||
@ -164,6 +136,9 @@ func (d *Local) MakeDir(ctx context.Context, parentDir model.Obj, dirName string
|
||||
func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
srcPath := srcObj.GetPath()
|
||||
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||
if utils.IsSubPath(srcPath, dstPath) {
|
||||
return fmt.Errorf("the destination folder is a subfolder of the source folder")
|
||||
}
|
||||
err := os.Rename(srcPath, dstPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -184,6 +159,9 @@ func (d *Local) Rename(ctx context.Context, srcObj model.Obj, newName string) er
|
||||
func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
srcPath := srcObj.GetPath()
|
||||
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||
if utils.IsSubPath(srcPath, dstPath) {
|
||||
return fmt.Errorf("the destination folder is a subfolder of the source folder")
|
||||
}
|
||||
var err error
|
||||
if srcObj.IsDir() {
|
||||
err = utils.CopyDir(srcPath, dstPath)
|
||||
|
@ -19,10 +19,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Local{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Local{}
|
||||
})
|
||||
}
|
||||
|
@ -8,14 +8,12 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
@ -36,16 +34,11 @@ func (d *MediaTrack) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *MediaTrack) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *MediaTrack) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.request("https://kayle.api.mediatrack.cn/users", http.MethodGet, nil, nil)
|
||||
func (d *MediaTrack) Init(ctx context.Context) error {
|
||||
_, err := d.request("https://kayle.api.mediatrack.cn/users", http.MethodGet, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -64,7 +57,7 @@ func (d *MediaTrack) List(ctx context.Context, dir model.Obj, args model.ListArg
|
||||
if f.File != nil && f.File.Cover != "" {
|
||||
thumb = "https://nano.mtres.cn/" + f.File.Cover
|
||||
}
|
||||
return &model.ObjThumb{
|
||||
return &Object{
|
||||
Object: model.Object{
|
||||
ID: f.ID,
|
||||
Name: f.Title,
|
||||
@ -73,15 +66,11 @@ func (d *MediaTrack) List(ctx context.Context, dir model.Obj, args model.ListArg
|
||||
Size: size,
|
||||
},
|
||||
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
||||
ParentID: dir.GetID(),
|
||||
}, nil
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *MediaTrack) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *MediaTrack) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
url := fmt.Sprintf("https://kayn.api.mediatrack.cn/v1/download_token/asset?asset_id=%s&source_type=project&password=&source_id=%s",
|
||||
file.GetID(), d.ProjectID)
|
||||
@ -156,16 +145,18 @@ func (d *MediaTrack) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
}
|
||||
|
||||
func (d *MediaTrack) Remove(ctx context.Context, obj model.Obj) error {
|
||||
dir, err := op.Get(ctx, d, path.Dir(obj.GetPath()))
|
||||
if err != nil {
|
||||
return err
|
||||
var parentID string
|
||||
if o, ok := obj.(*Object); ok {
|
||||
parentID = o.ParentID
|
||||
} else {
|
||||
return fmt.Errorf("obj is not local Object")
|
||||
}
|
||||
data := base.Json{
|
||||
"origin_id": dir.GetID(),
|
||||
"origin_id": parentID,
|
||||
"ids": []string{obj.GetID()},
|
||||
}
|
||||
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/delete"
|
||||
_, err = d.request(url, http.MethodDelete, func(req *resty.Request) {
|
||||
_, err := d.request(url, http.MethodDelete, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
return err
|
||||
@ -204,7 +195,7 @@ func (d *MediaTrack) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
||||
Key: &resp.Data.Object,
|
||||
Body: tempFile,
|
||||
}
|
||||
_, err = uploader.Upload(input)
|
||||
_, err = uploader.UploadWithContext(ctx, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &MediaTrack{}
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package mediatrack
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
)
|
||||
|
||||
type BaseResp struct {
|
||||
Status string `json:"status"`
|
||||
@ -60,3 +64,9 @@ type UploadResp struct {
|
||||
TraceID string `json:"trace_id"`
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
model.Object
|
||||
model.Thumbnail
|
||||
ParentID string
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"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/chanio"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/t3rm1n4l/go-mega"
|
||||
@ -26,15 +25,10 @@ func (d *Mega) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Mega) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Mega) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Mega) Init(ctx context.Context) error {
|
||||
d.c = mega.New()
|
||||
return d.c.Login(d.Email, d.Password)
|
||||
}
|
||||
@ -62,13 +56,10 @@ func (d *Mega) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]
|
||||
return nil, fmt.Errorf("unable to convert dir to mega node")
|
||||
}
|
||||
|
||||
func (d *Mega) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
if path == "/" {
|
||||
n := d.c.FS.GetRoot()
|
||||
log.Debugf("mega root: %+v", *n)
|
||||
return &MegaNode{n}, nil
|
||||
}
|
||||
return nil, errs.NotSupport
|
||||
func (d *Mega) GetRoot(ctx context.Context) (model.Obj, error) {
|
||||
n := d.c.FS.GetRoot()
|
||||
log.Debugf("mega root: %+v", *n)
|
||||
return &MegaNode{n}, nil
|
||||
}
|
||||
|
||||
func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
@ -85,17 +76,21 @@ func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*
|
||||
//u := down.GetResourceUrl()
|
||||
//u = strings.Replace(u, "http", "https", 1)
|
||||
//return &model.Link{URL: u}, nil
|
||||
c := chanio.New()
|
||||
r, w := io.Pipe()
|
||||
go func() {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
log.Debugf("chunk size: %d", down.Chunks())
|
||||
var (
|
||||
chunk []byte
|
||||
err error
|
||||
)
|
||||
for id := 0; id < down.Chunks(); id++ {
|
||||
chunk, err := down.DownloadChunk(id)
|
||||
chunk, err = down.DownloadChunk(id)
|
||||
if err != nil {
|
||||
log.Errorf("mega down: %+v", err)
|
||||
return
|
||||
break
|
||||
}
|
||||
log.Debugf("id: %d,len: %d", id, len(chunk))
|
||||
//_, _, err = down.ChunkLocation(id)
|
||||
@ -104,14 +99,16 @@ func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*
|
||||
// return
|
||||
//}
|
||||
//_, err = c.Write(chunk)
|
||||
_, err = c.Write(chunk)
|
||||
if _, err = w.Write(chunk); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
err := c.Close()
|
||||
err = w.CloseWithError(err)
|
||||
if err != nil {
|
||||
log.Errorf("mega down: %+v", err)
|
||||
}
|
||||
}()
|
||||
return &model.Link{Data: c}, nil
|
||||
return &model.Link{Data: r}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unable to convert dir to mega node")
|
||||
}
|
||||
@ -159,6 +156,9 @@ func (d *Mega) Put(ctx context.Context, dstDir model.Obj, stream model.FileStrea
|
||||
}
|
||||
|
||||
for id := 0; id < u.Chunks(); id++ {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
_, chkSize, err := u.ChunkLocation(id)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -20,7 +20,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Mega{}
|
||||
})
|
||||
}
|
||||
|
@ -2,14 +2,13 @@ package onedrive
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
stdpath "path"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"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/internal/op"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
@ -25,15 +24,10 @@ func (d *Onedrive) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Onedrive) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Onedrive) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Onedrive) Init(ctx context.Context) error {
|
||||
if d.ChunkSize < 1 {
|
||||
d.ChunkSize = 5
|
||||
}
|
||||
@ -50,7 +44,7 @@ func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||
return fileToObj(src), nil
|
||||
return fileToObj(src, dir.GetID()), nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -95,18 +89,21 @@ func (d *Onedrive) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
}
|
||||
|
||||
func (d *Onedrive) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
dstDir, err := op.Get(ctx, d, stdpath.Dir(srcObj.GetPath()))
|
||||
if err != nil {
|
||||
return err
|
||||
//dstDir, err := op.GetUnwrap(ctx, d, stdpath.Dir(srcObj.GetPath()))
|
||||
var parentID string
|
||||
if o, ok := srcObj.(*Object); ok {
|
||||
parentID = o.ParentID
|
||||
} else {
|
||||
return fmt.Errorf("srcObj is not Object")
|
||||
}
|
||||
data := base.Json{
|
||||
"parentReference": base.Json{
|
||||
"id": dstDir.GetID(),
|
||||
"id": parentID,
|
||||
},
|
||||
"name": newName,
|
||||
}
|
||||
url := d.GetMetaUrl(false, srcObj.GetPath())
|
||||
_, err = d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
||||
_, err := d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
}, nil)
|
||||
return err
|
||||
@ -140,7 +137,7 @@ func (d *Onedrive) Remove(ctx context.Context, obj model.Obj) error {
|
||||
func (d *Onedrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
var err error
|
||||
if stream.GetSize() <= 4*1024*1024 {
|
||||
err = d.upSmall(dstDir, stream)
|
||||
err = d.upSmall(ctx, dstDir, stream)
|
||||
} else {
|
||||
err = d.upBig(ctx, dstDir, stream, up)
|
||||
}
|
||||
|
@ -23,10 +23,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Onedrive{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Onedrive{}
|
||||
})
|
||||
}
|
||||
|
@ -42,21 +42,29 @@ type File struct {
|
||||
} `json:"parentReference"`
|
||||
}
|
||||
|
||||
func fileToObj(f File) *model.ObjThumbURL {
|
||||
type Object struct {
|
||||
model.ObjThumbURL
|
||||
ParentID string
|
||||
}
|
||||
|
||||
func fileToObj(f File, parentID string) *Object {
|
||||
thumb := ""
|
||||
if len(f.Thumbnails) > 0 {
|
||||
thumb = f.Thumbnails[0].Medium.Url
|
||||
}
|
||||
return &model.ObjThumbURL{
|
||||
Object: model.Object{
|
||||
ID: f.Id,
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
Modified: f.LastModifiedDateTime,
|
||||
IsFolder: f.File == nil,
|
||||
return &Object{
|
||||
ObjThumbURL: model.ObjThumbURL{
|
||||
Object: model.Object{
|
||||
ID: f.Id,
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
Modified: f.LastModifiedDateTime,
|
||||
IsFolder: f.File == nil,
|
||||
},
|
||||
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
||||
Url: model.Url{Url: f.Url},
|
||||
},
|
||||
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
||||
Url: model.Url{Url: f.Url},
|
||||
ParentID: parentID,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,14 +147,14 @@ func (d *Onedrive) GetFile(path string) (*File, error) {
|
||||
return &file, err
|
||||
}
|
||||
|
||||
func (d *Onedrive) upSmall(dstDir model.Obj, stream model.FileStreamer) error {
|
||||
func (d *Onedrive) upSmall(ctx context.Context, dstDir model.Obj, stream model.FileStreamer) error {
|
||||
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetPath(), stream.GetName())) + "/content"
|
||||
data, err := io.ReadAll(stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.Request(url, http.MethodPut, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
@ -185,6 +185,10 @@ func (d *Onedrive) upBig(ctx context.Context, dstDir model.Obj, stream model.Fil
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest("PUT", uploadUrl, bytes.NewBuffer(byteData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
||||
req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", finish, finish+byteSize-1, stream.GetSize()))
|
||||
finish += byteSize
|
||||
|
@ -35,15 +35,10 @@ func (d *PikPak) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *PikPak) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *PikPak) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *PikPak) Init(ctx context.Context) error {
|
||||
return d.login()
|
||||
}
|
||||
|
||||
@ -194,7 +189,7 @@ func (d *PikPak) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
Key: &key,
|
||||
Body: tempFile,
|
||||
}
|
||||
_, err = uploader.Upload(input)
|
||||
_, err = uploader.UploadWithContext(ctx, input)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &PikPak{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &PikPak{}
|
||||
})
|
||||
}
|
||||
|
81
drivers/pikpak_share/driver.go
Normal file
81
drivers/pikpak_share/driver.go
Normal file
@ -0,0 +1,81 @@
|
||||
package pikpak_share
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type PikPakShare struct {
|
||||
model.Storage
|
||||
Addition
|
||||
RefreshToken string
|
||||
AccessToken string
|
||||
PassCodeToken string
|
||||
}
|
||||
|
||||
func (d *PikPakShare) Config() driver.Config {
|
||||
return config
|
||||
}
|
||||
|
||||
func (d *PikPakShare) GetAddition() driver.Additional {
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *PikPakShare) Init(ctx context.Context) error {
|
||||
err := d.login()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.SharePwd != "" {
|
||||
err = d.getSharePassToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *PikPakShare) Drop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *PikPakShare) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
files, err := d.getFiles(dir.GetID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||
return fileToObj(src), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (d *PikPakShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
var resp ShareResp
|
||||
query := map[string]string{
|
||||
"share_id": d.ShareId,
|
||||
"file_id": file.GetID(),
|
||||
"pass_code_token": d.PassCodeToken,
|
||||
}
|
||||
_, err := d.request("https://api-drive.mypikpak.com/drive/v1/share/file_info", http.MethodGet, func(req *resty.Request) {
|
||||
req.SetQueryParams(query)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
link := model.Link{
|
||||
URL: resp.FileInfo.WebContentLink,
|
||||
}
|
||||
if len(resp.FileInfo.Medias) > 0 && resp.FileInfo.Medias[0].Link.Url != "" {
|
||||
log.Debugln("use media link")
|
||||
link.URL = resp.FileInfo.Medias[0].Link.Url
|
||||
}
|
||||
return &link, nil
|
||||
}
|
||||
|
||||
var _ driver.Driver = (*PikPakShare)(nil)
|
27
drivers/pikpak_share/meta.go
Normal file
27
drivers/pikpak_share/meta.go
Normal file
@ -0,0 +1,27 @@
|
||||
package pikpak_share
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
driver.RootID
|
||||
Username string `json:"username" required:"true"`
|
||||
Password string `json:"password" required:"true"`
|
||||
ShareId string `json:"share_id" required:"true"`
|
||||
SharePwd string `json:"share_pwd"`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "PikPakShare",
|
||||
LocalSort: true,
|
||||
NoUpload: true,
|
||||
DefaultRoot: "",
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &PikPakShare{}
|
||||
})
|
||||
}
|
80
drivers/pikpak_share/types.go
Normal file
80
drivers/pikpak_share/types.go
Normal file
@ -0,0 +1,80 @@
|
||||
package pikpak_share
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
)
|
||||
|
||||
type RespErr struct {
|
||||
ErrorCode int `json:"error_code"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type ShareResp struct {
|
||||
ShareStatus string `json:"share_status"`
|
||||
ShareStatusText string `json:"share_status_text"`
|
||||
FileInfo File `json:"file_info"`
|
||||
Files []File `json:"files"`
|
||||
NextPageToken string `json:"next_page_token"`
|
||||
PassCodeToken string `json:"pass_code_token"`
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Id string `json:"id"`
|
||||
ShareId string `json:"share_id"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
ModifiedTime time.Time `json:"modified_time"`
|
||||
Size string `json:"size"`
|
||||
ThumbnailLink string `json:"thumbnail_link"`
|
||||
WebContentLink string `json:"web_content_link"`
|
||||
Medias []Media `json:"medias"`
|
||||
}
|
||||
|
||||
func fileToObj(f File) *model.ObjThumb {
|
||||
size, _ := strconv.ParseInt(f.Size, 10, 64)
|
||||
return &model.ObjThumb{
|
||||
Object: model.Object{
|
||||
ID: f.Id,
|
||||
Name: f.Name,
|
||||
Size: size,
|
||||
Modified: f.ModifiedTime,
|
||||
IsFolder: f.Kind == "drive#folder",
|
||||
},
|
||||
Thumbnail: model.Thumbnail{
|
||||
Thumbnail: f.ThumbnailLink,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
MediaId string `json:"media_id"`
|
||||
MediaName string `json:"media_name"`
|
||||
Video struct {
|
||||
Height int `json:"height"`
|
||||
Width int `json:"width"`
|
||||
Duration int `json:"duration"`
|
||||
BitRate int `json:"bit_rate"`
|
||||
FrameRate int `json:"frame_rate"`
|
||||
VideoCodec string `json:"video_codec"`
|
||||
AudioCodec string `json:"audio_codec"`
|
||||
VideoType string `json:"video_type"`
|
||||
} `json:"video"`
|
||||
Link struct {
|
||||
Url string `json:"url"`
|
||||
Token string `json:"token"`
|
||||
Expire time.Time `json:"expire"`
|
||||
} `json:"link"`
|
||||
NeedMoreQuota bool `json:"need_more_quota"`
|
||||
VipTypes []interface{} `json:"vip_types"`
|
||||
RedirectLink string `json:"redirect_link"`
|
||||
IconLink string `json:"icon_link"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
Priority int `json:"priority"`
|
||||
IsOrigin bool `json:"is_origin"`
|
||||
ResolutionName string `json:"resolution_name"`
|
||||
IsVisible bool `json:"is_visible"`
|
||||
Category string `json:"category"`
|
||||
}
|
154
drivers/pikpak_share/util.go
Normal file
154
drivers/pikpak_share/util.go
Normal file
@ -0,0 +1,154 @@
|
||||
package pikpak_share
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
"github.com/go-resty/resty/v2"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
// do others that not defined in Driver interface
|
||||
|
||||
func (d *PikPakShare) login() error {
|
||||
url := "https://user.mypikpak.com/v1/auth/signin"
|
||||
var e RespErr
|
||||
res, err := base.RestyClient.R().SetError(&e).SetBody(base.Json{
|
||||
"captcha_token": "",
|
||||
"client_id": "YNxT9w7GMdWvEOKa",
|
||||
"client_secret": "dbw2OtmVEeuUvIptb1Coyg",
|
||||
"username": d.Username,
|
||||
"password": d.Password,
|
||||
}).Post(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e.ErrorCode != 0 {
|
||||
return errors.New(e.Error)
|
||||
}
|
||||
data := res.Body()
|
||||
d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString()
|
||||
d.AccessToken = jsoniter.Get(data, "access_token").ToString()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *PikPakShare) refreshToken() error {
|
||||
url := "https://user.mypikpak.com/v1/auth/token"
|
||||
var e RespErr
|
||||
res, err := base.RestyClient.R().SetError(&e).
|
||||
SetHeader("user-agent", "").SetBody(base.Json{
|
||||
"client_id": "YNxT9w7GMdWvEOKa",
|
||||
"client_secret": "dbw2OtmVEeuUvIptb1Coyg",
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": d.RefreshToken,
|
||||
}).Post(url)
|
||||
if err != nil {
|
||||
d.Status = err.Error()
|
||||
op.MustSaveDriverStorage(d)
|
||||
return err
|
||||
}
|
||||
if e.ErrorCode != 0 {
|
||||
if e.ErrorCode == 4126 {
|
||||
// refresh_token invalid, re-login
|
||||
return d.login()
|
||||
}
|
||||
d.Status = e.Error
|
||||
op.MustSaveDriverStorage(d)
|
||||
return errors.New(e.Error)
|
||||
}
|
||||
data := res.Body()
|
||||
d.Status = "work"
|
||||
d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString()
|
||||
d.AccessToken = jsoniter.Get(data, "access_token").ToString()
|
||||
op.MustSaveDriverStorage(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *PikPakShare) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
req := base.RestyClient.R()
|
||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||
if callback != nil {
|
||||
callback(req)
|
||||
}
|
||||
if resp != nil {
|
||||
req.SetResult(resp)
|
||||
}
|
||||
var e RespErr
|
||||
req.SetError(&e)
|
||||
res, err := req.Execute(method, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if e.ErrorCode != 0 {
|
||||
if e.ErrorCode == 16 {
|
||||
// login / refresh token
|
||||
err = d.refreshToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.request(url, method, callback, resp)
|
||||
}
|
||||
return nil, errors.New(e.Error)
|
||||
}
|
||||
return res.Body(), nil
|
||||
}
|
||||
|
||||
func (d *PikPakShare) getSharePassToken() error {
|
||||
query := map[string]string{
|
||||
"share_id": d.ShareId,
|
||||
"pass_code": d.SharePwd,
|
||||
"thumbnail_size": "SIZE_LARGE",
|
||||
"limit": "100",
|
||||
}
|
||||
var resp ShareResp
|
||||
_, err := d.request("https://api-drive.mypikpak.com/drive/v1/share", http.MethodGet, func(req *resty.Request) {
|
||||
req.SetQueryParams(query)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.PassCodeToken = resp.PassCodeToken
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *PikPakShare) getFiles(id string) ([]File, error) {
|
||||
res := make([]File, 0)
|
||||
pageToken := "first"
|
||||
for pageToken != "" {
|
||||
if pageToken == "first" {
|
||||
pageToken = ""
|
||||
}
|
||||
query := map[string]string{
|
||||
"parent_id": id,
|
||||
"share_id": d.ShareId,
|
||||
"thumbnail_size": "SIZE_LARGE",
|
||||
"with_audit": "true",
|
||||
"limit": "100",
|
||||
"filters": `{"phase":{"eq":"PHASE_TYPE_COMPLETE"},"trashed":{"eq":false}}`,
|
||||
"page_token": pageToken,
|
||||
"pass_code_token": d.PassCodeToken,
|
||||
}
|
||||
var resp ShareResp
|
||||
_, err := d.request("https://api-drive.mypikpak.com/drive/v1/share/detail", http.MethodGet, func(req *resty.Request) {
|
||||
req.SetQueryParams(query)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.ShareStatus != "OK" {
|
||||
if resp.ShareStatus == "PASS_CODE_EMPTY" || resp.ShareStatus == "PASS_CODE_ERROR" {
|
||||
err = d.getSharePassToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.getFiles(id)
|
||||
}
|
||||
return nil, errors.New(resp.ShareStatusText)
|
||||
}
|
||||
pageToken = resp.NextPageToken
|
||||
res = append(res, resp.Files...)
|
||||
}
|
||||
return res, nil
|
||||
}
|
@ -29,16 +29,11 @@ func (d *Quark) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Quark) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Quark) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.request("/config", http.MethodGet, nil, nil)
|
||||
func (d *Quark) Init(ctx context.Context) error {
|
||||
_, err := d.request("/config", http.MethodGet, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -56,11 +51,6 @@ func (d *Quark) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *Quark) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // TODO this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
data := base.Json{
|
||||
"fids": []string{file.GetID()},
|
||||
@ -189,6 +179,9 @@ func (d *Quark) Put(ctx context.Context, dstDir model.Obj, stream model.FileStre
|
||||
partNumber := 1
|
||||
sizeDivide100 := stream.GetSize() / 100
|
||||
for left > 0 {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
if left > int64(partSize) {
|
||||
bytes = defaultBytes
|
||||
} else {
|
||||
@ -200,7 +193,7 @@ func (d *Quark) Put(ctx context.Context, dstDir model.Obj, stream model.FileStre
|
||||
}
|
||||
left -= int64(partSize)
|
||||
log.Debugf("left: %d", left)
|
||||
m, err := d.upPart(pre, stream.GetMimetype(), partNumber, bytes)
|
||||
m, err := d.upPart(ctx, pre, stream.GetMimetype(), partNumber, bytes)
|
||||
//m, err := driver.UpPart(pre, file.GetMIMEType(), partNumber, bytes, account, md5Str, sha1Str)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -18,10 +18,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "0",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Quark{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Quark{}
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package quark
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
@ -118,7 +119,7 @@ func (d *Quark) upHash(md5, sha1, taskId string) (bool, error) {
|
||||
return resp.Data.Finish, err
|
||||
}
|
||||
|
||||
func (d *Quark) upPart(pre UpPreResp, mineType string, partNumber int, bytes []byte) (string, error) {
|
||||
func (d *Quark) upPart(ctx context.Context, pre UpPreResp, mineType string, partNumber int, bytes []byte) (string, error) {
|
||||
//func (driver Quark) UpPart(pre UpPreResp, mineType string, partNumber int, bytes []byte, account *model.Account, md5Str, sha1Str string) (string, error) {
|
||||
timeStr := time.Now().UTC().Format(http.TimeFormat)
|
||||
data := base.Json{
|
||||
@ -135,7 +136,7 @@ x-oss-user-agent:aliyun-sdk-js/6.6.1 Chrome 98.0.4758.80 on Windows 10 64-bit
|
||||
}
|
||||
var resp UpAuthResp
|
||||
_, err := d.request("/file/upload/auth", http.MethodPost, func(req *resty.Request) {
|
||||
req.SetBody(data)
|
||||
req.SetBody(data).SetContext(ctx)
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -150,7 +151,7 @@ x-oss-user-agent:aliyun-sdk-js/6.6.1 Chrome 98.0.4758.80 on Windows 10 64-bit
|
||||
// }
|
||||
//}
|
||||
u := fmt.Sprintf("https://%s.%s/%s", pre.Data.Bucket, pre.Data.UploadUrl[7:], pre.Data.ObjKey)
|
||||
res, err := base.RestyClient.R().
|
||||
res, err := base.RestyClient.R().SetContext(ctx).
|
||||
SetHeaders(map[string]string{
|
||||
"Authorization": resp.Data.AuthKey,
|
||||
"Content-Type": mineType,
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
@ -31,19 +30,14 @@ func (d *S3) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *S3) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *S3) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *S3) Init(ctx context.Context) error {
|
||||
if d.Region == "" {
|
||||
d.Region = "alist"
|
||||
}
|
||||
err = d.initSession()
|
||||
err := d.initSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -63,11 +57,6 @@ func (d *S3) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]mo
|
||||
return d.listV1(dir.GetPath())
|
||||
}
|
||||
|
||||
//func (d *S3) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *S3) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
path := getKey(file.GetPath(), false)
|
||||
disposition := fmt.Sprintf(`attachment;filename="%s"`, url.QueryEscape(stdpath.Base(path)))
|
||||
@ -145,7 +134,7 @@ func (d *S3) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreame
|
||||
Key: &key,
|
||||
Body: stream,
|
||||
}
|
||||
_, err := uploader.Upload(input)
|
||||
_, err := uploader.UploadWithContext(ctx, input)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -21,14 +21,13 @@ type Addition struct {
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "S3",
|
||||
DefaultRoot: "/",
|
||||
LocalSort: true,
|
||||
CheckStatus: true,
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &S3{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &S3{}
|
||||
})
|
||||
}
|
||||
|
@ -23,15 +23,10 @@ func (d *SFTP) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *SFTP) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *SFTP) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *SFTP) Init(ctx context.Context) error {
|
||||
return d.initClient()
|
||||
}
|
||||
|
||||
@ -52,11 +47,6 @@ func (d *SFTP) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *SFTP) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *SFTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
remoteFile, err := d.client.Open(file.GetPath())
|
||||
if err != nil {
|
||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
||||
CheckStatus: true,
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &SFTP{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &SFTP{}
|
||||
})
|
||||
}
|
||||
|
@ -26,16 +26,11 @@ func (d *SMB) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *SMB) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *SMB) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.Index(d.Addition.Address, ":") < 0{
|
||||
func (d *SMB) Init(ctx context.Context) error {
|
||||
if strings.Index(d.Addition.Address, ":") < 0 {
|
||||
d.Addition.Address = d.Addition.Address + ":445"
|
||||
}
|
||||
return d.initFS()
|
||||
@ -74,11 +69,6 @@ func (d *SMB) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]m
|
||||
return files, nil
|
||||
}
|
||||
|
||||
//func (d *SMB) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *SMB) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
if err := d.checkConn(); err != nil {
|
||||
return nil, err
|
||||
|
@ -22,7 +22,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &SMB{}
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
@ -22,16 +21,11 @@ func (d *Teambition) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Teambition) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Teambition) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.request("/api/v2/roles", http.MethodGet, nil, nil)
|
||||
func (d *Teambition) Init(ctx context.Context) error {
|
||||
_, err := d.request("/api/v2/roles", http.MethodGet, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -43,11 +37,6 @@ func (d *Teambition) List(ctx context.Context, dir model.Obj, args model.ListArg
|
||||
return d.getFiles(dir.GetID())
|
||||
}
|
||||
|
||||
//func (d *Teambition) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *Teambition) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
if u, ok := file.(model.URL); ok {
|
||||
url := u.URL()
|
||||
@ -143,11 +132,11 @@ func (d *Teambition) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
||||
var newFile *FileUpload
|
||||
if stream.GetSize() <= 20971520 {
|
||||
// post upload
|
||||
newFile, err = d.upload(stream, token)
|
||||
newFile, err = d.upload(ctx, stream, token)
|
||||
} else {
|
||||
// chunk upload
|
||||
//err = base.ErrNotImplement
|
||||
newFile, err = d.chunkUpload(stream, token, up)
|
||||
newFile, err = d.chunkUpload(ctx, stream, token, up)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -18,10 +18,8 @@ var config = driver.Config{
|
||||
Name: "Teambition",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Teambition{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Teambition{}
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package teambition
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -115,13 +117,15 @@ func (d *Teambition) getFiles(parentId string) ([]model.Obj, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (d *Teambition) upload(file model.FileStreamer, token string) (*FileUpload, error) {
|
||||
func (d *Teambition) upload(ctx context.Context, file model.FileStreamer, token string) (*FileUpload, error) {
|
||||
prefix := "tcs"
|
||||
if d.isInternational() {
|
||||
prefix = "us-tcs"
|
||||
}
|
||||
var newFile FileUpload
|
||||
_, err := base.RestyClient.R().SetResult(&newFile).SetHeader("Authorization", token).
|
||||
_, err := base.RestyClient.R().
|
||||
SetContext(ctx).
|
||||
SetResult(&newFile).SetHeader("Authorization", token).
|
||||
SetMultipartFormData(map[string]string{
|
||||
"name": file.GetName(),
|
||||
"type": file.GetMimetype(),
|
||||
@ -135,7 +139,7 @@ func (d *Teambition) upload(file model.FileStreamer, token string) (*FileUpload,
|
||||
return &newFile, nil
|
||||
}
|
||||
|
||||
func (d *Teambition) chunkUpload(file model.FileStreamer, token string, up driver.UpdateProgress) (*FileUpload, error) {
|
||||
func (d *Teambition) chunkUpload(ctx context.Context, file model.FileStreamer, token string, up driver.UpdateProgress) (*FileUpload, error) {
|
||||
prefix := "tcs"
|
||||
referer := "https://www.teambition.com/"
|
||||
if d.isInternational() {
|
||||
@ -153,6 +157,9 @@ func (d *Teambition) chunkUpload(file model.FileStreamer, token string, up drive
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < newChunk.Chunks; i++ {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
chunkSize := newChunk.ChunkSize
|
||||
if i == newChunk.Chunks-1 {
|
||||
chunkSize = int(file.GetSize()) - i*chunkSize
|
||||
@ -166,11 +173,13 @@ func (d *Teambition) chunkUpload(file model.FileStreamer, token string, up drive
|
||||
u := fmt.Sprintf("https://%s.teambition.net/upload/chunk/%s?chunk=%d&chunks=%d",
|
||||
prefix, newChunk.FileKey, i+1, newChunk.Chunks)
|
||||
log.Debugf("url: %s", u)
|
||||
_, err := base.RestyClient.R().SetHeaders(map[string]string{
|
||||
"Authorization": token,
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Referer": referer,
|
||||
}).SetBody(chunkData).Post(u)
|
||||
_, err := base.RestyClient.R().
|
||||
SetContext(ctx).
|
||||
SetHeaders(map[string]string{
|
||||
"Authorization": token,
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Referer": referer,
|
||||
}).SetBody(chunkData).Post(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"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"
|
||||
)
|
||||
|
||||
type Template struct {
|
||||
@ -19,18 +18,13 @@ func (d *Template) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *Template) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Template) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Template) Init(ctx context.Context) error {
|
||||
// TODO login / refresh token
|
||||
//op.MustSaveDriverStorage(d)
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Template) Drop(ctx context.Context) error {
|
||||
@ -42,11 +36,6 @@ func (d *Template) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
||||
return nil, errs.NotImplement
|
||||
}
|
||||
|
||||
//func (d *Template) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *Template) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
// TODO return link of file
|
||||
return nil, errs.NotImplement
|
||||
|
@ -25,7 +25,7 @@ var config = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Template{}
|
||||
})
|
||||
}
|
||||
|
214
drivers/terabox/driver.go
Normal file
214
drivers/terabox/driver.go
Normal file
@ -0,0 +1,214 @@
|
||||
package terbox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
stdpath "path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
)
|
||||
|
||||
type Terabox struct {
|
||||
model.Storage
|
||||
Addition
|
||||
}
|
||||
|
||||
func (d *Terabox) Config() driver.Config {
|
||||
return config
|
||||
}
|
||||
|
||||
func (d *Terabox) GetAddition() driver.Additional {
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Terabox) Init(ctx context.Context) error {
|
||||
_, err := d.request("https://www.terabox.com/api/check/login", http.MethodGet, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Terabox) Drop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Terabox) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
files, err := d.getFiles(dir.GetPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||
return fileToObj(src), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (d *Terabox) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
if d.DownloadAPI == "crack" {
|
||||
return d.linkCrack(file, args)
|
||||
}
|
||||
return d.linkOfficial(file, args)
|
||||
}
|
||||
|
||||
func (d *Terabox) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
_, err := d.create(stdpath.Join(parentDir.GetPath(), dirName), 0, 1, "", "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Terabox) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
data := []base.Json{
|
||||
{
|
||||
"path": srcObj.GetPath(),
|
||||
"dest": dstDir.GetPath(),
|
||||
"newname": srcObj.GetName(),
|
||||
},
|
||||
}
|
||||
_, err := d.manage("move", data)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Terabox) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
data := []base.Json{
|
||||
{
|
||||
"path": srcObj.GetPath(),
|
||||
"newname": newName,
|
||||
},
|
||||
}
|
||||
_, err := d.manage("rename", data)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Terabox) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
data := []base.Json{
|
||||
{
|
||||
"path": srcObj.GetPath(),
|
||||
"dest": dstDir.GetPath(),
|
||||
"newname": srcObj.GetName(),
|
||||
},
|
||||
}
|
||||
_, err := d.manage("copy", data)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Terabox) Remove(ctx context.Context, obj model.Obj) error {
|
||||
data := []string{obj.GetPath()}
|
||||
_, err := d.manage("delete", data)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Terabox) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
tempFile, err := utils.CreateTempFile(stream.GetReadCloser())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = tempFile.Close()
|
||||
_ = os.Remove(tempFile.Name())
|
||||
}()
|
||||
var Default int64 = 4 * 1024 * 1024
|
||||
defaultByteData := make([]byte, Default)
|
||||
count := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
||||
// cal md5
|
||||
h1 := md5.New()
|
||||
h2 := md5.New()
|
||||
block_list := make([]string, 0)
|
||||
left := stream.GetSize()
|
||||
for i := 0; i < count; i++ {
|
||||
byteSize := Default
|
||||
var byteData []byte
|
||||
if left < Default {
|
||||
byteSize = left
|
||||
byteData = make([]byte, byteSize)
|
||||
} else {
|
||||
byteData = defaultByteData
|
||||
}
|
||||
left -= byteSize
|
||||
_, err = io.ReadFull(tempFile, byteData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h1.Write(byteData)
|
||||
h2.Write(byteData)
|
||||
block_list = append(block_list, fmt.Sprintf("\"%s\"", hex.EncodeToString(h2.Sum(nil))))
|
||||
h2.Reset()
|
||||
}
|
||||
|
||||
_, err = tempFile.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rawPath := stdpath.Join(dstDir.GetPath(), stream.GetName())
|
||||
path := encodeURIComponent(rawPath)
|
||||
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
||||
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s",
|
||||
path, stream.GetSize(),
|
||||
block_list_str)
|
||||
params := map[string]string{}
|
||||
var precreateResp PrecreateResp
|
||||
_, err = d.post("/api/precreate", params, data, &precreateResp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("%+v", precreateResp)
|
||||
if precreateResp.ReturnType == 2 {
|
||||
return nil
|
||||
}
|
||||
params = map[string]string{
|
||||
"method": "upload",
|
||||
"path": path,
|
||||
"uploadid": precreateResp.Uploadid,
|
||||
"app_id": "250528",
|
||||
"web": "1",
|
||||
"channel": "dubox",
|
||||
"clienttype": "0",
|
||||
}
|
||||
left = stream.GetSize()
|
||||
for i, partseq := range precreateResp.BlockList {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return ctx.Err()
|
||||
}
|
||||
byteSize := Default
|
||||
var byteData []byte
|
||||
if left < Default {
|
||||
byteSize = left
|
||||
byteData = make([]byte, byteSize)
|
||||
} else {
|
||||
byteData = defaultByteData
|
||||
}
|
||||
left -= byteSize
|
||||
_, err = io.ReadFull(tempFile, byteData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u := "https://c-jp.terabox.com/rest/2.0/pcs/superfile2"
|
||||
params["partseq"] = strconv.Itoa(partseq)
|
||||
res, err := base.RestyClient.R().
|
||||
SetContext(ctx).
|
||||
SetQueryParams(params).
|
||||
SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).
|
||||
SetHeader("Cookie", d.Cookie).
|
||||
Post(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugln(res.String())
|
||||
if len(precreateResp.BlockList) > 0 {
|
||||
up(i * 100 / len(precreateResp.BlockList))
|
||||
}
|
||||
}
|
||||
_, err = d.create(rawPath, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||
return err
|
||||
}
|
||||
|
||||
var _ driver.Driver = (*Terabox)(nil)
|
25
drivers/terabox/meta.go
Normal file
25
drivers/terabox/meta.go
Normal file
@ -0,0 +1,25 @@
|
||||
package terbox
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
driver.RootPath
|
||||
Cookie string `json:"cookie" required:"true"`
|
||||
DownloadAPI string `json:"download_api" type:"select" options:"official,crack" default:"official"`
|
||||
OrderBy string `json:"order_by" type:"select" options:"name,time,size" default:"name"`
|
||||
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "Terabox",
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Terabox{}
|
||||
})
|
||||
}
|
92
drivers/terabox/types.go
Normal file
92
drivers/terabox/types.go
Normal file
@ -0,0 +1,92 @@
|
||||
package terbox
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
//TkbindId int `json:"tkbind_id"`
|
||||
//OwnerType int `json:"owner_type"`
|
||||
//Category int `json:"category"`
|
||||
//RealCategory string `json:"real_category"`
|
||||
FsId int64 `json:"fs_id"`
|
||||
ServerMtime int64 `json:"server_mtime"`
|
||||
//OperId int `json:"oper_id"`
|
||||
//ServerCtime int `json:"server_ctime"`
|
||||
Thumbs struct {
|
||||
//Icon string `json:"icon"`
|
||||
Url3 string `json:"url3"`
|
||||
//Url2 string `json:"url2"`
|
||||
//Url1 string `json:"url1"`
|
||||
} `json:"thumbs"`
|
||||
//Wpfile int `json:"wpfile"`
|
||||
//LocalMtime int `json:"local_mtime"`
|
||||
Size int64 `json:"size"`
|
||||
//ExtentTinyint7 int `json:"extent_tinyint7"`
|
||||
Path string `json:"path"`
|
||||
//Share int `json:"share"`
|
||||
//ServerAtime int `json:"server_atime"`
|
||||
//Pl int `json:"pl"`
|
||||
//LocalCtime int `json:"local_ctime"`
|
||||
ServerFilename string `json:"server_filename"`
|
||||
//Md5 string `json:"md5"`
|
||||
//OwnerId int `json:"owner_id"`
|
||||
//Unlist int `json:"unlist"`
|
||||
Isdir int `json:"isdir"`
|
||||
}
|
||||
|
||||
type ListResp struct {
|
||||
Errno int `json:"errno"`
|
||||
GuidInfo string `json:"guid_info"`
|
||||
List []File `json:"list"`
|
||||
RequestId int64 `json:"request_id"`
|
||||
Guid int `json:"guid"`
|
||||
}
|
||||
|
||||
func fileToObj(f File) *model.ObjThumb {
|
||||
return &model.ObjThumb{
|
||||
Object: model.Object{
|
||||
ID: strconv.FormatInt(f.FsId, 10),
|
||||
Name: f.ServerFilename,
|
||||
Size: f.Size,
|
||||
Modified: time.Unix(f.ServerMtime, 0),
|
||||
IsFolder: f.Isdir == 1,
|
||||
},
|
||||
Thumbnail: model.Thumbnail{Thumbnail: f.Thumbs.Url3},
|
||||
}
|
||||
}
|
||||
|
||||
type DownloadResp struct {
|
||||
Errno int `json:"errno"`
|
||||
Dlink []struct {
|
||||
Dlink string `json:"dlink"`
|
||||
} `json:"dlink"`
|
||||
}
|
||||
|
||||
type DownloadResp2 struct {
|
||||
Errno int `json:"errno"`
|
||||
Info []struct {
|
||||
Dlink string `json:"dlink"`
|
||||
} `json:"info"`
|
||||
RequestID int64 `json:"request_id"`
|
||||
}
|
||||
|
||||
type HomeInfoResp struct {
|
||||
Errno int `json:"errno"`
|
||||
Data struct {
|
||||
Sign1 string `json:"sign1"`
|
||||
Sign3 string `json:"sign3"`
|
||||
Timestamp int `json:"timestamp"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type PrecreateResp struct {
|
||||
Path string `json:"path"`
|
||||
Uploadid string `json:"uploadid"`
|
||||
ReturnType int `json:"return_type"`
|
||||
BlockList []int `json:"block_list"`
|
||||
Errno int `json:"errno"`
|
||||
RequestId int64 `json:"request_id"`
|
||||
}
|
192
drivers/terabox/util.go
Normal file
192
drivers/terabox/util.go
Normal file
@ -0,0 +1,192 @@
|
||||
package terbox
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (d *Terabox) request(furl string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||
req := base.RestyClient.R()
|
||||
req.SetHeaders(map[string]string{
|
||||
"Cookie": d.Cookie,
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
"Referer": "https://www.terabox.com/",
|
||||
"User-Agent": base.UserAgent,
|
||||
})
|
||||
req.SetQueryParam("app_id", "250528")
|
||||
req.SetQueryParam("web", "1")
|
||||
req.SetQueryParam("channel", "dubox")
|
||||
req.SetQueryParam("clienttype", "0")
|
||||
if callback != nil {
|
||||
callback(req)
|
||||
}
|
||||
if resp != nil {
|
||||
req.SetResult(resp)
|
||||
}
|
||||
res, err := req.Execute(method, furl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Body(), nil
|
||||
}
|
||||
|
||||
func (d *Terabox) get(pathname string, params map[string]string, resp interface{}) ([]byte, error) {
|
||||
return d.request("https://www.terabox.com"+pathname, http.MethodGet, func(req *resty.Request) {
|
||||
req.SetQueryParams(params)
|
||||
}, resp)
|
||||
}
|
||||
|
||||
func (d *Terabox) post(pathname string, params map[string]string, data interface{}, resp interface{}) ([]byte, error) {
|
||||
return d.request("https://www.terabox.com"+pathname, http.MethodPost, func(req *resty.Request) {
|
||||
req.SetQueryParams(params)
|
||||
req.SetBody(data)
|
||||
}, resp)
|
||||
}
|
||||
|
||||
func (d *Terabox) getFiles(dir string) ([]File, error) {
|
||||
page := 1
|
||||
num := 100
|
||||
params := map[string]string{
|
||||
"dir": dir,
|
||||
}
|
||||
if d.OrderBy != "" {
|
||||
params["order"] = d.OrderBy
|
||||
if d.OrderDirection == "desc" {
|
||||
params["desc"] = "1"
|
||||
}
|
||||
}
|
||||
res := make([]File, 0)
|
||||
for {
|
||||
params["page"] = strconv.Itoa(page)
|
||||
params["num"] = strconv.Itoa(num)
|
||||
var resp ListResp
|
||||
_, err := d.get("/api/list", params, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(resp.List) == 0 {
|
||||
break
|
||||
}
|
||||
res = append(res, resp.List...)
|
||||
page++
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func sign(s1, s2 string) string {
|
||||
var a = make([]int, 256)
|
||||
var p = make([]int, 256)
|
||||
var o []byte
|
||||
var v = len(s1)
|
||||
for q := 0; q < 256; q++ {
|
||||
a[q] = int(s1[(q % v) : (q%v)+1][0])
|
||||
p[q] = q
|
||||
}
|
||||
for u, q := 0, 0; q < 256; q++ {
|
||||
u = (u + p[q] + a[q]) % 256
|
||||
p[q], p[u] = p[u], p[q]
|
||||
}
|
||||
for i, u, q := 0, 0, 0; q < len(s2); q++ {
|
||||
i = (i + 1) % 256
|
||||
u = (u + p[i]) % 256
|
||||
p[i], p[u] = p[u], p[i]
|
||||
k := p[((p[i] + p[u]) % 256)]
|
||||
o = append(o, byte(int(s2[q])^k))
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(o)
|
||||
}
|
||||
|
||||
func (d *Terabox) genSign() (string, error) {
|
||||
var resp HomeInfoResp
|
||||
_, err := d.get("/api/home/info", map[string]string{}, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sign(resp.Data.Sign3, resp.Data.Sign1), nil
|
||||
}
|
||||
|
||||
func (d *Terabox) linkOfficial(file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
var resp DownloadResp
|
||||
signString, err := d.genSign()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params := map[string]string{
|
||||
"type": "dlink",
|
||||
"fidlist": fmt.Sprintf("[%s]", file.GetID()),
|
||||
"sign": signString,
|
||||
"vip": "2",
|
||||
"timestamp": strconv.FormatInt(time.Now().Unix(), 10),
|
||||
}
|
||||
_, err = d.get("/api/download", params, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := base.NoRedirectClient.R().SetHeader("Cookie", d.Cookie).SetHeader("User-Agent", base.UserAgent).Get(resp.Dlink[0].Dlink)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u := res.Header().Get("location")
|
||||
return &model.Link{
|
||||
URL: u,
|
||||
Header: http.Header{
|
||||
"User-Agent": []string{base.UserAgent},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Terabox) linkCrack(file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
var resp DownloadResp2
|
||||
param := map[string]string{
|
||||
"target": fmt.Sprintf("[\"%s\"]", file.GetPath()),
|
||||
"dlink": "1",
|
||||
"origin": "dlna",
|
||||
}
|
||||
_, err := d.get("/api/filemetas", param, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &model.Link{
|
||||
URL: resp.Info[0].Dlink,
|
||||
Header: http.Header{
|
||||
"User-Agent": []string{base.UserAgent},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Terabox) manage(opera string, filelist interface{}) ([]byte, error) {
|
||||
params := map[string]string{
|
||||
"onnest": "fail",
|
||||
"opera": opera,
|
||||
}
|
||||
marshal, err := utils.Json.Marshal(filelist)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := fmt.Sprintf("async=0&filelist=%s&ondup=newcopy", string(marshal))
|
||||
return d.post("/api/filemanager", params, data, nil)
|
||||
}
|
||||
|
||||
func (d *Terabox) create(path string, size int64, isdir int, uploadid, block_list string) ([]byte, error) {
|
||||
params := map[string]string{}
|
||||
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", encodeURIComponent(path), size, isdir)
|
||||
if uploadid != "" {
|
||||
data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
|
||||
}
|
||||
return d.post("/api/create", params, data, nil)
|
||||
}
|
||||
|
||||
func encodeURIComponent(str string) string {
|
||||
r := url.QueryEscape(str)
|
||||
r = strings.ReplaceAll(r, "+", "%20")
|
||||
return r
|
||||
}
|
@ -32,15 +32,10 @@ func (x *Thunder) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (x *Thunder) GetAddition() driver.Additional {
|
||||
return x.Addition
|
||||
return &x.Addition
|
||||
}
|
||||
|
||||
func (x *Thunder) Init(ctx context.Context, storage model.Storage) (err error) {
|
||||
x.Storage = storage
|
||||
if err = utils.Json.UnmarshalFromString(x.Storage.Addition, &x.Addition); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (x *Thunder) Init(ctx context.Context) (err error) {
|
||||
// 初始化所需参数
|
||||
if x.XunLeiCommon == nil {
|
||||
x.XunLeiCommon = &XunLeiCommon{
|
||||
@ -126,15 +121,10 @@ func (x *ThunderExpert) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (x *ThunderExpert) GetAddition() driver.Additional {
|
||||
return x.ExpertAddition
|
||||
return &x.ExpertAddition
|
||||
}
|
||||
|
||||
func (x *ThunderExpert) Init(ctx context.Context, storage model.Storage) (err error) {
|
||||
x.Storage = storage
|
||||
if err = utils.Json.UnmarshalFromString(x.Storage.Addition, &x.ExpertAddition); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (x *ThunderExpert) Init(ctx context.Context) (err error) {
|
||||
// 防止重复登录
|
||||
identity := x.GetIdentity()
|
||||
if identity != x.identity || !x.IsLogin() {
|
||||
|
@ -93,10 +93,10 @@ var configExpert = driver.Config{
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Thunder{}
|
||||
})
|
||||
op.RegisterDriver(configExpert, func() driver.Driver {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &ThunderExpert{}
|
||||
})
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
)
|
||||
|
||||
type ErrResp struct {
|
||||
@ -149,7 +147,7 @@ type Files struct {
|
||||
}
|
||||
|
||||
func (c *Files) GetSize() int64 { size, _ := strconv.ParseInt(c.Size, 10, 64); return size }
|
||||
func (c *Files) GetName() string { return utils.MappingName(c.Name) }
|
||||
func (c *Files) GetName() string { return c.Name }
|
||||
func (c *Files) ModTime() time.Time { return c.ModifiedTime }
|
||||
func (c *Files) IsDir() bool { return c.Kind == FOLDER }
|
||||
func (c *Files) GetID() string { return c.ID }
|
||||
|
@ -25,15 +25,10 @@ func (d *USS) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *USS) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *USS) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *USS) Init(ctx context.Context) error {
|
||||
d.client = upyun.NewUpYun(&upyun.UpYunConfig{
|
||||
Bucket: d.Bucket,
|
||||
Operator: d.OperatorName,
|
||||
@ -49,19 +44,17 @@ func (d *USS) Drop(ctx context.Context) error {
|
||||
func (d *USS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
prefix := getKey(dir.GetPath(), true)
|
||||
objsChan := make(chan *upyun.FileInfo, 10)
|
||||
var err error
|
||||
defer close(objsChan)
|
||||
go func() {
|
||||
err = d.client.List(&upyun.GetObjectsConfig{
|
||||
Path: prefix,
|
||||
ObjectsChan: objsChan,
|
||||
MaxListObjects: 0,
|
||||
MaxListLevel: 1,
|
||||
})
|
||||
}()
|
||||
if err != nil {
|
||||
|
||||
cfg := &upyun.GetObjectsConfig{
|
||||
Path: prefix,
|
||||
ObjectsChan: objsChan,
|
||||
MaxListObjects: 0,
|
||||
MaxListLevel: 1,
|
||||
}
|
||||
if err := d.client.List(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := make([]model.Obj, 0)
|
||||
for obj := range objsChan {
|
||||
t := obj.Time
|
||||
@ -73,14 +66,9 @@ func (d *USS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]m
|
||||
}
|
||||
res = append(res, &f)
|
||||
}
|
||||
return res, err
|
||||
return res, nil
|
||||
}
|
||||
|
||||
//func (d *USS) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *USS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
key := getKey(file.GetPath(), false)
|
||||
host := d.CustomHost
|
||||
@ -133,6 +121,7 @@ func (d *USS) Remove(ctx context.Context, obj model.Obj) error {
|
||||
}
|
||||
|
||||
func (d *USS) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||
// TODO not support cancel??
|
||||
return d.client.Put(&upyun.PutObjectConfig{
|
||||
Path: getKey(path.Join(dstDir.GetPath(), stream.GetName()), false),
|
||||
Reader: stream,
|
||||
|
@ -16,14 +16,13 @@ type Addition struct {
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "USS",
|
||||
LocalSort: true,
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &USS{}
|
||||
Name: "USS",
|
||||
LocalSort: true,
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &USS{}
|
||||
})
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/alist-org/alist/v3/pkg/utils/random"
|
||||
)
|
||||
|
||||
@ -20,12 +19,7 @@ func (d *Virtual) Config() driver.Config {
|
||||
return config
|
||||
}
|
||||
|
||||
func (d *Virtual) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (d *Virtual) Init(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -34,7 +28,7 @@ func (d *Virtual) Drop(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (d *Virtual) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *Virtual) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
||||
//NoCache: true,
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &Virtual{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Virtual{}
|
||||
})
|
||||
}
|
||||
|
@ -26,16 +26,11 @@ func (d *WebDav) Config() driver.Config {
|
||||
}
|
||||
|
||||
func (d *WebDav) GetAddition() driver.Additional {
|
||||
return d.Addition
|
||||
return &d.Addition
|
||||
}
|
||||
|
||||
func (d *WebDav) Init(ctx context.Context, storage model.Storage) error {
|
||||
d.Storage = storage
|
||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.setClient()
|
||||
func (d *WebDav) Init(ctx context.Context) error {
|
||||
err := d.setClient()
|
||||
if err == nil {
|
||||
d.cron = cron.NewCron(time.Hour * 12)
|
||||
d.cron.Do(func() {
|
||||
@ -67,11 +62,6 @@ func (d *WebDav) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
|
||||
})
|
||||
}
|
||||
|
||||
//func (d *WebDav) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
// // this is optional
|
||||
// return nil, errs.NotImplement
|
||||
//}
|
||||
|
||||
func (d *WebDav) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
url, header, err := d.client.Link(file.GetPath())
|
||||
if err != nil {
|
||||
@ -108,6 +98,7 @@ func (d *WebDav) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
r.Header.Set("Content-Type", stream.GetMimetype())
|
||||
r.ContentLength = stream.GetSize()
|
||||
}
|
||||
// TODO: support cancel
|
||||
err := d.client.WriteStream(path.Join(dstDir.GetPath(), stream.GetName()), stream, 0644, callback)
|
||||
return err
|
||||
}
|
||||
|
@ -20,10 +20,8 @@ var config = driver.Config{
|
||||
DefaultRoot: "/",
|
||||
}
|
||||
|
||||
func New() driver.Driver {
|
||||
return &WebDav{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(config, New)
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &WebDav{}
|
||||
})
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user