Browse Source

first time

Signed-off-by: 716 <[email protected]>
716 4 years ago
commit
3fcd5e52fb
7 changed files with 203 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 29 0
      README.md
  3. 90 0
      common/decode.go
  4. 54 0
      common/decode_test.go
  5. 8 0
      common/selferr.go
  6. 5 0
      go.mod
  7. 16 0
      go.sum

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/.idea

+ 29 - 0
README.md

@@ -0,0 +1,29 @@
+# ChineseSubFinder
+
+本项目的初衷仅仅是想自动化搞定限定条件下中文字幕下载。
+
+> 开发中,会制作 Docker 镜像挂机用
+>
+
+## Why?
+
+注意,因为近期参考《[高阶教程-追剧全流程自动化 | sleele的博客](https://sleele.com/tag/高阶教程-追剧全流程自动化/)》搞定了自动下载,美剧、电影没啥问题。但是遇到字幕下载的困难,里面推荐的都不好用,能下载一部分,大部分都不行。当然有可能是个人的问题。为此就打算自己整一个专用的下载器。
+
+手动去下载再丢过去改名也不是不行,这不是懒嘛...
+
+首先,明确一点,因为搞定了 sonarr 和 raddarr 以及 Emby,同时部分手动下载的视频也会使用 tinyMediaManager 去处理,所以可以认为所有的视频是都有 IMDB ID 的。那么就可以取巧,用 IMDB ID 去搜索(最差也能用标准的视频文件名称去搜索嘛)。
+
+## 限定条件
+
+* 电影(暂时做这个类型,后续会考虑:连续剧、动画)
+* 只搜索中文字幕
+* 必要条件,视频文件经过削刮器处理
+* 搜索优先级
+
+  * 经过削刮器处理
+    1. 视频经过削刮器(tinyMediaManager、Emby)处理,视频同级目录有 *.nfo 文件(Kodi 格式的)
+    2. 使用 Raddarr 下载的电影, Metadata 设置 Emby,存在一个 movie.xml 文件
+    3. 以上两个文件任意一个能读取到 IMDB ID
+  * 通过视频文件的唯一ID(针对不同搜索方式不同)进行搜索
+  * 视频文件名
+

+ 90 - 0
common/decode.go

@@ -0,0 +1,90 @@
+package common
+
+import (
+	"github.com/beevik/etree"
+	"io/ioutil"
+	"os"
+	"strings"
+)
+
+func get_IMDB_movie_xml(movieFilePath string) (string, error) {
+	doc := etree.NewDocument()
+	if err := doc.ReadFromFile(movieFilePath); err != nil {
+		return "", err
+	}
+	for _, t := range doc.FindElements("//IMDB") {
+		return t.Text(), nil
+	}
+
+	return "", CanNotFindIMDBID
+}
+
+func get_IMDB_nfo(nfoFilePath string) (string, error) {
+	doc := etree.NewDocument()
+	if err := doc.ReadFromFile(nfoFilePath); err != nil {
+		return "", err
+	}
+	for _, t := range doc.FindElements("//uniqueid[@type='Imdb']") {
+		return t.Text(), nil
+	}
+
+	return "", CanNotFindIMDBID
+}
+
+func Get_IMDB_Id(dirPth string) (string ,error) {
+	dir, err := ioutil.ReadDir(dirPth)
+	if err != nil {
+		return "", err
+	}
+	pathSep := string(os.PathSeparator)
+	// 优先找 movie.xml 这个是 raddarr 下载的电影会存下来的,可以在 Metadata 设置 Emby
+	var movieFilePath = ""
+	// 这个是使用 tinyMediaManager 削刮器按 Kodi 来存储的
+	var nfoFilePath = ""
+
+	for _, fi := range dir {
+		if fi.IsDir() == true {
+			continue
+		}
+		upperName := strings.ToUpper(fi.Name())
+		// 找 movie.xml
+		if upperName == strings.ToUpper(metadataFileEmby) {
+			movieFilePath = dirPth + pathSep + fi.Name()
+		}
+		// 找 *.nfo
+		ok := strings.HasSuffix(fi.Name(), suffixNameNfo)
+		if ok {
+			nfoFilePath = dirPth + pathSep + fi.Name()
+		}
+	}
+	// 根据找到的开始解析
+	if movieFilePath == "" && nfoFilePath == "" {
+		return "", NoMetadataFile
+	}
+
+	if movieFilePath != "" {
+		outId, err := get_IMDB_movie_xml(movieFilePath)
+		if err != nil {
+			println(err)
+		} else {
+			return outId, nil
+		}
+	}
+
+	if nfoFilePath != "" {
+		outId, err := get_IMDB_nfo(nfoFilePath)
+		if err != nil {
+			return "", err
+		} else {
+			return outId, nil
+		}
+	}
+
+	return "", CanNotFindIMDBID
+}
+
+const (
+	metadataFileEmby = "movie.xml"
+	suffixNameXml    = ".xml"
+	suffixNameNfo    = ".nfo"
+)

+ 54 - 0
common/decode_test.go

@@ -0,0 +1,54 @@
+package common
+
+import "testing"
+
+func TestGet_IMDB_Id(t *testing.T) {
+	type args struct {
+		dirPth string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    string
+		wantErr bool
+	}{
+		{name: "have", args: args{dirPth: "Y:\\电影\\Army of the Dead (2021)"}, want: "tt0993840", wantErr: false},
+		{name: "want error", args: args{dirPth: "Y:\\电影\\"}, want: "", wantErr: true},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := Get_IMDB_Id(tt.args.dirPth)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Get_IMDB_Id() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if got != tt.want {
+				t.Errorf("Get_IMDB_Id() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_get_IMDB_movie_xml(t *testing.T) {
+    want := "tt0993840"
+	dirPth := "Y:\\电影\\Army of the Dead (2021)\\movie.xml"
+	got, err := get_IMDB_movie_xml(dirPth)
+	if err != nil {
+		t.Error(err)
+	}
+	if got != want {
+		t.Errorf("Test_get_IMDB_movie_xml() got = %v, want %v", got, want)
+	}
+}
+
+func Test_get_IMDB_nfo(t *testing.T) {
+	want := "tt0993840"
+	dirPth := "Y:\\电影\\Army of the Dead (2021)\\Army of the Dead (2021) WEBDL-1080p.nfo"
+	got, err := get_IMDB_nfo(dirPth)
+	if err != nil {
+		t.Error(err)
+	}
+	if got != want {
+		t.Errorf("Test_get_IMDB_movie_xml() got = %v, want %v", got, want)
+	}
+}

+ 8 - 0
common/selferr.go

@@ -0,0 +1,8 @@
+package common
+
+import "errors"
+
+var(
+	NoMetadataFile = errors.New("no metadata file, movie.xml or *.nfo")
+	CanNotFindIMDBID = errors.New("can not find IMDB Id")
+)

+ 5 - 0
go.mod

@@ -0,0 +1,5 @@
+module github.com/allanpk716/ChineseSubFinder
+
+go 1.15
+
+require github.com/beevik/etree v1.1.0

+ 16 - 0
go.sum

@@ -0,0 +1,16 @@
+github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
+github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
+github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
+github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
+github.com/thedevsaddam/gojsonq v1.9.1 h1:zQulEP43nwmq5EKrNWyIgJVbqDeMdC1qzXM/f5O15a0=
+github.com/thedevsaddam/gojsonq v2.3.0+incompatible h1:i2lFTvGY4LvoZ2VUzedsFlRiyaWcJm3Uh6cQ9+HyQA8=
+github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
+github.com/thedevsaddam/gojsonq/v2 v2.5.2/go.mod h1:bv6Xa7kWy82uT0LnXPE2SzGqTj33TAEeR560MdJkiXs=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=