Jelajahi Sumber

完成 normal 字幕命名格式的实现

Signed-off-by: allan716 <[email protected]>
allan716 4 tahun lalu
induk
melakukan
5c188f8bbd

+ 11 - 0
internal/pkg/language/language.go

@@ -164,6 +164,17 @@ func Lang2ChineseString(lan types.Language) string {
 	}
 }
 
+// ChineseISOString2Lang 将 中文描述:zh、zho、chi 转换为 types.Language
+func ChineseISOString2Lang(chineseStr string) types.Language {
+
+	switch chineseStr {
+	case types.ChineseAbbr_639_1, types.ChineseAbbr_639_2T, types.ChineseAbbr_639_2B:
+		return types.ChineseSimple
+	default:
+		return types.Unknow
+	}
+}
+
 // ChineseString2Lang 将 中文描述:简、繁、简英 转换为 types.Language
 func ChineseString2Lang(chineseStr string) types.Language {
 	switch chineseStr {

+ 6 - 9
internal/pkg/sub_formatter/emby/emby.go

@@ -32,8 +32,8 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, types.Langua
 		[0][1]	简英,subhd or 简英
 		[0][2]	.ass
 	*/
-	if len(matched) < 1 || len(matched[0]) < 3 {
-		return false, "", types.ChineseSimple, ""
+	if matched == nil || len(matched) < 1 || len(matched[0]) < 3 {
+		return false, "", types.Unknow, ""
 	}
 	var subLang types.Language
 	var subLangStr string
@@ -43,7 +43,7 @@ func (f Formatter) IsMatchThisFormat(subName string) (bool, string, types.Langua
 	if strings.Contains(midString, ",") == true {
 		tmps := strings.Split(midString, ",")
 		if len(tmps) < 2 {
-			return false, "", types.ChineseSimple, ""
+			return false, "", types.Unknow, ""
 		}
 		subLangStr = tmps[0]
 		extraSubPreName = tmps[1]
@@ -68,13 +68,10 @@ func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang type
 	if extraSubPreName != "" {
 		note = "," + extraSubPreName
 	}
-	const defaultString = ".default"
-	const forcedString = ".forced"
-	const chineseString = ".chinese"
 
-	subNewName := videoFileNameWithOutExt + chineseString + "(" + language.Lang2ChineseString(subLang) + note + ")" + subExt
-	subNewNameWithDefault := videoFileNameWithOutExt + chineseString + "(" + language.Lang2ChineseString(subLang) + note + ")" + defaultString + subExt
-	subNewNameWithForced := videoFileNameWithOutExt + chineseString + "(" + language.Lang2ChineseString(subLang) + note + ")" + forcedString + subExt
+	subNewName := videoFileNameWithOutExt + types.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + subExt
+	subNewNameWithDefault := videoFileNameWithOutExt + types.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + types.Sub_Ext_Mark_Default + subExt
+	subNewNameWithForced := videoFileNameWithOutExt + types.Emby_chinese + "(" + language.Lang2ChineseString(subLang) + note + ")" + types.Sub_Ext_Mark_Forced + subExt
 
 	return subNewName, subNewNameWithDefault, subNewNameWithForced
 }

+ 1 - 1
internal/pkg/sub_formatter/emby/emby_test.go

@@ -58,7 +58,7 @@ func TestFormatter_IsMatchThisFormat(t *testing.T) {
 		{name: "03", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.chinese.ass"},
 			want:  false,
 			want1: "",
-			want2: types.ChineseSimple,
+			want2: types.Unknow,
 			want3: ""},
 	}
 	for _, tt := range tests {

+ 71 - 0
internal/pkg/sub_formatter/normal/normal.go

@@ -1 +1,72 @@
 package normal
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/language"
+	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"path/filepath"
+	"regexp"
+	"strings"
+)
+
+type Formatter struct {
+}
+
+func NewFormatter() *Formatter {
+	return &Formatter{}
+}
+
+// GetFormatterName 当前的 Formatter 是那个
+func (f Formatter) GetFormatterName() string {
+	return "normal formatter"
+}
+
+// IsMatchThisFormat 是否满足当前实现接口的字幕命名格式 - 是否符合规则、subExt string, subLang types.Language, extraSubPreName string
+func (f Formatter) IsMatchThisFormat(subName string) (bool, string, types.Language, string) {
+	/*
+		Emby 的命名规则比较特殊,而且本程序就是做中文字幕下载的,所以,下面的正则表达式比较特殊
+	*/
+	var re = regexp.MustCompile(`(?m)\.(\bzh\b|\bzho\b|\bchi\b)(\.\S+)`)
+	matched := re.FindAllStringSubmatch(subName, -1)
+	/*
+		The Boss Baby Family Business (2021) WEBDL-1080p.zh.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.zh.default.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.zh.forced.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.chi.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.chi.default.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.chi.forced.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.zho.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.zho.default.ass
+		The Boss Baby Family Business (2021) WEBDL-1080p.zho.forced.ass
+
+		[0][0]	.zh.ass
+		[0][1]	zh
+		[0][2]	.ass
+	*/
+	if matched == nil || len(matched) < 1 || len(matched[0]) < 3 {
+		return false, "", types.Unknow, ""
+	}
+	var subLang types.Language
+	var subLangStr string
+	var extraSubPreName string
+	subExt := matched[0][2]
+	subLangStr = matched[0][1]
+	extraSubPreName = ""
+	subLang = language.ChineseISOString2Lang(subLangStr)
+
+	return true, subExt, subLang, extraSubPreName
+}
+
+// GenerateMixSubName 通过视频和字幕信息,生成当前实现接口的字幕命名格式。extraSubPreName 一般是填写字幕网站,不填写则留空 - 新名称、新名称带有 default 标记,新名称带有 forced 标记
+func (f Formatter) GenerateMixSubName(videoFileName, subExt string, subLang types.Language, extraSubPreName string) (string, string, string) {
+	/*
+		这里会生成类似的文件名 xxxx.zh
+	*/
+	videoFileNameWithOutExt := strings.ReplaceAll(filepath.Base(videoFileName),
+		filepath.Ext(videoFileName), "")
+
+	subNewName := videoFileNameWithOutExt + "." + types.ChineseAbbr_639_1 + subExt
+	subNewNameWithDefault := videoFileNameWithOutExt + "." + types.ChineseAbbr_639_1 + types.Sub_Ext_Mark_Default + subExt
+	subNewNameWithForced := videoFileNameWithOutExt + "." + types.ChineseAbbr_639_1 + types.Sub_Ext_Mark_Forced + subExt
+
+	return subNewName, subNewNameWithDefault, subNewNameWithForced
+}

+ 115 - 0
internal/pkg/sub_formatter/normal/normal_test.go

@@ -0,0 +1,115 @@
+package normal
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/common"
+	"github.com/allanpk716/ChineseSubFinder/internal/types"
+	"testing"
+)
+
+func TestFormatter_GetFormatterName(t *testing.T) {
+	f := NewFormatter()
+	if f.GetFormatterName() != "normal formatter" {
+		t.Errorf("GetFormatterName error")
+	}
+}
+
+func TestFormatter_IsMatchThisFormat(t *testing.T) {
+	type args struct {
+		subName string
+	}
+	tests := []struct {
+		name  string
+		args  args
+		want  bool
+		want1 string
+		want2 types.Language
+		want3 string
+	}{
+		{name: "00", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.zh.ass"},
+			want:  true,
+			want1: ".ass",
+			want2: types.ChineseSimple,
+			want3: ""},
+		{name: "01", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.zh.default.ass"},
+			want:  true,
+			want1: ".default.ass",
+			want2: types.ChineseSimple,
+			want3: ""},
+		{name: "02", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.zh.forced.ass"},
+			want:  true,
+			want1: ".forced.ass",
+			want2: types.ChineseSimple,
+			want3: ""},
+		{name: "03", args: args{subName: "The Boss Baby Family Business (2021) WEBDL-1080p.cn.ass"},
+			want:  false,
+			want1: "",
+			want2: types.Unknow,
+			want3: ""},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			f := Formatter{}
+			got, got1, got2, got3 := f.IsMatchThisFormat(tt.args.subName)
+			if got != tt.want {
+				t.Errorf("IsMatchThisFormat() got = %v, want %v", got, tt.want)
+			}
+			if got1 != tt.want1 {
+				t.Errorf("IsMatchThisFormat() got1 = %v, want %v", got1, tt.want1)
+			}
+			if got2 != tt.want2 {
+				t.Errorf("IsMatchThisFormat() got2 = %v, want %v", got2, tt.want2)
+			}
+			if got3 != tt.want3 {
+				t.Errorf("IsMatchThisFormat() got3 = %v, want %v", got3, tt.want3)
+			}
+		})
+	}
+}
+
+func TestFormatter_GenerateMixSubName(t *testing.T) {
+
+	const videoFileName = "Django Unchained (2012) Bluray-1080p.mp4"
+	const videoFileNamePre = "Django Unchained (2012) Bluray-1080p"
+
+	type args struct {
+		videoFileName   string
+		subExt          string
+		subLang         types.Language
+		extraSubPreName string
+	}
+	tests := []struct {
+		name  string
+		args  args
+		want  string
+		want1 string
+		want2 string
+	}{
+		{name: "zh", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimple, extraSubPreName: ""},
+			want:  videoFileNamePre + ".zh.ass",
+			want1: videoFileNamePre + ".zh.default.ass",
+			want2: videoFileNamePre + ".zh.forced.ass"},
+		{name: "zh_shooter", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimple, extraSubPreName: "shooter"},
+			want:  videoFileNamePre + ".zh.ass",
+			want1: videoFileNamePre + ".zh.default.ass",
+			want2: videoFileNamePre + ".zh.forced.ass"},
+		{name: "zh_shooter2", args: args{videoFileName: videoFileName, subExt: common.SubExtASS, subLang: types.ChineseSimpleEnglish, extraSubPreName: "shooter"},
+			want:  videoFileNamePre + ".zh.ass",
+			want1: videoFileNamePre + ".zh.default.ass",
+			want2: videoFileNamePre + ".zh.forced.ass"},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			f := Formatter{}
+			got, got1, got2 := f.GenerateMixSubName(tt.args.videoFileName, tt.args.subExt, tt.args.subLang, tt.args.extraSubPreName)
+			if got != tt.want {
+				t.Errorf("GenerateMixSubName() got = %v, want %v", got, tt.want)
+			}
+			if got1 != tt.want1 {
+				t.Errorf("GenerateMixSubName() got1 = %v, want %v", got1, tt.want1)
+			}
+			if got2 != tt.want2 {
+				t.Errorf("GenerateMixSubName() got2 = %v, want %v", got2, tt.want2)
+			}
+		})
+	}
+}

+ 8 - 0
internal/types/language.go

@@ -1,6 +1,7 @@
 package types
 
 const (
+	// SubNameKeywordChineseSimple 用于区分字幕是简体中文还是繁体中文
 	SubNameKeywordChineseSimple = "chs"
 	SubNameKeywordTraditional   = "cht"
 )
@@ -23,6 +24,13 @@ const (
 	ChineseTraditionalKorean                   // 繁韩双语字幕
 )
 
+// 参考 https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 标准
+const (
+	ChineseAbbr_639_1  = "zh"
+	ChineseAbbr_639_2T = "zho"
+	ChineseAbbr_639_2B = "chi"
+)
+
 const (
 	Sub_Ext_Mark_Default = ".default" // 指定这个字幕是默认的
 	Sub_Ext_Mark_Forced  = ".forced"  // 指定这个字幕是强制的