Browse Source

Merge branch 'tv' of https://github.com/RuudBurger/CouchPotatoServer into tv_database

pull/2038/head
Jason Mehring 12 years ago
parent
commit
72ce919989
  1. 20
      couchpotato/core/downloaders/base.py
  2. 24
      couchpotato/core/downloaders/blackhole/main.py
  3. 2
      couchpotato/core/downloaders/nzbget/main.py
  4. 2
      couchpotato/core/downloaders/nzbvortex/main.py
  5. 4
      couchpotato/core/downloaders/pneumatic/main.py
  6. 2
      couchpotato/core/downloaders/sabnzbd/main.py
  7. 28
      couchpotato/core/downloaders/synology/main.py
  8. 8
      couchpotato/core/downloaders/transmission/main.py
  9. 10
      couchpotato/core/downloaders/utorrent/main.py
  10. 7
      couchpotato/core/loader.py
  11. 22
      couchpotato/core/media/_base/searcher/main.py
  12. 18
      couchpotato/core/media/movie/searcher/main.py
  13. 20
      couchpotato/core/plugins/base.py
  14. 39
      couchpotato/core/providers/base.py
  15. 3
      couchpotato/core/providers/nzb/base.py
  16. 4
      couchpotato/core/providers/torrent/base.py
  17. 56
      couchpotato/core/providers/torrent/sceneaccess/main.py

20
couchpotato/core/downloaders/base.py

