Skip to content

Commit

Permalink
feat: add sample/trailer/extras handling. other minor improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
dreulavelle committed Sep 17, 2024
1 parent 37986c3 commit 8b1d968
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 27 deletions.
21 changes: 17 additions & 4 deletions PTT/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ def add_defaults(parser: Parser):
# Torrent extension
parser.add_handler("torrent", regex.compile(r"\.torrent$"), boolean, {"remove": True})

# Extras (This stuff can be trashed)
parser.add_handler("extras", regex.compile(r"\bNCED\b", regex.IGNORECASE), uniq_concat(value("NCED")), {"remove": True})
parser.add_handler("extras", regex.compile(r"\bNCOP\b", regex.IGNORECASE), uniq_concat(value("NCOP")), {"remove": True})
parser.add_handler("extras", regex.compile(r"\b(?:Deleted[ .-]*)?Scene(?:s)?\b", regex.IGNORECASE), uniq_concat(value("Deleted Scene")), {"remove": False})
parser.add_handler("extras", regex.compile(r"(?:(?<=\b(?:19\d{2}|20\d{2})\b.*)\b(?:Featurettes?)\b|\bFeaturettes?\b(?!.*\b(?:19\d{2}|20\d{2})\b))", regex.IGNORECASE), uniq_concat(value("Featurette")), {"skipFromTitle": True, "remove": False})
parser.add_handler("extras", regex.compile(r"(?:(?<=\b(?:19\d{2}|20\d{2})\b.*)\b(?:Sample)\b|\b(?:Sample)\b(?!.*\b(?:19\d{2}|20\d{2})\b))", regex.IGNORECASE), uniq_concat(value("Sample")), {"skipFromTitle": True, "remove": False})
parser.add_handler("extras", regex.compile(r"(?:(?<=\b(?:19\d{2}|20\d{2})\b.*)\b(?:Trailers?)\b|\bTrailers?\b(?!.*\b(?:19\d{2}|20\d{2}|.(Park|And))\b))", regex.IGNORECASE), uniq_concat(value("Trailer")), {"skipFromTitle": True, "remove": False})

# PPV
parser.add_handler("ppv", regex.compile(r"\bPPV\b", regex.IGNORECASE), boolean, {"skipFromTitle": True, "remove": True})
parser.add_handler("ppv", regex.compile(r"\b\W?Fight.?Nights?\W?\b", regex.IGNORECASE), boolean, {"skipFromTitle": True, "remove": False})
Expand All @@ -45,13 +53,15 @@ def add_defaults(parser: Parser):
parser.add_handler("resolution", regex.compile(r"\[?\]?1280x\d{3}[\])?]?", regex.IGNORECASE), value("720p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"\[?\]?(\d{3,4}x\d{3,4})[\])?]?p?", regex.IGNORECASE), value("$1p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(480|720|1080)0[pi]", regex.IGNORECASE), value("$1p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:QHD|QuadHD|WQHD|2560(\d+)?x(\d+)?1440p?)", regex.IGNORECASE), value("1440p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:Full HD|FHD|1920(\d+)?x(\d+)?1080p?)", regex.IGNORECASE), value("1080p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:BD|HD|M)(2160p?|4k)", regex.IGNORECASE), value("2160p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:BD|HD|M)1080p?", regex.IGNORECASE), value("1080p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:BD|HD|M)720p?", regex.IGNORECASE), value("720p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:BD|HD|M)480p?", regex.IGNORECASE), value("480p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"\b(?:4k|2160p|1080p|720p|480p)(?!.*\b(?:4k|2160p|1080p|720p|480p)\b)", regex.IGNORECASE), transform_resolution, {"remove": True})
parser.add_handler("resolution", regex.compile(r"\b4k|21600?[pi]\b", regex.IGNORECASE), value("2160p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(?:^|\D)(\d{3,4})[pi]", regex.IGNORECASE), value("$1p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(\d{3,4})[pi]", regex.IGNORECASE), value("$1p"), {"remove": True})
parser.add_handler("resolution", regex.compile(r"(240|360|480|576|720|1080|2160|3840)[pi]", regex.IGNORECASE), lowercase, {"remove": True})

