diff --git a/go.mod b/go.mod index d7c4c28..7b2f10a 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( ) require ( + github.com/adrg/xdg v0.4.0 // indirect github.com/boltdb/bolt v1.3.1 // indirect github.com/btcsuite/btcd v0.22.1 // indirect github.com/cpuguy83/go-md2man v1.0.10 // indirect @@ -31,7 +32,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/russross/blackfriday v1.5.2 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect + golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect golang.org/x/text v0.3.7 // indirect ) diff --git a/go.sum b/go.sum index 0b7a94b..666459b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= +github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= +github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= @@ -98,6 +100,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tickstep/aliyunpan-api v0.2.1 h1:bPJGnLR2uwWZ5xNInH2xvVRynlLN3fNGk7CZeM7+TbY= github.com/tickstep/aliyunpan-api v0.2.1/go.mod h1:SN+N5Vh3lLq3dVimlxKxviCl50gLGXZO96nHHc3qd2o= github.com/tickstep/bolt v1.3.4 h1:UN1txRsauOfR8a5mUWm5So0ng233PsIMVR5/+3WowCE= @@ -123,6 +126,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= diff --git a/internal/config/pan_config.go b/internal/config/pan_config.go index df31549..18584a6 100644 --- a/internal/config/pan_config.go +++ b/internal/config/pan_config.go @@ -15,6 +15,7 @@ package config import ( "fmt" + "github.com/adrg/xdg" jsoniter "github.com/json-iterator/go" "github.com/tickstep/aliyunpan-api/aliyunpan" "github.com/tickstep/aliyunpan/cmder/cmdutil" @@ -24,6 +25,7 @@ import ( "github.com/tickstep/library-go/logger" "github.com/tickstep/library-go/requester" "os" + "path" "path/filepath" "runtime" "strings" @@ -31,6 +33,8 @@ import ( ) const ( + // EnvDownloadDir 配置下载环境变量 + EnvDownloadDir = "ALIYUNPAN_DOWNLOAD_DIR" // EnvVerbose 启用调试环境变量 EnvVerbose = "ALIYUNPAN_VERBOSE" // EnvConfigDir 配置路径环境变量 @@ -283,22 +287,7 @@ func (c *PanConfig) loadConfigFromFile() (err error) { } func (c *PanConfig) initDefaultConfig() { - // 设置默认的下载路径 - switch runtime.GOOS { - case "windows": - c.SaveDir = cmdutil.ExecutablePathJoin("Downloads") - case "android": - // TODO: 获取完整的的下载路径 - c.SaveDir = "/sdcard/Download" - default: - dataPath, ok := os.LookupEnv("HOME") - if !ok { - CmdConfigVerbose.Warn("Environment HOME not set") - c.SaveDir = cmdutil.ExecutablePathJoin("Downloads") - } else { - c.SaveDir = filepath.Join(dataPath, "Downloads") - } - } + //c.SaveDir = GetDefaultDownloadDir() c.ConfigVer = ConfigVersion c.VideoFileExtensions = DefaultVideoFileExtensions c.DeviceId = RandomDeviceId() // 生成默认客户端ID @@ -311,7 +300,7 @@ func (c *PanConfig) initDefaultConfig() { // GetConfigDir 获取配置路径 func GetConfigDir() string { // 按照以下顺序依次获取配置目录 - // 1.环境变量ALIYUNPAN_CONFIG_DIR => 2. /etc/aliyunpan/ => 3. ~/.aliyunpan/ => 4.当前程序目录 + // 1.环境变量ALIYUNPAN_CONFIG_DIR => 2. XDG_CONFIG_HOME/aliyunpan => 3. /etc/aliyunpan/ => 4. ~/.aliyunpan/ => 5.当前程序目录 // 1. 从环境变量读取 configDir, ok := os.LookupEnv(EnvConfigDir) @@ -325,7 +314,14 @@ func GetConfigDir() string { logger.Verboseln("use config dir from ALIYUNPAN_CONFIG_DIR env: ", configDir) return configDir } else { - // 2. /etc/aliyunpan/ + // 2. $XDG_CONFIG_HOME/aliyunpan + xdgConfigHome := path.Join(xdg.ConfigHome, "aliyunpan") + if IsFolderExist(xdgConfigHome) { + logger.Verboseln("use XDG home config dir: ", xdgConfigHome) + return xdgConfigHome + } + + // 3. /etc/aliyunpan/ if runtime.GOOS == "linux" { cd := "/etc/aliyunpan" if IsFolderExist(cd) { @@ -334,7 +330,7 @@ func GetConfigDir() string { } } - // 3. ~/.aliyunpan/ + // 4. ~/.aliyunpan/ if runtime.GOOS == "linux" || runtime.GOOS == "windows" { cd, er := homedir.Expand("~/.aliyunpan") if er == nil { @@ -346,12 +342,55 @@ func GetConfigDir() string { } } - // 4.当前程序所在目录 + // 5.当前程序所在目录 configDir = cmdutil.ExecutablePathJoin("") logger.Verboseln("use config dir: ", configDir) return configDir } +// GetDefaultDownloadDir 获取默认的下载目录 +func GetDefaultDownloadDir() string { + // 按照以下顺序依次获取下载目录 + // 1.环境变量ALIYUNPAN_DOWNLOAD_DIR => 2. XDG_DOWNLOAD_DIR目录 => 3. (当前程序目录)/Downloads + + downloadDir := "" + // 设置默认的下载路径 + switch runtime.GOOS { + case "android": + // TODO: 获取完整的的下载路径 + downloadDir = "/sdcard/Download" + return downloadDir + default: + // 1. 环境变量ALIYUNPAN_DOWNLOAD_DIR + d, ok := os.LookupEnv(EnvDownloadDir) + if ok { + logger.Verboseln("use download dir from ALIYUNPAN_DOWNLOAD_DIR env: ", d) + downloadDir = d + return downloadDir + } else { + // 2. $XDG_DOWNLOAD_DIR + xdgDownloadDir := path.Join(xdg.UserDirs.Download) + if IsFolderExist(xdgDownloadDir) { + logger.Verboseln("use XDG download dir: ", xdgDownloadDir) + return xdgDownloadDir + } + } + } + + // 3. (当前程序目录)/Downloads + downloadDir = cmdutil.ExecutablePathJoin("Downloads") + logger.Verboseln("use default download dir: ", downloadDir) + return downloadDir +} + +// GetDownloadDir 获取当前下载目录 +func GetDownloadDir() string { + if Config.SaveDir == "" { + return GetDefaultDownloadDir() + } + return Config.SaveDir +} + // GetPluginDir 获取插件文件夹路径 func GetPluginDir() string { return strings.TrimSuffix(GetConfigDir(), "/") + "/plugin" diff --git a/internal/config/pan_config_export.go b/internal/config/pan_config_export.go index 4545f83..ac3a3c9 100644 --- a/internal/config/pan_config_export.go +++ b/internal/config/pan_config_export.go @@ -113,7 +113,7 @@ func (c *PanConfig) PrintTable() { []string{"max_upload_parallel", strconv.Itoa(c.MaxUploadParallel), "1 ~ 20", "最大上传并发量,即同时上传文件最大数量"}, []string{"max_download_rate", showMaxRate(c.MaxDownloadRate), "", "限制单个文件最大下载速度, 0代表不限制"}, []string{"max_upload_rate", showMaxRate(c.MaxUploadRate), "", "限制单个文件最大上传速度, 0代表不限制"}, - []string{"savedir", c.SaveDir, "", "下载文件的储存目录"}, + []string{"savedir", GetDownloadDir(), "", "下载文件的储存目录"}, []string{"proxy", c.Proxy, "", "设置代理, 支持 http/socks5 代理,例如: http://127.0.0.1:8888 或者 socks5://127.0.0.1:8889"}, []string{"local_addrs", c.LocalAddrs, "", "绑定本地网卡地址, 多个地址用逗号隔开,支持网口名称,例如: 127.0.0.1,192.168.100.126,en0,eth0"}, []string{"ip_type", c.PreferIPType, "ipv4-优先IPv4,ipv6-优先IPv6", "设置域名解析IP优先类型。修改后需要重启应用生效"}, diff --git a/internal/config/pan_user.go b/internal/config/pan_user.go index 02e3d97..6dbed33 100644 --- a/internal/config/pan_user.go +++ b/internal/config/pan_user.go @@ -332,7 +332,7 @@ func (pu *PanUser) FreshWorkdirInfo() { // GetSavePath 根据提供的网盘文件路径 panpath, 返回本地储存路径, // 返回绝对路径, 获取绝对路径出错时才返回相对路径... func (pu *PanUser) GetSavePath(filePanPath string) string { - dirStr := filepath.Join(Config.SaveDir, fmt.Sprintf("%s", pu.UserId), filePanPath) + dirStr := filepath.Join(GetDownloadDir(), fmt.Sprintf("%s", pu.UserId), filePanPath) dir, err := filepath.Abs(dirStr) if err != nil { dir = filepath.Clean(dirStr)