コード例 #1
0
ファイル: rules.py プロジェクト: warrmr/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            sources = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'source')
            if len(sources) < 2:
                continue

            for candidate in reversed(sources):
                previous = matches.previous(candidate, predicate=lambda match: match.name == 'screen_size')
                next_range = matches.range(candidate.end, filepart.end,
                                           lambda match: match.name in ('audio_codec', 'video_codec', 'release_group'))
                # If we have at least 3 matches near by, then discard the other sources
                if len(previous) + len(next_range) > 1:
                    invalid_sources = {f.value for f in sources[0:-1]}
                    to_remove = matches.named('source', predicate=lambda m: m.value in invalid_sources)
                    return to_remove

                if matches.conflicting(candidate):
                    to_remove = matches.named('source', predicate=lambda m: m.value in candidate.value)
                    return to_remove
コード例 #2
0
ファイル: rules.py プロジェクト: warrmr/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        to_remove = []

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            m_x264 = matches.ending(filepart.end, predicate=lambda match: match.name == 'video_codec' and match.value == 'H.264', index=0)
            if not m_x264:
                continue

            m_hdtv = matches.previous(m_x264, predicate=lambda match: match.name == 'source' and match.value == 'HDTV', index=0)
            if not m_hdtv:
                continue

            video_codecs = matches.range(filepart.start, filepart.end, lambda match: match.name == 'video_codec')
            sources = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'source')
            if len(video_codecs) > 1:
                to_remove.append(m_x264)
                if len(sources) <= 1:
                    m_hdtv.tags.append('tvchaosuk')
            if len(sources) > 1:
                to_remove.append(m_hdtv)
                if len(video_codecs) <= 1:
                    m_x264.tags.append('tvchaosuk')

        return to_remove
コード例 #3
0
ファイル: rules.py プロジェクト: steflavoie/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        to_remove = []
        to_append = []
        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            season = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'season', index=0)
            if not season:
                continue

            episodes = matches.range(season.end, filepart.end,
                                     predicate=lambda match: match.name == 'episode' and 'weak-episode' in match.tags)
            if not episodes:
                continue

            if len(episodes) != len(matches.holes(season.end, episodes[-1].start, predicate=lambda hole: hole.raw in simple_separator)):
                continue

            for episode in episodes:
                new_season = copy.copy(episode)
                new_season.name = 'season'
                to_append.append(new_season)
                to_remove.append(episode)

        return to_append, to_remove
コード例 #4
0
ファイル: rules.py プロジェクト: warrmr/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        if context.get('show_type') == 'normal' or not matches.tagged('anime'):
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            seasons = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'season')
            for season in seasons:
                if not season.parent or not season.parent.private:
                    continue

                title = matches.previous(season, index=-1,
                                         predicate=lambda match: match.name == 'title' and match.end <= filepart.end)
                episode_title = matches.next(season, index=0,
                                             predicate=lambda match: (match.name == 'episode_title' and
                                                                      match.end <= filepart.end and
                                                                      match.value.isdigit()))

                # the previous match before the season is the series name and
                # the match after season is episode title and episode title is a number
                if not title or not episode_title:
                    continue

                to_remove = []
                to_append = []

                # adjust title to append the series name.
                # Only the season.parent contains the S prefix in its value
                new_title = copy.copy(title)
                new_title.value = ' '.join([title.value, season.parent.value])
                new_title.end = season.end

                # other fileparts might have the same season to be removed from the matches
                # e.g.: /Show.Name.S2/[Group].Show.Name.S2.-.19.[1080p]
                to_remove.extend(matches.named('season', predicate=lambda match: match.value == season.value))
                to_remove.append(title)
                to_append.append(new_title)

                # move episode_title to absolute_episode
                absolute_episode = copy.copy(episode_title)
                absolute_episode.name = 'absolute_episode'
                absolute_episode.value = int(episode_title.value)

                # always keep episode (subliminal needs it)
                episode = copy.copy(absolute_episode)
                episode.name = 'episode'

                to_remove.append(episode_title)
                to_append.append(absolute_episode)
                to_append.append(episode)
                return to_remove, to_append
コード例 #5
0
ファイル: rules.py プロジェクト: steflavoie/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            # retrieve all problematic titles
            problematic_titles = matches.range(filepart.start, filepart.end,
                                               predicate=lambda match: match.name in self.properties)

            to_remove = []
            to_append = []

            for title in problematic_titles:
                m = self.absolute_re.search(title.raw)
                if not m:
                    continue

                # Remove the problematic title
                to_remove.append(title)

                # Remove the title suffix
                new_value = title.raw[0: m.start()]
                if new_value:
                    # Add the correct title
                    new_title = copy.copy(title)
                    new_title.value = cleanup(new_value)
                    new_title.end = title.start + m.start()
                    to_append.append(new_title)

                # and add the absolute episode range
                g = m.groupdict()
                if not g['absolute_episode_end'] and title.name != 'alternative_title':
                    continue

                absolute_episode_start = int(g['absolute_episode_start'])
                absolute_episode_end = int(g['absolute_episode_end'] or g['absolute_episode_start'])
                for i in range(absolute_episode_start, absolute_episode_end + 1):
                    episode = copy.copy(title)
                    episode.name = 'absolute_episode'
                    episode.value = i
                    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
