flexget.plugins.output.pyload
Covered: 63 lines
Missed: 85 lines
Skipped 48 lines
Percent: 42 %
  3
from urllib import urlencode
  4
from urllib2 import urlopen, URLError, HTTPError
  5
from logging import getLogger
  6
from flexget.plugin import register_plugin, get_plugin_by_name, PluginError, DependencyError
  7
from flexget import validator
  9
log = getLogger('pyload')
 11
try:
 12
    import simplejson as json
 13
except ImportError:
 14
    try:
 15
        import json
 16
    except ImportError:
 17
        raise DependencyError(issued_by='pyload', missing='simplejson',
 18
                              message='pyload requires either simplejson module or python > 2.5')
 21
class PluginPyLoad(object):
 22
    """
 23
    Parse feed content or url for hoster links and adds them to pyLoad.
 25
    Example::
 27
      pyload:
 28
        api: http://localhost:8000/api
 29
        queue: yes
 30
        username: my_username
 31
        password: my_password
 32
        folder: desired_folder
 33
        hoster:
 34
          - YoutubeCom
 35
        parse_url: no
 36
        multiple_hoster: yes
 37
        enabled: yes
 39
    Default values for the config elements::
 41
      pyload:
 42
          api: http://localhost:8000/api
 43
          queue: no
 44
          hoster: ALL
 45
          parse_url: no
 46
          multiple_hoster: yes
 47
          enabled: yes
 48
    """
 50
    __author__ = 'http://pyload.org'
 51
    __version__ = '0.3'
 53
    DEFAULT_API = 'http://localhost:8000/api'
 54
    DEFAULT_QUEUE = False
 55
    DEFAULT_FOLDER = ''
 56
    DEFAULT_HOSTER = []
 57
    DEFAULT_PARSE_URL = False
 58
    DEFAULT_MULTIPLE_HOSTER = True
 60
    def __init__(self):
 61
        self.session = None
 63
    def validator(self):
 64
        """Return config validator"""
 65
        root = validator.factory()
 66
        root.accept('boolean')
 67
        advanced = root.accept('dict')
 68
        advanced.accept('text', key='api')
 69
        advanced.accept('text', key='username')
 70
        advanced.accept('text', key='password')
 71
        advanced.accept('text', key='folder')
 72
        advanced.accept('boolean', key='queue')
 73
        advanced.accept('boolean', key='parse_url')
 74
        advanced.accept('boolean', key='multiple_hoster')
 75
        advanced.accept('list', key='hoster').accept('text')
 76
        return root
 78
    def on_process_start(self, feed, config):
 79
        self.session = None
 80
        set_plugin = get_plugin_by_name('set')
 81
        set_plugin.instance.register_keys({'queue': 'boolean'})
 83
    def on_feed_output(self, feed, config):
 84
        if not config.get('enabled', True):
 85
            return
 86
        if not feed.accepted:
 87
            return
 89
        self.add_entries(feed, config)
 91
    def add_entries(self, feed, config):
 92
        """Adds accepted entries"""
 94
        try:
 95
            self.check_login(feed, config)
 96
        except URLError:
 97
            raise PluginError('pyLoad not reachable', log)
 98
        except PluginError:
 99
            raise
100
        except Exception, e:
101
            raise PluginError('Unknown error: %s' % str(e), log)
103
        api = config.get('api', self.DEFAULT_API)
104
        hoster = config.get('hoster', self.DEFAULT_HOSTER)
105
        folder = config.get('folder', self.DEFAULT_FOLDER)
107
        for entry in feed.accepted:
109
            content = entry['description'] + " " + entry['url']
110
            content = json.dumps(content.encode("utf8"))
112
            url = json.dumps(entry['url']) if config.get('parse_url', self.DEFAULT_PARSE_URL) else "''"
114
            log.debug("Parsing url %s" % url)
116
            result = query_api(api, "parseURLs", {"html": content, "url": url, "session": self.session})
119
            parsed = json.loads(result.read())
121
            urls = []
124
            for name in hoster:
125
                if name in parsed:
126
                    urls.extend(parsed[name])
127
                    if not config.get('multihoster', self.DEFAULT_MULTIPLE_HOSTER):
128
                        break
131
            if not urls:
132
                for name, purls in parsed.iteritems():
133
                    if name != "BasePlugin":
134
                        urls.extend(purls)
136
            if feed.manager.options.test:
137
                log.info('Would add `%s` to pyload' % urls)
138
                continue
141
            if not urls:
142
                log.info("No suited urls in entry %s" % entry['title'])
143
                continue
145
            log.debug("Add %d urls to pyLoad" % len(urls))
147
            try:
148
                dest = 1 if config.get('queue', self.DEFAULT_QUEUE) else 0 # Destination.Queue = 1
149
                post = {'name': "'%s'" % entry['title'],
150
                        'links': str(urls),
151
                        'dest': dest,
152
                        'session': self.session}
154
                pid = query_api(api, "addPackage", post).read()
155
                log.debug('added package pid: %s' % pid)
157
                if folder:
159
                    data = {'folder': folder}
160
                    query_api(api, "setPackageData", {'pid': pid, 'data': data, 'session': self.session})
162
            except Exception, e:
163
                feed.fail(entry, str(e))
165
    def check_login(self, feed, config):
166
        url = config.get('api', self.DEFAULT_API)
168
        if not self.session:
170
            post = {'username': config['username'], 'password': config['password']}
171
            result = query_api(url, "login", post)
172
            response = json.loads(result.read())
173
            if not response:
174
                raise PluginError('Login failed', log)
175
            self.session = response.replace('"', '')
176
        else:
177
            try:
178
                query_api(url, 'getServerVersion', {'session': self.session})
179
            except HTTPError, e:
180
                if e.code == 403: # Forbidden
181
                    self.session = None
182
                    return self.check_login(feed, config)
183
                else:
184
                    raise PluginError('HTTP Error %s' % e, log)
187
def query_api(url, method, post=None):
188
    try:
189
        return urlopen(url.rstrip("/") + "/" + method.strip("/"), urlencode(post) if post else None)
190
    except HTTPError, e:
191
        if e.code == 500:
192
            raise PluginError('Internal API Error', log)
193
        raise
195
register_plugin(PluginPyLoad, 'pyload', api_ver=2)