diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py
index 50a659b0..c2187246 100644
--- a/couchpotato/core/providers/base.py
+++ b/couchpotato/core/providers/base.py
@@ -4,9 +4,11 @@ from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
from urlparse import urlparse
+import cookielib
import re
import time
import traceback
+import urllib2
log = CPLog(__name__)
@@ -48,6 +50,8 @@ class YarrProvider(Provider):
sizeMb = ['mb', 'mib']
sizeKb = ['kb', 'kib']
+ login_opener = None
+
def __init__(self):
addEvent('provider.belongs_to', self.belongsTo)
@@ -56,6 +60,34 @@ class YarrProvider(Provider):
addEvent('nzb.feed', self.feed)
+ def login(self):
+
+ try:
+ cookiejar = cookielib.CookieJar()
+ opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
+ urllib2.install_opener(opener)
+ log.info2('Logging into %s', self.urls['login'])
+ f = opener.open(self.urls['login'], self.getLoginParams())
+ f.read()
+ f.close()
+ self.login_opener = opener
+ return True
+ except:
+ log.error('Failed to login %s: %s', (self.getName(), traceback.format_exc()))
+
+ return False
+
+ def loginDownload(self, url = '', nzb_id = ''):
+ try:
+ if not self.login_opener and not self.login():
+ log.error('Failed downloading from %s', self.getName())
+ return self.urlopen(url, opener = self.login_opener)
+ except:
+ log.error('Failed downloading from %s: %s', (self.getName(), traceback.format_exc()))
+
+ def getLoginParams(self):
+ return ''
+
def download(self, url = '', nzb_id = ''):
try:
return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}, show_error = False)
diff --git a/couchpotato/core/providers/nzb/ftdworld/__init__.py b/couchpotato/core/providers/nzb/ftdworld/__init__.py
new file mode 100644
index 00000000..e11f486a
--- /dev/null
+++ b/couchpotato/core/providers/nzb/ftdworld/__init__.py
@@ -0,0 +1,31 @@
+from .main import FTDWorld
+
+def start():
+ return FTDWorld()
+
+config = [{
+ 'name': 'ftdworld',
+ 'groups': [
+ {
+ 'tab': 'searcher',
+ 'subtab': 'nzb_providers',
+ 'name': 'FTDWorld',
+ 'description': 'Free provider, less accurate. See FTDWorld',
+ 'options': [
+ {
+ 'name': 'enabled',
+ 'type': 'enabler',
+ },
+ {
+ 'name': 'username',
+ 'default': '',
+ },
+ {
+ 'name': 'password',
+ 'default': '',
+ 'type': 'password',
+ },
+ ],
+ },
+ ],
+}]
diff --git a/couchpotato/core/providers/nzb/ftdworld/main.py b/couchpotato/core/providers/nzb/ftdworld/main.py
new file mode 100644
index 00000000..8b27e00b
--- /dev/null
+++ b/couchpotato/core/providers/nzb/ftdworld/main.py
@@ -0,0 +1,107 @@
+from bs4 import BeautifulSoup
+from couchpotato.core.event import fireEvent
+from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode, \
+ simplifyString
+from couchpotato.core.helpers.variable import tryInt, getTitle
+from couchpotato.core.logger import CPLog
+from couchpotato.core.providers.nzb.base import NZBProvider
+from couchpotato.environment import Env
+from dateutil.parser import parse
+import re
+import time
+
+log = CPLog(__name__)
+
+
+class FTDWorld(NZBProvider):
+
+ urls = {
+ 'search': 'http://ftdworld.net/category.php?%s',
+ 'detail': 'http://ftdworld.net/spotinfo.php?id=%s',
+ 'download': 'http://ftdworld.net/cgi-bin/nzbdown.pl?fileID=%s',
+ 'login': 'http://ftdworld.net/index.php',
+ }
+
+ http_time_between_calls = 1 #seconds
+
+ cat_ids = [
+ ([4, 11], ['dvdr']),
+ ([1], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip']),
+ ([10, 13, 14], ['bd50', '720p', '1080p']),
+ ]
+ cat_backup_id = [1]
+
+ def search(self, movie, quality):
+
+ results = []
+ if self.isDisabled():
+ return results
+
+ q = '%s %s' % (simplifyString(getTitle(movie['library'])), movie['library']['year'])
+
+ params = {
+ 'ctitle': q,
+ 'customQuery': 'usr',
+ 'cage': Env.setting('retention', 'nzb'),
+ 'csizemin': quality.get('size_min'),
+ 'csizemax': quality.get('size_max'),
+ 'ccategory': 14,
+ 'ctype': ','.join([str(x) for x in self.getCatId(quality['identifier'])]),
+ }
+
+ cache_key = 'ftdworld.%s.%s' % (movie['library']['identifier'], q)
+ data = self.getCache(cache_key, self.urls['search'] % tryUrlencode(params), opener = self.login_opener)
+
+ if data:
+ try:
+
+ html = BeautifulSoup(data)
+ main_table = html.find('table', attrs = {'id':'ftdresult'})
+
+ if not main_table:
+ return results
+
+ items = main_table.find_all('tr', attrs = {'class': re.compile('tcontent')})
+
+ for item in items:
+ tds = item.find_all('td')
+ nzb_id = tryInt(item.attrs['data-spot'])
+
+ up = item.find('img', attrs = {'src': re.compile('up.png')})
+ down = item.find('img', attrs = {'src': re.compile('down.png')})
+
+ new = {
+ 'id': nzb_id,
+ 'type': 'nzb',
+ 'provider': self.getName(),
+ 'name': toUnicode(item.find('a', attrs = {'href': re.compile('./spotinfo')}).text.strip()),
+ 'age': self.calculateAge(int(time.mktime(parse(tds[2].text).timetuple()))),
+ 'size': 0,
+ 'url': self.urls['download'] % nzb_id,
+ 'download': self.loginDownload,
+ 'detail_url': self.urls['detail'] % nzb_id,
+ 'description': '',
+ 'score': (tryInt(up.attrs['title'].split(' ')[0]) * 3) - (tryInt(down.attrs['title'].split(' ')[0]) * 3),
+ }
+
+ is_correct_movie = fireEvent('searcher.correct_movie',
+ nzb = new, movie = movie, quality = quality,
+ imdb_results = False, single = True)
+
+ if is_correct_movie:
+ new['score'] += fireEvent('score.calculate', new, movie, single = True)
+ results.append(new)
+ self.found(new)
+
+ return results
+ except SyntaxError:
+ log.error('Failed to parse XML response from NZBClub')
+
+ return results
+
+ def getLoginParams(self):
+ return tryUrlencode({
+ 'userlogin': self.conf('username'),
+ 'passlogin': self.conf('password'),
+ 'submit': 'Log In',
+ })
diff --git a/couchpotato/core/providers/nzb/newznab/__init__.py b/couchpotato/core/providers/nzb/newznab/__init__.py
index b0e8b484..c9507f91 100644
--- a/couchpotato/core/providers/nzb/newznab/__init__.py
+++ b/couchpotato/core/providers/nzb/newznab/__init__.py
@@ -11,7 +11,9 @@ config = [{
'subtab': 'nzb_providers',
'name': 'newznab',
'order': 10,
- 'description': 'Enable multiple NewzNab providers such as NZB.su and nzbs.org',
+ 'description': 'Enable NewzNab providers such as NZB.su, \
+ NZBs.org, DOGnzb.cr, \
+ Spotweb',
'wizard': True,
'options': [
{
diff --git a/couchpotato/core/providers/torrent/base.py b/couchpotato/core/providers/torrent/base.py
index fc2d35e2..79d5b1e6 100644
--- a/couchpotato/core/providers/torrent/base.py
+++ b/couchpotato/core/providers/torrent/base.py
@@ -1,9 +1,6 @@
from couchpotato.core.helpers.variable import getImdb, md5
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.base import YarrProvider
-import cookielib
-import traceback
-import urllib2
log = CPLog(__name__)
@@ -11,7 +8,6 @@ log = CPLog(__name__)
class TorrentProvider(YarrProvider):
type = 'torrent'
- login_opener = None
def imdbMatch(self, url, imdbId):
if getImdb(url) == imdbId:
@@ -28,30 +24,3 @@ class TorrentProvider(YarrProvider):
return getImdb(data) == imdbId
return False
-
- def login(self):
-
- try:
- cookiejar = cookielib.CookieJar()
- opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
- urllib2.install_opener(opener)
- f = opener.open(self.urls['login'], self.getLoginParams())
- f.read()
- f.close()
- self.login_opener = opener
- return True
- except:
- log.error('Failed to login %s: %s', (self.getName(), traceback.format_exc()))
-
- return False
-
- def loginDownload(self, url = '', nzb_id = ''):
- try:
- if not self.login_opener and not self.login():
- log.error('Failed downloading from %s', self.getName())
- return self.urlopen(url, opener = self.login_opener)
- except:
- log.error('Failed downloading from %s: %s', (self.getName(), traceback.format_exc()))
-
- def getLoginParams(self):
- return ''