flexget.plugins.filter.crossmatch
Covered: 30 lines
Missed: 43 lines
Skipped 26 lines
Percent: 41 %
 1
import logging
 2
from flexget.plugin import register_plugin, add_plugin_validators, PluginError, get_plugin_by_name
 4
log = logging.getLogger('crossmatch')
 7
class CrossMatch(object):
 8
    """
 9
    Perform action based on item on current feed and other inputs.
11
    Example::
13
      crossmatch:
14
        from:
15
          - rss: http://example.com/
16
        fields:
17
          - title
18
        action: reject
19
    """
21
    def validator(self):
22
        from flexget.validator import factory
23
        root = factory('dict')
24
        root.accept('list', key='fields', required=True).accept('text')
25
        root.accept('choice', key='action', required=True).accept_choices(['accept', 'reject'])
27
        inputs = root.accept('list', key='from', required=True)
28
        add_plugin_validators(inputs, phase='input')
29
        return root
31
    def on_feed_filter(self, feed, config):
33
        fields = config['fields']
34
        action = config['action']
36
        result = []
42
        for item in config['from']:
43
            for input_name, input_config in item.iteritems():
44
                input = get_plugin_by_name(input_name)
45
                if input.api_ver == 1:
46
                    raise PluginError('Plugin %s does not support API v2' % input_name)
47
                method = input.phase_handlers['input']
48
                try:
49
                    result.extend(method(feed, input_config))
50
                except PluginError, e:
51
                    log.warning('Error during input plugin %s: %s' % (input_name, e))
52
                    continue
53
                if not result:
54
                    log.warning('Input %s did not return anything' % input_name)
55
                    continue
58
        for entry in feed.entries:
59
            for generated_entry in result:
60
                log.trace('checking if %s matches %s' % (entry['title'], generated_entry['title']))
61
                common = self.entry_intersects(entry, generated_entry, fields)
62
                if common:
63
                    msg = 'intersects with %s on field(s) %s' % \
64
                          (generated_entry['title'], ', '.join(common))
65
                    if action == 'reject':
66
                        feed.reject(entry, msg)
67
                    if action == 'accept':
68
                        feed.accept(entry, msg)
70
    def entry_intersects(self, e1, e2, fields=None):
71
        """
72
        :param e1: First :class:`flexget.entry.Entry`
73
        :param e2: Second :class:`flexget.entry.Entry`
74
        :param fields: List of fields which are checked
75
        :return: List of field names in common
76
        """
78
        if fields is None:
79
            fields = []
81
        common_fields = []
83
        for field in fields:
85
            log.trace('checking field %s' % field)
86
            v1 = e1.get(field, object())
87
            v2 = e2.get(field, object())
88
            log.trace('v1: %r' % v1)
89
            log.trace('v2: %r' % v2)
91
            if v1 == v2:
92
                common_fields.append(field)
93
            else:
94
                log.trace('not matching')
95
        return common_fields
98
register_plugin(CrossMatch, 'crossmatch', api_ver=2)