decode.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package model
  2. import (
  3. "errors"
  4. "github.com/allanpk716/ChineseSubFinder/common"
  5. "github.com/beevik/etree"
  6. PTN "github.com/middelink/go-parse-torrent-name"
  7. "io/ioutil"
  8. "os"
  9. "path/filepath"
  10. "regexp"
  11. "strconv"
  12. "strings"
  13. )
  14. func getImdbAndYearMovieXml(movieFilePath string) (common.VideoInfo, error) {
  15. videoInfo := common.VideoInfo{}
  16. doc := etree.NewDocument()
  17. if err := doc.ReadFromFile(movieFilePath); err != nil {
  18. return videoInfo, err
  19. }
  20. for _, t := range doc.FindElements("//IMDB") {
  21. videoInfo.ImdbId = t.Text()
  22. break
  23. }
  24. for _, t := range doc.FindElements("//ProductionYear") {
  25. videoInfo.Year = t.Text()
  26. break
  27. }
  28. if videoInfo.ImdbId != "" {
  29. return videoInfo, nil
  30. }
  31. return videoInfo, common.CanNotFindIMDBID
  32. }
  33. func getImdbAndYearNfo(nfoFilePath string) (common.VideoInfo, error) {
  34. // TODO 新增 TVDB ID 的读取
  35. imdbInfo := common.VideoInfo{}
  36. doc := etree.NewDocument()
  37. // 这里会遇到一个梗,下面的关键词,可能是小写、大写、首字母大写
  38. // 读取文件转换为全部的小写,然后在解析 xml ? etree 在转换为小写后,某些类型的文件的内容会崩溃···
  39. // 所以这里很傻的方式解决
  40. err := doc.ReadFromFile(nfoFilePath)
  41. if err != nil {
  42. return imdbInfo, err
  43. }
  44. for _, t := range doc.FindElements("//uniqueid[@type='imdb']") {
  45. imdbInfo.ImdbId = t.Text()
  46. break
  47. }
  48. for _, t := range doc.FindElements("//uniqueid[@type='Imdb']") {
  49. imdbInfo.ImdbId = t.Text()
  50. break
  51. }
  52. for _, t := range doc.FindElements("//uniqueid[@type='IMDB']") {
  53. imdbInfo.ImdbId = t.Text()
  54. break
  55. }
  56. for _, t := range doc.FindElements("./movie/year") {
  57. imdbInfo.Year = t.Text()
  58. break
  59. }
  60. if imdbInfo.ImdbId != "" {
  61. return imdbInfo, nil
  62. }
  63. return imdbInfo, common.CanNotFindIMDBID
  64. }
  65. func GetImdbInfo(dirPth string) (common.VideoInfo, error) {
  66. imdbInfo := common.VideoInfo{}
  67. dir, err := ioutil.ReadDir(dirPth)
  68. if err != nil {
  69. return imdbInfo, err
  70. }
  71. pathSep := string(os.PathSeparator)
  72. // 优先找 movie.xml 这个是 raddarr 下载的电影会存下来的,可以在 Metadata 设置 Emby
  73. var movieFilePath = ""
  74. // 这个是使用 tinyMediaManager 削刮器按 Kodi 来存储的
  75. var nfoFilePath = ""
  76. for _, fi := range dir {
  77. if fi.IsDir() == true {
  78. continue
  79. }
  80. upperName := strings.ToUpper(fi.Name())
  81. // 找 movie.xml
  82. if upperName == strings.ToUpper(metadataFileEmby) {
  83. movieFilePath = dirPth + pathSep + fi.Name()
  84. }
  85. // 找 *.nfo
  86. ok := strings.HasSuffix(fi.Name(), suffixNameNfo)
  87. if ok {
  88. nfoFilePath = dirPth + pathSep + fi.Name()
  89. }
  90. }
  91. // 根据找到的开始解析
  92. if movieFilePath == "" && nfoFilePath == "" {
  93. return imdbInfo, common.NoMetadataFile
  94. }
  95. if movieFilePath != "" {
  96. imdbInfo, err = getImdbAndYearMovieXml(movieFilePath)
  97. if err != nil {
  98. GetLogger().Errorln("getImdbAndYearMovieXml error, move on:", err)
  99. } else {
  100. return imdbInfo, nil
  101. }
  102. }
  103. if nfoFilePath != "" {
  104. imdbInfo, err = getImdbAndYearNfo(nfoFilePath)
  105. if err != nil {
  106. return imdbInfo, err
  107. } else {
  108. return imdbInfo, nil
  109. }
  110. }
  111. return imdbInfo, common.CanNotFindIMDBID
  112. }
  113. //GetVideoInfoFromFileName 从文件名推断视频文件的信息
  114. func GetVideoInfoFromFileName(videoFileName string) (*PTN.TorrentInfo, error) {
  115. parse, err := PTN.Parse(filepath.Base(videoFileName))
  116. if err != nil {
  117. return nil, err
  118. }
  119. compile, err := regexp.Compile(regFixTitle2)
  120. if err != nil {
  121. return nil, err
  122. }
  123. match := compile.ReplaceAllString(parse.Title, "")
  124. match = strings.TrimRight(match, "")
  125. parse.Title = match
  126. return parse, nil
  127. }
  128. func GetNumber2Float(input string) (float32, error) {
  129. compile := regexp.MustCompile(regGetNumber)
  130. params := compile.FindStringSubmatch(input)
  131. if len(params) == 0 {
  132. return 0, errors.New("get number not match")
  133. }
  134. fNum, err := strconv.ParseFloat(params[0],32)
  135. if err != nil {
  136. return 0, errors.New("get number ParseFloat error")
  137. }
  138. return float32(fNum), nil
  139. }
  140. func GetNumber2int(input string) (int, error) {
  141. compile := regexp.MustCompile(regGetNumber)
  142. params := compile.FindStringSubmatch(input)
  143. if len(params) == 0 {
  144. return 0, errors.New("get number not match")
  145. }
  146. fNum, err := strconv.Atoi(params[0])
  147. if err != nil {
  148. return 0, errors.New("get number ParseFloat error")
  149. }
  150. return fNum, nil
  151. }
  152. const (
  153. metadataFileEmby = "movie.xml"
  154. suffixNameXml = ".xml"
  155. suffixNameNfo = ".nfo"
  156. // 去除特殊字符,仅仅之有中文
  157. regFixTitle = "[^\u4e00-\u9fa5a-zA-Z0-9\\s]"
  158. // 去除特殊字符,把特殊字符都写进去
  159. regFixTitle2 = "[`~!@#$%^&*()+-=|{}';'\\[\\].<>/?~!@#¥%……&*()——+|{}【】';”“’。、?]"
  160. // 获取数字
  161. regGetNumber = "(?:\\-)?\\d{1,}(?:\\.\\d{1,})?"
  162. )