# Trash (Equivalent to RTN auto-trasher) - DO NOT REMOVE HERE!
Expand Down Expand Up @@ -231,7 +241,8 @@ def handle_space_in_codec(context):
parser.add_handler("audio", regex.compile(r"\b(?!.+HR)(DTS.?HD.?Ma(ster)?|DTS.?X)\b", regex.IGNORECASE), uniq_concat(value("DTS Lossless")), {"remove": True, "skipIfAlreadyFound": False})
parser.add_handler("audio", regex.compile(r"\bDTS(?!(.?HD.?Ma(ster)?|.X)).?(HD.?HR|HD)?\b", regex.IGNORECASE), uniq_concat(value("DTS Lossy")), {"remove": True, "skipIfAlreadyFound": False})
parser.add_handler("audio", regex.compile(r"\b(Dolby.?)?Atmos\b", regex.IGNORECASE), uniq_concat(value("Atmos")), {"remove": True, "skipIfAlreadyFound": False})
parser.add_handler("audio", regex.compile(r"\bTrue(HD)?\b", regex.IGNORECASE), uniq_concat(value("TrueHD")), {"remove": True, "skipIfAlreadyFound": False})
parser.add_handler("audio", regex.compile(r"\b(TrueHD|\.True\.)\b", regex.IGNORECASE), uniq_concat(value("TrueHD")), {"remove": True, "skipIfAlreadyFound": False, "skipFromTitle": True})
parser.add_handler("audio", regex.compile(r"\bTRUE\b"), uniq_concat(value("TrueHD")), {"remove": True, "skipIfAlreadyFound": False, "skipFromTitle": True})
parser.add_handler("audio", regex.compile(r"\bFLAC(?:\+?2\.0)?(x[2-4])?\b", regex.IGNORECASE), uniq_concat(value("FLAC")), {"remove": True, "skipIfAlreadyFound": False})
parser.add_handler("audio", regex.compile(r"\bEAC-?3(?:[. -]?[256]\.[01])?\b", regex.IGNORECASE), uniq_concat(value("EAC3")), {"remove": True, "skipIfAlreadyFound": False})
parser.add_handler("audio", regex.compile(r"\bAC-?3(x2)?(?:[ .-](5\.1)?[x+]2\.?0?x?3?)?\b", regex.IGNORECASE), uniq_concat(value("AC3")), {"remove": True, "skipIfAlreadyFound": False})
Expand Down Expand Up @@ -314,13 +325,14 @@ def handle_volumes(context):
parser.add_handler("episodes", regex.compile(r"(?:[\W\d]|^)(?:episodes?|[Сс]ерии:?)[ .]?[([]?(\d{1,3}(?:[ .+]*[&+][ .]?\d{1,3})+)(?:\W|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"[([]?(?:\D|^)(\d{1,3}[ .]?ao[ .]?\d{1,3})[)\]]?(?:\W|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"(?:[\W\d]|^)(?:e|eps?|episodes?|[Сс]ерии:?|\d+[xх])[ .]*[([]?(\d{1,3}(?:-\d{1,3})+)(?:\W|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"(?:\W|^)[st]\d{1,2}[. ]?[xх-]?[. ]?(?:e|x|х|ep|-|\.)[. ]?(\d{1,3})(?:[abc]|v0?[1-4]|\D|$)", regex.IGNORECASE), array(integer))
parser.add_handler("episodes", regex.compile(r"(?:\W|^)[st]\d{1,2}[. ]?[xх-]?[. ]?(?:e|x|х|ep|-|\.)[. ]?(\d{1,4})(?:[abc]|v0?[1-4]|\D|$)", regex.IGNORECASE), array(integer))
parser.add_handler("episodes", regex.compile(r"\b[st]\d{2}(\d{2})\b", regex.IGNORECASE), array(integer))
parser.add_handler("episodes", regex.compile(r"(?:\W|^)(\d{1,3}(?:[ .]*~[ .]*\d{1,3})+)(?:\W|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"-\s(\d{1,3}[ .]*-[ .]*\d{1,3})(?!-\d)(?:\W|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"s\d{1,2}\s?\((\d{1,3}[ .]*-[ .]*\d{1,3})\)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"(?:^|\/)\d{1,2}-(\d{2})\b(?!-\d)"), array(integer))
parser.add_handler("episodes", regex.compile(r"(?<!\d-)\b\d{1,2}-(\d{2})(?=\.\w{2,4}$)"), array(integer))
parser.add_handler("episodes", regex.compile(r"(?<=^\[.+].+)[. ]+-[. ]+(\d{1,4})[. ]+(?=\W)", regex.IGNORECASE), array(integer))
parser.add_handler("episodes", regex.compile(r"(?<!(?:seasons?|[Сс]езони?)\W*)(?:[ .([-]|^)(\d{1,3}(?:[ .]?[,&+~][ .]?\d{1,3})+)(?:[ .)\]-]|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"(?<!(?:seasons?|[Сс]езони?)\W*)(?:[ .([-]|^)(\d{1,3}(?:-\d{1,3})+)(?:[ .)(\]]|-\D|$)", regex.IGNORECASE), range_func)
parser.add_handler("episodes", regex.compile(r"\bEp(?:isode)?\W+\d{1,2}\.(\d{1,3})\b", regex.IGNORECASE), array(integer))
Expand Down Expand Up @@ -463,6 +475,7 @@ def handle_episodes(context):
parser.add_handler("languages", regex.compile(r"\barab.*(?:audio|lang(?:uage)?|sub(?:s|titles?)?)\b", regex.IGNORECASE), uniq_concat(value("ar")), {"skipFromTitle": True, "skipIfAlreadyFound": False})
parser.add_handler("languages", regex.compile(r"\bar(?=\.(?:ass|ssa|srt|sub|idx)$)", regex.IGNORECASE), uniq_concat(value("ar")), {"skipFromTitle": True, "skipIfAlreadyFound": False})
parser.add_handler("languages", regex.compile(r"\b(?:turkish|tur(?:co)?)\b", regex.IGNORECASE), uniq_concat(value("tr")), {"skipFromTitle": True, "skipIfAlreadyFound": False})
parser.add_handler("languages", regex.compile(r"\b(TİVİBU|tivibu|bitturk(.net)?|turktorrent)\b", regex.IGNORECASE), uniq_concat(value("tr")), {"skipFromTitle": True, "skipIfAlreadyFound": False})
parser.add_handler("languages", regex.compile(r"\bvietnamese\b|\bvie(?=[\]_)]?\.\w{2,4}$)", regex.IGNORECASE), uniq_concat(value("vi")), {"skipFromTitle": True, "skipIfAlreadyFound": False})
parser.add_handler("languages", regex.compile(r"\bind(?:onesian)?\b", regex.IGNORECASE), uniq_concat(value("id")), {"skipFromTitle": True, "skipIfAlreadyFound": False})
parser.add_handler("languages", regex.compile(r"\b(thai|tailand[eê]s)\b", regex.IGNORECASE), uniq_concat(value("th")), {"skipIfFirst": True, "skipIfAlreadyFound": False})
Expand Down Expand Up @@ -576,4 +589,4 @@ def handle_group_exclusion(context):
parser.add_handler("trash", regex.compile(r"acesse o original", regex.IGNORECASE), boolean, {"remove": True})

# Title (hardcoded cleanup)
parser.add_handler("title", regex.compile(r"\b100[ .-]*years?[ .-]*quest\b", regex.IGNORECASE), none, {"remove": True})
parser.add_handler("title", regex.compile(r"\b100[ .-]*years?[ .-]*quest\b", regex.IGNORECASE), none, {"remove": True}) # episode title
36 changes: 36 additions & 0 deletions tests/test_anime.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,42 @@
"extension": "mkv",
"subbed": True,
}),
("One.Piece.S01E1116.Lets.Go.Get.It!.Buggys.Big.Declaration.2160p.B-Global.WEB-DL.JPN.AAC2.0.H.264.MSubs-ToonsHub.mkv", {
"title": "One Piece",
"seasons": [1],
"episodes": [1116],
"languages": ["ja"],
"resolution": "2160p",
"quality": "WEB-DL",
"audio": ["AAC"],
"codec": "avc",
"group": "ToonsHub",
"container": "mkv",
"extension": "mkv",
"subbed": True,
}),
("[Erai-raws] 2-5 Jigen no Ririsa - 08 [480p][Multiple Subtitle][972D0669].mkv", {
"title": "2-5 Jigen no Ririsa",
"seasons": [],
"episodes": [8],
"languages": [],
"resolution": "480p",
"group": "Erai-raws",
"episode_code": "972D0669",
"container": "mkv",
"extension": "mkv",
"subbed": True,
}),
("[Exiled-Destiny]_Tokyo_Underground_Ep02v2_(41858470).mkv", {
"title": "Tokyo Underground",
"seasons": [],
"episodes": [2],
"languages": [],
"group": "Exiled-Destiny",
"episode_code": "41858470",
"container": "mkv",
"extension": "mkv",
}),
])
def test_random_anime_parse(release_name, expected):
result = parse_title(release_name)
Expand Down
1 change: 1 addition & 0 deletions tests/test_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def parser():
("Godzilla.x.Kong.The.New.Empire.2024.2160p.BluRay.REMUX.DV.P7.HDR.ENG.LATINO.GER.ITA.FRE.HINDI.CHINESE.TrueHD.Atmos.7.1.H265-BEN.THE.MEN", ["en", "zh", "fr", "la", "it", "de", "hi"]),
("Sampurna.2023.Bengali.S02.1080p.AMZN.WEB-DL.DD+2.0.H.265-TheBiscuitMan", ["bn"]),
("Kingdom.of.the.Planet.of.the.Apes.2024.HDRIP.1080P.[xDark [SaveHD] Latin + English + Hindi.mp4", ["en", "la", "hi"]),
("The Karate Kid Part III 1989 1080p DUAL TİVİBU WEB-DL x264 AAC - HdT", ["tr"])
])
def test_languages_detection(release_name, expected_languages, parser):
result = parser.parse(release_name)
Expand Down
93 changes: 70 additions & 23 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,14 +506,6 @@ def parser():
"extension": "mkv",
"resolution": "1080p"
}),
("Бриджертоны.S02.WEB-DL.1080.HDR", {
"title": "Бриджертоны",
"seasons": [2],
"episodes": [],
"languages": ["ru"],
"quality": "WEB-DL",
"hdr": ["HDR"],
}),
("{WWW.BLUDV.TV} Love, Death & Robots - 1ª Temporada Completa 2019 (1080p) Acesse o ORIGINAL WWW.BLUDV.TV", {
"title": "Love, Death & Robots",
"seasons": [1],
Expand Down Expand Up @@ -906,25 +898,80 @@ def parser():
"channels": ["5.1"],
"group": "GalaxyRG265",
"quality": "BluRay"
})
])
def test_random_releases_parse(parser, release_name, expected):
assert parser.parse(release_name) == expected

