Documentation
¶
Overview ¶
Package release provides release name parsing via PCRE-compatible regex patterns sourced from TRaSH Guides and Sonarr/Radarr QualityParser.
pcre.go provides a thin PCRE-to-RE2 compatibility layer. Go's regexp (RE2) does not support lookaheads or lookbehinds. This file implements a Pattern type that compiles the RE2-compatible core of a PCRE regex and validates lookaround assertions programmatically after each match.
Index ¶
- Constants
- Variables
- func CompareSource(matches *api.MatchSet, a, b string)
- func MatchFirst(formats []Format, name string) string
- func ParseReleaseGroup(name string) string
- func SourceOrFamily(src string) string
- func SplitTopLevelAlternation(pattern string) []string
- type Format
- type Info
- type Pattern
Constants ¶
const ( NormRemux = "remux" NormBluray = "bluray" NormWebDL = "webdl" NormWebRip = "webrip" NormHDTV = "hdtv" NormSDTV = "sdtv" NormDVD = "dvd" NormCam = "cam" NormTelesync = "telesync" NormTelecine = "telecine" NormHDRip = "hdrip" )
Normalized source labels.
Variables ¶
var ( CompiledReleaseGroup *Pattern CompiledAnimeReleaseGroup *regexp.Regexp FileExtRe = regexp.MustCompile(`(?i)\.[a-z0-9]{2,4}$`) )
var ( CompiledSources []Format CompiledVideoCodecs []Format CompiledHDR []Format CompiledStreaming []Format )
Compiled pattern caches — built once at init.
var SonarrSources = []Format{ { Name: "Remux", Normalize: NormRemux, Regex: `(?:[_. ]|\d{4}p-|\bHybrid-)(?:(BD|UHD)[-_. ]?)?Remux\b|(?:(BD|UHD)[-_. ]?)?Remux[_. ]\d{4}p`, }, { Name: "BluRay", Normalize: NormBluray, Regex: `\b(?:BluRay|Blu-Ray|HD-?DVD|BDMux|BD(?!$))\b`, }, { Name: "WEB-DL", Normalize: NormWebDL, Regex: `WEB[-_. ]DL(?:mux)?|WEBDL|AmazonHD|AmazonSD|iTunesHD|MaxdomeHD|NetflixU?HD|WebHD|HBOMaxHD|DisneyHD|[. ]WEB[. ](?:[xh][ .]?26[45]|AVC|HEVC|DDP?5[. ]1)|[. ](?-i:WEB)$|(?:720|1080|2160)p[-. ]WEB[-. ]|[-. ]WEB[-. ](?:720|1080|2160)p|\b\s/\sWEB\s/\s\b|(?:AMZN|NF|DP)[. -]WEB[. -](?!Rip)`, }, { Name: "WEBRip", Normalize: NormWebRip, Regex: `\b(?:WebRip|Web-Rip|WEBMux)\b`, }, { Name: "HDTV", Normalize: NormHDTV, Regex: `\b(?:HDTV)\b`, }, { Name: "BDRip", Normalize: NormBluray, Regex: `\b(?:BDRip|BDLight)\b`, }, { Name: "BRRip", Normalize: NormBluray, Regex: `\b(?:BRRip)\b`, }, { Name: "DVD", Normalize: NormDVD, Regex: `\b(?:DVD|DVDRip|NTSC|PAL|xvidvd)\b`, }, { Name: "DSR", Normalize: NormSDTV, Regex: `\b(?:WS[-_. ]DSR|DSR)\b`, }, { Name: "PDTV", Normalize: NormSDTV, Regex: `\b(?:PDTV)\b`, }, { Name: "SDTV", Normalize: NormSDTV, Regex: `\b(?:SDTV)\b`, }, { Name: "TVRip", Normalize: NormSDTV, Regex: `\b(?:TVRip)\b`, }, { Name: "HD-TV", Normalize: NormHDTV, Regex: `HD[-_. ]TV`, }, { Name: "SD-TV", Normalize: NormSDTV, Regex: `SD[-_. ]TV`, }, { Name: "Anime BD", Normalize: NormBluray, Regex: `bd(?:720|1080|2160)|(?<=[-_. (\[])bd(?=[-_. )\]])`, }, { Name: "Anime WEB", Normalize: NormWebDL, Regex: `\[WEB\]|[\[\(]WEB[ .]`, }, { Name: "CAM", Normalize: NormCam, Regex: `\b(?:CAM|HDCAM)\b`, }, { Name: "Telesync", Normalize: NormTelesync, Regex: `\b(?:Telesync|TS|PDVD)\b`, }, { Name: "Telecine", Normalize: NormTelecine, Regex: `\b(?:Telecine|TC)\b`, }, { Name: "HDRip", Normalize: NormHDRip, Regex: `\b(?:HDRip)\b`, }, }
SonarrSources are source patterns ported from Sonarr QualityParser.cs.
var SourceFamily = map[string]string{ NormWebDL: "web", NormWebRip: "web", NormBluray: "bluray", NormRemux: "bluray", NormHDTV: "tv", NormSDTV: "tv", NormDVD: "dvd", NormCam: NormCam, NormTelesync: NormCam, NormTelecine: NormCam, NormHDRip: "hdrip", }
SourceFamily maps granular source labels to their family for comparison.
var TrashHDRFormats = []Format{
{Name: "HDR10+", Regex: `\b(HDR10(?=[+]|P(lus)?))`, Normalize: "hdr10+"},
{Name: "HDR10", Regex: `\b(HDR10(?![+]|P(lus)?))`, Normalize: "hdr10"},
{Name: "HDR", Regex: `\b(HDR)\b`, Normalize: "hdr"},
{Name: "DV", Regex: `\b(dv|dovi|dolby[ .]?v(ision)?)\b`, Normalize: "dv"},
{Name: "HLG", Regex: `\b(HLG)\b`, Normalize: "hlg"},
{Name: "PQ", Regex: `\b(PQ)\b`, Normalize: "pq"},
{Name: "WCG", Regex: `\b(WCG)\b`, Normalize: "wcg"},
}
TrashHDRFormats defines TRaSH HDR patterns.
var TrashStreamingServices = []Format{
{Name: "AMZN", Regex: `\b(amzn|amazon(hd)?)\b`, Normalize: "AMZN"},
{Name: "NF", Regex: `\b(nf|netflix(u?hd)?)\b`, Normalize: "NF"},
{Name: "DSNP", Regex: `\b(dsnp|dsny|disney|Disney\+)\b`, Normalize: "DSNP"},
{Name: "ATVP", Regex: `\b(atvp|aptv|Apple TV\+)\b`, Normalize: "ATVP"},
{Name: "ATV", Regex: `\b(ATV)\b`, Normalize: "ATV"},
{Name: "HMAX", Regex: `\b(hmax|hbom|hbo[ ._-]?max)\b(?=[ ._-]web[ ._-]?(dl|rip)\b)`, Normalize: "HMAX"},
{Name: "HBO", Regex: `\b(hbo)(?![ ._-]max)\b(?=[ ._-]web[ ._-]?(dl|rip)\b)`, Normalize: "HBO"},
{Name: "MAX", Regex: `\b((?<!hbo[ ._-])max)\b(?=[ ._-]web[ ._-]?(dl|rip)\b)`, Normalize: "MAX"},
{Name: "HULU", Regex: `\b(hulu)\b`, Normalize: "HULU"},
{Name: "PCOK", Regex: `\b(pcok|peacock)\b`, Normalize: "PCOK"},
{Name: "PMTP", Regex: `\b(pmtp|Paramount Plus)\b`, Normalize: "PMTP"},
{Name: "BCORE", Regex: `\b(BCORE)\b|\b(\d{3,4}(p|i))\b.*\b(CORE)\b`, Normalize: "BCORE"},
{Name: "CRAV", Regex: `\b(crav(e)?)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "CRAV"},
{Name: "CRiT", Regex: `\b(CRiT)\b`, Normalize: "CRIT"},
{Name: "ROKU", Regex: `\b(ROKU)\b`, Normalize: "ROKU"},
{Name: "STAN", Regex: `\b(stan)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "STAN"},
{Name: "MA", Regex: `(?<!dts[ .-]?hd[ .-]?)\b(ma|ykw)\b(?=.*\bweb[ ._-]?(dl|rip)\b)`, Normalize: "MA"},
{Name: "iT", Regex: `\b(it|itunes)\b(?=[ ._-]web[ ._-]?(dl|rip)\b)`, Normalize: "IT"},
{Name: "STRP", Regex: `\b(STRP)\b`, Normalize: "STRP"},
{Name: "SHO", Regex: `\b(sho|showtime)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "SHO"},
{Name: "PLAY", Regex: `\b(Play)\b(?=[ ._-]web[ ._-]?(dl|rip)\b)`, Normalize: "PLAY"},
{Name: "NOW", Regex: `\b(now)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "NOW"},
{Name: "IP", Regex: `\b(ip|iplayer)\b`, Normalize: "IP"},
{Name: "ITVX", Regex: `\b(ITVX?)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "ITVX"},
{Name: "MY5", Regex: `\b(MY5)\b`, Normalize: "MY5"},
{Name: "ALL4", Regex: `\b(ALL4)\b`, Normalize: "ALL4"},
{Name: "4OD", Regex: `\b(4OD)\b`, Normalize: "4OD"},
{Name: "Pathe", Regex: `\b(Pathe)\b`, Normalize: "PATHE"},
{Name: "OViD", Regex: `\b(ovid)\b`, Normalize: "OVID"},
{Name: "NLZ", Regex: `\b(nlz|NLZiet)\b`, Normalize: "NLZ"},
{Name: "VDL", Regex: `\b(vdl)\b`, Normalize: "VDL"},
{Name: "CC", Regex: `\b(CC)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "CC"},
{Name: "RED", Regex: `\b(red|youtube red)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "RED"},
{Name: "SYFY", Regex: `\b(SYFY)\b`, Normalize: "SYFY"},
{Name: "CBC", Regex: `\b(CBC)\b`, Normalize: "CBC"},
{Name: "AUBC", Regex: `\b(AUBC)\b`, Normalize: "AUBC"},
{Name: "HTSR", Regex: `\b(HTSR|DSNPHS|HS)\b`, Normalize: "HTSR"},
{Name: "VIU", Regex: `\b(viu)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "VIU"},
{Name: "TVING", Regex: `\b(tving)\b[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "TVING"},
{Name: "TVer", Regex: `\b(tver)\b`, Normalize: "TVER"},
{Name: "FOD", Regex: `\b(fod)\b`, Normalize: "FOD"},
{Name: "U-NEXT", Regex: `\b(u-next)\b`, Normalize: "UNEXT"},
{Name: "ABEMA", Regex: `\b(ABEMA[ ._-]?(TV)?)\b`, Normalize: "ABEMA"},
{Name: "B-Global", Regex: `\b(B[ .-]?Global)\b`, Normalize: "BGLOBAL"},
{Name: "CR", Regex: `\b(C(runchy)?[ .-]?R(oll)?)\b`, Normalize: "CR"},
{Name: "HIDIVE", Regex: `\b(HIDI(VE)?)\b`, Normalize: "HIDIVE"},
{Name: "FUNi", Regex: `\b(FUNi(mation)?)\b`, Normalize: "FUNI"},
{Name: "Bilibili", Regex: `\b(Bili(bili)?)\b`, Normalize: "BILI"},
{Name: "VRV", Regex: `\b(vrv)\b`, Normalize: "VRV"},
{Name: "DSCP", Regex: `\b((dscp|dcp|disc)\b|dscv\+?)[ ._-]web[ ._-]?(dl|rip)?\b`, Normalize: "DSCP"},
{Name: "DCU", Regex: `\b(dcu|DC Universe)\b`, Normalize: "DCU"},
{Name: "QIBI", Regex: `\b(qibi|quibi)\b`, Normalize: "QIBI"},
{Name: "NICK", Regex: `\b(nick)\b`, Normalize: "NICK"},
{Name: "VDMO", Regex: `\b(vdmo)\b`, Normalize: "VDMO"},
{Name: "MUBI", Regex: `\b(mubi)\b`, Normalize: "MUBI"},
}
TrashStreamingServices defines TRaSH streaming service patterns.
var TrashVideoCodecs = []Format{
{Name: "x264", Regex: `[xh][ ._-]?264|\bAVC(\b|\d)`, Normalize: "h264"},
{Name: "x265", Regex: `[xh][ ._-]?265|\bHEVC(\b|\d)`, Normalize: "h265"},
{Name: "x266", Regex: `[xh][ ._-]?266|\bVVC(\b|\d)`, Normalize: "h266"},
{Name: "AV1", Regex: `\bAV1\b`, Normalize: "av1"},
{Name: "VC-1", Regex: `\bVC[-_. ]?1\b`, Normalize: "vc1"},
{Name: "MPEG2", Regex: `MPEG[-.]?2`, Normalize: "mpeg2"},
{Name: "VP9", Regex: `\bVP9\b`, Normalize: "vp9"},
{Name: "XviD", Regex: `\b[Xx][Vv][Ii][Dd]\b`, Normalize: "xvid"},
{Name: "DivX", Regex: `\b[Dd][Ii][Vv][Xx]\b`, Normalize: "divx"},
}
TrashVideoCodecs defines TRaSH video codec patterns.
Functions ¶
func CompareSource ¶
CompareSource checks if two sources are in the same family.
func MatchFirst ¶
MatchFirst returns the Normalize label of the first matching format, or empty string if none match.
func ParseReleaseGroup ¶
ParseReleaseGroup extracts the release group from a release name.
func SourceOrFamily ¶
SourceOrFamily returns the source family for comparison.
func SplitTopLevelAlternation ¶
SplitTopLevelAlternation splits a regex on top-level | characters, respecting groups (...), character classes [...], and escapes.
Types ¶
type Format ¶
type Format struct {
Name string // Format name (e.g. "x265", "DTS-HD MA", "BluRay")
Regex string // Regex pattern (PCRE syntax where needed)
Compiled *Pattern // Compiled via CompilePCRE (set by init)
Normalize string // Normalized label for scoring (e.g. "h265", "bluray")
}
Format holds one regex pattern for release name parsing.
type Info ¶
type Info struct {
Source string
VideoCodec string
ReleaseGroup string
StreamingService string
Edition string
HDR string
}
Info holds metadata extracted from a release/scene name.
func ParseReleaseName ¶
ParseReleaseName extracts metadata from a scene/release name.
type Pattern ¶
type Pattern struct {
// contains filtered or unexported fields
}
Pattern wraps an RE2 regex with optional lookaround assertions. For alternation patterns, branches holds independently compiled alternatives.
func CompilePCRE ¶
CompilePCRE compiles a case-insensitive PCRE pattern into an RE2 core + assertions.
func (*Pattern) FindStringSubmatch ¶
FindStringSubmatch returns the last match and its submatches that satisfies all assertions, or nil.
func (*Pattern) MatchString ¶
MatchString reports whether s contains a match satisfying all assertions.