コード例 #6
0
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        # Do not concatenate the titles if it's not an anime and there are languages
        if not matches.tagged('anime') and matches.named('language'):
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            title = matches.range(
                filepart.start,
                filepart.end,
                predicate=lambda match: match.name == 'title',
                index=0)
            if not title:
                continue

            alternative_titles = matches.range(
                filepart.start,
                filepart.end,
                predicate=lambda match: match.name == 'alternative_title')
            if not alternative_titles:
                continue

            previous = title
            alias = copy.copy(title)
            alias.name = 'alias'
            alias.value = title.value

            # extended title is the concatenation between title and all alternative titles
            for alternative_title in alternative_titles:
                holes = matches.holes(start=previous.end,
                                      end=alternative_title.start)
                # if the separator is a dash, add an extra space before and after
                if six.PY3:
                    separators = [
                        ' ' + h.value + ' ' if h.value == '-' else h.value
                        for h in holes
                    ]
                    separator = ' '.join(separators) if separators else ' '
                else:
                    separators = [
                        b' ' + h.value + b' ' if h.value == b'-' else h.value
                        for h in holes
                    ]
                    separator = b' '.join(separators) if separators else b' '
                alias.value += separator + alternative_title.value

                previous = alternative_title

            alias.end = previous.end
            return [alias]
コード例 #7
0
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        # Don't add additional alias if we already have one from the previous rules
        if matches.named('alias'):
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            title = matches.range(
                filepart.start,
                filepart.end,
                predicate=lambda match: match.name == 'title',
                index=0)
            if not title:
                continue

            after_title = matches.next(title,
                                       index=0,
                                       predicate=lambda match:
                                       (match.end <= filepart.end and match.
                                        name in self.affected_names))

            # only if there's a country or year
            if not after_title:
                continue

            # skip if season == year. E.g.: Show.Name.S2016E01
            if matches.conflicting(
                    after_title,
                    predicate=lambda match: match.name == 'season',
                    index=0):
                continue

            # Only add country or year if the next match is season, episode or date
            next_match = matches.next(after_title,
                                      index=0,
                                      predicate=lambda match: match.name in
                                      ('season', 'episode', 'date'))
            if next_match:
                alias = copy.copy(title)
                alias.name = 'alias'
                if six.PY3:
                    alias.value = alias.value + ' ' + re.sub(
                        r'\W*', '', after_title.raw)
                else:
                    alias.value = alias.value + b' ' + re.sub(
                        r'\W*', b'', after_title.raw)
                alias.end = after_title.end
                alias.raw_end = after_title.raw_end
                return [alias]
コード例 #8
0
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        if context.get('show_type') == 'normal':
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            # get the group (e.g.: [abc]) at the beginning of this filepart
            group = matches.markers.at_index(
                filepart.start,
                index=0,
                predicate=lambda marker: marker.name == 'group')
            if not group or matches.at_match(group):
                continue

            # don't use websites as release group
            websites = matches.named('website')
            if websites and any(ws
                                for ws in websites if ws.value in group.value):
                continue

            if (not matches.tagged('anime')
                    and not matches.named('video_profile')
                    and matches.named('season') and matches.named('episode')):
                continue

            groups = matches.range(
                filepart.start,
                filepart.end,
                predicate=lambda match: match.name == 'release_group')
            if not groups:
                continue

            to_remove = []
            to_append = []
            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
コード例 #9
0
ファイル: rules.py プロジェクト: warrmr/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            # retrieve all problematic groups
            problematic_groups = matches.range(filepart.start, filepart.end,
                                               predicate=lambda match: match.name == 'release_group')

            to_remove = []
            to_append = []

            for group in problematic_groups:
                filename = fileparts[-1].raw
                m = self.absolute_re.search(filename)
                if not m:
                    continue

                # Remove the problematic group
                to_remove.append(group)

                # and add the absolute episode range
                g = m.groupdict()
                if not g['absolute_episode_end']:
                    continue

                absolute_episode_start = int(g['absolute_episode_start'])
                absolute_episode_end = int(g['absolute_episode_end'] or g['absolute_episode_start'])
                for i in range(absolute_episode_start, absolute_episode_end + 1):
                    episode = copy.copy(group)
                    episode.name = 'absolute_episode'
                    episode.value = i
                    if i == absolute_episode_start:
                        episode.start = group.start + m.start('absolute_episode_start')
                        episode.end = group.start + m.end('absolute_episode_start')
                    elif i < absolute_episode_end:
                        episode.start = group.start + m.end('absolute_episode_start')
                        episode.end = group.start + m.start('absolute_episode_end')
                    else:
                        episode.start = group.start + m.start('absolute_episode_end')
                        episode.end = group.start + m.end('absolute_episode_end')

                    to_append.append(episode)

                return to_remove, to_append
