initial commit
This commit is contained in:
		
							
								
								
									
										52
									
								
								analyze_file.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								analyze_file.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| package parsers | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"os" | ||||
|  | ||||
| 	"git.tordarus.net/nyaanime/model" | ||||
| 	"gopkg.in/vansante/go-ffprobe.v2" | ||||
| ) | ||||
|  | ||||
| // TODO cache | ||||
| func AnalyzeFile(path string) (*model.ParsedFile, error) { | ||||
| 	props := &model.ParsedFile{File: path} | ||||
|  | ||||
| 	file, err := os.Open(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	data, err := ffprobe.ProbeReader(context.Background(), file) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	defaultVideoLang := "" | ||||
| 	for _, s := range data.StreamType(ffprobe.StreamVideo) { | ||||
| 		if s.Disposition.Default > 0 { | ||||
| 			props.Resolution = model.Resolution(s.Height) | ||||
| 			defaultVideoLang = ParseLanguage(s.Tags.Language) | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for _, s := range data.StreamType(ffprobe.StreamAudio) { | ||||
| 		if s.Tags.Language != "" { | ||||
| 			props.Languages = append(props.Languages, ParseLanguage(s.Tags.Language)) | ||||
| 		} else if s.Disposition.Default > 0 { | ||||
| 			props.Languages = append(props.Languages, defaultVideoLang) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for _, s := range data.StreamType(ffprobe.StreamSubtitle) { | ||||
| 		if s.Tags.Language != "" { | ||||
| 			props.Subtitles = append(props.Subtitles, ParseLanguage(s.Tags.Language)) | ||||
| 		} else if s.Disposition.Default > 0 { | ||||
| 			props.Subtitles = append(props.Subtitles, defaultVideoLang) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return props, nil | ||||
| } | ||||
							
								
								
									
										11
									
								
								errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								errors.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| package parsers | ||||
|  | ||||
| import "git.tordarus.net/tordarus/adverr/v2" | ||||
|  | ||||
| var ( | ||||
| 	ErrTorrentParserInsufficientData           = adverr.NewErrTmpl("ErrTorrentParserInsufficientData", "regex '%s' must at least provide title and episode") | ||||
| 	ErrTorrentParserInsufficientLanguageData   = adverr.NewErrTmpl("ErrTorrentParserInsufficientLanguageData", "no language reference in regex and no default language set") | ||||
| 	ErrTorrentParserInsufficientSubtitleData   = adverr.NewErrTmpl("ErrTorrentParserInsufficientSubtitleData", "no subtitle reference in regex and no default subtitle set") | ||||
| 	ErrTorrentParserInsufficientResolutionData = adverr.NewErrTmpl("ErrTorrentParserInsufficientResolutionData", "no resolution reference in regex and no default resolution set") | ||||
| 	ErrTorrentParserInvalidGroupReference      = adverr.NewErrTmpl("ErrTorrentParserInvalidGroupReference", "options references group %d but regex only has %d groups") | ||||
| ) | ||||
							
								
								
									
										11
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| module git.tordarus.net/tordarus/parsers | ||||
|  | ||||
| go 1.18 | ||||
|  | ||||
| require ( | ||||
| 	git.tordarus.net/nyaanime/model v0.0.1 | ||||
| 	git.tordarus.net/tordarus/adverr/v2 v2.0.2 | ||||
| 	gopkg.in/vansante/go-ffprobe.v2 v2.2.1 | ||||
| ) | ||||
|  | ||||
| require git.tordarus.net/tordarus/anilist v1.5.2 // indirect | ||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| git.tordarus.net/nyaanime/model v0.0.1 h1:/I+87Z6eEw/o2adltKnCk4FZai2mPekjYlzEjY1ppyQ= | ||||
| git.tordarus.net/nyaanime/model v0.0.1/go.mod h1:oHV82UMNy4XgPHkI6tZiwabdi6myqHXgjMi9sNZ+rG4= | ||||
| git.tordarus.net/tordarus/adverr/v2 v2.0.2 h1:7nvNjMMjtGPq0EY6duMiv+seJ7MacNvKSBmckHl6Erg= | ||||
| git.tordarus.net/tordarus/adverr/v2 v2.0.2/go.mod h1:gCC46KsWosZJh7MVNDEU99hKQoxEWZgHITDHtmFwwiQ= | ||||
| git.tordarus.net/tordarus/anilist v1.5.2 h1:SxlovS+e3lgL2SowQQwj8dQrIZzRFPomcGCw3V+My0Q= | ||||
| git.tordarus.net/tordarus/anilist v1.5.2/go.mod h1:Mrhx/9+8HJVj5ebQ5fJuXqL220tEJhgQIqFK2WKPXgA= | ||||
| gopkg.in/vansante/go-ffprobe.v2 v2.2.1 h1:sFV08OT1eZ1yroLCZVClIVd9YySgCh9eGjBWO0oRayI= | ||||
| gopkg.in/vansante/go-ffprobe.v2 v2.2.1/go.mod h1:qF0AlAjk7Nqzqf3y333Ly+KxN3cKF2JqA3JT5ZheUGE= | ||||
							
								
								
									
										148
									
								
								lang_codes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								lang_codes.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,148 @@ | ||||
| package parsers | ||||
|  | ||||
| import "strings" | ||||
|  | ||||
| // langSynonyms converts all irregular lang codes to ISO 639-1 | ||||
| var langSynonyms = map[string]string{ | ||||
| 	// english | ||||
| 	"eng": "en", // Erai-Raws | ffprobe | ||||
| 	"us":  "en", // Erai-Raws | ||||
|  | ||||
| 	// portuguese | ||||
| 	"por-br": "pt", // Erai-Raws | ||||
| 	"por":    "pt", // Erai-Raws | ffprobe | ||||
| 	"br":     "pt", // Erai-Raws | ||||
|  | ||||
| 	// spanish | ||||
| 	"spa-la": "es", // Erai-Raws | ||||
| 	"spa":    "es", // Erai-Raws | ffprobe | ||||
| 	"mx":     "es", // Erai-Raws | ||||
|  | ||||
| 	// arabic | ||||
| 	"ara": "ar", // Erai-Raws | ffprobe | ||||
| 	"sa":  "ar", // Erai-Raws | ||||
|  | ||||
| 	// french | ||||
| 	"fre": "fr", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// german | ||||
| 	"ger": "de", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// italian | ||||
| 	"ita": "it", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// finnish | ||||
| 	"fin": "fi", // ffprobe | ffprobe | ||||
|  | ||||
| 	// russian | ||||
| 	"rus": "ru", // Erai-Raws | ||||
|  | ||||
| 	// japanese | ||||
| 	"jpn": "ja", // Erai-Raws | ffprobe | ||||
| 	"jp":  "ja", // Erai-Raws | ||||
|  | ||||
| 	// polish | ||||
| 	"pol": "pl", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// dutch | ||||
| 	"dut": "nl", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// norwegian | ||||
| 	"nob": "no", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// turkish | ||||
| 	"tur": "tr", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// swedish | ||||
| 	"swe": "sv", // Erai-Raws | ffprobe | ||||
| 	"se":  "sv", // Erai-Raws | ||||
|  | ||||
| 	// greek | ||||
| 	"gre": "el", // Erai-Raws | ffprobe | ||||
| 	"gr":  "el", // Erai-Raws | ||||
|  | ||||
| 	// hebrew | ||||
| 	"heb": "he", // Erai-Raws | ffprobe | ||||
| 	"il":  "he", // Erai-Raws | ||||
|  | ||||
| 	// romanian | ||||
| 	"rum": "ro", // Erai-Raws | ||||
| 	"rom": "ro", // ffprobe | ||||
|  | ||||
| 	// indonesian | ||||
| 	"ind": "id", // Erai-Raws | ||||
|  | ||||
| 	// thai | ||||
| 	"tha": "th", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// korean | ||||
| 	"kor": "ko", // Erai-Raws | ffprobe | ||||
| 	"kr":  "ko", // Erai-Raws | ||||
|  | ||||
| 	// danish | ||||
| 	"dan": "da", // Erai-Raws | ffprobe | ||||
| 	"dk":  "da", // Erai-Raws | ||||
|  | ||||
| 	// chinese (simplified & traditional) | ||||
| 	"chi": "zh", // Erai-Raws | ffprobe | ||||
| 	"cn":  "zh", // Erai-Raws | ||||
|  | ||||
| 	// bulgarian | ||||
| 	"bul": "bg", // Erai-Raws | ffprobe | ||||
|  | ||||
| 	// vietnamese | ||||
| 	"vie": "vi", // Erai-Raws | ||||
| 	"vn":  "vi", // Erai-Raws | ||||
|  | ||||
| 	// hindi | ||||
| 	"hin": "hi", // Erai-Raws | ||||
| 	"in":  "hi", // Erai-Raws | ||||
|  | ||||
| 	// tamil | ||||
| 	"tel": "ta", // Erai-Raws | ||||
| 	"lk":  "ta", // Erai-Raws | ||||
|  | ||||
| 	// ukrainian | ||||
| 	"ukr": "uk", // Erai-Raws | ||||
| 	"ua":  "uk", // Erai-Raws | ||||
|  | ||||
| 	// hungarian | ||||
| 	"hun": "hu", // Erai-Raws | ||||
|  | ||||
| 	// czech | ||||
| 	"ces": "cs", // Erai-Raws | ||||
| 	"cz":  "cs", // Erai-Raws | ||||
|  | ||||
| 	// croatian | ||||
| 	"hrv": "hr", // Erai-Raws | ||||
|  | ||||
| 	// malaysian | ||||
| 	"may": "ms", // Erai-Raws | ||||
| 	"my":  "ms", // Erai-Raws | ||||
|  | ||||
| 	// slovakian | ||||
| 	"slk": "sk", // Erai-Raws | ||||
|  | ||||
| 	// filipino | ||||
| 	"fil": "tl", // Erai-Raws | ||||
| 	"ph":  "tl", // Erai-Raws | ||||
| } | ||||
|  | ||||
| // ParseLanguage converts irregular language codes to ISO 639-1 | ||||
| func ParseLanguage(str string) string { | ||||
| 	if code, ok := langSynonyms[strings.ToLower(str)]; ok { | ||||
| 		return code | ||||
| 	} | ||||
|  | ||||
| 	return strings.ToLower(str) | ||||
| } | ||||
|  | ||||
| // ParseLanguages converts multiple irregular language codes to ISO 639-1. | ||||
| // It simply calls ParseLanguage for each language code | ||||
| func ParseLanguages(langCodes []string) []string { | ||||
| 	codes := make([]string, 0, len(langCodes)) | ||||
| 	for _, irregularLangCode := range langCodes { | ||||
| 		codes = append(codes, ParseLanguage(irregularLangCode)) | ||||
| 	} | ||||
| 	return codes | ||||
| } | ||||
							
								
								
									
										56
									
								
								parse_file.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								parse_file.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| package parsers | ||||
|  | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
|  | ||||
| 	"git.tordarus.net/nyaanime/model" | ||||
| ) | ||||
|  | ||||
| // FileParseOptions holds the subgroup index in which information can be found in a given regex | ||||
| type FileParseOptions struct { | ||||
| 	Name    int | ||||
| 	Episode int | ||||
| } | ||||
|  | ||||
| func RegexFileParser(regex string, options FileParseOptions) model.FileParserFunc { | ||||
| 	pattern := regexp.MustCompile(regex) | ||||
|  | ||||
| 	// handle faulty regexes | ||||
| 	if options.Name == 0 || options.Episode == 0 { | ||||
| 		panic(ErrTorrentParserInsufficientData.New(regex)) | ||||
| 	} | ||||
|  | ||||
| 	// handle faulty group references | ||||
| 	for _, g := range []int{options.Name, options.Episode} { | ||||
| 		if g > pattern.NumSubexp() { | ||||
| 			panic(ErrTorrentParserInvalidGroupReference.New(g, pattern.NumSubexp())) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return func(parser *model.Parser, path string) (file *model.ParsedFile, ok bool) { | ||||
| 		filename := filepath.Base(path) | ||||
| 		matches := pattern.FindStringSubmatch(filename) | ||||
|  | ||||
| 		if matches == nil { | ||||
| 			return nil, false | ||||
| 		} | ||||
|  | ||||
| 		episode, ok := atoi(matches[options.Episode]) | ||||
| 		if !ok { | ||||
| 			return nil, false | ||||
| 		} | ||||
|  | ||||
| 		parsedFile, err := AnalyzeFile(path) | ||||
| 		if err != nil { | ||||
| 			return nil, false | ||||
| 		} | ||||
|  | ||||
| 		parsedFile.OriginalAnimeTitle = matches[options.Name] | ||||
| 		parsedFile.Episode = episode | ||||
| 		parsedFile.Parser = parser | ||||
| 		parsedFile.File = path | ||||
|  | ||||
| 		return parsedFile, true | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										11
									
								
								parse_language.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								parse_language.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| package parsers | ||||
|  | ||||
| import "regexp" | ||||
|  | ||||
| type LanguageParserFunc func(str string) []string | ||||
|  | ||||
| var SquareBracketsLanguageParserRegex = regexp.MustCompile(`\[.+?\]`) | ||||
|  | ||||
| func SquareBracketsLanguageParser(str string) []string { | ||||
| 	return TrimPrefixSuffix(SquareBracketsLanguageParserRegex.FindAllString(str, -1), "[", "]") | ||||
| } | ||||
							
								
								
									
										93
									
								
								parse_torrent.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								parse_torrent.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| package parsers | ||||
|  | ||||
| import ( | ||||
| 	"regexp" | ||||
|  | ||||
| 	"git.tordarus.net/nyaanime/model" | ||||
| ) | ||||
|  | ||||
| // TorrentParseOptions holds the subgroup index in which information can be found in a given regex | ||||
| // as well as some parser specific functions | ||||
| type TorrentParseOptions struct { | ||||
| 	// regex group references | ||||
| 	Name       int | ||||
| 	Episode    int | ||||
| 	Languages  int | ||||
| 	Subtitles  int | ||||
| 	Resolution int | ||||
|  | ||||
| 	// language parsers | ||||
| 	LanguageParser LanguageParserFunc | ||||
| 	SubtitleParser LanguageParserFunc | ||||
|  | ||||
| 	// default values used when group reference is 0 | ||||
| 	DefaultLanguages  []string | ||||
| 	DefaultSubtitles  []string | ||||
| 	DefaultResolution model.Resolution | ||||
| } | ||||
|  | ||||
| func RegexTorrentParser(regex string, options TorrentParseOptions) model.TorrentParserFunc { | ||||
| 	pattern := regexp.MustCompile(regex) | ||||
|  | ||||
| 	// handle faulty regexes | ||||
| 	if options.Name == 0 || options.Episode == 0 { | ||||
| 		panic(ErrTorrentParserInsufficientData.New(regex)) | ||||
| 	} else if options.Languages == 0 && options.DefaultLanguages == nil { | ||||
| 		panic(ErrTorrentParserInsufficientLanguageData.New(regex)) | ||||
| 	} else if options.Subtitles == 0 && options.DefaultSubtitles == nil { | ||||
| 		panic(ErrTorrentParserInsufficientSubtitleData.New(regex)) | ||||
| 	} else if options.Resolution == 0 && options.DefaultResolution == 0 { | ||||
| 		panic(ErrTorrentParserInsufficientResolutionData.New(regex)) | ||||
| 	} | ||||
|  | ||||
| 	// handle faulty group references | ||||
| 	for _, g := range []int{options.Name, options.Episode, options.Languages, options.Subtitles, options.Resolution} { | ||||
| 		if g > pattern.NumSubexp() { | ||||
| 			panic(ErrTorrentParserInvalidGroupReference.New(g, pattern.NumSubexp())) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return func(parser *model.Parser, torrent *model.Torrent) (ParsedTorrent *model.ParsedTorrent, ok bool) { | ||||
| 		var err error | ||||
|  | ||||
| 		matches := pattern.FindStringSubmatch(torrent.Title) | ||||
|  | ||||
| 		if matches == nil { | ||||
| 			return nil, false | ||||
| 		} | ||||
|  | ||||
| 		episode, ok := atoi(matches[options.Episode]) | ||||
| 		if !ok { | ||||
| 			return nil, false | ||||
| 		} | ||||
|  | ||||
| 		resolution := options.DefaultResolution | ||||
| 		if options.Resolution != 0 { | ||||
| 			resolution, err = model.ParseResolution(matches[options.Resolution]) | ||||
| 			if err != nil { | ||||
| 				return nil, false | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		languages := options.DefaultLanguages | ||||
| 		if options.Languages != 0 { | ||||
| 			languages = options.LanguageParser(matches[options.Languages]) | ||||
| 		} | ||||
|  | ||||
| 		subtitles := options.DefaultSubtitles | ||||
| 		if options.Subtitles != 0 { | ||||
| 			subtitles = options.SubtitleParser(matches[options.Subtitles]) | ||||
| 		} | ||||
|  | ||||
| 		return &model.ParsedTorrent{ | ||||
| 			OriginalAnimeTitle: matches[options.Name], | ||||
| 			Episode:            episode, | ||||
| 			Resolution:         resolution, | ||||
| 			Parser:             parser, | ||||
| 			Languages:          ParseLanguages(languages), | ||||
| 			Subtitles:          ParseLanguages(subtitles), | ||||
|  | ||||
| 			Torrent: torrent, | ||||
| 		}, true | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										128
									
								
								parsers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								parsers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | ||||
| package parsers | ||||
|  | ||||
| import "git.tordarus.net/nyaanime/model" | ||||
|  | ||||
| /* | ||||
| how to get all torrent names on a nyaa page: | ||||
|  | ||||
| let s = ""; | ||||
| document.querySelectorAll("tr > td:nth-child(2) > a:not(.comments)").forEach(element => { | ||||
|   s += element.textContent + "\n"; | ||||
| }) | ||||
| console.log(s); | ||||
|  | ||||
| */ | ||||
|  | ||||
| var Parsers = []model.Parser{ | ||||
| 	{ | ||||
| 		Identity: "Erai-Raws", | ||||
| 		TorrentParser: RegexTorrentParser( | ||||
| 			`^\[Erai-raws\] (.*) - (.*?) (?:END )?(?:\[v\d+\])?\[(.*?)p\](?:\[HEVC\])?(?:\[Multiple Subtitle\])?(?:\s(\[.*?\]+)?|\[[A-Z0-9]{8}\]\.mkv)$`, | ||||
| 			TorrentParseOptions{ | ||||
| 				Name:             1, | ||||
| 				Episode:          2, | ||||
| 				Resolution:       3, | ||||
| 				Subtitles:        4, | ||||
| 				SubtitleParser:   SquareBracketsLanguageParser, | ||||
| 				DefaultLanguages: []string{"ja"}, | ||||
| 			}, | ||||
| 		), | ||||
| 		FileParser: RegexFileParser( | ||||
| 			`^\[Erai-raws\] (.*?) - (\d+?) .*?\.mkv$`, | ||||
| 			FileParseOptions{ | ||||
| 				Name:    1, | ||||
| 				Episode: 2, | ||||
| 			}, | ||||
| 		), | ||||
| 	}, | ||||
|  | ||||
| 	{ | ||||
| 		Identity: "SubsPlease", | ||||
| 		TorrentParser: RegexTorrentParser( | ||||
| 			`^\[SubsPlease\] (.*) - (\d+?) \((.*?)\) \[.*?\].mkv$`, | ||||
| 			TorrentParseOptions{ | ||||
| 				Name:             1, | ||||
| 				Episode:          2, | ||||
| 				Resolution:       3, | ||||
| 				DefaultLanguages: []string{"ja"}, | ||||
| 				DefaultSubtitles: []string{"en"}, | ||||
| 			}, | ||||
| 		), | ||||
| 		FileParser: RegexFileParser( | ||||
| 			`^\[SubsPlease\] (.*?) - (\d+?) .*?\.mkv$`, | ||||
| 			FileParseOptions{ | ||||
| 				Name:    1, | ||||
| 				Episode: 2, | ||||
| 			}, | ||||
| 		), | ||||
| 	}, | ||||
|  | ||||
| 	{ | ||||
| 		Identity: "PuyaSubs!", | ||||
| 		TorrentParser: RegexTorrentParser( | ||||
| 			`^\[PuyaSubs!\] (.*) - (\d+?) \[ESP-ENG\]\[(.*?)\]\[.*?\]\.mkv$`, | ||||
| 			TorrentParseOptions{ | ||||
| 				Name:             1, | ||||
| 				Episode:          2, | ||||
| 				Resolution:       3, | ||||
| 				DefaultLanguages: []string{"ja"}, | ||||
| 				DefaultSubtitles: []string{"en"}, | ||||
| 			}, | ||||
| 		), | ||||
| 		FileParser: RegexFileParser( | ||||
| 			`^\[PuyaSubs!\] (.*?) - (\d+?) .*?\.mkv$`, | ||||
| 			FileParseOptions{ | ||||
| 				Name:    1, | ||||
| 				Episode: 2, | ||||
| 			}, | ||||
| 		), | ||||
|  | ||||
| 		// tag 0th audio stream as japanese language and copy all other streams unchanged into output file | ||||
| 		FileEncoding: "-map 0 -c:v copy -c:a copy -c:s copy -metadata:s:a:0 language=jpn", | ||||
| 	}, | ||||
|  | ||||
| 	{ | ||||
| 		Identity: "NanakoRaws-JP", | ||||
| 		TorrentParser: RegexTorrentParser( | ||||
| 			`^\[NanakoRaws\] (.*?) - (\d+?)(?:v\d+)?(?: END)? \((.*?)p\)(?: \(.*?\))?\.mkv \(include JPsub.*?\)$`, | ||||
| 			TorrentParseOptions{ | ||||
| 				Name:             1, | ||||
| 				Episode:          2, | ||||
| 				Resolution:       3, | ||||
| 				DefaultLanguages: []string{"ja"}, | ||||
| 				DefaultSubtitles: []string{"ja"}, | ||||
| 			}, | ||||
| 		), | ||||
| 		FileParser: RegexFileParser( | ||||
| 			`^\[NanakoRaws\] (.*?) - (\d+?)(?:v\d+)?(?: END)? \((.*?)p\)(?: \(.*?\))?\.mkv$`, | ||||
| 			FileParseOptions{ | ||||
| 				Name:    1, | ||||
| 				Episode: 2, | ||||
| 			}, | ||||
| 		), | ||||
|  | ||||
| 		// tag 0th audio stream and subtitle stream as japanese language and copy all other streams unchanged into output file | ||||
| 		FileEncoding: "-map 0 -c:v copy -c:a copy -c:s copy -metadata:s:a:0 language=jpn -metadata:s:s:0 language=jpn", | ||||
| 	}, | ||||
|  | ||||
| 	{ | ||||
| 		Identity: "Ohys-Raws", | ||||
| 		TorrentParser: RegexTorrentParser( | ||||
| 			`^\[Ohys-Raws\] (.*?) - (\d+?) \(.*? \d+x(\d+?) .*?\)(?: v2)?\.mp4$`, | ||||
| 			TorrentParseOptions{ | ||||
| 				Name:             1, | ||||
| 				Episode:          2, | ||||
| 				Resolution:       3, | ||||
| 				DefaultLanguages: []string{"ja"}, | ||||
| 				DefaultSubtitles: []string{}, | ||||
| 			}, | ||||
| 		), | ||||
| 		FileParser: RegexFileParser( | ||||
| 			`^\[Ohys-Raws\] (.*) - (.*?) (?:END )?\(.*?\)(?: v2)?\.mp4$`, | ||||
| 			FileParseOptions{ | ||||
| 				Name:    1, | ||||
| 				Episode: 2, | ||||
| 			}, | ||||
| 		), | ||||
| 	}, | ||||
| } | ||||
							
								
								
									
										22
									
								
								utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								utils.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| package parsers | ||||
|  | ||||
| import ( | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| func atoi(s string) (int, bool) { | ||||
| 	v, err := strconv.Atoi(s) | ||||
| 	if err != nil { | ||||
| 		return 0, false | ||||
| 	} | ||||
| 	return v, true | ||||
| } | ||||
|  | ||||
| func TrimPrefixSuffix(arr []string, prefix, suffix string) []string { | ||||
| 	trims := make([]string, 0, len(arr)) | ||||
| 	for _, str := range arr { | ||||
| 		trims = append(trims, strings.TrimSuffix(strings.TrimPrefix(str, prefix), suffix)) | ||||
| 	} | ||||
| 	return trims | ||||
| } | ||||
		Reference in New Issue
	
	Block a user