settings.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package settings
  2. import (
  3. "net/url"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "sync"
  8. "github.com/ChineseSubFinder/ChineseSubFinder/pkg/strcut_json"
  9. )
  10. type Settings struct {
  11. SpeedDevMode bool // 是否为开发模式,代码开启这个会跳过某些流程,加快测试速度
  12. configFPath string
  13. UserInfo *UserInfo `json:"user_info"`
  14. CommonSettings *CommonSettings `json:"common_settings"`
  15. SubtitleSources *SubtitleSources `json:"subtitle_sources"`
  16. AdvancedSettings *AdvancedSettings `json:"advanced_settings"`
  17. EmbySettings *EmbySettings `json:"emby_settings"`
  18. DeveloperSettings *DeveloperSettings `json:"developer_settings"`
  19. TimelineFixerSettings *TimelineFixerSettings `json:"timeline_fixer_settings"`
  20. ExperimentalFunction *ExperimentalFunction `json:"experimental_function"`
  21. }
  22. // Get 获取 Settings 的实例
  23. func Get(reloadSettings ...bool) *Settings {
  24. _settingsLocker.Lock()
  25. defer _settingsLocker.Unlock()
  26. if _settings == nil {
  27. _settingsOnce.Do(func() {
  28. if _configRootPath == "" {
  29. panic("请先调用 SetConfigRootPath 设置配置文件的根目录")
  30. }
  31. _settings = NewSettings(_configRootPath)
  32. if isFile(_settings.configFPath) == false {
  33. err := os.MkdirAll(filepath.Dir(_settings.configFPath), os.ModePerm)
  34. if err != nil {
  35. panic("创建配置文件目录失败," + err.Error())
  36. }
  37. // 配置文件不存在,新建一个空白的
  38. err = _settings.Save()
  39. if err != nil {
  40. panic("Can't Save Config File:" + configName + " Error: " + err.Error())
  41. }
  42. } else {
  43. // 读取存在的文件
  44. err := _settings.read()
  45. if err != nil {
  46. panic("Can't Read Config File:" + configName + " Error: " + err.Error())
  47. }
  48. // 因为 SuppliersSettings 中每个网站的 searchUrl 参数没有开放更改,所以如果有变动,需要重新设置
  49. _settings.AdvancedSettings.SuppliersSettings.ReSetSearchUrl()
  50. }
  51. })
  52. // 是否需要重新读取配置信息,这个可能在每次保存配置文件后需要操作
  53. if len(reloadSettings) >= 1 {
  54. if reloadSettings[0] == true {
  55. err := _settings.read()
  56. if err != nil {
  57. panic("Can't Read Config File:" + configName + " Error: " + err.Error())
  58. }
  59. }
  60. }
  61. }
  62. return _settings
  63. }
  64. // SetFullNewSettings 从 Web 端传入新的 Settings 完整设置
  65. func SetFullNewSettings(inSettings *Settings) error {
  66. _settingsLocker.Lock()
  67. defer _settingsLocker.Unlock()
  68. nowConfigFPath := _settings.configFPath
  69. _settings = inSettings
  70. _settings.configFPath = nowConfigFPath
  71. return _settings.Save()
  72. }
  73. // SetConfigRootPath 需要先设置这个信息再调用 Get
  74. func SetConfigRootPath(configRootPath string) {
  75. _configRootPath = configRootPath
  76. }
  77. func NewSettings(configRootDirFPath string) *Settings {
  78. nowConfigFPath := filepath.Join(configRootDirFPath, configName)
  79. return &Settings{
  80. configFPath: nowConfigFPath,
  81. UserInfo: &UserInfo{},
  82. CommonSettings: NewCommonSettings(),
  83. SubtitleSources: NewSubtitleSources(),
  84. AdvancedSettings: NewAdvancedSettings(),
  85. EmbySettings: NewEmbySettings(),
  86. DeveloperSettings: NewDeveloperSettings(),
  87. TimelineFixerSettings: NewTimelineFixerSettings(),
  88. ExperimentalFunction: NewExperimentalFunction(),
  89. }
  90. }
  91. func (s *Settings) read() error {
  92. err := strcut_json.ToStruct(s.configFPath, s)
  93. if err != nil {
  94. return err
  95. }
  96. // 需要检查 url 是否正确
  97. newEmbyAddressUrl := removeSuffixAddressSlash(s.EmbySettings.AddressUrl)
  98. _, err = url.Parse(newEmbyAddressUrl)
  99. if err != nil {
  100. return err
  101. }
  102. s.EmbySettings.AddressUrl = newEmbyAddressUrl
  103. return nil
  104. }
  105. func (s *Settings) Save() error {
  106. // 需要检查 url 是否正确
  107. newEmbyAddressUrl := removeSuffixAddressSlash(s.EmbySettings.AddressUrl)
  108. _, err := url.Parse(newEmbyAddressUrl)
  109. if err != nil {
  110. return err
  111. }
  112. s.EmbySettings.AddressUrl = newEmbyAddressUrl
  113. return strcut_json.ToFile(s.configFPath, s)
  114. }
  115. func (s *Settings) GetNoPasswordSettings() *Settings {
  116. nowSettings := NewSettings(_configRootPath)
  117. err := nowSettings.read()
  118. if err != nil {
  119. panic("Can't Read Config File:" + configName + " Error: " + err.Error())
  120. }
  121. // 需要关闭本地代理的实例,否则无法进行 clone 操作
  122. //_ = s.AdvancedSettings.ProxySettings.CloseLocalHttpProxyServer()
  123. //nowSettings := clone.Clone(s).(*Settings)
  124. nowSettings.UserInfo.Password = noPassword4Show
  125. return nowSettings
  126. }
  127. // Check 检测,某些参数有范围限制
  128. func (s *Settings) Check() {
  129. // 每个网站最多找 Top 几的字幕结果,评价系统成熟后,才有设计的意义
  130. if s.AdvancedSettings.Topic < 0 || s.AdvancedSettings.Topic > 3 {
  131. s.AdvancedSettings.Topic = 1
  132. }
  133. // 如果 Debug 模式开启了,强制设置线程数为1,方便定位问题
  134. if s.AdvancedSettings.DebugMode == true {
  135. s.CommonSettings.Threads = 1
  136. } else {
  137. // 并发线程的范围控制
  138. if s.CommonSettings.Threads <= 0 || s.CommonSettings.Threads > 6 {
  139. s.CommonSettings.Threads = 6
  140. }
  141. }
  142. // 这里需要做一次 Default 的检查,因为有设置会被改写低于预期,至少要在 Default 之上
  143. s.AdvancedSettings.TaskQueue.Check()
  144. s.AdvancedSettings.DownloadFileCache.Check()
  145. }
  146. // isDir 存在且是文件夹
  147. func isDir(path string) bool {
  148. s, err := os.Stat(path)
  149. if err != nil {
  150. return false
  151. }
  152. return s.IsDir()
  153. }
  154. // isFile 存在且是文件
  155. func isFile(filePath string) bool {
  156. s, err := os.Stat(filePath)
  157. if err != nil {
  158. return false
  159. }
  160. return !s.IsDir()
  161. }
  162. // 将字符串后面最后一个字符,如果是 / 那么则替换掉,多个也会
  163. func removeSuffixAddressSlash(orgAddressUrlString string) string {
  164. outString := orgAddressUrlString
  165. for {
  166. if strings.HasSuffix(outString, "/") == true {
  167. outString = outString[:len(outString)-1]
  168. } else {
  169. break
  170. }
  171. }
  172. return outString
  173. }
  174. var (
  175. _settings *Settings
  176. _settingsLocker sync.Mutex
  177. _settingsOnce sync.Once
  178. _configRootPath string
  179. )
  180. const (
  181. noPassword4Show = "******" // 填充使用
  182. configName = "ChineseSubFinderSettings.json"
  183. )