@ -11,7 +11,7 @@ log = CPLog(__name__)
class Downloader(Provider):
type = []
protocol = []
http_time_between_calls = 0
torrent_sources = [
@ -36,16 +36,16 @@ class Downloader(Provider):
def __init__(self):
addEvent('download', self._download)
addEvent('download.enabled', self._isEnabled)
addEvent('download.enabled_types', self.getEnabledDownloadType)
addEvent('download.enabled_protocols', self.getEnabledProtocol)
addEvent('download.status', self._getAllDownloadStatus)
addEvent('download.remove_failed', self._removeFailed)
addEvent('download.pause', self._pause)
addEvent('download.process_complete', self._processComplete)
def getEnabledDownloadType(self):
for download_type in self.type:
if self.isEnabled(manual = True, data = {'type': download_type}):
return self.type
def getEnabledProtocol(self):
for download_protocol in self.protocol:
if self.isEnabled(manual = True, data = {'protocol': download_protocol}):
return self.protocol
return []
@ -91,11 +91,11 @@ class Downloader(Provider):
def processComplete(self, item, delete_files):
return
def isCorrectType(self, item_type):
is_correct = item_type in self.type
def isCorrectProtocol(self, item_protocol):
is_correct = item_protocol in self.protocol
if not is_correct:
log.debug("Downloader doesn't support this type")
log.debug("Downloader doesn't support this protocol")
return is_correct
@ -140,7 +140,7 @@ class Downloader(Provider):
d_manual = self.conf('manual', default = False)
return super(Downloader, self).isEnabled() and \
((d_manual and manual) or (d_manual is False)) and \
(not data or self.isCorrectType(data.get('type')))
(not data or self.isCorrectProtocol(data.get('protocol')))
def _pause(self, item, pause = True):
if self.isDisabled(manual = True, data = {}):

24
couchpotato/core/downloaders/blackhole/main.py

@ -10,20 +10,20 @@ log = CPLog(__name__)
class Blackhole(Downloader):
type = ['nzb', 'torrent', 'torrent_magnet']
protocol = ['nzb', 'torrent', 'torrent_magnet']
def download(self, data = {}, movie = {}, filedata = None):
directory = self.conf('directory')
if not directory or not os.path.isdir(directory):
log.error('No directory set for blackhole %s download.', data.get('type'))
log.error('No directory set for blackhole %s download.', data.get('protocol'))
else:
try:
if not filedata or len(filedata) < 50:
try:
if data.get('type') == 'torrent_magnet':
if data.get('protocol') == 'torrent_magnet':
filedata = self.magnetToTorrent(data.get('url'))
data['type'] = 'torrent'
data['protocol'] = 'torrent'
except:
log.error('Failed download torrent via magnet url: %s', traceback.format_exc())
@ -35,7 +35,7 @@ class Blackhole(Downloader):
try:
if not os.path.isfile(fullPath):
log.info('Downloading %s to %s.', (data.get('type'), fullPath))
log.info('Downloading %s to %s.', (data.get('protocol'), fullPath))
with open(fullPath, 'wb') as f:
f.write(filedata)
os.chmod(fullPath, Env.getPermission('file'))
@ -54,20 +54,20 @@ class Blackhole(Downloader):
return False
def getEnabledDownloadType(self):
def getEnabledProtocol(self):
if self.conf('use_for') == 'both':
return super(Blackhole, self).getEnabledDownloadType()
return super(Blackhole, self).getEnabledProtocol()
elif self.conf('use_for') == 'torrent':
return ['torrent', 'torrent_magnet']
else:
return ['nzb']
def isEnabled(self, manual, data = {}):
for_type = ['both']
if data and 'torrent' in data.get('type'):
for_type.append('torrent')
for_protocol = ['both']
if data and 'torrent' in data.get('protocol'):
for_protocol.append('torrent')
elif data:
for_type.append(data.get('type'))
for_protocol.append(data.get('protocol'))
return super(Blackhole, self).isEnabled(manual, data) and \
((self.conf('use_for') in for_type))
((self.conf('use_for') in for_protocol))

2
couchpotato/core/downloaders/nzbget/main.py

@ -15,7 +15,7 @@ log = CPLog(__name__)
class NZBGet(Downloader):
type = ['nzb']
protocol = ['nzb']
url = 'http://%(username)s:%(password)s@%(host)s/xmlrpc'

2
couchpotato/core/downloaders/nzbvortex/main.py

@ -19,7 +19,7 @@ log = CPLog(__name__)
class NZBVortex(Downloader):
type = ['nzb']
protocol = ['nzb']
api_level = None
session_id = None

4
couchpotato/core/downloaders/pneumatic/main.py

@ -9,7 +9,7 @@ log = CPLog(__name__)
class Pneumatic(Downloader):
type = ['nzb']
protocol = ['nzb']
strm_syntax = 'plugin://plugin.program.pneumatic/?mode=strm&type=add_file&nzb=%s&nzbname=%s'
def download(self, data = {}, movie = {}, filedata = None):
@ -27,7 +27,7 @@ class Pneumatic(Downloader):
try:
if not os.path.isfile(fullPath):
log.info('Downloading %s to %s.', (data.get('type'), fullPath))
log.info('Downloading %s to %s.', (data.get('protocol'), fullPath))
with open(fullPath, 'wb') as f:
f.write(filedata)

2
couchpotato/core/downloaders/sabnzbd/main.py

@ -13,7 +13,7 @@ log = CPLog(__name__)
class Sabnzbd(Downloader):
type = ['nzb']
protocol = ['nzb']
def download(self, data = {}, movie = {}, filedata = None):

28
couchpotato/core/downloaders/synology/main.py

@ -9,13 +9,13 @@ log = CPLog(__name__)
class Synology(Downloader):
type = ['nzb', 'torrent', 'torrent_magnet']
protocol = ['nzb', 'torrent', 'torrent_magnet']
log = CPLog(__name__)
def download(self, data, movie, filedata = None):
response = False
log.error('Sending "%s" (%s) to Synology.', (data['name'], data['type']))
log.error('Sending "%s" (%s) to Synology.', (data['name'], data['protocol']))
# Load host from config and split out port.
host = self.conf('host').split(':')
@ -26,38 +26,38 @@ class Synology(Downloader):
try:
# Send request to Synology
srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password'))
if data['type'] == 'torrent_magnet':
if data['protocol'] == 'torrent_magnet':
log.info('Adding torrent URL %s', data['url'])
response = srpc.create_task(url = data['url'])
elif data['type'] in ['nzb', 'torrent']:
log.info('Adding %s' % data['type'])
elif data['protocol'] in ['nzb', 'torrent']:
log.info('Adding %s' % data['protocol'])
if not filedata:
log.error('No %s data found' % data['type'])
log.error('No %s data found' % data['protocol'])
else:
filename = data['name'] + '.' + data['type']
filename = data['name'] + '.' + data['protocol']
response = srpc.create_task(filename = filename, filedata = filedata)
except Exception, err:
log.error('Exception while adding torrent: %s', err)
finally:
return response
def getEnabledDownloadType(self):
def getEnabledProtocol(self):
if self.conf('use_for') == 'both':
return super(Synology, self).getEnabledDownloadType()
return super(Synology, self).getEnabledProtocol()
elif self.conf('use_for') == 'torrent':
return ['torrent', 'torrent_magnet']
else:
return ['nzb']
def isEnabled(self, manual, data = {}):
for_type = ['both']
if data and 'torrent' in data.get('type'):
for_type.append('torrent')
for_protocol = ['both']
if data and 'torrent' in data.get('protocol'):
for_protocol.append('torrent')
elif data:
for_type.append(data.get('type'))
for_protocol.append(data.get('protocol'))
return super(Synology, self).isEnabled(manual, data) and\
((self.conf('use_for') in for_type))
((self.conf('use_for') in for_protocol))
class SynologyRPC(object):

8
couchpotato/core/downloaders/transmission/main.py

@ -16,7 +16,7 @@ log = CPLog(__name__)
class Transmission(Downloader):
type = ['torrent', 'torrent_magnet']
protocol = ['torrent', 'torrent_magnet']
log = CPLog(__name__)
trpc = None
@ -34,12 +34,12 @@ class Transmission(Downloader):
def download(self, data, movie, filedata = None):
log.info('Sending "%s" (%s) to Transmission.', (data.get('name'), data.get('type')))
log.info('Sending "%s" (%s) to Transmission.', (data.get('name'), data.get('protocol')))
if not self.connect():
return False
if not filedata and data.get('type') == 'torrent':
if not filedata and data.get('protocol') == 'torrent':
log.error('Failed sending torrent, no data')
return False
@ -64,7 +64,7 @@ class Transmission(Downloader):
torrent_params['seedIdleMode'] = 1
# Send request to Transmission
if data.get('type') == 'torrent_magnet':
if data.get('protocol') == 'torrent_magnet':
remote_torrent = self.trpc.add_torrent_uri(data.get('url'), arguments = params)
torrent_params['trackerAdd'] = self.torrent_trackers
else:

10
couchpotato/core/downloaders/utorrent/main.py

@ -20,7 +20,7 @@ log = CPLog(__name__)
class uTorrent(Downloader):
type = ['torrent', 'torrent_magnet']
protocol = ['torrent', 'torrent_magnet']
utorrent_api = None
def connect(self):
@ -36,7 +36,7 @@ class uTorrent(Downloader):
def download(self, data, movie, filedata = None):
log.debug('Sending "%s" (%s) to uTorrent.', (data.get('name'), data.get('type')))
log.debug('Sending "%s" (%s) to uTorrent.', (data.get('name'), data.get('protocol')))
if not self.connect():
return False
@ -63,11 +63,11 @@ class uTorrent(Downloader):
if self.conf('label'):
torrent_params['label'] = self.conf('label')
if not filedata and data.get('type') == 'torrent':
if not filedata and data.get('protocol') == 'torrent':
log.error('Failed sending torrent, no data')
return False
if data.get('type') == 'torrent_magnet':
if data.get('protocol') == 'torrent_magnet':
torrent_hash = re.findall('urn:btih:([\w]{32,40})', data.get('url'))[0].upper()
torrent_params['trackers'] = '%0D%0A%0D%0A'.join(self.torrent_trackers)
else:
@ -88,7 +88,7 @@ class uTorrent(Downloader):
torrent_hash = b16encode(b32decode(torrent_hash))
# Send request to uTorrent
if data.get('type') == 'torrent_magnet':
if data.get('protocol') == 'torrent_magnet':
self.utorrent_api.add_torrent_uri(data.get('url'))
else:
self.utorrent_api.add_torrent_file(torrent_filename, filedata)

7
couchpotato/core/loader.py

@ -116,12 +116,7 @@ class Loader(object):
def loadPlugins(self, module, name):
try:
klass = module.start()
klass.registerPlugin()
if klass and getattr(klass, 'auto_register_static'):
klass.registerStatic(module.__file__)
module.start()
return True
except Exception, e:
log.error('Failed loading plugin "%s": %s', (module.__file__, traceback.format_exc()))

22
couchpotato/core/media/_base/searcher/main.py

@ -19,7 +19,7 @@ log = CPLog(__name__)
class Searcher(SearcherBase):
def __init__(self):
addEvent('searcher.get_types', self.getSearchTypes)
addEvent('searcher.protocols', self.getSearchProtocols)
addEvent('searcher.contains_other_quality', self.containsOtherQuality)
addEvent('searcher.correct_year', self.correctYear)
addEvent('searcher.correct_name', self.correctName)
@ -122,29 +122,29 @@ class Searcher(SearcherBase):
return True
log.info('Tried to download, but none of the "%s" downloaders are enabled or gave an error', (data.get('type', '')))
log.info('Tried to download, but none of the "%s" downloaders are enabled or gave an error', (data.get('protocol', '')))
return False
def getSearchTypes(self):
def getSearchProtocols(self):
download_types = fireEvent('download.enabled_types', merge = True)
provider_types = fireEvent('provider.enabled_types', merge = True)
download_protocols = fireEvent('download.enabled_protocols', merge = True)
provider_protocols = fireEvent('provider.enabled_protocols', merge = True)
if download_types and len(list(set(provider_types) & set(download_types))) == 0:
log.error('There aren\'t any providers enabled for your downloader (%s). Check your settings.', ','.join(download_types))
if download_protocols and len(list(set(provider_protocols) & set(download_protocols))) == 0:
log.error('There aren\'t any providers enabled for your downloader (%s). Check your settings.', ','.join(download_protocols))
return []
for useless_provider in list(set(provider_types) - set(download_types)):
for useless_provider in list(set(provider_protocols) - set(download_protocols)):
log.debug('Provider for "%s" enabled, but no downloader.', useless_provider)
search_types = download_types
search_protocols = download_protocols
if len(search_types) == 0:
if len(search_protocols) == 0:
log.error('There aren\'t any downloaders enabled. Please pick one in settings.')
return []
return search_types
return search_protocols
def containsOtherQuality(self, nzb, movie_year = None, preferred_quality = {}):

18
couchpotato/core/media/movie/searcher/main.py

@ -85,7 +85,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
}
try:
search_types = fireEvent('searcher.get_types', single = True)
search_protocols = fireEvent('searcher.protocols', single = True)
for movie in movies:
movie_dict = movie.to_dict({
@ -97,7 +97,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
})
try:
self.single(movie_dict, search_types)
self.single(movie_dict, search_protocols)
except IndexError:
log.error('Forcing library update for %s, if you see this often, please report: %s', (movie_dict['library']['identifier'], traceback.format_exc()))
fireEvent('library.update.movie', movie_dict['library']['identifier'], force = True)
@ -115,12 +115,12 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
self.in_progress = False
def single(self, movie, search_types = None):
def single(self, movie, search_protocols = None):
# Find out search type
try:
if not search_types:
search_types = fireEvent('searcher.get_types', single = True)
if not search_protocols:
search_protocols = fireEvent('searcher.protocols', single = True)
except SearchSetupError:
return
@ -168,10 +168,10 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
quality = fireEvent('quality.single', identifier = quality_type['quality']['identifier'], single = True)
results = []
for search_type in search_types:
type_results = fireEvent('%s.search' % search_type, movie, quality, merge = True)
if type_results:
results += type_results
for search_protocol in search_protocols:
protocol_results = fireEvent('provider.search.%s.movie' % search_protocol, movie, quality, merge = True)
if protocol_results:
results += protocol_results
sorted_results = sorted(results, key = lambda k: k['score'], reverse = True)
if len(sorted_results) == 0:

20
couchpotato/core/plugins/base.py

@ -12,6 +12,7 @@ from urlparse import urlparse
import cookielib
import glob
import gzip
import inspect
import math
import os.path
import re
@ -24,6 +25,8 @@ log = CPLog(__name__)
class Plugin(object):
_class_name = None
enabled_option = 'enabled'
auto_register_static = True
@ -35,16 +38,29 @@ class Plugin(object):
http_failed_request = {}
http_failed_disabled = {}
def __new__(typ, *args, **kwargs):
new_plugin = super(Plugin, typ).__new__(typ, *args, **kwargs)
new_plugin.registerPlugin()
return new_plugin
def registerPlugin(self):
addEvent('app.do_shutdown', self.doShutdown)
addEvent('plugin.running', self.isRunning)
self._running = []
if self.auto_register_static:
self.registerStatic(inspect.getfile(self.__class__))
def conf(self, attr, value = None, default = None, section = None):
return Env.setting(attr, section = section if section else self.getName().lower(), value = value, default = default)
class_name = self.getName().lower().split(':')
return Env.setting(attr, section = section if section else class_name[0].lower(), value = value, default = default)
def getName(self):
return self.__class__.__name__
return self._class_name or self.__class__.__name__
def setName(self, name):
self._class_name = name
def renderTemplate(self, parent_file, templ, **params):

