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