@pytest.mark.parametrize("release_name, expected", [
("Mad Max Fury Road (2015) [1080p] [BluRay] [x265] [10bit] [5.1] [YTS.MX]", {
"title": "Mad Max Fury Road",
"year": 2015,
}),
("Властелин колец: Кольца власти (S1E1-8 of 8) / The Lord of the Rings: The Rings of Power (2022) WEB-DL", {
"title": "Властелин колец: Кольца власти", # The Lord of the Rings: The Rings of Power - We probably want the US title instead here
"year": 2022,
"seasons": [1],
"episodes": [1, 2, 3, 4, 5, 6, 7, 8],
"languages": ["ru"],
"quality": "WEB-DL"
}),
("抓娃娃 Successor.2024.TC1080P.国语中字", {
"title": "Successor",
"year": 2024,
"seasons": [],
"episodes": [],
"languages": [],
"languages": ["zh"],
"resolution": "1080p",
"quality": "TeleCine",
"trash": True
}),
("True.Detective.S03E02.720p.WEB.x265-MiNX[eztv].mkv", {
"title": "True Detective",
"seasons": [3],
"episodes": [2],
"languages": [],
"resolution": "720p",
"quality": "WEB",
"codec": "hevc",
"bit_depth": "10bit",
"channels": ["5.1"],
"audio": ["AC3"],
"group": "MiNX",
"extension": "mkv",
"container": "mkv"
}),
("True.Grit.1969.720p.WEB.x265-MiNX[eztv].mkv", {
"title": "True Grit",
"year": 1969,
"seasons": [],
"episodes": [],
"languages": [],
"resolution": "720p",
"quality": "WEB",
"codec": "hevc",
"group": "MiNX",
"extension": "mkv",
"container": "mkv"
}),
("Free Samples (2012) [BluRay] [1080p] [YTS.AM]", {
"title": "Free Samples",
"year": 2012,
"seasons": [],
"episodes": [],
"languages": [],
"resolution": "1080p",
"quality": "BluRay"
}),
("Trailer Park Boys S01-S10 + Movies + Specials + Extras [Ultimate Collection]-CAPTAiN", {
"title": "Trailer Park Boys",
"seasons": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
"episodes": [],
"languages": [],
"complete": True,
"group": "CAPTAiN"
})
])
def test_debug_releases_parse(parser, release_name, expected):
assert parser.parse(release_name) == expected
def test_random_releases_parse(parser, release_name, expected):
assert parser.parse(release_name) == expected

# @pytest.mark.parametrize("release_name, expected", [
# ("Trailer Park Boys S01-S10 + Movies + Specials + Extras [Ultimate Collection]-CAPTAiN", {
# "title": "Trailer Park Boys",
# "seasons": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
# "episodes": [],
# "languages": [],
# "complete": True,
# "group": "CAPTAiN"
# })
# ])
# def test_debug_releases_parse(parser, release_name, expected):
# assert parser.parse(release_name) == expected
1 change: 1 addition & 0 deletions tests/test_trash.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def parser():
("Brave.2012.R5.DVDRip.XViD.LiNE-UNiQUE", True),
("Guardians of the Galaxy (CamRip / 2014)", True),
("Guardians of the Galaxy (2014) 1080p BluRay 5.1 DTS-HD MA 7.1 [YTS] [YIFY]", False),
("抓娃娃 Successor.2024.TC1080P.国语中字", True)
])
def test_trash_parser(release_name, expected_trash, parser):
result = parser.parse(release_name)
Expand Down

0 comments on commit 8b1d968

Please sign in to comment.