Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix guessit parsing numbered episode titles as multi season #8413

Merged
merged 10 commits into from Aug 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
199 changes: 148 additions & 51 deletions medusa/name_parser/rules/rules.py
Expand Up @@ -181,7 +181,6 @@ class FixInvalidAbsoluteReleaseGroups(Rule):
"type": "episode"
}


with this fix:
For: Show.Name.s16e03-05.313-315
GuessIt found: {
Expand Down Expand Up @@ -713,6 +712,97 @@ def when(self, matches, context):
return to_remove, to_append


class OnePreGroupAsMultiEpisode(Rule):
"""Remove last episode (one) and add the first episode as absolute.

There are animes where the absolute episode is detected as
multi episode because of a number (one) before the group.

Medusa rule:
- The first episode should be added as absolute
- The last episode should be removed
- Episode title should be release group

e.g.: Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated

guessit -t episode "Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated"

without this rule:
For: Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated
GuessIt found: {
"title": "Kemono Michi Rise Up",
"episode": [
3,
1
],
"screen_size": "1080p",
"source": "Web",
"video_codec": "H.264",
"episode_title": "URANiME",
"other": "Obfuscated",
"type": "episode"
}

with this rule:
For: Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated
GuessIt found: {
"title": "Kemono Michi Rise Up",
"episode": 3,
"absolute_episode": 3,
"screen_size": "1080p",
"source": "Web",
"video_codec": "H.264",
"release_group": "URANiME",
"other": "Obfuscated",
"type": "episode"
}
"""

priority = POST_PROCESS
consequence = [RemoveMatch, AppendMatch]

def when(self, matches, context):
"""Evaluate the rule.

:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
"""
titles = matches.named('title')
if not titles:
return

episodes = matches.named('episode')
if not episodes or len(episodes) != 2:
return

is_anime = context.get('show_type') == 'anime' or matches.tagged('anime')
if is_anime or matches.named('season'):
return

sorted_episodes = sorted(episodes)
if sorted_episodes[-1].value != 1:
return

episode = copy.copy(sorted_episodes[0])
episode.name = 'absolute_episode'

to_remove = [sorted_episodes[-1]]
to_append = [episode]

episode_titles = matches.named('episode_title')
if episode_titles:
release_group = copy.copy(episode_titles[0])
release_group.name = 'release_group'

to_remove.append(episode_titles[0])
to_append.append(release_group)

return to_remove, to_append


class AnimeAbsoluteEpisodeNumbers(Rule):
"""Move episode numbers to absolute episode numbers for animes.

Expand Down Expand Up @@ -851,7 +941,6 @@ class AbsoluteEpisodeNumbers(Rule):
"screen_size": "720p",
"type": "episode"
}

"""

priority = POST_PROCESS
Expand Down Expand Up @@ -906,54 +995,50 @@ def when(self, matches, context):
return to_remove, to_append


class OnePreGroupAsMultiEpisode(Rule):
"""Remove last episode (one) and add the first episode as absolute.
class FixEpisodeTitleAsMultiSeason(Rule):
"""Remove the last season and add it to the episode title.

There are animes where the absolute episode is detected as
multi episode because of a number (one) before the group.
e.g.: The.X-Flies.S09E06.Trust.No.1.x265.HEVC-Qman[UTR].mkv

Medusa rule:
- The first episode should be added as absolute
- The last episode should be removed
- Episode title should be release group

e.g.: Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated

guessit -t episode "Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated"
guessit -t episode "The.X-Flies.S09E06.Trust.No.1.x265.HEVC-Qman[UTR].mkv"

without this rule:
For: Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated
For: The.X-Flies.S09E06.Trust.No.1.x265.HEVC-Qman[UTR].mkv
GuessIt found: {
"title": "Kemono Michi Rise Up",
"episode": [
3,
"title": "The X-Flies",
"season": [
9,
1
],
"screen_size": "1080p",
"source": "Web",
"video_codec": "H.264",
"episode_title": "URANiME",
"other": "Obfuscated",
"episode": 6,
"episode_title": "Trust No",
"video_codec": "H.265",
"video_profile": "High Efficiency Video Coding",
"release_group": "Qman[UTR]",
"container": "mkv",
"mimetype": "video/x-matroska",
"type": "episode"
}

with this rule:
For: Kemono.Michi.Rise.Up.E03.1080p.WEB.x264.1-URANiME-Obfuscated
For: The.X-Flies.S09E06.Trust.No.1.x265.HEVC-Qman[UTR].mkv
GuessIt found: {
"title": "Kemono Michi Rise Up",
"episode": 3,
"absolute_episode": 3,
"screen_size": "1080p",
"source": "Web",
"video_codec": "H.264",
"release_group": "URANiME",
"other": "Obfuscated",
"title": "The X-Flies",
"season": 9
"episode": 6,
"episode_title": "Trust No 1",
"video_codec": "H.265",
"video_encoder": "x265",
"video_profile": "High Efficiency Video Coding",
"release_group": "Qman",
"container": "mkv",
"mimetype": "video/x-matroska",
"type": "episode"
}
"""

priority = POST_PROCESS
consequence = [RemoveMatch, AppendMatch]
consequence = [RemoveMatch]

def when(self, matches, context):
"""Evaluate the rule.
Expand All @@ -968,33 +1053,45 @@ def when(self, matches, context):
if not titles:
return

episodes = matches.named('episode')
if not episodes or len(episodes) != 2:
return

is_anime = context.get('show_type') == 'anime' or matches.tagged('anime')
if is_anime or matches.named('season'):
if is_anime:
return

sorted_episodes = sorted(episodes)
if sorted_episodes[-1].value != 1:
seasons = matches.named('season')
if not seasons or len(seasons) not in [2, 3]:
return

episode = copy.copy(sorted_episodes[0])
episode.name = 'absolute_episode'
if len(seasons) == 2:
season = seasons[-1]
else:
season = seasons[len(seasons) - 2]

to_remove = [sorted_episodes[-1]]
to_append = [episode]
next_episode = matches.next(season, predicate=lambda match: match.name == 'episode')
if next_episode:
return

to_remove = []

episode_titles = matches.named('episode_title')
if episode_titles:
release_group = copy.copy(episode_titles[0])
release_group.name = 'release_group'
previous = matches.previous(season, predicate=lambda match: match.name == 'episode_title')
if not previous:
return

to_remove.append(episode_titles[0])
to_append.append(release_group)
episode_title = episode_titles[0]
if not episode_title.value[0].isdigit():
episode_title.value = episode_title.value + ' ' + str(season.value)
to_remove.append(season)
else:
previous = matches.previous(season, predicate=lambda match: match.name == 'episode')
if not previous:
return

return to_remove, to_append
episode_title = season
episode_title.name = 'episode_title'
episode_title.value = str(season.value)

return to_remove


class PartsAsEpisodeNumbers(Rule):
Expand Down Expand Up @@ -1141,6 +1238,7 @@ class FixParentFolderReplacingTitle(Rule):
"mimetype": "video/x-matroska",
"type": "episode"
}

with the rule:
For: /Comedy 23/Funny.Show.S4E19.mkv
GuessIt found: {
Expand Down Expand Up @@ -1220,7 +1318,6 @@ class FixMultipleSources(Rule):
"type": "episode"
}


with this rule:
For: Show.Name.S02E01.eps2.0.unm4sk-pt1.tc.1080p.WEB-DL.DD5.1.H264-GROUP
GuessIt found: {
Expand Down Expand Up @@ -1462,7 +1559,6 @@ class ReleaseGroupPostProcessor(Rule):
"type": "episode"
}


with this post processor:
For: Some.Show.S02E14.1080p.HDTV.X264-GROUP[TRASH]
GuessIt found: {
Expand Down Expand Up @@ -1582,6 +1678,7 @@ def rules():
AnimeWithSeasonMultipleEpisodeNumbers,
AnimeAbsoluteEpisodeNumbers,
AbsoluteEpisodeNumbers,
FixEpisodeTitleAsMultiSeason,
OnePreGroupAsMultiEpisode,
PartsAsEpisodeNumbers,
RemoveInvalidEpisodeSeparator,
Expand Down
52 changes: 52 additions & 0 deletions tests/test_guessit.yml
Expand Up @@ -1402,6 +1402,58 @@
release_group: Group
type: episode

? The.X-Flies.S09E06.Trust.No.1.x265.HEVC-Group.mkv
: title: The X-Flies
season: 9
episode: 6
episode_title: Trust No 1
video_codec: H.265
video_encoder: x265
video_profile: High Efficiency Video Coding
release_group: Group
container: mkv
mimetype: video/x-matroska
type: episode

? /media/Season 09/The.X-Flies.S09E06.Trust.No.1.x265.HEVC-Group.mkv
: title: The X-Flies
season: 9
episode: 6
episode_title: Trust No 1
video_codec: H.265
video_encoder: x265
video_profile: High Efficiency Video Coding
release_group: Group
container: mkv
mimetype: video/x-matroska
type: episode

? The.X-Flies.S09E07.3.x265.HEVC-Group.mkv
: title: The X-Flies
season: 9
episode: 7
episode_title: '3'
video_codec: H.265
video_encoder: x265
video_profile: High Efficiency Video Coding
release_group: Group
container: mkv
mimetype: video/x-matroska
type: episode

? /media/Season 09/The.X-Flies.S09E07.3.x265.HEVC-Group.mkv
: title: The X-Flies
season: 9
episode: 7
episode_title: '3'
video_codec: H.265
video_encoder: x265
video_profile: High Efficiency Video Coding
release_group: Group
container: mkv
mimetype: video/x-matroska
type: episode

# https://github.com/guessit-io/guessit/issues/295
? - Some.Show.S02E14.X264.1080p.HDTV
- /Some.Show.S02E14.X264.1080p.HDTV/Some.Show.S02E14.X264.1080p.HDTV
Expand Down