コード例 #10
0
ファイル: rules.py プロジェクト: pymedusa/SickRage
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        if context.get('show_type') == 'normal':
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            # get the group (e.g.: [abc]) at the beginning of this filepart
            group = matches.markers.at_index(filepart.start, index=0, predicate=lambda marker: marker.name == 'group')
            if not group or matches.at_match(group):
                continue

            # don't use websites as release group
            websites = matches.named('website')
            if websites and any(ws for ws in websites if ws.value in group.value):
                continue

            if (not matches.tagged('anime') and not matches.named('video_profile') and
                    matches.named('season') and matches.named('episode')):
                continue

            groups = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'release_group')
            if not groups:
                continue

            to_remove = []
            to_append = []
            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
コード例 #11
0
ファイル: rules.py プロジェクト: pymedusa/SickRage
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        # Do not concatenate the titles if it's not an anime and there are languages
        if not matches.tagged('anime') and matches.named('language'):
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            title = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'title', index=0)
            if not title:
                continue

            alternative_titles = matches.range(filepart.start, filepart.end,
                                               predicate=lambda match: match.name == 'alternative_title')
            if not alternative_titles:
                continue

            previous = title
            alias = copy.copy(title)
            alias.name = 'alias'
            alias.value = title.value

            # extended title is the concatenation between title and all alternative titles
            for alternative_title in alternative_titles:
                holes = matches.holes(start=previous.end, end=alternative_title.start)
                # if the separator is a dash, add an extra space before and after
                if six.PY3:
                    separators = [' ' + h.value + ' ' if h.value == '-' else h.value for h in holes]
                    separator = ' '.join(separators) if separators else ' '
                else:
                    separators = [b' ' + h.value + b' ' if h.value == b'-' else h.value for h in holes]
                    separator = b' '.join(separators) if separators else b' '
                alias.value += separator + alternative_title.value

                previous = alternative_title

            alias.end = previous.end
            return [alias]
コード例 #12
0
ファイル: rules.py プロジェクト: pymedusa/SickRage
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        # Don't add additional alias if we already have one from the previous rules
        if matches.named('alias'):
            return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            title = matches.range(filepart.start, filepart.end, predicate=lambda match: match.name == 'title', index=0)
            if not title:
                continue

            after_title = matches.next(title, index=0,
                                       predicate=lambda match: (
                                           match.end <= filepart.end and match.name in self.affected_names))

            # only if there's a country or year
            if not after_title:
                continue

            # skip if season == year. E.g.: Show.Name.S2016E01
            if matches.conflicting(after_title, predicate=lambda match: match.name == 'season', index=0):
                continue

            # Only add country or year if the next match is season, episode or date
            next_match = matches.next(after_title, index=0,
                                      predicate=lambda match: match.name in ('season', 'episode', 'date'))
            if next_match:
                alias = copy.copy(title)
                alias.name = 'alias'
                if six.PY3:
                    alias.value = alias.value + ' ' + re.sub(r'\W*', '', after_title.raw)
                else:
                    alias.value = alias.value + b' ' + re.sub(r'\W*', b'', after_title.raw)
                alias.end = after_title.end
                alias.raw_end = after_title.raw_end
                return [alias]
コード例 #13
0
ファイル: rules.py プロジェクト: warrmr/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :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
コード例 #14
0
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        if not matches.named('type', lambda m: m.value == 'episode'):
            return

        to_rename = []
        file_parts = matches.markers.named('path')
        for file_part in marker_sorted(file_parts, matches):
            parts = matches.range(file_part.start, file_part.end, predicate=lambda match: match.name == 'part')
            # Only apply when there's no episode
            if parts and not matches.range(file_part.start, file_part.end,
                                           predicate=lambda match: match.name == 'episode'):
                to_rename.extend(parts)

        return to_rename
