settings.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package settings
  2. import (
  3. "net/url"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "sync"
  8. "github.com/allanpk716/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. }
  49. })
  50. // 是否需要重新读取配置信息,这个可能在每次保存配置文件后需要操作
  51. if len(reloadSettings) >= 1 {
  52. if reloadSettings[0] == true {
  53. err := _settings.read()
  54. if err != nil {
  55. panic("Can't Read Config File:" + configName + " Error: " + err.Error())
  56. }
  57. }
  58. }
  59. }
  60. return _settings
  61. }
  62. // SetFullNewSettings 从 Web 端传入新的 Settings 完整设置
  63. func SetFullNewSettings(inSettings *Settings) error {
  64. _settingsLocker.Lock()
  65. defer _settingsLocker.Unlock()
  66. // 保存前进行本地代理的关闭
  67. err := _settings.AdvancedSettings.ProxySettings.CloseLocalHttpProxyServer()
  68. if err != nil {
  69. return err
  70. }
  71. nowConfigFPath := _settings.configFPath
  72. _settings = inSettings
  73. _settings.configFPath = nowConfigFPath
  74. return _settings.Save()
  75. }
  76. // SetConfigRootPath 需要先设置这个信息再调用 Get
  77. func SetConfigRootPath(configRootPath string) {
  78. _configRootPath = configRootPath
  79. }
  80. func NewSettings(configRootDirFPath string) *Settings {
  81. nowConfigFPath := filepath.Join(configRootDirFPath, configName)
  82. return &Settings{
  83. configFPath: nowConfigFPath,
  84. UserInfo: &UserInfo{},
  85. CommonSettings: NewCommonSettings(),
  86. SubtitleSources: NewSubtitleSources(),
  87. AdvancedSettings: NewAdvancedSettings(),
  88. EmbySettings: NewEmbySettings(),
  89. DeveloperSettings: NewDeveloperSettings(),
  90. TimelineFixerSettings: NewTimelineFixerSettings(),
  91. ExperimentalFunction: NewExperimentalFunction(),
  92. }
  93. }
  94. func (s *Settings) read() error {
  95. // 需要检查 url 是否正确
  96. newEmbyAddressUrl := removeSuffixAddressSlash(s.EmbySettings.AddressUrl)
  97. _, err := url.Parse(newEmbyAddressUrl)
  98. if err != nil {
  99. return err
  100. }
  101. // 因为是重新加载配置文件信息,所以需要考虑提前关闭之前开启的本地代理
  102. err = s.AdvancedSettings.ProxySettings.CloseLocalHttpProxyServer()
  103. if err != nil {
  104. return err
  105. }
  106. err = strcut_json.ToStruct(s.configFPath, s)
  107. if err != nil {
  108. return err
  109. }
  110. s.EmbySettings.AddressUrl = newEmbyAddressUrl
  111. return nil
  112. }
  113. func (s *Settings) Save() error {
  114. // 需要检查 url 是否正确
  115. newEmbyAddressUrl := removeSuffixAddressSlash(s.EmbySettings.AddressUrl)
  116. _, err := url.Parse(newEmbyAddressUrl)
  117. if err != nil {
  118. return err
  119. }
  120. err = s.AdvancedSettings.ProxySettings.CloseLocalHttpProxyServer()
  121. if err != nil {
  122. return err
  123. }
  124. s.EmbySettings.AddressUrl = newEmbyAddressUrl
  125. return strcut_json.ToFile(s.configFPath, s)
  126. }
  127. func (s *Settings) GetNoPasswordSettings() *Settings {
  128. nowSettings := NewSettings(_configRootPath)
  129. err := nowSettings.read()
  130. if err != nil {
  131. panic("Can't Read Config File:" + configName + " Error: " + err.Error())
  132. }
  133. // 需要关闭本地代理的实例,否则无法进行 clone 操作
  134. //_ = s.AdvancedSettings.ProxySettings.CloseLocalHttpProxyServer()
  135. //nowSettings := clone.Clone(s).(*Settings)
  136. nowSettings.UserInfo.Password = noPassword4Show
  137. return nowSettings
  138. }
  139. // Check 检测,某些参数有范围限制
  140. func (s *Settings) Check() {
  141. // 每个网站最多找 Top 几的字幕结果,评价系统成熟后,才有设计的意义
  142. if s.AdvancedSettings.Topic < 0 || s.AdvancedSettings.Topic > 3 {
  143. s.AdvancedSettings.Topic = 1
  144. }
  145. // 如果 Debug 模式开启了,强制设置线程数为1,方便定位问题
  146. if s.AdvancedSettings.DebugMode == true {
  147. s.CommonSettings.Threads = 1
  148. } else {
  149. // 并发线程的范围控制
  150. if s.CommonSettings.Threads <= 0 || s.CommonSettings.Threads > 6 {
  151. s.CommonSettings.Threads = 6
  152. }
  153. }
  154. }
  155. // isDir 存在且是文件夹
  156. func isDir(path string) bool {
  157. s, err := os.Stat(path)
  158. if err != nil {
  159. return false
  160. }
  161. return s.IsDir()
  162. }
  163. // isFile 存在且是文件
  164. func isFile(filePath string) bool {
  165. s, err := os.Stat(filePath)
  166. if err != nil {
  167. return false
  168. }
  169. return !s.IsDir()
  170. }
  171. // 将字符串后面最后一个字符,如果是 / 那么则替换掉,多个也会
  172. func removeSuffixAddressSlash(orgAddressUrlString string) string {
  173. outString := orgAddressUrlString
  174. for {
  175. if strings.HasSuffix(outString, "/") == true {
  176. outString = outString[:len(outString)-1]
  177. } else {
  178. break
  179. }
  180. }
  181. return outString
  182. }
  183. var (
  184. _settings *Settings
  185. _settingsLocker sync.Mutex
  186. _settingsOnce sync.Once
  187. _configRootPath string
  188. )
  189. const (
  190. noPassword4Show = "******" // 填充使用
  191. configName = "ChineseSubFinderSettings.json"
  192. )