Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
:type context: dict
:return:
"""
# only if there's no season and no episode
to_rename = []
fileparts = matches.markers.named('path')
for filepart in marker_sorted(fileparts, matches):
parts = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'part')
if parts and not matches.range(filepart.start, filepart.end,
predicate=lambda match: match.name in ('season', 'episode', 'date')):
to_rename.extend(parts)
return to_rename
class FixMultipleReleaseGroups(Rule):
"""Fix multiple release groups.
TODO: Document
"""
priority = POST_PROCESS
consequence = RemoveMatch
def when(self, matches, context):
"""Evaluate the rule.
:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
"""
to_remove = []
for bl in matches.tagged('should-have-container-before'):
if not matches.previous(bl, predicate=lambda match: match.name == 'container', index=0):
to_remove.append(bl)
return to_remove
class RemoveBlacklisted(Rule):
"""Remove blacklisted properties from final result."""
priority = POST_PROCESS - 9000
consequence = RemoveMatch
def when(self, matches, context):
"""Remove blacklisted properties.
:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
"""
return matches.named('blacklist')
to_append = []
parts = matches.named('part')
if parts:
part = parts[0]
previous = matches.previous(part, predicate=lambda match: match.name == 'title')
if previous:
# Append to title
title = previous[0]
title.value = cleanup(title.initiator.raw + s2n(' ') + part.initiator.raw)
to_remove.extend(parts)
to_append.append(title)
return to_remove, to_append
class AppendLineToMovieTitle(Rule):
"""Append 'Line' to the movie title.
Example:
guessit -t movie "The.Thin.Red.Line.1998.1080p.BluRay.H264.AAC-RARBG.mkv"
without the rule:
For: The.Thin.Red.Line.1998.1080p.BluRay.H264.AAC-RARBG.mkv
GuessIt found: {
"title": "The Thin Red",
"other": "Line Audio",
"year": 1998,
"screen_size": "1080p",
"source": "Blu-ray",
"video_codec": "H.264",
"audio_codec": "AAC",
"release_group": "SPARKS",
"""Evaluate the rule.
:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
"""
for screen_size in matches.named('screen_size'):
if screen_size.raw.lower().endswith('i'):
screen_size.value = screen_size.value.replace('p', 'i')
elif screen_size.value == '4K':
screen_size.value = '2160p'
class AudioCodecStandardizer(Rule):
"""DolbyDigital is AC3.
Rename DolbyDigital to AC3
"""
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:
rebulk = rebulk.regex_defaults(flags=re.IGNORECASE, abbreviations=[dash])
rebulk.defaults(name='audio_bit_rate', validator=seps_surround)
rebulk.regex(r'\d+-?[kmg]b(ps|its?)', r'\d+\.\d+-?[kmg]b(ps|its?)',
conflict_solver=(
lambda match, other: match
if other.name == 'audio_channels' and 'weak-audio_channels' not in other.tags
else other
),
formatter=BitRate.fromstring, tags=['release-group-prefix'])
rebulk.rules(BitRateTypeRule)
return rebulk
class BitRateTypeRule(Rule):
"""
Convert audio bit rate guess into video bit rate.
"""
consequence = [RenameMatch('video_bit_rate'), RemoveMatch]
def when(self, matches, context):
to_rename = []
to_remove = []
if is_disabled(context, 'audio_bit_rate'):
to_remove.extend(matches.named('audio_bit_rate'))
else:
video_bit_rate_disabled = is_disabled(context, 'video_bit_rate')
for match in matches.named('audio_bit_rate'):
previous = matches.previous(match, index=0,
predicate=lambda m: m.name in ('source', 'screen_size', 'video_codec'))
rebulk.string('SPKE', 'SpikeTV', 'Spike TV', value='Spike TV')
rebulk.string('SYFY', 'Syfy', value='Syfy')
rebulk.string('TFOU', 'TFou', value='TFou')
rebulk.string('TLC', value='TLC')
rebulk.string('TV3', value='TV3 Ireland')
rebulk.string('TV4', value='TV4 Sweeden')
rebulk.string('TVL', 'TVLand', 'TV Land', value='TV Land')
rebulk.string('UFC', value='UFC')
rebulk.string('USAN', value='USA Network')
rebulk.rules(ValidateStreamingService)
return rebulk
class ValidateStreamingService(Rule):
"""Validate streaming service matches."""
priority = 32
consequence = RemoveMatch
def when(self, matches, context):
"""Streaming service is always before format.
:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
"""
to_remove = []
for service in matches.named('streaming_service'):
for name in ('episode_title', 'format', 'release_group', 'title'):
values = matches.named(name)
unique_values = {v.value for v in values}
if len(unique_values) > 1:
if name == 'title':
to_remove.extend(matches.named('title', predicate=lambda match: match.value != values[0].value))
continue
log.debug(u"Guessed more than one '%s' for '%s': %s",
name, matches.input_string, u','.join(unique_values), exc_info=False)
to_remove.extend(values)
return to_remove
class ReleaseGroupPostProcessor(Rule):
"""Post process release group.
Removes invalid parts from the release group property.
e.g.: Some.Show.S02E14.1080p.HDTV.X264-GROUP[TRASH]
guessit -t episode "Some.Show.S02E14.1080p.HDTV.X264-GROUP[TRASH]"
without this post processor:
For: Some.Show.S02E14.1080p.HDTV.X264-GROUP[TRASH]
GuessIt found: {
"title": "Some Show",
"season": 2,
"episode": 14,
"screen_size": "1080p",
"format": "HDTV",
if i == absolute_episode_start:
episode.start = title.start + m.start('absolute_episode_start')
episode.end = title.start + m.end('absolute_episode_start')
elif i < absolute_episode_end:
episode.start = title.start + m.end('absolute_episode_start')
episode.end = title.start + m.start('absolute_episode_end')
else:
episode.start = title.start + m.start('absolute_episode_end')
episode.end = title.start + m.end('absolute_episode_end')
to_append.append(episode)
return to_remove, to_append
class CreateAliasWithAlternativeTitles(Rule):
"""Create alias property using alternative titles.
'alias' - post processor to create aliases using alternative titles.
e.g.: [SuperGroup].Show.Name.-.Still+Name.-.11.[1080p]
guessit -t episode "[SuperGroup].Show.Name.-.Still+Name.-.11.[1080p]"
without this rule:
For: [SuperGroup].Show.Name.-.Still+Name.-.11.[1080p]
GuessIt found: {
"release_group": "SuperGroup",
"title": "Show Name",
"alternative_title": [
"Still",
"Name"
rebulk.defaults(name='streaming_service', tags=['source-prefix'])
for value, items in config.items():
patterns = items if isinstance(items, list) else [items]
for pattern in patterns:
if pattern.startswith('re:'):
rebulk.regex(pattern, value=value)
else:
rebulk.string(pattern, value=value)
rebulk.rules(ValidateStreamingService)
return rebulk
class ValidateStreamingService(Rule):
"""Validate streaming service matches."""
priority = 128
consequence = RemoveMatch
def when(self, matches, context):
"""Streaming service is always before source.
:param matches:
:type matches: rebulk.match.Matches
:param context:
:type context: dict
:return:
"""
to_remove = []
for service in matches.named('streaming_service'):
if group:
to_remove.extend(groups)
rg = copy.copy(groups[0])
rg.start = group.start
rg.end = group.end
rg.value = cleanup(group.value)
rg.tags = ['anime']
to_append.append(rg)
else:
# anime should pick the first in the list and discard the rest
to_remove.append(groups[1:])
return to_remove, to_append
class FixSeasonRangeWithGap(Rule):
"""Fix season range with gap.
guessit -t episode "Show.Name.-.Season.1.3.4-.Mp4.1080p"
Without this fix:
For: Show.Name.-.Season.1.3.4-.Mp4.1080p
GuessIt found: {
"title": "Show Name",
"season": 1,
"episode": [
3,
4
],
"container": "MP4",
"screen_size": "1080p",
"type": "episode"