コード例 #15
0
ファイル: rules.py プロジェクト: warrmr/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        season = matches.named('season')
        year = matches.named('year')
        valid_season = bool(season) and (not year or season[0].value != year[0].value)
        anime_type = context.get('show_type') == 'anime'

        # only for shows that seems to be animes
        if not anime_type and valid_season:
            return

        # if it's not detected as anime and season is valid, then skip.
        if not matches.named('video_profile') and not matches.tagged('anime') and valid_season:
            is_anime = False
            groups = matches.markers.named('group')
            for group in groups:
                screen_size = matches.range(group.start, group.end, index=0,
                                            predicate=lambda match: match.name == 'screen_size')
                if screen_size:
                    is_anime = True
                    screen_size.tags.append('anime')
                    break
            if not is_anime:
                return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            season = matches.range(filepart.start, filepart.end, index=0,
                                   predicate=lambda match: match.name == 'season' and match.raw.isdigit())
            if not season:
                continue

            episodes = matches.named('episode')
            if episodes:
                to_append = []
                to_remove = []
                for episode in episodes:
                    if 'anime' in episode.tags or (anime_type and not valid_season):
                        absolute_episode = copy.copy(episode)
                        absolute_episode.name = 'absolute_episode'
                        to_append.append(absolute_episode)

                episode_title = matches.next(
                    episode,
                    index=0,
                    predicate=lambda match: match.name == 'episode_title' and match.value.isdigit(),
                )
                if episode_title and to_append:
                    if matches.input_string[episode.end:episode_title.start + 1] in range_separator:
                        end_value = int(episode_title.value)
                        for i in range(absolute_episode.value + 1, end_value + 1):
                            episode = copy.copy(absolute_episode)
                            episode.value = i
                            if i < end_value:
                                episode.start = episode.end
                                episode.end = episode_title.start
                            else:
                                episode.start = episode_title.start
                                episode.end = episode_title.end

                            ep = copy.copy(episode)
                            ep.name = 'episode'
                            to_append.append(episode)
                            to_append.append(ep)

                        to_remove.append(episode_title)

                return to_remove, to_append
コード例 #16
0
ファイル: rules.py プロジェクト: steflavoie/Medusa
    def when(self, matches, context):
        """Evaluate the rule.

        :param matches:
        :type matches: rebulk.match.Matches
        :param context:
        :type context: dict
        :return:
        """
        weak_duplicate = matches.tagged('weak-duplicate', index=0)
        # only for shows that seems to be animes
        if context.get('show_type') == 'normal' or not weak_duplicate:
            return

        # if it's not detected as anime and season (weak_duplicate) is not 0, then skip.
        if not matches.named('video_profile') and not matches.tagged('anime') and weak_duplicate.value > 0:
            is_anime = False
            groups = matches.markers.named('group')
            for group in groups:
                screen_size = matches.range(group.start, group.end, index=0, predicate=lambda match: match.name == 'screen_size')
                if screen_size:
                    is_anime = True
                    screen_size.tags.append('anime')
                    break
            if not is_anime:
                return

        fileparts = matches.markers.named('path')
        for filepart in marker_sorted(fileparts, matches):
            season = matches.range(filepart.start, filepart.end, index=0,
                                   predicate=lambda match: match.name == 'season' and match.raw.isdigit())
            if not season:
                continue

            episode = matches.next(season, index=0,
                                   predicate=lambda match: (match.name == 'episode' and
                                                            match.end <= filepart.end and
                                                            match.raw.isdigit()))

            # there should be season and episode and the episode should start right after the season and both raw values
            # should be digit
            if season and episode and season.end == episode.start:
                # then make them an absolute episode:
                absolute_episode = copy.copy(episode)
                absolute_episode.name = 'absolute_episode'
                absolute_episode.start = season.start
                # raw value contains the season and episode altogether
                absolute_episode.value = int(episode.parent.raw if episode.parent else episode.raw)

                # always keep episode (subliminal needs it)
                corrected_episode = copy.copy(absolute_episode)
                corrected_episode.name = 'episode'
                corrected_episode.start = season.start

                to_remove = [season, episode]
                to_append = [absolute_episode, corrected_episode]

                episode_title = matches.next(episode, index=0, predicate=lambda match: match.name == 'episode_title' and match.value.isdigit())
                if episode_title:
                    if matches.input_string[episode.end:episode_title.start + 1] in range_separator:
                        end_value = int(episode_title.value)
                        for i in range(absolute_episode.value + 1, end_value + 1):
                            episode = copy.copy(absolute_episode)
                            episode.value = i
                            if i < end_value:
                                episode.start = episode.end
                                episode.end = episode_title.start
                            else:
                                episode.start = episode_title.start
                                episode.end = episode_title.end

                            ep = copy.copy(episode)
                            ep.name = 'episode'
                            to_append.append(episode)
                            to_append.append(ep)

                        to_remove.append(episode_title)

                return to_remove, to_append