mirror of
https://gitee.com/zhangsken/aliyunpan.git
synced 2026-10-16 02:23:49 +08:00
add album command
This commit is contained in:
+130
-442
@@ -14,46 +14,36 @@
|
|||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
||||||
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
|
|
||||||
"github.com/tickstep/aliyunpan-api/aliyunpan_web"
|
|
||||||
"github.com/tickstep/aliyunpan/cmder"
|
"github.com/tickstep/aliyunpan/cmder"
|
||||||
"github.com/tickstep/aliyunpan/cmder/cmdtable"
|
"github.com/tickstep/aliyunpan/cmder/cmdtable"
|
||||||
"github.com/tickstep/aliyunpan/internal/config"
|
"github.com/tickstep/aliyunpan/internal/config"
|
||||||
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
||||||
"github.com/tickstep/aliyunpan/internal/functions/pandownload"
|
"github.com/tickstep/aliyunpan/internal/functions/pandownload"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/global"
|
||||||
"github.com/tickstep/aliyunpan/internal/taskframework"
|
"github.com/tickstep/aliyunpan/internal/taskframework"
|
||||||
"github.com/tickstep/aliyunpan/internal/utils"
|
"github.com/tickstep/aliyunpan/internal/utils"
|
||||||
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
||||||
"github.com/tickstep/library-go/converter"
|
"github.com/tickstep/library-go/converter"
|
||||||
"github.com/tickstep/library-go/logger"
|
"github.com/tickstep/library-go/logger"
|
||||||
|
"github.com/tickstep/library-go/requester"
|
||||||
"github.com/tickstep/library-go/requester/rio/speeds"
|
"github.com/tickstep/library-go/requester/rio/speeds"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
|
||||||
AlbumFileCategoryOption string
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ImageOnlyOption AlbumFileCategoryOption = "image"
|
|
||||||
VideoOnlyOption AlbumFileCategoryOption = "video"
|
|
||||||
ImageVideoOnlyOption AlbumFileCategoryOption = "image_video"
|
|
||||||
AllFileOption AlbumFileCategoryOption = "none"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CmdAlbum() cli.Command {
|
func CmdAlbum() cli.Command {
|
||||||
return cli.Command{
|
return cli.Command{
|
||||||
Name: "album",
|
Name: "album",
|
||||||
Aliases: []string{"abm"},
|
Aliases: []string{"abm"},
|
||||||
Usage: "个人相册(Beta)",
|
Usage: "共享相册",
|
||||||
UsageText: cmder.App().Name + " album",
|
UsageText: cmder.App().Name + " album",
|
||||||
Category: "阿里云盘",
|
Category: "阿里云盘",
|
||||||
Before: ReloadConfigFunc,
|
Before: ReloadConfigFunc,
|
||||||
@@ -66,12 +56,11 @@ func CmdAlbum() cli.Command {
|
|||||||
{
|
{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
Usage: "展示相簿列表",
|
Usage: "展示共享相簿列表",
|
||||||
UsageText: cmder.App().Name + " album list",
|
UsageText: cmder.App().Name + " album list",
|
||||||
Description: `
|
Description: `
|
||||||
示例:
|
示例:
|
||||||
|
展示共享相簿列表
|
||||||
展示相簿列表
|
|
||||||
aliyunpan album ls
|
aliyunpan album ls
|
||||||
`,
|
`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
@@ -79,94 +68,7 @@ func CmdAlbum() cli.Command {
|
|||||||
fmt.Println("未登录账号")
|
fmt.Println("未登录账号")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
RunShareAlbumList()
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumList()
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "new",
|
|
||||||
Aliases: []string{""},
|
|
||||||
Usage: "创建相簿",
|
|
||||||
UsageText: cmder.App().Name + " album new",
|
|
||||||
Description: `
|
|
||||||
示例:
|
|
||||||
|
|
||||||
新建相簿,名称为:我的相簿2022
|
|
||||||
aliyunpan album new "我的相簿2022"
|
|
||||||
|
|
||||||
新建相簿,名称为:我的相簿2022,描述为:存放2022所有文件
|
|
||||||
aliyunpan album new "我的相簿2022" "存放2022所有文件"
|
|
||||||
`,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
if config.Config.ActiveUser() == nil {
|
|
||||||
fmt.Println("未登录账号")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumCreate(c.Args().Get(0), c.Args().Get(1))
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "rm",
|
|
||||||
Aliases: []string{""},
|
|
||||||
Usage: "删除相簿",
|
|
||||||
UsageText: cmder.App().Name + " album rm",
|
|
||||||
Description: `
|
|
||||||
删除相簿,同名的相簿只会删除第一个符合条件的
|
|
||||||
示例:
|
|
||||||
|
|
||||||
删除名称为"我的相簿2022"的相簿
|
|
||||||
aliyunpan album rm "我的相簿2022"
|
|
||||||
|
|
||||||
删除名称为"我的相簿2022-1" 和 "我的相簿2022-2"的相簿
|
|
||||||
aliyunpan album rm "我的相簿2022-1" "我的相簿2022-2"
|
|
||||||
`,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
if config.Config.ActiveUser() == nil {
|
|
||||||
fmt.Println("未登录账号")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumDelete(c.Args())
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "rename",
|
|
||||||
Aliases: []string{""},
|
|
||||||
Usage: "重命名相簿",
|
|
||||||
UsageText: cmder.App().Name + " album rename",
|
|
||||||
Description: `
|
|
||||||
重命名相簿,同名的相簿只会修改第一个符合条件的
|
|
||||||
示例:
|
|
||||||
|
|
||||||
重命名相簿"我的相簿2022"为新的名称"我的相簿2022-new"
|
|
||||||
aliyunpan album rename "我的相簿2022" "我的相簿2022-new"
|
|
||||||
`,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
if config.Config.ActiveUser() == nil {
|
|
||||||
fmt.Println("未登录账号")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumRename(c.Args().Get(0), c.Args().Get(1))
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{},
|
||||||
@@ -188,76 +90,7 @@ func CmdAlbum() cli.Command {
|
|||||||
fmt.Println("未登录账号")
|
fmt.Println("未登录账号")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
RunShareAlbumListFile(c.Args().Get(0))
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumListFile(c.Args().Get(0))
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "rm-file",
|
|
||||||
Aliases: []string{"rf"},
|
|
||||||
Usage: "移除相簿中的文件",
|
|
||||||
UsageText: cmder.App().Name + " album rm-file",
|
|
||||||
Description: `
|
|
||||||
移除相簿中的文件,同名的相簿只会移除第一个符合条件的
|
|
||||||
示例:
|
|
||||||
|
|
||||||
移除相簿 "我的相簿2022" 中的文件 1.png 2.png
|
|
||||||
aliyunpan album rm-file 我的相簿2022 1.png 2.png
|
|
||||||
`,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
if config.Config.ActiveUser() == nil {
|
|
||||||
fmt.Println("未登录账号")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
subArgs := c.Args()
|
|
||||||
if len(subArgs) < 2 {
|
|
||||||
fmt.Println("请指定移除的文件")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumRmFile(subArgs[0], subArgs[1:])
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "add-file",
|
|
||||||
Aliases: []string{"af"},
|
|
||||||
Usage: "增加(文件/相册)网盘文件到相簿中",
|
|
||||||
UsageText: cmder.App().Name + " album add-file",
|
|
||||||
Description: `
|
|
||||||
增加文件到相簿中
|
|
||||||
示例:
|
|
||||||
|
|
||||||
增加当前目录下的 1.png 2.png 文件到相簿 "我的相簿2022" 中
|
|
||||||
aliyunpan album add-file 我的相簿2022 1.png 2.png
|
|
||||||
|
|
||||||
增加当前目录下的 myFolder 文件夹下所有文件到相簿 "我的相簿2022" 中
|
|
||||||
aliyunpan album add-file 我的相簿2022 myFolder
|
|
||||||
`,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
if config.Config.ActiveUser() == nil {
|
|
||||||
fmt.Println("未登录账号")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
subArgs := c.Args()
|
|
||||||
if len(subArgs) < 2 {
|
|
||||||
fmt.Println("请指定增加的文件")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
RunAlbumAddFile(subArgs[0], subArgs[1:], ImageVideoOnlyOption)
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{},
|
||||||
@@ -273,17 +106,12 @@ func CmdAlbum() cli.Command {
|
|||||||
|
|
||||||
下载相簿 "我的相簿2022" 里面的所有文件
|
下载相簿 "我的相簿2022" 里面的所有文件
|
||||||
aliyunpan album download-file 我的相簿2022
|
aliyunpan album download-file 我的相簿2022
|
||||||
|
|
||||||
`,
|
`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
if config.Config.ActiveUser() == nil {
|
if config.Config.ActiveUser() == nil {
|
||||||
fmt.Println("未登录账号")
|
fmt.Println("未登录账号")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
|
||||||
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
subArgs := c.Args()
|
subArgs := c.Args()
|
||||||
if len(subArgs) == 0 {
|
if len(subArgs) == 0 {
|
||||||
fmt.Println("请指定下载的相簿名称")
|
fmt.Println("请指定下载的相簿名称")
|
||||||
@@ -312,7 +140,7 @@ func CmdAlbum() cli.Command {
|
|||||||
ExcludeNames: []string{},
|
ExcludeNames: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
RunAlbumDownloadFile(c.Args(), do)
|
RunShareAlbumDownloadFile(c.Args(), do)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
@@ -334,76 +162,25 @@ func CmdAlbum() cli.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunAlbumList() {
|
func RunShareAlbumList() {
|
||||||
activeUser := GetActiveUser()
|
activeUser := GetActiveUser()
|
||||||
records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan_web.AlbumListParam{})
|
records, err := activeUser.PanClient().OpenapiPanClient().ShareAlbumListGetAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("获取相簿列表失败: %s\n", err)
|
fmt.Printf("获取相簿列表失败: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tb := cmdtable.NewTable(os.Stdout)
|
tb := cmdtable.NewTable(os.Stdout)
|
||||||
tb.SetHeader([]string{"#", "ALBUM_ID", "名称", "文件数量", "创建日期", "修改日期"})
|
tb.SetHeader([]string{"#", "ALBUM_ID", "名称", "更新日期", "创建日期"})
|
||||||
tb.SetColumnAlignment([]int{tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_DEFAULT})
|
tb.SetColumnAlignment([]int{tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_DEFAULT})
|
||||||
for k, record := range records {
|
for k, record := range records {
|
||||||
tb.Append([]string{strconv.Itoa(k + 1), record.AlbumId, record.Name, strconv.Itoa(record.FileCount),
|
tb.Append([]string{strconv.Itoa(k + 1), record.AlbumId, record.Name, record.UpdatedAtStr(), record.CreatedAtStr()})
|
||||||
record.CreatedAtStr(), record.UpdatedAtStr()})
|
|
||||||
}
|
}
|
||||||
tb.Render()
|
tb.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunAlbumCreate(name, description string) {
|
func getShareAlbumFromName(activeUser *config.PanUser, name string) *aliyunpan.AlbumEntity {
|
||||||
if name == "" {
|
records, err := activeUser.PanClient().OpenapiPanClient().ShareAlbumListGetAll()
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
activeUser := GetActiveUser()
|
|
||||||
_, err := activeUser.PanClient().WebapiPanClient().AlbumCreate(&aliyunpan_web.AlbumCreateParam{
|
|
||||||
Name: name,
|
|
||||||
Description: description,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("创建相簿失败: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Printf("创建相簿成功: %s\n", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunAlbumDelete(nameList []string) {
|
|
||||||
if len(nameList) == 0 {
|
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
activeUser := GetActiveUser()
|
|
||||||
records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan_web.AlbumListParam{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("获取相簿列表失败: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, record := range records {
|
|
||||||
for i, name := range nameList {
|
|
||||||
if name == record.Name {
|
|
||||||
nameList = append(nameList[:i], nameList[i+1:]...)
|
|
||||||
_, err := activeUser.PanClient().WebapiPanClient().AlbumDelete(&aliyunpan_web.AlbumDeleteParam{
|
|
||||||
AlbumId: record.AlbumId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("删除相簿失败: %s\n", name)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
fmt.Printf("删除相簿成功: %s\n", name)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAlbumFromName(activeUser *config.PanUser, name string) *aliyunpan.AlbumEntity {
|
|
||||||
records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan_web.AlbumListParam{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("获取相簿列表失败: %s\n", err)
|
fmt.Printf("获取相簿列表失败: %s\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -417,48 +194,21 @@ func getAlbumFromName(activeUser *config.PanUser, name string) *aliyunpan.AlbumE
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunAlbumRename(name, newName string) {
|
func RunShareAlbumListFile(name string) {
|
||||||
if len(name) == 0 {
|
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(newName) == 0 {
|
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
activeUser := GetActiveUser()
|
|
||||||
record := getAlbumFromName(activeUser, name)
|
|
||||||
if record == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err := activeUser.PanClient().WebapiPanClient().AlbumEdit(&aliyunpan_web.AlbumEditParam{
|
|
||||||
AlbumId: record.AlbumId,
|
|
||||||
Description: record.Description,
|
|
||||||
Name: newName,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("重命名相簿失败: %s\n", name)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
fmt.Printf("重命名相簿成功: %s -> %s\n", name, newName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunAlbumListFile(name string) {
|
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
activeUser := GetActiveUser()
|
activeUser := GetActiveUser()
|
||||||
record := getAlbumFromName(activeUser, name)
|
record := getShareAlbumFromName(activeUser, name)
|
||||||
if record == nil {
|
if record == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan_web.AlbumListFileParam{
|
fileList, er := activeUser.PanClient().OpenapiPanClient().ShareAlbumListFileGetAll(&aliyunpan.ShareAlbumListFileParam{
|
||||||
AlbumId: record.AlbumId,
|
AlbumId: record.AlbumId,
|
||||||
|
Limit: 100,
|
||||||
})
|
})
|
||||||
if er != nil {
|
if er != nil {
|
||||||
fmt.Printf("获取相簿文件列表失败:%s\n", er)
|
fmt.Printf("获取相簿文件列表失败:%s\n", er)
|
||||||
@@ -467,174 +217,13 @@ func RunAlbumListFile(name string) {
|
|||||||
renderTable(opLs, false, "", fileList)
|
renderTable(opLs, false, "", fileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunAlbumRmFile(name string, nameList []string) {
|
func RunShareAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
||||||
if len(name) == 0 {
|
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(nameList) == 0 {
|
|
||||||
fmt.Printf("指定文件不能为空\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
activeUser := GetActiveUser()
|
|
||||||
album := getAlbumFromName(activeUser, name)
|
|
||||||
if album == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan_web.AlbumListFileParam{
|
|
||||||
AlbumId: album.AlbumId,
|
|
||||||
})
|
|
||||||
if er != nil {
|
|
||||||
fmt.Printf("获取相簿文件列表失败:%s\n", er)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
param := &aliyunpan_web.AlbumDeleteFileParam{
|
|
||||||
AlbumId: album.AlbumId,
|
|
||||||
DriveFileList: []aliyunpan.FileBatchActionParam{},
|
|
||||||
}
|
|
||||||
for _, file := range fileList {
|
|
||||||
if len(nameList) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for i, name := range nameList {
|
|
||||||
if name == file.FileName {
|
|
||||||
nameList = append(nameList[:i], nameList[i+1:]...)
|
|
||||||
param.AddFileItem(file.DriveId, file.FileId)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1-500 范围
|
|
||||||
if len(param.DriveFileList) == 0 {
|
|
||||||
fmt.Printf("没有符合的文件\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// delete file
|
|
||||||
_, e := activeUser.PanClient().WebapiPanClient().AlbumDeleteFile(param)
|
|
||||||
if e != nil {
|
|
||||||
fmt.Printf("删除相簿文件失败:%s\n", e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Printf("删除相簿文件成功:%s\n", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunAlbumAddFile 增加网盘文件到相簿
|
|
||||||
func RunAlbumAddFile(albumName string, filePathList []string, filterOption AlbumFileCategoryOption) {
|
|
||||||
activeUser := GetActiveUser()
|
|
||||||
|
|
||||||
if albumName == "" {
|
|
||||||
fmt.Printf("必须指定相簿名称\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
album := getAlbumFromName(activeUser, albumName)
|
|
||||||
if album == nil {
|
|
||||||
fmt.Printf("相簿不存在\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
paths, err := makePathAbsolute(activeUser.ActiveDriveId, filePathList...)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(paths) == 0 {
|
|
||||||
fmt.Printf("没有有效的文件\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("正在获取增加的文件信息,该操作可能会非常耗费时间,请耐心等待...\n")
|
|
||||||
param := &aliyunpan_web.AlbumAddFileParam{
|
|
||||||
AlbumId: album.AlbumId,
|
|
||||||
DriveFileList: []aliyunpan.FileBatchActionParam{},
|
|
||||||
}
|
|
||||||
for k := range paths {
|
|
||||||
filePath := paths[k]
|
|
||||||
fileInfo, apierr := activeUser.PanClient().WebapiPanClient().FileInfoByPath(activeUser.ActiveDriveId, filePath)
|
|
||||||
if apierr != nil {
|
|
||||||
fmt.Printf("获取文件信息失败: %s\n", filePath)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fileInfo.IsFile() {
|
|
||||||
// file
|
|
||||||
if isFileMatchCondition(fileInfo, filterOption) {
|
|
||||||
param.AddFileItem(fileInfo.DriveId, fileInfo.FileId)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// folder
|
|
||||||
activeUser.PanClient().WebapiPanClient().FilesDirectoriesRecurseList(activeUser.ActiveDriveId, fileInfo.Path, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool {
|
|
||||||
if apiError != nil {
|
|
||||||
logger.Verbosef("%s\n", apiError)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if !fd.IsFolder() {
|
|
||||||
if isFileMatchCondition(fd, filterOption) {
|
|
||||||
param.AddFileItem(fd.DriveId, fd.FileId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(param.DriveFileList) == 0 {
|
|
||||||
fmt.Printf("没有符合的文件\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// add file
|
|
||||||
_, e := activeUser.PanClient().WebapiPanClient().AlbumAddFile(param)
|
|
||||||
if e != nil {
|
|
||||||
fmt.Printf("增加相簿文件失败:%s\n", e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Printf("增加相簿文件成功:%s\n", albumName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isFileMatchCondition(fileInfo *aliyunpan.FileEntity, filterOption AlbumFileCategoryOption) bool {
|
|
||||||
if fileInfo == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if filterOption == ImageOnlyOption {
|
|
||||||
return fileInfo.Category == "image"
|
|
||||||
} else if filterOption == VideoOnlyOption {
|
|
||||||
return fileInfo.Category == "video"
|
|
||||||
} else if filterOption == ImageVideoOnlyOption {
|
|
||||||
return fileInfo.Category == "image" || fileInfo.Category == "video"
|
|
||||||
} else if filterOption == AllFileOption {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|
||||||
if len(albumNames) == 0 {
|
if len(albumNames) == 0 {
|
||||||
fmt.Printf("相簿名称不能为空\n")
|
fmt.Printf("请指定相簿名称\n")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
activeUser := GetActiveUser()
|
activeUser := GetActiveUser()
|
||||||
activeUser.PanClient().WebapiPanClient().EnableCache()
|
|
||||||
activeUser.PanClient().WebapiPanClient().ClearCache()
|
|
||||||
defer activeUser.PanClient().WebapiPanClient().DisableCache()
|
|
||||||
// pan token expired checker
|
|
||||||
continueFlag := int32(0)
|
|
||||||
atomic.StoreInt32(&continueFlag, 0)
|
|
||||||
defer func() {
|
|
||||||
atomic.StoreInt32(&continueFlag, 1)
|
|
||||||
}()
|
|
||||||
go func(flag *int32) {
|
|
||||||
for atomic.LoadInt32(flag) == 0 {
|
|
||||||
time.Sleep(time.Duration(1) * time.Minute)
|
|
||||||
if RefreshWebTokenInNeed(activeUser, config.Config.DeviceName) {
|
|
||||||
logger.Verboseln("update access token for download task")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(&continueFlag)
|
|
||||||
|
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = &DownloadOptions{}
|
options = &DownloadOptions{}
|
||||||
}
|
}
|
||||||
@@ -668,6 +257,10 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|||||||
if options.Parallel > config.MaxFileDownloadParallelNum {
|
if options.Parallel > config.MaxFileDownloadParallelNum {
|
||||||
options.Parallel = config.MaxFileDownloadParallelNum
|
options.Parallel = config.MaxFileDownloadParallelNum
|
||||||
}
|
}
|
||||||
|
// 设置单个文件下载分片线程数
|
||||||
|
if options.SliceParallel < 1 {
|
||||||
|
options.SliceParallel = 1
|
||||||
|
}
|
||||||
|
|
||||||
// 保存文件的本地根文件夹
|
// 保存文件的本地根文件夹
|
||||||
originSaveRootPath := ""
|
originSaveRootPath := ""
|
||||||
@@ -693,6 +286,7 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|||||||
panClient = activeUser.PanClient()
|
panClient = activeUser.PanClient()
|
||||||
)
|
)
|
||||||
cfg.MaxParallel = options.Parallel
|
cfg.MaxParallel = options.Parallel
|
||||||
|
cfg.SliceParallel = options.SliceParallel
|
||||||
|
|
||||||
var (
|
var (
|
||||||
executor = taskframework.TaskExecutor{
|
executor = taskframework.TaskExecutor{
|
||||||
@@ -707,14 +301,26 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|||||||
globalSpeedsStat := &speeds.Speeds{}
|
globalSpeedsStat := &speeds.Speeds{}
|
||||||
|
|
||||||
// 处理队列
|
// 处理队列
|
||||||
|
allShareAlbumList, err := activeUser.PanClient().OpenapiPanClient().ShareAlbumListGetAll()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("获取相簿列表失败: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
for k := range albumNames {
|
for k := range albumNames {
|
||||||
record := getAlbumFromName(activeUser, albumNames[k])
|
var record *aliyunpan.AlbumEntity
|
||||||
|
for _, album := range allShareAlbumList {
|
||||||
|
if album.Name == albumNames[k] {
|
||||||
|
record = album
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if record == nil {
|
if record == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 获取相簿下的所有文件
|
// 获取相簿下的所有文件
|
||||||
fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan_web.AlbumListFileParam{
|
fileList, er := activeUser.PanClient().OpenapiPanClient().ShareAlbumListFileGetAll(&aliyunpan.ShareAlbumListFileParam{
|
||||||
AlbumId: record.AlbumId,
|
AlbumId: record.AlbumId,
|
||||||
|
Limit: 100,
|
||||||
})
|
})
|
||||||
if er != nil {
|
if er != nil {
|
||||||
fmt.Printf("获取相簿文件出错,请稍后重试: %s\n", albumNames[k])
|
fmt.Printf("获取相簿文件出错,请稍后重试: %s\n", albumNames[k])
|
||||||
@@ -724,9 +330,61 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|||||||
fmt.Printf("相簿里面没有文件: %s\n", albumNames[k])
|
fmt.Printf("相簿里面没有文件: %s\n", albumNames[k])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, f := range fileList {
|
|
||||||
// 补全虚拟网盘路径,规则:/<相簿名称>/文件名称
|
// 相薄文件是没有子文件夹的,这个fileList就是该相册里面的全部文件了,所以不需要再遍历子文件夹了
|
||||||
f.Path = "/" + albumNames[k] + "/" + f.FileName
|
idx := 0
|
||||||
|
for {
|
||||||
|
if idx >= len(fileList) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
f := fileList.Item(idx)
|
||||||
|
idx += 1
|
||||||
|
// 处理实况照片
|
||||||
|
if f.IsAlbumLivePhotoFile() {
|
||||||
|
// 如果是实况照片,则需要下载图片+视频两个文件
|
||||||
|
// 获取下载链接
|
||||||
|
durl, apierr := activeUser.PanClient().OpenapiPanClient().ShareAlbumGetFileDownloadUrl(&aliyunpan.ShareAlbumGetFileUrlParam{
|
||||||
|
AlbumId: f.AlbumId,
|
||||||
|
DriveId: f.DriveId,
|
||||||
|
FileId: f.FileId,
|
||||||
|
})
|
||||||
|
if apierr != nil {
|
||||||
|
logger.Verbosef("ERROR: get album file download url error: %s\n", f.FileId)
|
||||||
|
fmt.Printf("\n下载照片失败: %s\n", f.FileName)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if durl.StreamsUrl != nil { // 实况图片(照片+视频)下载链接
|
||||||
|
// 照片文件
|
||||||
|
photoFile := cloneFileEntity(f)
|
||||||
|
photoFileSize := int64(0)
|
||||||
|
if durl.StreamsUrl.Heic != "" {
|
||||||
|
beforeStr, _ := strings.CutSuffix(f.FileName, ".livp")
|
||||||
|
photoFile.FileName = beforeStr + ".HEIC"
|
||||||
|
photoFile.FileExtension = "heic"
|
||||||
|
photoFileSize = getHttpDownloadFileSize(durl.StreamsUrl.Heic)
|
||||||
|
} else if durl.StreamsUrl.Jpeg != "" {
|
||||||
|
beforeStr, _ := strings.CutSuffix(f.FileName, ".livp")
|
||||||
|
photoFile.FileName = beforeStr + ".JPG"
|
||||||
|
photoFile.FileExtension = "jpg"
|
||||||
|
photoFileSize = getHttpDownloadFileSize(durl.StreamsUrl.Jpeg)
|
||||||
|
}
|
||||||
|
photoFile.FileSize = photoFileSize
|
||||||
|
fileList = append(fileList, photoFile)
|
||||||
|
|
||||||
|
// 视频文件
|
||||||
|
videoFile := cloneFileEntity(f)
|
||||||
|
videoFile.FileSize = f.FileSize - photoFileSize
|
||||||
|
if durl.StreamsUrl.Mov != "" {
|
||||||
|
beforeStr, _ := strings.CutSuffix(f.FileName, ".livp")
|
||||||
|
videoFile.FileName = beforeStr + ".MOV"
|
||||||
|
videoFile.FileExtension = "mov"
|
||||||
|
}
|
||||||
|
fileList = append(fileList, videoFile)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 补全虚拟网盘路径,规则:/共享相册/<相簿名称>/文件名称
|
||||||
|
f.Path = "/共享相册/" + albumNames[k] + "/" + f.FileName
|
||||||
|
|
||||||
// 生成下载项
|
// 生成下载项
|
||||||
newCfg := *cfg
|
newCfg := *cfg
|
||||||
@@ -741,15 +399,15 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|||||||
IsExecutedPermission: options.IsExecutedPermission,
|
IsExecutedPermission: options.IsExecutedPermission,
|
||||||
IsOverwrite: options.IsOverwrite,
|
IsOverwrite: options.IsOverwrite,
|
||||||
NoCheck: options.NoCheck,
|
NoCheck: options.NoCheck,
|
||||||
|
FilePanSource: global.AlbumSource,
|
||||||
FilePanPath: f.Path,
|
FilePanPath: f.Path,
|
||||||
DriveId: f.DriveId, // 必须使用文件的DriveId,因为一个相簿的文件会来自多个网盘(资源库/备份盘)
|
DriveId: f.DriveId, // 一个相簿的文件会来自多个网盘(资源库/备份盘)
|
||||||
GlobalSpeedsStat: globalSpeedsStat,
|
GlobalSpeedsStat: globalSpeedsStat,
|
||||||
FileRecorder: nil,
|
FileRecorder: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 相册下载需要重构
|
|
||||||
// 设置相簿文件信息
|
// 设置相簿文件信息
|
||||||
//unit.SetFileInfo(pandownload.AlbumFileSource, f)
|
unit.SetFileInfo(global.AlbumSource, f)
|
||||||
|
|
||||||
// 设置储存的路径
|
// 设置储存的路径
|
||||||
if options.SaveTo != "" {
|
if options.SaveTo != "" {
|
||||||
@@ -785,3 +443,33 @@ func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
|||||||
tb.Render()
|
tb.Render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cloneFileEntity(entity *aliyunpan.FileEntity) *aliyunpan.FileEntity {
|
||||||
|
data, err := json.Marshal(entity) // 序列化原始对象
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
newEntity := &aliyunpan.FileEntity{}
|
||||||
|
err = json.Unmarshal(data, newEntity) // 反序列化到新的对象中
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return newEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHttpDownloadFileSize(fileUrl string) int64 {
|
||||||
|
client := requester.NewHTTPClient()
|
||||||
|
client.SetKeepAlive(true)
|
||||||
|
client.SetTimeout(10 * time.Minute)
|
||||||
|
// header
|
||||||
|
headers := map[string]string{
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
||||||
|
"referer": "https://www.aliyundrive.com/",
|
||||||
|
}
|
||||||
|
resp, err := client.Req("GET", fileUrl, nil, headers)
|
||||||
|
if err != nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
fileSize := resp.ContentLength
|
||||||
|
return fileSize
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,786 @@
|
|||||||
|
// Copyright (c) 2020 tickstep.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
|
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
||||||
|
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
|
||||||
|
"github.com/tickstep/aliyunpan-api/aliyunpan_web"
|
||||||
|
"github.com/tickstep/aliyunpan/cmder"
|
||||||
|
"github.com/tickstep/aliyunpan/cmder/cmdtable"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/config"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/functions/pandownload"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/taskframework"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/utils"
|
||||||
|
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
||||||
|
"github.com/tickstep/library-go/converter"
|
||||||
|
"github.com/tickstep/library-go/logger"
|
||||||
|
"github.com/tickstep/library-go/requester/rio/speeds"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
AlbumFileCategoryOption string
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ImageOnlyOption AlbumFileCategoryOption = "image"
|
||||||
|
VideoOnlyOption AlbumFileCategoryOption = "video"
|
||||||
|
ImageVideoOnlyOption AlbumFileCategoryOption = "image_video"
|
||||||
|
AllFileOption AlbumFileCategoryOption = "none"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdAlbumWeb() cli.Command {
|
||||||
|
return cli.Command{
|
||||||
|
Name: "albumw",
|
||||||
|
Usage: "个人相册",
|
||||||
|
UsageText: cmder.App().Name + " albumw",
|
||||||
|
Category: "阿里云盘",
|
||||||
|
Before: ReloadConfigFunc,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
cli.ShowCommandHelp(c, c.Command.Name)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "list",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Usage: "展示相簿列表",
|
||||||
|
UsageText: cmder.App().Name + " album list",
|
||||||
|
Description: `
|
||||||
|
示例:
|
||||||
|
|
||||||
|
展示相簿列表
|
||||||
|
aliyunpan albumw ls
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumList()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "new",
|
||||||
|
Aliases: []string{""},
|
||||||
|
Usage: "创建相簿",
|
||||||
|
UsageText: cmder.App().Name + " album new",
|
||||||
|
Description: `
|
||||||
|
示例:
|
||||||
|
|
||||||
|
新建相簿,名称为:我的相簿2022
|
||||||
|
aliyunpan albumw new "我的相簿2022"
|
||||||
|
|
||||||
|
新建相簿,名称为:我的相簿2022,描述为:存放2022所有文件
|
||||||
|
aliyunpan albumw new "我的相簿2022" "存放2022所有文件"
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumCreate(c.Args().Get(0), c.Args().Get(1))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "rm",
|
||||||
|
Aliases: []string{""},
|
||||||
|
Usage: "删除相簿",
|
||||||
|
UsageText: cmder.App().Name + " album rm",
|
||||||
|
Description: `
|
||||||
|
删除相簿,同名的相簿只会删除第一个符合条件的
|
||||||
|
示例:
|
||||||
|
|
||||||
|
删除名称为"我的相簿2022"的相簿
|
||||||
|
aliyunpan albumw rm "我的相簿2022"
|
||||||
|
|
||||||
|
删除名称为"我的相簿2022-1" 和 "我的相簿2022-2"的相簿
|
||||||
|
aliyunpan albumw rm "我的相簿2022-1" "我的相簿2022-2"
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumDelete(c.Args())
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "rename",
|
||||||
|
Aliases: []string{""},
|
||||||
|
Usage: "重命名相簿",
|
||||||
|
UsageText: cmder.App().Name + " album rename",
|
||||||
|
Description: `
|
||||||
|
重命名相簿,同名的相簿只会修改第一个符合条件的
|
||||||
|
示例:
|
||||||
|
|
||||||
|
重命名相簿"我的相簿2022"为新的名称"我的相簿2022-new"
|
||||||
|
aliyunpan albumw rename "我的相簿2022" "我的相簿2022-new"
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumRename(c.Args().Get(0), c.Args().Get(1))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "list-file",
|
||||||
|
Aliases: []string{"lf"},
|
||||||
|
Usage: "展示相簿中的文件",
|
||||||
|
UsageText: cmder.App().Name + " album list-file",
|
||||||
|
Description: `
|
||||||
|
展示相簿中文件,同名的相簿只会展示第一个符合条件的
|
||||||
|
示例:
|
||||||
|
|
||||||
|
展示相簿中文件"我的相簿2022"
|
||||||
|
aliyunpan albumw list-file "我的相簿2022"
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumListFile(c.Args().Get(0))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "rm-file",
|
||||||
|
Aliases: []string{"rf"},
|
||||||
|
Usage: "移除相簿中的文件",
|
||||||
|
UsageText: cmder.App().Name + " album rm-file",
|
||||||
|
Description: `
|
||||||
|
移除相簿中的文件,同名的相簿只会移除第一个符合条件的
|
||||||
|
示例:
|
||||||
|
|
||||||
|
移除相簿 "我的相簿2022" 中的文件 1.png 2.png
|
||||||
|
aliyunpan albumw rm-file 我的相簿2022 1.png 2.png
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
subArgs := c.Args()
|
||||||
|
if len(subArgs) < 2 {
|
||||||
|
fmt.Println("请指定移除的文件")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumRmFile(subArgs[0], subArgs[1:])
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "add-file",
|
||||||
|
Aliases: []string{"af"},
|
||||||
|
Usage: "增加(文件/相册)网盘文件到相簿中",
|
||||||
|
UsageText: cmder.App().Name + " album add-file",
|
||||||
|
Description: `
|
||||||
|
增加文件到相簿中
|
||||||
|
示例:
|
||||||
|
|
||||||
|
增加当前目录下的 1.png 2.png 文件到相簿 "我的相簿2022" 中
|
||||||
|
aliyunpan albumw add-file 我的相簿2022 1.png 2.png
|
||||||
|
|
||||||
|
增加当前目录下的 myFolder 文件夹下所有文件到相簿 "我的相簿2022" 中
|
||||||
|
aliyunpan albumw add-file 我的相簿2022 myFolder
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
subArgs := c.Args()
|
||||||
|
if len(subArgs) < 2 {
|
||||||
|
fmt.Println("请指定增加的文件")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
RunAlbumAddFile(subArgs[0], subArgs[1:], ImageVideoOnlyOption)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "download-file",
|
||||||
|
Aliases: []string{"df"},
|
||||||
|
Usage: "下载相簿中的所有文件到本地",
|
||||||
|
UsageText: cmder.App().Name + " album download-file",
|
||||||
|
Description: `
|
||||||
|
下载相簿中的所有文件
|
||||||
|
示例:
|
||||||
|
|
||||||
|
下载相簿 "我的相簿2022" 里面的所有文件
|
||||||
|
aliyunpan albumw download-file 我的相簿2022
|
||||||
|
|
||||||
|
`,
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if config.Config.ActiveUser() == nil {
|
||||||
|
fmt.Println("未登录账号")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.Config.ActiveUser().PanClient().WebapiPanClient() == nil {
|
||||||
|
fmt.Println("WEB客户端未登录,请登录后再使用该命令")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
subArgs := c.Args()
|
||||||
|
if len(subArgs) == 0 {
|
||||||
|
fmt.Println("请指定下载的相簿名称")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理saveTo
|
||||||
|
var (
|
||||||
|
saveTo string
|
||||||
|
)
|
||||||
|
if c.String("saveto") != "" {
|
||||||
|
saveTo = filepath.Clean(c.String("saveto"))
|
||||||
|
}
|
||||||
|
|
||||||
|
do := &DownloadOptions{
|
||||||
|
IsPrintStatus: false,
|
||||||
|
IsExecutedPermission: false,
|
||||||
|
IsOverwrite: c.Bool("ow"),
|
||||||
|
SaveTo: saveTo,
|
||||||
|
Parallel: 0,
|
||||||
|
Load: 0,
|
||||||
|
MaxRetry: pandownload.DefaultDownloadMaxRetry,
|
||||||
|
NoCheck: false,
|
||||||
|
ShowProgress: !c.Bool("np"),
|
||||||
|
DriveId: parseDriveId(c),
|
||||||
|
ExcludeNames: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
RunAlbumDownloadFile(c.Args(), do)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "ow",
|
||||||
|
Usage: "overwrite, 覆盖已存在的文件",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "saveto",
|
||||||
|
Usage: "将下载的文件直接保存到指定的目录",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "np",
|
||||||
|
Usage: "no progress 不展示下载进度条",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumList() {
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan_web.AlbumListParam{})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("获取相簿列表失败: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tb := cmdtable.NewTable(os.Stdout)
|
||||||
|
tb.SetHeader([]string{"#", "ALBUM_ID", "名称", "文件数量", "创建日期", "修改日期"})
|
||||||
|
tb.SetColumnAlignment([]int{tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_DEFAULT, tablewriter.ALIGN_DEFAULT})
|
||||||
|
for k, record := range records {
|
||||||
|
tb.Append([]string{strconv.Itoa(k + 1), record.AlbumId, record.Name, strconv.Itoa(record.FileCount),
|
||||||
|
record.CreatedAtStr(), record.UpdatedAtStr()})
|
||||||
|
}
|
||||||
|
tb.Render()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumCreate(name, description string) {
|
||||||
|
if name == "" {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
_, err := activeUser.PanClient().WebapiPanClient().AlbumCreate(&aliyunpan_web.AlbumCreateParam{
|
||||||
|
Name: name,
|
||||||
|
Description: description,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("创建相簿失败: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("创建相簿成功: %s\n", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumDelete(nameList []string) {
|
||||||
|
if len(nameList) == 0 {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan_web.AlbumListParam{})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("获取相簿列表失败: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range records {
|
||||||
|
for i, name := range nameList {
|
||||||
|
if name == record.Name {
|
||||||
|
nameList = append(nameList[:i], nameList[i+1:]...)
|
||||||
|
_, err := activeUser.PanClient().WebapiPanClient().AlbumDelete(&aliyunpan_web.AlbumDeleteParam{
|
||||||
|
AlbumId: record.AlbumId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("删除相簿失败: %s\n", name)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
fmt.Printf("删除相簿成功: %s\n", name)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAlbumFromName(activeUser *config.PanUser, name string) *aliyunpan.AlbumEntity {
|
||||||
|
records, err := activeUser.PanClient().WebapiPanClient().AlbumListGetAll(&aliyunpan_web.AlbumListParam{})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("获取相簿列表失败: %s\n", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range records {
|
||||||
|
if name == record.Name {
|
||||||
|
return record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumRename(name, newName string) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(newName) == 0 {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
record := getAlbumFromName(activeUser, name)
|
||||||
|
if record == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err := activeUser.PanClient().WebapiPanClient().AlbumEdit(&aliyunpan_web.AlbumEditParam{
|
||||||
|
AlbumId: record.AlbumId,
|
||||||
|
Description: record.Description,
|
||||||
|
Name: newName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("重命名相簿失败: %s\n", name)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
fmt.Printf("重命名相簿成功: %s -> %s\n", name, newName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumListFile(name string) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
record := getAlbumFromName(activeUser, name)
|
||||||
|
if record == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan_web.AlbumListFileParam{
|
||||||
|
AlbumId: record.AlbumId,
|
||||||
|
})
|
||||||
|
if er != nil {
|
||||||
|
fmt.Printf("获取相簿文件列表失败:%s\n", er)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
renderTable(opLs, false, "", fileList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumRmFile(name string, nameList []string) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(nameList) == 0 {
|
||||||
|
fmt.Printf("指定文件不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
album := getAlbumFromName(activeUser, name)
|
||||||
|
if album == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan_web.AlbumListFileParam{
|
||||||
|
AlbumId: album.AlbumId,
|
||||||
|
})
|
||||||
|
if er != nil {
|
||||||
|
fmt.Printf("获取相簿文件列表失败:%s\n", er)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
param := &aliyunpan_web.AlbumDeleteFileParam{
|
||||||
|
AlbumId: album.AlbumId,
|
||||||
|
DriveFileList: []aliyunpan.FileBatchActionParam{},
|
||||||
|
}
|
||||||
|
for _, file := range fileList {
|
||||||
|
if len(nameList) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for i, name := range nameList {
|
||||||
|
if name == file.FileName {
|
||||||
|
nameList = append(nameList[:i], nameList[i+1:]...)
|
||||||
|
param.AddFileItem(file.DriveId, file.FileId)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1-500 范围
|
||||||
|
if len(param.DriveFileList) == 0 {
|
||||||
|
fmt.Printf("没有符合的文件\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// delete file
|
||||||
|
_, e := activeUser.PanClient().WebapiPanClient().AlbumDeleteFile(param)
|
||||||
|
if e != nil {
|
||||||
|
fmt.Printf("删除相簿文件失败:%s\n", e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("删除相簿文件成功:%s\n", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunAlbumAddFile 增加网盘文件到相簿
|
||||||
|
func RunAlbumAddFile(albumName string, filePathList []string, filterOption AlbumFileCategoryOption) {
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
|
||||||
|
if albumName == "" {
|
||||||
|
fmt.Printf("必须指定相簿名称\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
album := getAlbumFromName(activeUser, albumName)
|
||||||
|
if album == nil {
|
||||||
|
fmt.Printf("相簿不存在\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
paths, err := makePathAbsolute(activeUser.ActiveDriveId, filePathList...)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(paths) == 0 {
|
||||||
|
fmt.Printf("没有有效的文件\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("正在获取增加的文件信息,该操作可能会非常耗费时间,请耐心等待...\n")
|
||||||
|
param := &aliyunpan_web.AlbumAddFileParam{
|
||||||
|
AlbumId: album.AlbumId,
|
||||||
|
DriveFileList: []aliyunpan.FileBatchActionParam{},
|
||||||
|
}
|
||||||
|
for k := range paths {
|
||||||
|
filePath := paths[k]
|
||||||
|
fileInfo, apierr := activeUser.PanClient().WebapiPanClient().FileInfoByPath(activeUser.ActiveDriveId, filePath)
|
||||||
|
if apierr != nil {
|
||||||
|
fmt.Printf("获取文件信息失败: %s\n", filePath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fileInfo.IsFile() {
|
||||||
|
// file
|
||||||
|
if isFileMatchCondition(fileInfo, filterOption) {
|
||||||
|
param.AddFileItem(fileInfo.DriveId, fileInfo.FileId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// folder
|
||||||
|
activeUser.PanClient().WebapiPanClient().FilesDirectoriesRecurseList(activeUser.ActiveDriveId, fileInfo.Path, func(depth int, _ string, fd *aliyunpan.FileEntity, apiError *apierror.ApiError) bool {
|
||||||
|
if apiError != nil {
|
||||||
|
logger.Verbosef("%s\n", apiError)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !fd.IsFolder() {
|
||||||
|
if isFileMatchCondition(fd, filterOption) {
|
||||||
|
param.AddFileItem(fd.DriveId, fd.FileId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(param.DriveFileList) == 0 {
|
||||||
|
fmt.Printf("没有符合的文件\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// add file
|
||||||
|
_, e := activeUser.PanClient().WebapiPanClient().AlbumAddFile(param)
|
||||||
|
if e != nil {
|
||||||
|
fmt.Printf("增加相簿文件失败:%s\n", e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("增加相簿文件成功:%s\n", albumName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFileMatchCondition(fileInfo *aliyunpan.FileEntity, filterOption AlbumFileCategoryOption) bool {
|
||||||
|
if fileInfo == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if filterOption == ImageOnlyOption {
|
||||||
|
return fileInfo.Category == "image"
|
||||||
|
} else if filterOption == VideoOnlyOption {
|
||||||
|
return fileInfo.Category == "video"
|
||||||
|
} else if filterOption == ImageVideoOnlyOption {
|
||||||
|
return fileInfo.Category == "image" || fileInfo.Category == "video"
|
||||||
|
} else if filterOption == AllFileOption {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunAlbumDownloadFile(albumNames []string, options *DownloadOptions) {
|
||||||
|
if len(albumNames) == 0 {
|
||||||
|
fmt.Printf("相簿名称不能为空\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
activeUser := GetActiveUser()
|
||||||
|
activeUser.PanClient().WebapiPanClient().EnableCache()
|
||||||
|
activeUser.PanClient().WebapiPanClient().ClearCache()
|
||||||
|
defer activeUser.PanClient().WebapiPanClient().DisableCache()
|
||||||
|
// pan token expired checker
|
||||||
|
continueFlag := int32(0)
|
||||||
|
atomic.StoreInt32(&continueFlag, 0)
|
||||||
|
defer func() {
|
||||||
|
atomic.StoreInt32(&continueFlag, 1)
|
||||||
|
}()
|
||||||
|
go func(flag *int32) {
|
||||||
|
for atomic.LoadInt32(flag) == 0 {
|
||||||
|
time.Sleep(time.Duration(1) * time.Minute)
|
||||||
|
if RefreshWebTokenInNeed(activeUser, config.Config.DeviceName) {
|
||||||
|
logger.Verboseln("update access token for download task")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(&continueFlag)
|
||||||
|
|
||||||
|
if options == nil {
|
||||||
|
options = &DownloadOptions{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.MaxRetry < 0 {
|
||||||
|
options.MaxRetry = pandownload.DefaultDownloadMaxRetry
|
||||||
|
}
|
||||||
|
options.IsExecutedPermission = false
|
||||||
|
|
||||||
|
// 设置下载配置
|
||||||
|
cfg := &downloader.Config{
|
||||||
|
Mode: transfer.RangeGenMode_BlockSize,
|
||||||
|
CacheSize: config.Config.CacheSize,
|
||||||
|
BlockSize: MaxDownloadRangeSize,
|
||||||
|
MaxRate: config.Config.MaxDownloadRate,
|
||||||
|
InstanceStateStorageFormat: downloader.InstanceStateStorageFormatJSON,
|
||||||
|
ShowProgress: options.ShowProgress,
|
||||||
|
ExcludeNames: options.ExcludeNames,
|
||||||
|
}
|
||||||
|
if cfg.CacheSize == 0 {
|
||||||
|
cfg.CacheSize = int(DownloadCacheSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置下载最大并发量
|
||||||
|
if options.Parallel < 1 {
|
||||||
|
options.Parallel = config.Config.MaxDownloadParallel
|
||||||
|
if options.Parallel == 0 {
|
||||||
|
options.Parallel = config.DefaultFileDownloadParallelNum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if options.Parallel > config.MaxFileDownloadParallelNum {
|
||||||
|
options.Parallel = config.MaxFileDownloadParallelNum
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存文件的本地根文件夹
|
||||||
|
originSaveRootPath := ""
|
||||||
|
if options.SaveTo != "" {
|
||||||
|
originSaveRootPath = options.SaveTo
|
||||||
|
} else {
|
||||||
|
// 使用默认的保存路径
|
||||||
|
originSaveRootPath = GetActiveUser().GetSavePath("")
|
||||||
|
}
|
||||||
|
fi, err1 := os.Stat(originSaveRootPath)
|
||||||
|
if err1 != nil && !os.IsExist(err1) {
|
||||||
|
os.MkdirAll(originSaveRootPath, 0777) // 首先在本地创建目录
|
||||||
|
} else {
|
||||||
|
if !fi.IsDir() {
|
||||||
|
fmt.Println("本地保存路径不是文件夹,请删除或者创建对应的文件夹:", originSaveRootPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n[0] 当前文件下载最大并发量为: %d, 下载缓存为: %s\n\n", options.Parallel, converter.ConvertFileSize(int64(cfg.CacheSize), 2))
|
||||||
|
|
||||||
|
var (
|
||||||
|
panClient = activeUser.PanClient()
|
||||||
|
)
|
||||||
|
cfg.MaxParallel = options.Parallel
|
||||||
|
|
||||||
|
var (
|
||||||
|
executor = taskframework.TaskExecutor{
|
||||||
|
IsFailedDeque: true, // 统计失败的列表
|
||||||
|
}
|
||||||
|
statistic = &pandownload.DownloadStatistic{}
|
||||||
|
)
|
||||||
|
// 配置执行器任务并发数,即同时下载文件并发数
|
||||||
|
executor.SetParallel(cfg.MaxParallel)
|
||||||
|
|
||||||
|
// 全局速度统计
|
||||||
|
globalSpeedsStat := &speeds.Speeds{}
|
||||||
|
|
||||||
|
// 处理队列
|
||||||
|
for k := range albumNames {
|
||||||
|
record := getAlbumFromName(activeUser, albumNames[k])
|
||||||
|
if record == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 获取相簿下的所有文件
|
||||||
|
fileList, er := activeUser.PanClient().WebapiPanClient().AlbumListFileGetAll(&aliyunpan_web.AlbumListFileParam{
|
||||||
|
AlbumId: record.AlbumId,
|
||||||
|
})
|
||||||
|
if er != nil {
|
||||||
|
fmt.Printf("获取相簿文件出错,请稍后重试: %s\n", albumNames[k])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fileList == nil || len(fileList) == 0 {
|
||||||
|
fmt.Printf("相簿里面没有文件: %s\n", albumNames[k])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, f := range fileList {
|
||||||
|
// 补全虚拟网盘路径,规则:/<相簿名称>/文件名称
|
||||||
|
f.Path = "/" + albumNames[k] + "/" + f.FileName
|
||||||
|
|
||||||
|
// 生成下载项
|
||||||
|
newCfg := *cfg
|
||||||
|
unit := pandownload.DownloadTaskUnit{
|
||||||
|
Cfg: &newCfg, // 复制一份新的cfg
|
||||||
|
PanClient: panClient,
|
||||||
|
VerbosePrinter: panCommandVerbose,
|
||||||
|
PrintFormat: downloadPrintFormat(options.Load),
|
||||||
|
ParentTaskExecutor: &executor,
|
||||||
|
DownloadStatistic: statistic,
|
||||||
|
IsPrintStatus: options.IsPrintStatus,
|
||||||
|
IsExecutedPermission: options.IsExecutedPermission,
|
||||||
|
IsOverwrite: options.IsOverwrite,
|
||||||
|
NoCheck: options.NoCheck,
|
||||||
|
FilePanPath: f.Path,
|
||||||
|
DriveId: f.DriveId, // 必须使用文件的DriveId,因为一个相簿的文件会来自多个网盘(资源库/备份盘)
|
||||||
|
GlobalSpeedsStat: globalSpeedsStat,
|
||||||
|
FileRecorder: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 相册下载需要重构
|
||||||
|
// 设置相簿文件信息
|
||||||
|
//unit.SetFileInfo(pandownload.AlbumFileSource, f)
|
||||||
|
|
||||||
|
// 设置储存的路径
|
||||||
|
if options.SaveTo != "" {
|
||||||
|
unit.OriginSaveRootPath = options.SaveTo
|
||||||
|
unit.SavePath = filepath.Join(options.SaveTo, f.Path)
|
||||||
|
} else {
|
||||||
|
// 使用默认的保存路径
|
||||||
|
unit.OriginSaveRootPath = GetActiveUser().GetSavePath("")
|
||||||
|
unit.SavePath = GetActiveUser().GetSavePath(f.Path)
|
||||||
|
}
|
||||||
|
info := executor.Append(&unit, options.MaxRetry)
|
||||||
|
fmt.Printf("[%s] 加入下载队列: %s\n", info.Id(), f.Path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始计时
|
||||||
|
statistic.StartTimer()
|
||||||
|
|
||||||
|
// 开始执行
|
||||||
|
executor.Execute()
|
||||||
|
|
||||||
|
fmt.Printf("\n下载结束, 时间: %s, 数据总量: %s\n", utils.ConvertTime(statistic.Elapsed()), converter.ConvertFileSize(statistic.TotalSize(), 2))
|
||||||
|
|
||||||
|
// 输出失败的文件列表
|
||||||
|
failedList := executor.FailedDeque()
|
||||||
|
if failedList.Size() != 0 {
|
||||||
|
fmt.Printf("以下文件下载失败: \n")
|
||||||
|
tb := cmdtable.NewTable(os.Stdout)
|
||||||
|
for e := failedList.Shift(); e != nil; e = failedList.Shift() {
|
||||||
|
item := e.(*taskframework.TaskInfoItem)
|
||||||
|
tb.Append([]string{item.Info.Id(), item.Unit.(*pandownload.DownloadTaskUnit).FilePanPath})
|
||||||
|
}
|
||||||
|
tb.Render()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/tickstep/aliyunpan/internal/config"
|
"github.com/tickstep/aliyunpan/internal/config"
|
||||||
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
||||||
"github.com/tickstep/aliyunpan/internal/functions/pandownload"
|
"github.com/tickstep/aliyunpan/internal/functions/pandownload"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/global"
|
||||||
"github.com/tickstep/aliyunpan/internal/log"
|
"github.com/tickstep/aliyunpan/internal/log"
|
||||||
"github.com/tickstep/aliyunpan/internal/taskframework"
|
"github.com/tickstep/aliyunpan/internal/taskframework"
|
||||||
"github.com/tickstep/aliyunpan/internal/utils"
|
"github.com/tickstep/aliyunpan/internal/utils"
|
||||||
@@ -415,6 +416,7 @@ func RunDownload(paths []string, options *DownloadOptions) {
|
|||||||
IsExecutedPermission: options.IsExecutedPermission,
|
IsExecutedPermission: options.IsExecutedPermission,
|
||||||
IsOverwrite: options.IsOverwrite,
|
IsOverwrite: options.IsOverwrite,
|
||||||
NoCheck: options.NoCheck,
|
NoCheck: options.NoCheck,
|
||||||
|
FilePanSource: global.FileSource,
|
||||||
FilePanPath: f.Path,
|
FilePanPath: f.Path,
|
||||||
DriveId: options.DriveId,
|
DriveId: options.DriveId,
|
||||||
GlobalSpeedsStat: globalSpeedsStat,
|
GlobalSpeedsStat: globalSpeedsStat,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
|
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
|
||||||
"github.com/tickstep/aliyunpan/cmder/cmdutil"
|
"github.com/tickstep/aliyunpan/cmder/cmdutil"
|
||||||
"github.com/tickstep/aliyunpan/internal/config"
|
"github.com/tickstep/aliyunpan/internal/config"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/global"
|
||||||
"github.com/tickstep/aliyunpan/internal/waitgroup"
|
"github.com/tickstep/aliyunpan/internal/waitgroup"
|
||||||
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
||||||
"github.com/tickstep/library-go/cachepool"
|
"github.com/tickstep/library-go/cachepool"
|
||||||
@@ -54,6 +55,7 @@ type (
|
|||||||
monitorCancelFunc context.CancelFunc
|
monitorCancelFunc context.CancelFunc
|
||||||
globalSpeedsStat *speeds.Speeds // 全局速度统计
|
globalSpeedsStat *speeds.Speeds // 全局速度统计
|
||||||
|
|
||||||
|
filePanSource global.FileSourceType // 要下载的网盘文件来源
|
||||||
fileInfo *aliyunpan.FileEntity // 下载的文件信息
|
fileInfo *aliyunpan.FileEntity // 下载的文件信息
|
||||||
driveId string
|
driveId string
|
||||||
loadBalancerCompareFunc LoadBalancerCompareFunc // 负载均衡检测函数
|
loadBalancerCompareFunc LoadBalancerCompareFunc // 负载均衡检测函数
|
||||||
@@ -97,11 +99,11 @@ func NewDownloader(writer io.WriterAt, config *Config, p *config.PanClient, sp [
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClient 设置http客户端
|
// SetFileInfo 设置文件信息
|
||||||
func (der *Downloader) SetFileInfo(f *aliyunpan.FileEntity) {
|
func (der *Downloader) SetFileInfo(source global.FileSourceType, f *aliyunpan.FileEntity) {
|
||||||
|
der.filePanSource = source
|
||||||
der.fileInfo = f
|
der.fileInfo = f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (der *Downloader) SetDriveId(driveId string) {
|
func (der *Downloader) SetDriveId(driveId string) {
|
||||||
der.driveId = driveId
|
der.driveId = driveId
|
||||||
}
|
}
|
||||||
@@ -389,27 +391,7 @@ func (der *Downloader) Execute() error {
|
|||||||
writeMu = &sync.Mutex{}
|
writeMu = &sync.Mutex{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 获取下载链接
|
// 获取各个账号网盘客户端的下载链接
|
||||||
//var apierr *apierror.ApiError
|
|
||||||
//durl, apierr := der.panClient.OpenapiPanClient().GetFileDownloadUrl(&aliyunpan.GetFileDownloadUrlParam{
|
|
||||||
// DriveId: der.driveId,
|
|
||||||
// FileId: der.fileInfo.FileId,
|
|
||||||
//})
|
|
||||||
//time.Sleep(time.Duration(200) * time.Millisecond)
|
|
||||||
//if apierr != nil {
|
|
||||||
// logger.Verbosef("ERROR: get download url error: %s\n", der.fileInfo.FileId)
|
|
||||||
// cmdutil.Trigger(der.onCancelEvent)
|
|
||||||
// return apierr
|
|
||||||
//}
|
|
||||||
//if durl == nil || durl.Url == "" || strings.HasPrefix(durl.Url, aliyunpan.IllegalDownloadUrlPrefix) {
|
|
||||||
// logger.Verbosef("无法获取有效的下载链接: %+v\n", durl)
|
|
||||||
// cmdutil.Trigger(der.onCancelEvent)
|
|
||||||
// der.removeInstanceState() // 移除断点续传文件
|
|
||||||
// cmdutil.Trigger(der.onFailedEvent)
|
|
||||||
// return ErrFileDownloadForbidden
|
|
||||||
//}
|
|
||||||
|
|
||||||
// 获取各个网盘客户端的下载链接
|
|
||||||
panClientFileUrl, err := der.getFileAllClientDownloadUrl()
|
panClientFileUrl, err := der.getFileAllClientDownloadUrl()
|
||||||
if err != nil || panClientFileUrl == nil {
|
if err != nil || panClientFileUrl == nil {
|
||||||
logger.Verbosef("ERROR: get download url error: %s\n", der.fileInfo.FileId)
|
logger.Verbosef("ERROR: get download url error: %s\n", der.fileInfo.FileId)
|
||||||
@@ -476,8 +458,19 @@ func (der *Downloader) Execute() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取对应网盘的下载链接
|
// 获取对应网盘文件的下载链接
|
||||||
func (der *Downloader) getFileAllClientDownloadUrl() ([]*panClientDownloadUrlEntity, error) {
|
func (der *Downloader) getFileAllClientDownloadUrl() ([]*panClientDownloadUrlEntity, error) {
|
||||||
|
if der.filePanSource == global.AlbumSource {
|
||||||
|
// 相册源只支持主账号下载
|
||||||
|
return der.getAlbumSourceDownloadUrl()
|
||||||
|
} else {
|
||||||
|
// 文件源支持多账号分流下载
|
||||||
|
return der.getFileSourceDownloadUrl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFileSourceDownloadUrl 获取文件源的文件下载链接
|
||||||
|
func (der *Downloader) getFileSourceDownloadUrl() ([]*panClientDownloadUrlEntity, error) {
|
||||||
result := []*panClientDownloadUrlEntity{}
|
result := []*panClientDownloadUrlEntity{}
|
||||||
|
|
||||||
// 主账号(必须存在)
|
// 主账号(必须存在)
|
||||||
@@ -523,7 +516,7 @@ func (der *Downloader) getFileAllClientDownloadUrl() ([]*panClientDownloadUrlEnt
|
|||||||
// 网盘文件路径
|
// 网盘文件路径
|
||||||
mainFileFullPath := der.fileInfo.Path
|
mainFileFullPath := der.fileInfo.Path
|
||||||
|
|
||||||
// 铺助账号的下载链接
|
// 铺助账号的下载链接,只支持文件源
|
||||||
if der.subPanClientList != nil {
|
if der.subPanClientList != nil {
|
||||||
for _, spc := range der.subPanClientList {
|
for _, spc := range der.subPanClientList {
|
||||||
driveId := ""
|
driveId := ""
|
||||||
@@ -570,6 +563,60 @@ func (der *Downloader) getFileAllClientDownloadUrl() ([]*panClientDownloadUrlEnt
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAlbumSourceDownloadUrl 获取相册源的文件下载链接
|
||||||
|
func (der *Downloader) getAlbumSourceDownloadUrl() ([]*panClientDownloadUrlEntity, error) {
|
||||||
|
result := []*panClientDownloadUrlEntity{}
|
||||||
|
|
||||||
|
// 相册源只能使用主账号
|
||||||
|
// 获取下载链接
|
||||||
|
var apierr *apierror.ApiError
|
||||||
|
durl, apierr := der.panClient.OpenapiPanClient().ShareAlbumGetFileDownloadUrl(&aliyunpan.ShareAlbumGetFileUrlParam{
|
||||||
|
AlbumId: der.fileInfo.AlbumId,
|
||||||
|
DriveId: der.fileInfo.DriveId,
|
||||||
|
FileId: der.fileInfo.FileId,
|
||||||
|
})
|
||||||
|
time.Sleep(time.Duration(200) * time.Millisecond)
|
||||||
|
if apierr != nil {
|
||||||
|
logger.Verbosef("ERROR: get album file download url error: %s\n", der.fileInfo.FileId)
|
||||||
|
cmdutil.Trigger(der.onCancelEvent)
|
||||||
|
return nil, apierr
|
||||||
|
}
|
||||||
|
realUrl := ""
|
||||||
|
if durl.StreamsUrl != nil { // 实况图片
|
||||||
|
if strings.ToLower(der.fileInfo.FileExtension) == "mov" {
|
||||||
|
// 视频文件
|
||||||
|
if durl.StreamsUrl.Mov != "" {
|
||||||
|
realUrl = durl.StreamsUrl.Mov
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 照片文件
|
||||||
|
if durl.StreamsUrl.Heic != "" {
|
||||||
|
realUrl = durl.StreamsUrl.Heic
|
||||||
|
} else if durl.StreamsUrl.Jpeg != "" {
|
||||||
|
realUrl = durl.StreamsUrl.Jpeg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if durl.Url != "" { // 普通图片
|
||||||
|
realUrl = durl.Url
|
||||||
|
}
|
||||||
|
if realUrl == "" {
|
||||||
|
logger.Verbosef("无法获取有效的相册文件下载链接: %+v\n", durl)
|
||||||
|
cmdutil.Trigger(der.onCancelEvent)
|
||||||
|
der.removeInstanceState() // 移除断点续传文件
|
||||||
|
cmdutil.Trigger(der.onFailedEvent)
|
||||||
|
return nil, ErrFileDownloadForbidden
|
||||||
|
}
|
||||||
|
// 返回下载链接
|
||||||
|
result = append(result, &panClientDownloadUrlEntity{
|
||||||
|
PanClient: der.panClient,
|
||||||
|
FileInfo: der.fileInfo,
|
||||||
|
DriveId: der.driveId,
|
||||||
|
FileId: der.fileInfo.FileId,
|
||||||
|
FileUrl: realUrl,
|
||||||
|
})
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// downloadStatusEvent 执行状态处理事件
|
// downloadStatusEvent 执行状态处理事件
|
||||||
func (der *Downloader) downloadStatusEvent() {
|
func (der *Downloader) downloadStatusEvent() {
|
||||||
if der.onDownloadStatusEvent == nil {
|
if der.onDownloadStatusEvent == nil {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/tickstep/aliyunpan/internal/config"
|
"github.com/tickstep/aliyunpan/internal/config"
|
||||||
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
||||||
"github.com/tickstep/aliyunpan/internal/functions"
|
"github.com/tickstep/aliyunpan/internal/functions"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/global"
|
||||||
"github.com/tickstep/aliyunpan/internal/localfile"
|
"github.com/tickstep/aliyunpan/internal/localfile"
|
||||||
"github.com/tickstep/aliyunpan/internal/log"
|
"github.com/tickstep/aliyunpan/internal/log"
|
||||||
"github.com/tickstep/aliyunpan/internal/plugins"
|
"github.com/tickstep/aliyunpan/internal/plugins"
|
||||||
@@ -40,8 +41,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
FileSourceType string
|
|
||||||
|
|
||||||
// DownloadTaskUnit 下载的任务单元
|
// DownloadTaskUnit 下载的任务单元
|
||||||
DownloadTaskUnit struct {
|
DownloadTaskUnit struct {
|
||||||
taskInfo *taskframework.TaskInfo // 任务信息
|
taskInfo *taskframework.TaskInfo // 任务信息
|
||||||
@@ -62,10 +61,11 @@ type (
|
|||||||
IsOverwrite bool // 是否覆盖已存在的文件
|
IsOverwrite bool // 是否覆盖已存在的文件
|
||||||
NoCheck bool // 不校验文件
|
NoCheck bool // 不校验文件
|
||||||
|
|
||||||
FilePanPath string // 要下载的网盘文件路径
|
FilePanSource global.FileSourceType // 要下载的网盘文件来源
|
||||||
SavePath string // 文件保存在本地的路径
|
FilePanPath string // 要下载的网盘文件路径
|
||||||
OriginSaveRootPath string // 文件保存在本地的根目录路径
|
SavePath string // 文件保存在本地的路径
|
||||||
DriveId string
|
OriginSaveRootPath string // 文件保存在本地的根目录路径
|
||||||
|
DriveId string // 网盘ID
|
||||||
|
|
||||||
fileInfo *aliyunpan.FileEntity // 文件或目录详情
|
fileInfo *aliyunpan.FileEntity // 文件或目录详情
|
||||||
|
|
||||||
@@ -89,15 +89,14 @@ const (
|
|||||||
StrDownloadChecksumFailed = "检测文件有效性失败"
|
StrDownloadChecksumFailed = "检测文件有效性失败"
|
||||||
// DefaultDownloadMaxRetry 默认下载失败最大重试次数
|
// DefaultDownloadMaxRetry 默认下载失败最大重试次数
|
||||||
DefaultDownloadMaxRetry = 3
|
DefaultDownloadMaxRetry = 3
|
||||||
|
|
||||||
// BackupFileSource 备份盘文件
|
|
||||||
BackupFileSource FileSourceType = "backup"
|
|
||||||
// ResourceFileSource 资源库文件
|
|
||||||
ResourceFileSource FileSourceType = "resource"
|
|
||||||
// AlbumFileSource 相册文件
|
|
||||||
AlbumFileSource FileSourceType = "album"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SetFileInfo 设置文件信息
|
||||||
|
func (dtu *DownloadTaskUnit) SetFileInfo(source global.FileSourceType, f *aliyunpan.FileEntity) {
|
||||||
|
dtu.FilePanSource = source
|
||||||
|
dtu.fileInfo = f
|
||||||
|
}
|
||||||
|
|
||||||
func (dtu *DownloadTaskUnit) SetTaskInfo(info *taskframework.TaskInfo) {
|
func (dtu *DownloadTaskUnit) SetTaskInfo(info *taskframework.TaskInfo) {
|
||||||
dtu.taskInfo = info
|
dtu.taskInfo = info
|
||||||
}
|
}
|
||||||
@@ -172,7 +171,7 @@ func (dtu *DownloadTaskUnit) download() (err error) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
der := downloader.NewDownloader(writer, dtu.Cfg, dtu.PanClient, dtu.SubPanClientList, dtu.GlobalSpeedsStat)
|
der := downloader.NewDownloader(writer, dtu.Cfg, dtu.PanClient, dtu.SubPanClientList, dtu.GlobalSpeedsStat)
|
||||||
der.SetFileInfo(dtu.fileInfo)
|
der.SetFileInfo(dtu.FilePanSource, dtu.fileInfo)
|
||||||
der.SetDriveId(dtu.DriveId)
|
der.SetDriveId(dtu.DriveId)
|
||||||
der.SetStatusCodeBodyCheckFunc(func(respBody io.Reader) error {
|
der.SetStatusCodeBodyCheckFunc(func(respBody io.Reader) error {
|
||||||
// 解析错误
|
// 解析错误
|
||||||
@@ -568,6 +567,7 @@ func (dtu *DownloadTaskUnit) Run() (result *taskframework.TaskUnitRunResult) {
|
|||||||
newCfg := *dtu.Cfg
|
newCfg := *dtu.Cfg
|
||||||
subUnit.Cfg = &newCfg
|
subUnit.Cfg = &newCfg
|
||||||
subUnit.fileInfo = fileList[k] // 保存文件信息
|
subUnit.fileInfo = fileList[k] // 保存文件信息
|
||||||
|
subUnit.FilePanSource = dtu.FilePanSource
|
||||||
subUnit.FilePanPath = fileList[k].Path
|
subUnit.FilePanPath = fileList[k].Path
|
||||||
subUnit.SavePath = filepath.Join(dtu.OriginSaveRootPath, fileList[k].Path) // 保存位置
|
subUnit.SavePath = filepath.Join(dtu.OriginSaveRootPath, fileList[k].Path) // 保存位置
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package global
|
||||||
|
|
||||||
|
type (
|
||||||
|
FileSourceType string
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FileSource 文件,包括:资源盘文件、备份盘文件
|
||||||
|
FileSource FileSourceType = "file"
|
||||||
|
// AlbumSource 相册
|
||||||
|
AlbumSource FileSourceType = "album"
|
||||||
|
)
|
||||||
@@ -478,6 +478,9 @@ func main() {
|
|||||||
// 分享文件/目录 share
|
// 分享文件/目录 share
|
||||||
command.CmdShare(),
|
command.CmdShare(),
|
||||||
|
|
||||||
|
// 相簿
|
||||||
|
command.CmdAlbum(),
|
||||||
|
|
||||||
// 显示命令历史
|
// 显示命令历史
|
||||||
{
|
{
|
||||||
Name: "history",
|
Name: "history",
|
||||||
@@ -686,9 +689,6 @@ func main() {
|
|||||||
// Category: "debug",
|
// Category: "debug",
|
||||||
// Before: command.ReloadConfigFunc,
|
// Before: command.ReloadConfigFunc,
|
||||||
// Action: func(c *cli.Context) error {
|
// Action: func(c *cli.Context) error {
|
||||||
// os.Setenv(config.EnvVerbose, "1")
|
|
||||||
// logger.IsVerbose = true
|
|
||||||
// fmt.Println("显示调试日志", logger.IsVerbose)
|
|
||||||
// return nil
|
// return nil
|
||||||
// },
|
// },
|
||||||
// Flags: []cli.Flag{
|
// Flags: []cli.Flag{
|
||||||
|
|||||||
Reference in New Issue
Block a user