folder.go 10 KB

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