39
couchpotato/core/providers/base.py

@ -13,13 +13,32 @@ import traceback
import urllib2
import xml.etree.ElementTree as XMLTree
log = CPLog(__name__)
class MultiProvider(Plugin):
def __init__(self):
self._classes = []
for Type in self.getTypes():
klass = Type()
# Overwrite name so logger knows what we're talking about
klass.setName('%s:%s' % (self.getName(), klass.getName()))
self._classes.append(klass)
def getTypes(self):
return []
def getClasses(self):
return self._classes
class Provider(Plugin):
type = None # movie, nzb, torrent, subtitle, trailer
type = None # movie, show, subtitle, trailer, ...
http_time_between_calls = 10 # Default timeout for url requests
last_available_check = {}
@ -79,7 +98,11 @@ class Provider(Plugin):
class YarrProvider(Provider):
cat_ids = []
protocol = None # nzb, torrent, torrent_magnet
type = 'movie'
cat_ids = {}
cat_backup_id = None
sizeGb = ['gb', 'gib']
sizeMb = ['mb', 'mib']
@ -89,14 +112,13 @@ class YarrProvider(Provider):
last_login_check = 0
def __init__(self):
addEvent('provider.enabled_types', self.getEnabledProviderType)
addEvent('provider.enabled_protocols', self.getEnabledProtocol)
addEvent('provider.belongs_to', self.belongsTo)
addEvent('yarr.search', self.search)
addEvent('%s.search' % self.type, self.search)
addEvent('provider.search.%s.%s' % (self.protocol, self.type), self.search)
def getEnabledProviderType(self):
def getEnabledProtocol(self):
if self.isEnabled():
return self.type
return self.protocol
else:
return []
@ -273,6 +295,7 @@ class ResultList(list):
defaults = {
'id': 0,
'protocol': self.provider.protocol,
'type': self.provider.type,
'provider': self.provider.getName(),
'download': self.provider.loginDownload if self.provider.urls.get('login') else self.provider.download,

3
couchpotato/core/providers/nzb/base.py

@ -3,7 +3,8 @@ import time
class NZBProvider(YarrProvider):
type = 'nzb'
protocol = 'nzb'
def calculateAge(self, unix):
return int(time.time() - unix) / 24 / 60 / 60

4
couchpotato/core/providers/torrent/base.py

@ -7,7 +7,7 @@ log = CPLog(__name__)
class TorrentProvider(YarrProvider):
type = 'torrent'
protocol = 'torrent'
def imdbMatch(self, url, imdbId):
if getImdb(url) == imdbId:
@ -27,6 +27,6 @@ class TorrentProvider(YarrProvider):
class TorrentMagnetProvider(TorrentProvider):
type = 'torrent_magnet'
protocol = 'torrent_magnet'
download = None

56
couchpotato/core/providers/torrent/sceneaccess/main.py

@ -2,13 +2,21 @@ from bs4 import BeautifulSoup
from couchpotato.core.helpers.encoding import tryUrlencode, toUnicode
from couchpotato.core.helpers.variable import tryInt
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.base import MultiProvider
from couchpotato.core.providers.movie.base import MovieProvider
from couchpotato.core.providers.torrent.base import TorrentProvider
import traceback
log = CPLog(__name__)
class SceneAccess(TorrentProvider):
class SceneAccess(MultiProvider):
def getTypes(self):
return [Movie]
class Base(TorrentProvider):
urls = {
'test': 'https://www.sceneaccess.eu/',
@ -19,28 +27,26 @@ class SceneAccess(TorrentProvider):
'download': 'https://www.sceneaccess.eu/%s',
}
cat_ids = [
([22], ['720p', '1080p']),
([7], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip']),
([8], ['dvdr']),
]
http_time_between_calls = 1 #seconds
def _search(self, movie, quality, results):
def _buildUrl(self, search, quality_identifier):
url = self.urls['search'] % (
self.getCatId(quality['identifier'])[0],
self.getCatId(quality['identifier'])[0]
self.getCatId(quality_identifier)[0],
self.getCatId(quality_identifier)[0]
)
arguments = tryUrlencode({
'search': movie['library']['identifier'],
'search': search,
'method': 1,
})
url = "%s&%s" % (url, arguments)
return url
def _search(self, media, quality, results):
url = self.buildUrl(media, quality)
data = self.getHTMLData(url, opener = self.login_opener)
if data:
@ -73,13 +79,6 @@ class SceneAccess(TorrentProvider):
except:
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
return tryUrlencode({
'username': self.conf('username'),
'password': self.conf('password'),
'submit': 'come on in',
})
def getMoreInfo(self, item):
full_description = self.getCache('sceneaccess.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
html = BeautifulSoup(full_description)
@ -89,7 +88,28 @@ class SceneAccess(TorrentProvider):
item['description'] = description
return item
# Login
def getLoginParams(self):
return tryUrlencode({
'username': self.conf('username'),
'password': self.conf('password'),
'submit': 'come on in',
})
def loginSuccess(self, output):
return '/inbox' in output.lower()
loginCheckSuccess = loginSuccess
class Movie(Base, MovieProvider):
cat_ids = [
([22], ['720p', '1080p']),
([7], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip']),
([8], ['dvdr']),
]
def buildUrl(self, media, quality):
return self._buildUrl(media['library']['identifier'], quality['identifier'])

Loading…
Cancel
Save