Source code for couchpotato.core.downloaders.synology

import json
import traceback

from couchpotato.core._base.downloader.main import DownloaderBase
from couchpotato.core.helpers.encoding import isInt
from couchpotato.core.helpers.variable import cleanHost
from couchpotato.core.logger import CPLog
import requests


log = CPLog(__name__)

autoload = 'Synology'


[docs]class Synology(DownloaderBase):
protocol = ['nzb', 'torrent', 'torrent_magnet'] status_support = False def download(self, data = None, media = None, filedata = None): """ Send a torrent/nzb file to the downloader :param data: dict returned from provider Contains the release information :param media: media dict with information Used for creating the filename when possible :param filedata: downloaded torrent/nzb filedata The file gets downloaded in the searcher and send to this function This is done to have failed checking before using the downloader, so the downloader doesn't need to worry about that :return: boolean One faile returns false, but the downloaded should log his own errors """ if not media: media = {} if not data: data = {} response = False log.error('Sending "%s" (%s) to Synology.', (data['name'], data['protocol'])) # Load host from config and split out port. host = cleanHost(self.conf('host'), protocol = False).split(':') if not isInt(host[1]): log.error('Config properties are not filled in correctly, port is missing.') return False try: # Send request to Synology srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password'), self.conf('destination')) if data['protocol'] == 'torrent_magnet': log.info('Adding torrent URL %s', data['url']) response = srpc.create_task(url = data['url']) elif data['protocol'] in ['nzb', 'torrent']: log.info('Adding %s' % data['protocol']) if not filedata: log.error('No %s data found', data['protocol']) else: filename = data['name'] + '.' + data['protocol'] response = srpc.create_task(filename = filename, filedata = filedata) except: log.error('Exception while adding torrent: %s', traceback.format_exc()) finally: return self.downloadReturnId('') if response else False def test(self): """ Check if connection works :return: bool """ host = cleanHost(self.conf('host'), protocol = False).split(':') try: srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password')) test_result = srpc.test() except: return False return test_result def getEnabledProtocol(self): if self.conf('use_for') == 'both': return super(Synology, self).getEnabledProtocol() elif self.conf('use_for') == 'torrent': return ['torrent', 'torrent_magnet'] else: return ['nzb'] def isEnabled(self, manual = False, data = None): if not data: data = {} for_protocol = ['both'] if data and 'torrent' in data.get('protocol'): for_protocol.append('torrent') elif data: for_protocol.append(data.get('protocol')) return super(Synology, self).isEnabled(manual, data) and\ ((self.conf('use_for') in for_protocol))
[docs]class SynologyRPC(object):
"""SynologyRPC lite library""" def __init__(self, host = 'localhost', port = 5000, username = None, password = None, destination = None): super(SynologyRPC, self).__init__() self.download_url = 'http://%s:%s/webapi/DownloadStation/task.cgi' % (host, port) self.auth_url = 'http://%s:%s/webapi/auth.cgi' % (host, port) self.sid = None self.username = username self.password = password self.destination = destination self.session_name = 'DownloadStation' def _login(self): if self.username and self.password: args = {'api': 'SYNO.API.Auth', 'account': self.username, 'passwd': self.password, 'version': 2, 'method': 'login', 'session': self.session_name, 'format': 'sid'} response = self._req(self.auth_url, args) if response['success']: self.sid = response['data']['sid'] log.debug('sid=%s', self.sid) else: log.error('Couldn\'t login to Synology, %s', response) return response['success'] else: log.error('User or password missing, not using authentication.') return False def _logout(self): args = {'api':'SYNO.API.Auth', 'version':1, 'method':'logout', 'session':self.session_name, '_sid':self.sid} return self._req(self.auth_url, args) def _req(self, url, args, files = None): response = {'success': False} try: req = requests.post(url, data = args, files = files, verify = False) req.raise_for_status() response = json.loads(req.text) if response['success']: log.info('Synology action successfull') return response except requests.ConnectionError as err: log.error('Synology connection error, check your config %s', err) except requests.HTTPError as err: log.error('SynologyRPC HTTPError: %s', err) except Exception as err: log.error('Exception: %s', err) finally: return response def create_task(self, url = None, filename = None, filedata = None): """ Creates new download task in Synology DownloadStation. Either specify url or pair (filename, filedata). Returns True if task was created, False otherwise """ result = False # login if self._login(): args = {'api': 'SYNO.DownloadStation.Task', 'version': '1', 'method': 'create', '_sid': self.sid} if self.destination and len(self.destination) > 0: args['destination'] = self.destination if url: log.info('Login success, adding torrent URI') args['uri'] = url response = self._req(self.download_url, args = args) log.info('Response: %s', response) result = response['success'] elif filename and filedata: log.info('Login success, adding torrent') files = {'file': (filename, filedata)} response = self._req(self.download_url, args = args, files = files) log.info('Response: %s', response) result = response['success'] else: log.error('Invalid use of SynologyRPC.create_task: either url or filename+filedata must be specified') self._logout() return result def test(self): return bool(self._login()) config = [{ 'name': 'synology', 'groups': [ { 'tab': 'downloaders', 'list': 'download_providers', 'name': 'synology', 'label': 'Synology', 'description': 'Use <a href="http://www.synology.com/dsm/home_home_applications_download_station.php" target="_blank">Synology Download Station</a> to download.', 'wizard': True, 'options': [ { 'name': 'enabled', 'default': 0, 'type': 'enabler', 'radio_group': 'nzb,torrent', }, { 'name': 'host', 'default': 'localhost:5000', 'description': 'Hostname with port. Usually <strong>localhost:5000</strong>', }, { 'name': 'username', }, { 'name': 'password', 'type': 'password', }, { 'name': 'destination', 'description': 'Specify <strong>existing</strong> destination share to where your files will be downloaded, usually <strong>Downloads</strong>', 'advanced': True, }, { 'name': 'use_for', 'label': 'Use for', 'default': 'both', 'type': 'dropdown', 'values': [('usenet & torrents', 'both'), ('usenet', 'nzb'), ('torrent', 'torrent')], }, { 'name': 'manual', 'default': 0, 'type': 'bool', 'advanced': True, 'description': 'Disable this downloader for automated searches, but use it when I manually send a release.', }, ], } ], }]