folder.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. package my_util
  2. import (
  3. "github.com/allanpk716/ChineseSubFinder/internal/pkg/get_access_time"
  4. "github.com/allanpk716/ChineseSubFinder/internal/pkg/global_value"
  5. "github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
  6. "os"
  7. "path/filepath"
  8. "runtime"
  9. "time"
  10. )
  11. func init() {
  12. err := Init()
  13. if err != nil {
  14. log_helper.GetLogger().Panicln("my_util.Init", err)
  15. }
  16. }
  17. func Init() error {
  18. var err error
  19. global_value.ConfigRootDirFPath = GetConfigRootDirFPath()
  20. global_value.DefDebugFolder, err = GetRootDebugFolder()
  21. if err != nil {
  22. log_helper.GetLogger().Panicln("GetRootDebugFolder", err)
  23. }
  24. global_value.DefTmpFolder, err = GetRootTmpFolder()
  25. if err != nil {
  26. log_helper.GetLogger().Panicln("GetRootTmpFolder", err)
  27. }
  28. global_value.DefRodTmpRootFolder, err = GetRodTmpRootFolder()
  29. if err != nil {
  30. log_helper.GetLogger().Panicln("GetRodTmpRootFolder", err)
  31. }
  32. global_value.DefSubFixCacheFolder, err = GetRootSubFixCacheFolder()
  33. if err != nil {
  34. log_helper.GetLogger().Panicln("GetRootTmpFolder", err)
  35. }
  36. global_value.AdblockTmpFolder, err = GetPluginFolderByName(Plugin_Adblock)
  37. if err != nil {
  38. log_helper.GetLogger().Panicln("GetPluginFolderByName", Plugin_Adblock, err)
  39. }
  40. return nil
  41. }
  42. // --------------------------------------------------------------
  43. // Debug
  44. // --------------------------------------------------------------
  45. // GetRootDebugFolder 在程序的根目录新建,调试用文件夹
  46. func GetRootDebugFolder() (string, error) {
  47. nowProcessRoot, err := os.Getwd()
  48. if err != nil {
  49. return "", err
  50. }
  51. nowProcessRoot = filepath.Join(nowProcessRoot, cacheRootFolderName, DebugFolder)
  52. err = os.MkdirAll(nowProcessRoot, os.ModePerm)
  53. if err != nil {
  54. return "", err
  55. }
  56. return nowProcessRoot, err
  57. }
  58. // GetDebugFolderByName 根据传入的 strings (["aa", "bb"]) 组成 DebugFolder/aa/bb 这样的路径
  59. func GetDebugFolderByName(names []string) (string, error) {
  60. rootPath, err := GetRootDebugFolder()
  61. if err != nil {
  62. return "", err
  63. }
  64. tmpFolderFullPath := rootPath
  65. for _, name := range names {
  66. tmpFolderFullPath = filepath.Join(tmpFolderFullPath, name)
  67. }
  68. err = os.MkdirAll(tmpFolderFullPath, os.ModePerm)
  69. if err != nil {
  70. return "", err
  71. }
  72. return tmpFolderFullPath, nil
  73. }
  74. // CopyFiles2DebugFolder 把文件放入到 Debug 文件夹中,新建 desFolderName 文件夹
  75. func CopyFiles2DebugFolder(names []string, subFiles []string) error {
  76. debugFolderByName, err := GetDebugFolderByName(names)
  77. if err != nil {
  78. return err
  79. }
  80. // 复制下载在 tmp 文件夹中的字幕文件到视频文件夹下面
  81. for _, subFile := range subFiles {
  82. newFn := filepath.Join(debugFolderByName, filepath.Base(subFile))
  83. err = CopyFile(subFile, newFn)
  84. if err != nil {
  85. return err
  86. }
  87. }
  88. return nil
  89. }
  90. // --------------------------------------------------------------
  91. // Tmp
  92. // --------------------------------------------------------------
  93. // GetRootTmpFolder 在程序的根目录新建,取缓用文件夹,每一个视频的缓存将在其中额外新建子集文件夹
  94. func GetRootTmpFolder() (string, error) {
  95. nowProcessRoot, err := os.Getwd()
  96. if err != nil {
  97. return "", err
  98. }
  99. nowProcessRoot = filepath.Join(nowProcessRoot, cacheRootFolderName, TmpFolder)
  100. err = os.MkdirAll(nowProcessRoot, os.ModePerm)
  101. if err != nil {
  102. return "", err
  103. }
  104. return nowProcessRoot, err
  105. }
  106. // GetTmpFolderByName 获取缓存的文件夹,没有则新建
  107. func GetTmpFolderByName(folderName string) (string, error) {
  108. rootPath, err := GetRootTmpFolder()
  109. if err != nil {
  110. return "", err
  111. }
  112. tmpFolderFullPath := filepath.Join(rootPath, folderName)
  113. err = os.MkdirAll(tmpFolderFullPath, os.ModePerm)
  114. if err != nil {
  115. return "", err
  116. }
  117. return tmpFolderFullPath, nil
  118. }
  119. // ClearTmpFolderByName 清理指定的缓存文件夹
  120. func ClearTmpFolderByName(folderName string) error {
  121. nowTmpFolder, err := GetTmpFolderByName(folderName)
  122. if err != nil {
  123. return err
  124. }
  125. return ClearFolder(nowTmpFolder)
  126. }
  127. // ClearRootTmpFolder 清理缓存的根目录,将里面的子文件夹一并清理
  128. func ClearRootTmpFolder() error {
  129. nowTmpFolder, err := GetRootTmpFolder()
  130. if err != nil {
  131. return err
  132. }
  133. pathSep := string(os.PathSeparator)
  134. files, err := os.ReadDir(nowTmpFolder)
  135. if err != nil {
  136. return err
  137. }
  138. for _, curFile := range files {
  139. fullPath := nowTmpFolder + pathSep + curFile.Name()
  140. if curFile.IsDir() {
  141. err = os.RemoveAll(fullPath)
  142. if err != nil {
  143. return err
  144. }
  145. } else {
  146. // 这里就是文件了
  147. err = os.Remove(fullPath)
  148. if err != nil {
  149. return err
  150. }
  151. }
  152. }
  153. return nil
  154. }
  155. // --------------------------------------------------------------
  156. // Adblock Cache
  157. // --------------------------------------------------------------
  158. // GetPluginRootFolder 在程序的根目录新建,取缓用文件夹,每一个视频的缓存将在其中额外新建子集文件夹
  159. func GetPluginRootFolder() (string, error) {
  160. nowProcessRoot, err := os.Getwd()
  161. if err != nil {
  162. return "", err
  163. }
  164. nowProcessRoot = filepath.Join(nowProcessRoot, cacheRootFolderName, PluginFolder)
  165. err = os.MkdirAll(nowProcessRoot, os.ModePerm)
  166. if err != nil {
  167. return "", err
  168. }
  169. return nowProcessRoot, err
  170. }
  171. // GetPluginFolderByName 获取缓存的文件夹,没有则新建
  172. func GetPluginFolderByName(folderName string) (string, error) {
  173. rootPath, err := GetPluginRootFolder()
  174. if err != nil {
  175. return "", err
  176. }
  177. tmpFolderFullPath := filepath.Join(rootPath, folderName)
  178. err = os.MkdirAll(tmpFolderFullPath, os.ModePerm)
  179. if err != nil {
  180. return "", err
  181. }
  182. return tmpFolderFullPath, nil
  183. }
  184. // ClearPluginFolderByName 清理指定的缓存文件夹
  185. func ClearPluginFolderByName(folderName string) error {
  186. nowTmpFolder, err := GetPluginFolderByName(folderName)
  187. if err != nil {
  188. return err
  189. }
  190. return ClearFolder(nowTmpFolder)
  191. }
  192. // --------------------------------------------------------------
  193. // Rod Cache
  194. // --------------------------------------------------------------
  195. // GetRodTmpRootFolder 在程序的根目录新建,rod 缓存用文件夹
  196. func GetRodTmpRootFolder() (string, error) {
  197. nowProcessRoot, err := os.Getwd()
  198. if err != nil {
  199. return "", err
  200. }
  201. nowProcessRoot = filepath.Join(nowProcessRoot, cacheRootFolderName, RodCacheFolder)
  202. err = os.MkdirAll(nowProcessRoot, os.ModePerm)
  203. if err != nil {
  204. return "", err
  205. }
  206. return nowProcessRoot, err
  207. }
  208. // ClearRodTmpRootFolder 清理 rod 缓存文件夹
  209. func ClearRodTmpRootFolder() error {
  210. nowTmpFolder, err := GetRodTmpRootFolder()
  211. if err != nil {
  212. return err
  213. }
  214. pathSep := string(os.PathSeparator)
  215. files, err := os.ReadDir(nowTmpFolder)
  216. if err != nil {
  217. return err
  218. }
  219. for _, curFile := range files {
  220. fullPath := nowTmpFolder + pathSep + curFile.Name()
  221. if curFile.IsDir() {
  222. err = os.RemoveAll(fullPath)
  223. if err != nil {
  224. return err
  225. }
  226. } else {
  227. // 这里就是文件了
  228. err = os.Remove(fullPath)
  229. if err != nil {
  230. return err
  231. }
  232. }
  233. }
  234. return nil
  235. }
  236. // --------------------------------------------------------------
  237. // Sub Fix Cache
  238. // --------------------------------------------------------------
  239. // GetRootSubFixCacheFolder 在程序的根目录新建,字幕时间校正的缓存文件夹
  240. func GetRootSubFixCacheFolder() (string, error) {
  241. nowProcessRoot, err := os.Getwd()
  242. if err != nil {
  243. return "", err
  244. }
  245. nowProcessRoot = filepath.Join(nowProcessRoot, cacheRootFolderName, SubFixCacheFolder)
  246. err = os.MkdirAll(nowProcessRoot, os.ModePerm)
  247. if err != nil {
  248. return "", err
  249. }
  250. return nowProcessRoot, err
  251. }
  252. // GetSubFixCacheFolderByName 获取缓存的文件夹,没有则新建
  253. func GetSubFixCacheFolderByName(folderName string) (string, error) {
  254. rootPath, err := GetRootSubFixCacheFolder()
  255. if err != nil {
  256. return "", err
  257. }
  258. tmpFolderFullPath := filepath.Join(rootPath, folderName)
  259. err = os.MkdirAll(tmpFolderFullPath, os.ModePerm)
  260. if err != nil {
  261. return "", err
  262. }
  263. return tmpFolderFullPath, nil
  264. }
  265. // --------------------------------------------------------------
  266. // Common
  267. // --------------------------------------------------------------
  268. // ClearFolder 清空文件夹
  269. func ClearFolder(folderFullPath string) error {
  270. pathSep := string(os.PathSeparator)
  271. files, err := os.ReadDir(folderFullPath)
  272. if err != nil {
  273. return err
  274. }
  275. for _, curFile := range files {
  276. fullPath := folderFullPath + pathSep + curFile.Name()
  277. if curFile.IsDir() {
  278. err = os.RemoveAll(fullPath)
  279. if err != nil {
  280. return err
  281. }
  282. } else {
  283. // 这里就是文件了
  284. err = os.Remove(fullPath)
  285. if err != nil {
  286. return err
  287. }
  288. }
  289. }
  290. return nil
  291. }
  292. // GetConfigRootDirFPath 获取 Config 的根目录,不同系统不一样
  293. func GetConfigRootDirFPath() string {
  294. nowConfigFPath := ""
  295. sysType := runtime.GOOS
  296. if sysType == "linux" {
  297. nowConfigFPath = configDirRootFPathLinux
  298. } else if sysType == "windows" {
  299. nowConfigFPath = configDirRootFPathWindows
  300. } else if sysType == "darwin" {
  301. home, err := os.UserHomeDir()
  302. if err != nil {
  303. panic("GetConfigRootDirFPath darwin get UserHomeDir, Error:" + err.Error())
  304. }
  305. nowConfigFPath = home + configDirRootFPathDarwin
  306. } else {
  307. panic("GetConfigRootDirFPath can't matched OSType: " + sysType + " ,You Should Implement It Yourself")
  308. }
  309. return nowConfigFPath
  310. }
  311. // ClearIdleSubFixCacheFolder 清理闲置的字幕修正缓存文件夹
  312. func ClearIdleSubFixCacheFolder(rootSubFixCacheFolder string, outOfDate time.Duration) error {
  313. /*
  314. 从 GetRootSubFixCacheFolder 目录下,遍历第一级目录中的文件夹
  315. 然后每个文件夹中,统计里面最后的访问时间(可能有多个文件),如果超过某个时间范围就标记删除这个文件夹
  316. */
  317. pathSep := string(os.PathSeparator)
  318. files, err := os.ReadDir(rootSubFixCacheFolder)
  319. if err != nil {
  320. return err
  321. }
  322. wait2ScanFolder := make([]string, 0)
  323. for _, curFile := range files {
  324. fullPath := rootSubFixCacheFolder + pathSep + curFile.Name()
  325. if curFile.IsDir() == true {
  326. // 需要关注文件夹
  327. wait2ScanFolder = append(wait2ScanFolder, fullPath)
  328. }
  329. }
  330. wait2DeleteFolder := make([]string, 0)
  331. getAccessTimeEx := get_access_time.GetAccessTimeEx{}
  332. cutOff := time.Now().Add(-outOfDate)
  333. for _, s := range wait2ScanFolder {
  334. files, err = os.ReadDir(s)
  335. if err != nil {
  336. return err
  337. }
  338. maxAccessTime := time.Now()
  339. // 需要统计这个文件夹下的所有文件的 AccessTIme,找出最新(最大的值)的那个时间,再比较
  340. for i, curFile := range files {
  341. fullPath := s + pathSep + curFile.Name()
  342. if curFile.IsDir() == true {
  343. continue
  344. }
  345. // 只需要关注文件
  346. accessTime, err := getAccessTimeEx.GetAccessTime(fullPath)
  347. if err != nil {
  348. return err
  349. }
  350. if i == 0 {
  351. maxAccessTime = accessTime
  352. }
  353. if Time2SecondNumber(accessTime) > Time2SecondNumber(maxAccessTime) {
  354. maxAccessTime = accessTime
  355. }
  356. }
  357. if maxAccessTime.Sub(cutOff) <= 0 {
  358. // 确认可以删除
  359. wait2DeleteFolder = append(wait2DeleteFolder, s)
  360. }
  361. }
  362. // 统一清理过期的文件夹
  363. for _, s := range wait2DeleteFolder {
  364. log_helper.GetLogger().Infoln("Try 2 clear SubFixCache Folder:", s)
  365. err := os.RemoveAll(s)
  366. if err != nil {
  367. return err
  368. }
  369. }
  370. return nil
  371. }
  372. // 缓存文件的位置信息,都是在程序的根目录下的 cache 中
  373. const (
  374. cacheRootFolderName = "cache" // 缓存文件夹总名称
  375. TmpFolder = "tmp" // 临时缓存的文件夹
  376. RodCacheFolder = "rod" // rod 的缓存目录
  377. PluginFolder = "Plugin" // 插件的目录
  378. DebugFolder = "CSF-DebugThings" // 调试相关的文件夹
  379. SubFixCacheFolder = "CSF-SubFixCache" // 字幕时间校正的缓存文件夹,一般可以不清理
  380. )
  381. const (
  382. Plugin_Adblock = "adblock"
  383. )
  384. // 配置文件的位置信息,这个会根据系统版本做区分
  385. const (
  386. configDirRootFPathWindows = "." // Windows 就是在当前的程序目录
  387. configDirRootFPathLinux = "/config" // Linux 是在 /config 下
  388. configDirRootFPathDarwin = "/.config/chinesesubfinder" // Darwin 是在 os.UserHomeDir()/.config/chinesesubfinder/ 下
  389. )