github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/internal/pcsconfig/pcsconfig.go (about) 1 // Package pcsconfig 配置包 2 package pcsconfig 3 4 import ( 5 "github.com/json-iterator/go" 6 "github.com/qjfoidnh/BaiduPCS-Go/baidupcs" 7 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil" 8 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/jsonhelper" 9 "github.com/qjfoidnh/BaiduPCS-Go/pcsverbose" 10 "github.com/qjfoidnh/BaiduPCS-Go/requester" 11 "os" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "sync" 16 ) 17 18 const ( 19 // EnvConfigDir 配置路径环境变量 20 EnvConfigDir = "BAIDUPCS_GO_CONFIG_DIR" 21 // ConfigName 配置文件名 22 ConfigName = "pcs_config.json" 23 ) 24 25 var ( 26 pcsConfigVerbose = pcsverbose.New("PCSCONFIG") 27 configFilePath = filepath.Join(GetConfigDir(), ConfigName) 28 29 // Config 配置信息, 由外部调用 30 Config = NewConfig(configFilePath) 31 ) 32 33 // PCSConfig 配置详情 34 type PCSConfig struct { 35 BaiduActiveUID uint64 `json:"baidu_active_uid"` 36 BaiduUserList BaiduUserList `json:"baidu_user_list"` 37 38 AppID int `json:"appid"` // appid 39 40 CacheSize int `json:"cache_size"` // 下载缓存 41 MaxParallel int `json:"max_parallel"` // 最大下载并发量 42 MaxUploadParallel int `json:"max_upload_parallel"` // 最大上传并发量 43 MaxDownloadLoad int `json:"max_download_load"` // 同时进行下载文件的最大数量 44 MaxUploadLoad int `json:"max_upload_load"` // 同时进行上传文件的最大数量 45 46 MaxDownloadRate int64 `json:"max_download_rate"` // 限制最大下载速度 47 MaxUploadRate int64 `json:"max_upload_rate"` // 限制最大上传速度 48 49 UserAgent string `json:"user_agent"` // 浏览器标识 50 PCSUA string `json:"pcs_ua"` // PCS浏览器标识 51 PCSAddr string `json:"pcs_addr"` // PCS服务器域名 52 PanUA string `json:"pan_ua"` // PAN浏览器标识 53 SaveDir string `json:"savedir"` // 下载储存路径 54 EnableHTTPS bool `json:"enable_https"` // 启用https 55 ForceLogin string `json:"force_login_username"` // 强制登录 56 Proxy string `json:"proxy"` // 代理 57 LocalAddrs string `json:"local_addrs"` // 本地网卡地址 58 NoCheck bool `json:"no_check"` // 禁用下载md5校验 59 IgnoreIllegal bool `json:"ignore_illegal"` // 禁用上传文件名非法字符检查 60 UPolicy string `json:"u_policy"` // 上传重名文件处理策略 61 62 configFilePath string 63 configFile *os.File 64 fileMu sync.Mutex 65 activeUser *Baidu 66 pcs *baidupcs.BaiduPCS 67 } 68 69 // NewConfig 返回 PCSConfig 指针对象 70 func NewConfig(configFilePath string) *PCSConfig { 71 c := &PCSConfig{ 72 configFilePath: configFilePath, 73 } 74 return c 75 } 76 77 // Init 初始化配置 78 func (c *PCSConfig) Init() error { 79 return c.init() 80 } 81 82 // Reload 从文件重载配置 83 func (c *PCSConfig) Reload() error { 84 return c.init() 85 } 86 87 // Close 关闭配置文件 88 func (c *PCSConfig) Close() error { 89 if c.configFile != nil { 90 err := c.configFile.Close() 91 c.configFile = nil 92 return err 93 } 94 return nil 95 } 96 97 // Save 保存配置信息到配置文件 98 func (c *PCSConfig) Save() error { 99 // 检测配置项是否合法, 不合法则自动修复 100 c.fix() 101 102 err := c.lazyOpenConfigFile() 103 if err != nil { 104 return err 105 } 106 107 c.fileMu.Lock() 108 defer c.fileMu.Unlock() 109 110 data, err := jsoniter.MarshalIndent(c, "", " ") 111 if err != nil { 112 // json数据生成失败 113 panic(err) 114 } 115 116 // 减掉多余的部分 117 err = c.configFile.Truncate(int64(len(data))) 118 if err != nil { 119 return err 120 } 121 122 _, err = c.configFile.Seek(0, os.SEEK_SET) 123 if err != nil { 124 return err 125 } 126 127 _, err = c.configFile.Write(data) 128 if err != nil { 129 return err 130 } 131 132 return nil 133 } 134 135 func (c *PCSConfig) init() error { 136 if c.configFilePath == "" { 137 return ErrConfigFileNotExist 138 } 139 140 c.InitDefaultConfig() 141 err := c.loadConfigFromFile() 142 if err != nil { 143 return err 144 } 145 146 // 载入配置 147 // 如果 activeUser 已初始化, 则跳过 148 if c.activeUser != nil && c.activeUser.UID == c.BaiduActiveUID { 149 return nil 150 } 151 152 c.activeUser, err = c.GetBaiduUser(&BaiduBase{ 153 UID: c.BaiduActiveUID, 154 }) 155 if err != nil { 156 return err 157 } 158 c.pcs = c.activeUser.BaiduPCS() 159 c.pcs.SetPCSAddr(c.PCSAddr) 160 161 // 设置全局User-Agent 162 requester.UserAgent = c.UserAgent 163 // 设置全局代理 164 requester.SetGlobalProxy(c.Proxy) 165 // 设置本地网卡地址 166 requester.SetLocalTCPAddrList(strings.Split(c.LocalAddrs, ",")...) 167 168 return nil 169 } 170 171 // lazyOpenConfigFile 打开配置文件 172 func (c *PCSConfig) lazyOpenConfigFile() (err error) { 173 if c.configFile != nil { 174 return nil 175 } 176 177 c.fileMu.Lock() 178 os.MkdirAll(filepath.Dir(c.configFilePath), 0700) 179 c.configFile, err = os.OpenFile(c.configFilePath, os.O_CREATE|os.O_RDWR, 0600) 180 c.fileMu.Unlock() 181 182 if err != nil { 183 if os.IsPermission(err) { 184 return ErrConfigFileNoPermission 185 } 186 if os.IsExist(err) { 187 return ErrConfigFileNotExist 188 } 189 return err 190 } 191 return nil 192 } 193 194 // loadConfigFromFile 载入配置 195 func (c *PCSConfig) loadConfigFromFile() (err error) { 196 err = c.lazyOpenConfigFile() 197 if err != nil { 198 return err 199 } 200 201 // 未初始化 202 info, err := c.configFile.Stat() 203 if err != nil { 204 return err 205 } 206 207 if info.Size() == 0 { 208 err = c.Save() 209 return err 210 } 211 212 c.fileMu.Lock() 213 defer c.fileMu.Unlock() 214 215 _, err = c.configFile.Seek(0, os.SEEK_SET) 216 if err != nil { 217 return err 218 } 219 220 err = jsonhelper.UnmarshalData(c.configFile, c) 221 if err != nil { 222 return ErrConfigContentsParseError 223 } 224 return nil 225 } 226 227 func (c *PCSConfig) InitDefaultConfig() { 228 c.AppID = 266719 229 c.CacheSize = 65536 230 c.MaxParallel = 1 231 c.MaxUploadParallel = 4 232 c.MaxUploadLoad = 4 233 c.MaxDownloadLoad = 1 234 c.UserAgent = requester.UserAgent 235 c.PCSUA = "" 236 c.PCSAddr = "pcs.baidu.com" 237 c.PanUA = baidupcs.NetdiskUA 238 c.EnableHTTPS = true 239 c.NoCheck = true 240 c.UPolicy = "fail" 241 242 // 设置默认的下载路径 243 switch runtime.GOOS { 244 case "windows": 245 c.SaveDir = pcsutil.ExecutablePathJoin("Downloads") 246 case "android": 247 // TODO: 获取完整的的下载路径 248 c.SaveDir = "/sdcard/Download" 249 default: 250 dataPath, ok := os.LookupEnv("HOME") 251 if !ok { 252 pcsConfigVerbose.Warn("Environment HOME not set") 253 c.SaveDir = pcsutil.ExecutablePathJoin("Downloads") 254 } else { 255 c.SaveDir = filepath.Join(dataPath, "Downloads") 256 } 257 } 258 } 259 260 // GetConfigDir 获取配置路径 261 func GetConfigDir() string { 262 // 从环境变量读取 263 configDir, ok := os.LookupEnv(EnvConfigDir) 264 if ok { 265 if filepath.IsAbs(configDir) { 266 return configDir 267 } 268 // 如果不是绝对路径, 从程序目录寻找 269 return pcsutil.ExecutablePathJoin(configDir) 270 } 271 272 // 使用旧版 273 // 如果旧版的配置文件存在, 则使用旧版 274 oldConfigDir := pcsutil.ExecutablePath() 275 _, err := os.Stat(filepath.Join(oldConfigDir, ConfigName)) 276 if err == nil { 277 return oldConfigDir 278 } 279 280 switch runtime.GOOS { 281 case "windows": 282 dataPath, ok := os.LookupEnv("APPDATA") 283 if !ok { 284 pcsConfigVerbose.Warn("Environment APPDATA not set") 285 return oldConfigDir 286 } 287 return filepath.Join(dataPath, "BaiduPCS-Go") 288 default: 289 dataPath, ok := os.LookupEnv("HOME") 290 if !ok { 291 pcsConfigVerbose.Warn("Environment HOME not set") 292 return oldConfigDir 293 } 294 configDir = filepath.Join(dataPath, ".config", "BaiduPCS-Go") 295 296 // 检测是否可写 297 err = os.MkdirAll(configDir, 0700) 298 if err != nil { 299 pcsConfigVerbose.Warnf("check config dir error: %s\n", err) 300 return oldConfigDir 301 } 302 return configDir 303 } 304 } 305 306 func (c *PCSConfig) fix() { 307 if c.CacheSize < 1024 { 308 c.CacheSize = 1024 309 } 310 if c.MaxParallel < 1 { 311 c.MaxParallel = 1 312 } 313 if c.MaxUploadParallel < 1 { 314 c.MaxUploadParallel = 1 315 } 316 if c.MaxDownloadLoad < 1 { 317 c.MaxDownloadLoad = 1 318 } 319 if c.MaxUploadLoad < 1 { 320 c.MaxUploadLoad = 1 321 } 322 if c.UPolicy != "fail" && c.UPolicy != "newcopy" && c.UPolicy != "overwrite" && c.UPolicy != "skip" && c.UPolicy != "rsync" { 323 c.UPolicy = "fail" 324 } 325 }