diff --git a/couchpotato/core/downloaders/utorrent.py b/couchpotato/core/downloaders/utorrent.py
index 2bfc64e..264e496 100644
--- a/couchpotato/core/downloaders/utorrent.py
+++ b/couchpotato/core/downloaders/utorrent.py
@@ -176,7 +176,7 @@ class uTorrent(DownloaderBase):
status = 'busy'
if (torrent[1] & self.status_flags['STARTED'] or torrent[1] & self.status_flags['QUEUED']) and torrent[4] == 1000:
status = 'seeding'
- elif torrent[1] & self.status_flags['ERROR']:
+ elif torrent[1] & self.status_flags['ERROR'] and 'There is not enough space on the disk' not in torrent[21]:
status = 'failed'
elif torrent[4] == 1000:
status = 'completed'
diff --git a/couchpotato/core/media/_base/providers/torrent/torrentday.py b/couchpotato/core/media/_base/providers/torrent/torrentday.py
index 2d27d24..aecb682 100644
--- a/couchpotato/core/media/_base/providers/torrent/torrentday.py
+++ b/couchpotato/core/media/_base/providers/torrent/torrentday.py
@@ -9,12 +9,12 @@ log = CPLog(__name__)
class Base(TorrentProvider):
urls = {
- 'test': 'https://classic.torrentday.com/',
- 'login': 'https://classic.torrentday.com/torrents/',
- 'login_check': 'https://classic.torrentday.com/userdetails.php',
- 'detail': 'https://classic.torrentday.com/details.php?id=%s',
- 'search': 'https://classic.torrentday.com/V3/API/API.php',
- 'download': 'https://classic.torrentday.com/download.php/%s/%s',
+ 'test': 'https://www.torrentday.com/',
+ 'login': 'https://www.torrentday.com/torrents/',
+ 'login_check': 'https://www.torrentday.com/userdetails.php',
+ 'detail': 'https://www.torrentday.com/details.php?id=%s',
+ 'search': 'https://www.torrentday.com/V3/API/API.php',
+ 'download': 'https://www.torrentday.com/download.php/%s/%s',
}
http_time_between_calls = 1 # Seconds
@@ -86,7 +86,7 @@ config = [{
'tab': 'searcher',
'list': 'torrent_providers',
'name': 'TorrentDay',
- 'description': 'TorrentDay',
+ 'description': 'TorrentDay',
'wizard': True,
'icon': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC5ElEQVQ4y12TXUgUURTH//fO7Di7foeQJH6gEEEIZZllVohfSG/6UA+RSFAQQj74VA8+Bj30lmAlRVSEvZRfhNhaka5ZUG1paKaW39tq5O6Ou+PM3M4o6m6X+XPPzD3zm/+dcy574r515WfIW8CZBM4YAA5Gc/aQC3yd7oXYEONcsISE5dTDh91HS0t7FEWhBUAeN9ynV/d9qJAgE4AECURAcVsGlCCnly26LMA0IQwTa52dje3d3e3hcPi8qqrrMjcVYI3EHCQZlkFOHBwR2QHh2ASAAIJxWGAQEDxjePhs3527XjJwnb37OHBq0T+Tyyjh+9KnEzNJ7nouc1Q/3A3HGsOvnJy+PSUlj81w2Lny9WuJ6+3AmTjD4HOcrdR2dWXLRQePvyaSLfQOPMPC8mC9iHCsOxSyzJCelzdSXlNzD5ujpb25Wbfc/XXJemTXF4+nnCNq+AMLe50uFfEJTiw4GXSFtiHL0SnIq66+p0kSArqO+eH3RdsAv9+f5vW7L7GICq6rmM8XBCAXlBw90rOyxibn5yzfkg/L09M52/jxqdESaIrBXHYZZbB1GX8cEpySxKIB8S5XcOnvqpli1zuwmrTtoLjw5LOK/eeuWsE4JH5IRPaPZKiKigmPp+5pa+u1aEjIMhEgrRkmi9mgxGUhM7LNJSzOzsE3+cOeExovXOjdytE0LV4zqNZUtV0uZzAGoGkhDH/2YHZiErmv4uyWQnZZWc+hoqL3WzlTExN5hhA8IEwkZWZOxwB++30YG/9GkYCPvqAaHAW5uWPROW86OmqCprUR7z1yZDAGQNuCvkoB/baIKUBWMTYymv+gra3eJNvjXu+B562tFyXqTJ6YuHK8rKwvBmC3vR7cOCPQLWFz8LnfXWUrJo9U19BwMyUlJRjTSMJ2ENxUiGxq9KXQfwqYlnWstvbR5aamG9g0uzM8Q4OFt++3NNixQ2NgYmeN03FOTUv7XVpV9aKisvLl1vN/WVhNc/Fi1NEAAAAASUVORK5CYII=',
'options': [
diff --git a/couchpotato/core/media/_base/providers/torrent/yts.py b/couchpotato/core/media/_base/providers/torrent/yts.py
index f4567a9..188f9e5 100644
--- a/couchpotato/core/media/_base/providers/torrent/yts.py
+++ b/couchpotato/core/media/_base/providers/torrent/yts.py
@@ -1,7 +1,6 @@
from datetime import datetime
-from couchpotato.core.helpers.variable import tryInt
+from couchpotato.core.helpers.variable import tryInt, getIdentifier
from couchpotato.core.logger import CPLog
-from couchpotato.core.helpers.variable import getTitle
from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider
import random
@@ -19,7 +18,7 @@ class Base(TorrentMagnetProvider):
def _search(self, movie, quality, results):
limit = 10
page = 1
- data = self.getJsonData(self.urls['search'] % (getTitle(movie), limit, page))
+ data = self.getJsonData(self.urls['search'] % (getIdentifier(movie), limit, page))
if data:
movie_count = tryInt(data['data']['movie_count'])
@@ -32,37 +31,32 @@ class Base(TorrentMagnetProvider):
for i in range(0,len(movie_results)):
result = data['data']['movies'][i]
name = result['title']
-
- t = movie['info']['original_title'].split(' ')
-
- if all(word in name for word in t) and movie['info']['year'] == result['year']:
-
- year = result['year']
- detail_url = result['url']
-
- for torrent in result['torrents']:
- t_quality = torrent['quality']
-
- if t_quality in quality['label']:
- hash = torrent['hash']
- size = tryInt(torrent['size_bytes'] / 1048576)
- seeders = tryInt(torrent['seeds'])
- leechers = tryInt(torrent['peers'])
- pubdate = torrent['date_uploaded'] # format: 2017-02-17 18:40:03
- pubdate = datetime.strptime(pubdate, '%Y-%m-%d %H:%M:%S')
- age = (datetime.now() - pubdate).days
-
- results.append({
- 'id': random.randint(100, 9999),
- 'name': '%s (%s) %s %s %s' % (name, year, 'YTS', t_quality, 'BR-Rip'),
- 'url': self.make_magnet(hash, name),
- 'size': size,
- 'seeders': seeders,
- 'leechers': leechers,
- 'age': age,
- 'detail_url': detail_url,
- 'score': 1
- })
+ year = result['year']
+ detail_url = result['url']
+
+ for torrent in result['torrents']:
+ t_quality = torrent['quality']
+
+ if t_quality in quality['label']:
+ hash = torrent['hash']
+ size = tryInt(torrent['size_bytes'] / 1048576)
+ seeders = tryInt(torrent['seeds'])
+ leechers = tryInt(torrent['peers'])
+ pubdate = torrent['date_uploaded'] # format: 2017-02-17 18:40:03
+ pubdate = datetime.strptime(pubdate, '%Y-%m-%d %H:%M:%S')
+ age = (datetime.now() - pubdate).days
+
+ results.append({
+ 'id': random.randint(100, 9999),
+ 'name': '%s (%s) %s %s %s' % (name, year, 'YTS', t_quality, 'BR-Rip'),
+ 'url': self.make_magnet(hash, name),
+ 'size': size,
+ 'seeders': seeders,
+ 'leechers': leechers,
+ 'age': age,
+ 'detail_url': detail_url,
+ 'score': 1
+ })
return
diff --git a/couchpotato/core/media/movie/providers/automation/kinepolis.py b/couchpotato/core/media/movie/providers/automation/kinepolis.py
deleted file mode 100644
index a0f2596..0000000
--- a/couchpotato/core/media/movie/providers/automation/kinepolis.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import datetime
-
-from couchpotato.core.helpers.rss import RSS
-from couchpotato.core.logger import CPLog
-from couchpotato.core.media.movie.providers.automation.base import Automation
-
-
-log = CPLog(__name__)
-
-autoload = 'Kinepolis'
-
-
-class Kinepolis(Automation, RSS):
-
- interval = 1800
- rss_url = 'http://kinepolis.be/nl/top10-box-office/feed'
-
- def getIMDBids(self):
-
- movies = []
-
- rss_movies = self.getRSSData(self.rss_url)
-
- for movie in rss_movies:
- name = self.getTextElement(movie, 'title')
- year = datetime.datetime.now().strftime('%Y')
-
- imdb = self.search(name, year)
-
- if imdb and self.isMinimalMovie(imdb):
- movies.append(imdb['imdb'])
-
- return movies
-
-
-config = [{
- 'name': 'kinepolis',
- 'groups': [
- {
- 'tab': 'automation',
- 'list': 'automation_providers',
- 'name': 'kinepolis_automation',
- 'label': 'Kinepolis',
- 'description': 'Imports movies from the current top 10 of kinepolis.',
- 'options': [
- {
- 'name': 'automation_enabled',
- 'default': False,
- 'type': 'enabler',
- },
- ],
- },
- ],
-}]
diff --git a/couchpotato/core/media/movie/providers/automation/moviemeter.py b/couchpotato/core/media/movie/providers/automation/moviemeter.py
deleted file mode 100644
index 624ffb6..0000000
--- a/couchpotato/core/media/movie/providers/automation/moviemeter.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from couchpotato.core.helpers.rss import RSS
-from couchpotato.core.logger import CPLog
-from couchpotato.core.media.movie.providers.automation.base import Automation
-
-log = CPLog(__name__)
-
-autoload = 'Moviemeter'
-
-
-class Moviemeter(Automation, RSS):
-
- interval = 1800
- rss_url = 'http://www.moviemeter.nl/rss/cinema'
-
- def getIMDBids(self):
-
- movies = []
-
- rss_movies = self.getRSSData(self.rss_url)
-
- for movie in rss_movies:
- imdb = self.search(self.getTextElement(movie, 'title'))
-
- if imdb and self.isMinimalMovie(imdb):
- movies.append(imdb['imdb'])
-
- return movies
-
-
-config = [{
- 'name': 'moviemeter',
- 'groups': [
- {
- 'tab': 'automation',
- 'list': 'automation_providers',
- 'name': 'moviemeter_automation',
- 'label': 'Moviemeter',
- 'description': 'Imports movies from the current top 10 of moviemeter.nl.',
- 'options': [
- {
- 'name': 'automation_enabled',
- 'default': False,
- 'type': 'enabler',
- },
- ],
- },
- ],
-}]
diff --git a/couchpotato/core/media/movie/providers/automation/movies_io.py b/couchpotato/core/media/movie/providers/automation/movies_io.py
deleted file mode 100644
index 3930906..0000000
--- a/couchpotato/core/media/movie/providers/automation/movies_io.py
+++ /dev/null
@@ -1,72 +0,0 @@
-from couchpotato.core.event import fireEvent
-from couchpotato.core.helpers.rss import RSS
-from couchpotato.core.helpers.variable import tryInt, splitString
-from couchpotato.core.logger import CPLog
-from couchpotato.core.media.movie.providers.automation.base import Automation
-
-log = CPLog(__name__)
-
-autoload = 'MoviesIO'
-
-
-class MoviesIO(Automation, RSS):
-
- interval = 1800
-
- def getIMDBids(self):
-
- movies = []
-
- enablers = [tryInt(x) for x in splitString(self.conf('automation_urls_use'))]
-
- index = -1
- for rss_url in splitString(self.conf('automation_urls')):
-
- index += 1
- if not enablers[index]:
- continue
-
- rss_movies = self.getRSSData(rss_url, headers = {'Referer': ''})
-
- for movie in rss_movies:
-
- nameyear = fireEvent('scanner.name_year', self.getTextElement(movie, 'title'), single = True)
- imdb = self.search(nameyear.get('name'), nameyear.get('year'), imdb_only = True)
-
- if not imdb:
- continue
-
- movies.append(imdb)
-
- return movies
-
-
-config = [{
- 'name': 'moviesio',
- 'groups': [
- {
- 'tab': 'automation',
- 'list': 'watchlist_providers',
- 'name': 'moviesio',
- 'label': 'Movies.IO',
- 'description': 'Imports movies from Movies.io RSS watchlists',
- 'options': [
- {
- 'name': 'automation_enabled',
- 'default': False,
- 'type': 'enabler',
- },
- {
- 'name': 'automation_urls_use',
- 'label': 'Use',
- },
- {
- 'name': 'automation_urls',
- 'label': 'url',
- 'type': 'combined',
- 'combine': ['automation_urls_use', 'automation_urls'],
- },
- ],
- },
- ],
-}]
diff --git a/couchpotato/core/media/movie/providers/info/omdbapi.py b/couchpotato/core/media/movie/providers/info/omdbapi.py
index 3f257c6..e72762f 100644
--- a/couchpotato/core/media/movie/providers/info/omdbapi.py
+++ b/couchpotato/core/media/movie/providers/info/omdbapi.py
@@ -18,8 +18,8 @@ autoload = 'OMDBAPI'
class OMDBAPI(MovieProvider):
urls = {
- 'search': 'http://www.omdbapi.com/?type=movie&%s',
- 'info': 'http://www.omdbapi.com/?type=movie&i=%s',
+ 'search': 'https://www.omdbapi.com/?apikey=%s&type=movie&%s',
+ 'info': 'https://www.omdbapi.com/?apikey=%s&type=movie&i=%s',
}
http_time_between_calls = 0
@@ -30,6 +30,8 @@ class OMDBAPI(MovieProvider):
addEvent('movie.info', self.getInfo)
def search(self, q, limit = 12):
+ if self.isDisabled():
+ return []
name_year = fireEvent('scanner.name_year', q, single = True)
@@ -39,7 +41,7 @@ class OMDBAPI(MovieProvider):
}
cache_key = 'omdbapi.cache.%s' % q
- url = self.urls['search'] % tryUrlencode({'t': name_year.get('name'), 'y': name_year.get('year', '')})
+ url = self.urls['search'] % (self.getApiKey(), tryUrlencode({'t': name_year.get('name'), 'y': name_year.get('year', '')}))
cached = self.getCache(cache_key, url, timeout = 3, headers = {'User-Agent': Env.getIdentifier()})
if cached:
@@ -53,12 +55,12 @@ class OMDBAPI(MovieProvider):
return []
def getInfo(self, identifier = None, **kwargs):
-
- if not identifier:
+ if self.isDisabled() or not identifier:
return {}
cache_key = 'omdbapi.cache.%s' % identifier
- cached = self.getCache(cache_key, self.urls['info'] % identifier, timeout = 3, headers = {'User-Agent': Env.getIdentifier()})
+ url = self.urls['info'] % (self.getApiKey(), identifier)
+ cached = self.getCache(cache_key, url, timeout = 3, headers = {'User-Agent': Env.getIdentifier()})
if cached:
result = self.parseMovie(cached)
@@ -89,7 +91,7 @@ class OMDBAPI(MovieProvider):
tmp_movie = movie.copy()
for key in tmp_movie:
tmp_movie_elem = tmp_movie.get(key)
- if not isinstance(tmp_movie_elem, str) or tmp_movie_elem.lower() == 'n/a':
+ if not isinstance(tmp_movie_elem, (str, unicode)) or tmp_movie_elem.lower() == 'n/a':
del movie[key]
year = tryInt(movie.get('Year', ''))
@@ -123,6 +125,16 @@ class OMDBAPI(MovieProvider):
return movie_data
+ def isDisabled(self):
+ if self.getApiKey() == '':
+ log.error('No API key provided.')
+ return True
+ return False
+
+ def getApiKey(self):
+ apikey = self.conf('api_key')
+ return apikey
+
def runtimeToMinutes(self, runtime_str):
runtime = 0
@@ -133,3 +145,24 @@ class OMDBAPI(MovieProvider):
runtime += tryInt(nr) * (60 if 'h' is str(size)[0] else 1)
return runtime
+
+
+config = [{
+ 'name': 'omdbapi',
+ 'groups': [
+ {
+ 'tab': 'providers',
+ 'name': 'tmdb',
+ 'label': 'OMDB API',
+ 'hidden': True,
+ 'description': 'Used for all calls to TheMovieDB.',
+ 'options': [
+ {
+ 'name': 'api_key',
+ 'default': 'bbc0e412', # Don't be a dick and use this somewhere else
+ 'label': 'Api Key',
+ },
+ ],
+ },
+ ],
+}]
diff --git a/couchpotato/core/media/movie/providers/userscript/filmstarts.py b/couchpotato/core/media/movie/providers/userscript/filmstarts.py
index 4e61f29..5201ce0 100644
--- a/couchpotato/core/media/movie/providers/userscript/filmstarts.py
+++ b/couchpotato/core/media/movie/providers/userscript/filmstarts.py
@@ -1,5 +1,6 @@
from bs4 import BeautifulSoup
from couchpotato.core.media._base.providers.userscript.base import UserscriptBase
+import re
autoload = 'Filmstarts'
@@ -15,16 +16,16 @@ class Filmstarts(UserscriptBase):
return
html = BeautifulSoup(data)
- table = html.find("table", attrs={"class": "table table-standard thead-standard table-striped_2 fs11"})
+ table = html.find("section", attrs={"class": "section ovw ovw-synopsis", "id": "synopsis-details"})
- if table.find(text='Originaltitel'):
+ if table.find(text=re.compile('Originaltitel')): #some trailing whitespaces on some pages
# Get original film title from the table specified above
- name = table.find("div", text="Originaltitel").parent.parent.parent.td.text
+ name = name = table.find("span", text=re.compile("Originaltitel")).findNext('h2').text
else:
# If none is available get the title from the meta data
name = html.find("meta", {"property":"og:title"})['content']
# Year of production is not available in the meta data, so get it from the table
- year = table.find(text="Produktionsjahr").parent.parent.next_sibling.text
+ year = table.find("span", text=re.compile("Produktionsjahr")).findNext('span').text
return self.search(name, year)
diff --git a/couchpotato/core/notifications/script.py b/couchpotato/core/notifications/script.py
index 9d8f753..1736c33 100644
--- a/couchpotato/core/notifications/script.py
+++ b/couchpotato/core/notifications/script.py
@@ -1,38 +1,48 @@
import traceback
import subprocess
+import os
from couchpotato.core.helpers.encoding import toUnicode
from couchpotato.core.helpers.variable import getIdentifier
+from couchpotato.api import addApiView
+from couchpotato.core.event import addEvent
from couchpotato.core.logger import CPLog
from couchpotato.core.notifications.base import Notification
+
+
log = CPLog(__name__)
autoload = 'Script'
class Script(Notification):
- def notify(self, message = '', data = None, listener = None):
- if not data: data = {}
+ def __init__(self):
+ addApiView(self.testNotifyName(), self.test)
- script_data = {
- 'message': toUnicode(message)
- }
+ addEvent('renamer.after', self.runScript)
- if getIdentifier(data):
- script_data.update({
- 'imdb_id': getIdentifier(data)
- })
+ def runScript(self, message = None, group = None):
+ if self.isDisabled(): return
+ if not group: group = {}
+ command = [self.conf('path'), group.get('destination_dir')]
+ log.info('Executing script command: %s ', command)
try:
- subprocess.call([self.conf('path'), message])
+ p = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
+ out = p.communicate()
+ log.info('Result from script: %s', str(out))
return True
- except:
- log.error('Script notification failed: %s', traceback.format_exc())
+ except OSError as e:
+ log.error('Unable to run script: %s', e)
return False
+ def test(self, **kwargs):
+ return {
+ 'success': os.path.isfile(self.conf('path'))
+ }
config = [{
'name': 'script',
diff --git a/couchpotato/core/plugins/log/static/log.js b/couchpotato/core/plugins/log/static/log.js
index a0b1f7c..997ec87 100644
--- a/couchpotato/core/plugins/log/static/log.js
+++ b/couchpotato/core/plugins/log/static/log.js
@@ -250,7 +250,7 @@ Page.Log = new Class({
new Element('a.button', {
'target': '_blank',
'text': 'the contributing guide',
- 'href': 'https://github.com/CouchPotato/CouchPotatoServer/blob/develop/contributing.md'
+ 'href': 'https://github.com/CouchPotato/CouchPotatoServer/wiki/Developer-branch'
}),
new Element('span', {
'html': ' before posting, then copy the text below and FILL IN the dots.'
diff --git a/couchpotato/core/plugins/subtitle.py b/couchpotato/core/plugins/subtitle.py
index 135ec2d..110fe11 100644
--- a/couchpotato/core/plugins/subtitle.py
+++ b/couchpotato/core/plugins/subtitle.py
@@ -16,7 +16,7 @@ autoload = 'Subtitle'
class Subtitle(Plugin):
- services = ['opensubtitles', 'thesubdb', 'subswiki', 'subscenter']
+ services = ['opensubtitles', 'thesubdb', 'subswiki', 'subscenter', 'wizdom']
def __init__(self):
addEvent('renamer.before', self.searchSingle)
diff --git a/couchpotato/static/scripts/combined.plugins.min.js b/couchpotato/static/scripts/combined.plugins.min.js
index 475c053..b93d282 100644
--- a/couchpotato/static/scripts/combined.plugins.min.js
+++ b/couchpotato/static/scripts/combined.plugins.min.js
@@ -3093,7 +3093,7 @@ Page.Log = new Class({
}), new Element("a.button", {
target: "_blank",
text: "the contributing guide",
- href: "https://github.com/CouchPotato/CouchPotatoServer/blob/develop/contributing.md"
+ href: "https://github.com/CouchPotato/CouchPotatoServer/wiki/Developer-branch"
}), new Element("span", {
html: " before posting, then copy the text below and FILL IN the dots."
})), textarea = new Element("textarea", {
diff --git a/libs/rtorrent/__init__.py b/libs/rtorrent/__init__.py
index 0d64e81..f6980bd 100644
--- a/libs/rtorrent/__init__.py
+++ b/libs/rtorrent/__init__.py
@@ -74,7 +74,9 @@ class RTorrent:
if m.is_retriever() and m.is_available(self)]
m = rtorrent.rpc.Multicall(self)
- m.add("d.multicall", view, "d.get_hash=",
+ # multicall2 wants .. something .. as its first argument. It accepts a blank string, so let's go with that.
+ MCFirstArg = ""
+ m.add("d.multicall2", MCFirstArg, view, "d.hash=",
*[method.rpc_call + "=" for method in retriever_methods])
results = m.call()[0] # only sent one call, only need first result
@@ -116,7 +118,7 @@ class RTorrent:
elif verbose:
func_name = "load.verbose"
else:
- func_name = "load"
+ func_name = "load.normal"
elif file_type in ["file", "raw"]:
if start and verbose:
func_name = "load.raw_start_verbose"
@@ -137,31 +139,49 @@ class RTorrent:
func_name = self._get_load_function("url", start, verbose)
+ # rtorrent > 0.9.6 requires first parameter @target
+ target = ""
# load magnet
- getattr(p, func_name)(magneturl)
+ getattr(p, func_name)(target, magneturl)
if verify_load:
+ magnet = False
i = 0
while i < verify_retries:
- for torrent in self.get_torrents():
- if torrent.info_hash != info_hash:
- continue
+ for m in self.get_torrents():
+ # This block finds the magnet that was just added, starts it, breaks
+ # out of the for loop, and then out of the while loop.
+ # If it can't find the magnet, magnet won't get defined.
+ if m.info_hash == info_hash:
+ magnet = m
+ magnet.start()
+ i += 999
+ break
+
+ # If torrent hasn't been defined, sleep for a second and check again.
+ if not magnet:
time.sleep(1)
i += 1
- # Resolve magnet to torrent
- torrent.start()
+ # This bit waits for the magnet to be resolved into an actual
+ # torrent, and then starts it.
+ torrent = False
+ i = 0
+ while i < verify_retries:
+ for t in self.get_torrents():
+ if t.info_hash == info_hash:
+ if str(info_hash) not in str(t.name):
+ torrent = t
+ torrent.start()
+ i += 999
+ break
+ if not torrent:
+ time.sleep(1)
+ i += 1
assert info_hash in [t.info_hash for t in self.torrents],\
"Adding magnet was unsuccessful."
- i = 0
- while i < verify_retries:
- for torrent in self.get_torrents():
- if torrent.info_hash == info_hash:
- if str(info_hash) not in str(torrent.name):
- time.sleep(1)
- i += 1
return(torrent)
diff --git a/libs/rtorrent/file.py b/libs/rtorrent/file.py
index a3db35c..758ed76 100755
--- a/libs/rtorrent/file.py
+++ b/libs/rtorrent/file.py
@@ -59,29 +59,29 @@ class File:
methods = [
# RETRIEVERS
- Method(File, 'get_last_touched', 'f.get_last_touched'),
- Method(File, 'get_range_second', 'f.get_range_second'),
- Method(File, 'get_size_bytes', 'f.get_size_bytes'),
- Method(File, 'get_priority', 'f.get_priority'),
- Method(File, 'get_match_depth_next', 'f.get_match_depth_next'),
+ Method(File, 'get_last_touched', 'f.last_touched'),
+ Method(File, 'get_range_second', 'f.range_second'),
+ Method(File, 'get_size_bytes', 'f.size_bytes'),
+ Method(File, 'get_priority', 'f.priority'),
+ Method(File, 'get_match_depth_next', 'f.match_depth_next'),
Method(File, 'is_resize_queued', 'f.is_resize_queued',
boolean=True,
),
- Method(File, 'get_range_first', 'f.get_range_first'),
- Method(File, 'get_match_depth_prev', 'f.get_match_depth_prev'),
- Method(File, 'get_path', 'f.get_path'),
- Method(File, 'get_completed_chunks', 'f.get_completed_chunks'),
- Method(File, 'get_path_components', 'f.get_path_components'),
+ Method(File, 'get_range_first', 'f.range_first'),
+ Method(File, 'get_match_depth_prev', 'f.match_depth_prev'),
+ Method(File, 'get_path', 'f.path'),
+ Method(File, 'get_completed_chunks', 'f.completed_chunks'),
+ Method(File, 'get_path_components', 'f.path_components'),
Method(File, 'is_created', 'f.is_created',
boolean=True,
),
Method(File, 'is_open', 'f.is_open',
boolean=True,
),
- Method(File, 'get_size_chunks', 'f.get_size_chunks'),
- Method(File, 'get_offset', 'f.get_offset'),
- Method(File, 'get_frozen_path', 'f.get_frozen_path'),
- Method(File, 'get_path_depth', 'f.get_path_depth'),
+ Method(File, 'get_size_chunks', 'f.size_chunks'),
+ Method(File, 'get_offset', 'f.offset'),
+ Method(File, 'get_frozen_path', 'f.frozen_path'),
+ Method(File, 'get_path_depth', 'f.path_depth'),
Method(File, 'is_create_queued', 'f.is_create_queued',
boolean=True,
),
diff --git a/libs/rtorrent/peer.py b/libs/rtorrent/peer.py
index 61ca094..f998812 100755
--- a/libs/rtorrent/peer.py
+++ b/libs/rtorrent/peer.py
@@ -60,39 +60,39 @@ methods = [
Method(Peer, 'is_preferred', 'p.is_preferred',
boolean=True,
),
- Method(Peer, 'get_down_rate', 'p.get_down_rate'),
+ Method(Peer, 'get_down_rate', 'p.down_rate'),
Method(Peer, 'is_unwanted', 'p.is_unwanted',
boolean=True,
),
- Method(Peer, 'get_peer_total', 'p.get_peer_total'),
- Method(Peer, 'get_peer_rate', 'p.get_peer_rate'),
- Method(Peer, 'get_port', 'p.get_port'),
+ Method(Peer, 'get_peer_total', 'p.peer_total'),
+ Method(Peer, 'get_peer_rate', 'p.peer_rate'),
+ Method(Peer, 'get_port', 'p.port'),
Method(Peer, 'is_snubbed', 'p.is_snubbed',
boolean=True,
),
- Method(Peer, 'get_id_html', 'p.get_id_html'),
- Method(Peer, 'get_up_rate', 'p.get_up_rate'),
+ Method(Peer, 'get_id_html', 'p.id_html'),
+ Method(Peer, 'get_up_rate', 'p.up_rate'),
Method(Peer, 'is_banned', 'p.banned',
boolean=True,
),
- Method(Peer, 'get_completed_percent', 'p.get_completed_percent'),
+ Method(Peer, 'get_completed_percent', 'p.completed_percent'),
Method(Peer, 'completed_percent', 'p.completed_percent'),
- Method(Peer, 'get_id', 'p.get_id'),
+ Method(Peer, 'get_id', 'p.id'),
Method(Peer, 'is_obfuscated', 'p.is_obfuscated',
boolean=True,
),
- Method(Peer, 'get_down_total', 'p.get_down_total'),
- Method(Peer, 'get_client_version', 'p.get_client_version'),
- Method(Peer, 'get_address', 'p.get_address'),
+ Method(Peer, 'get.down.total', 'p.down_total'),
+ Method(Peer, 'get_client_version', 'p.client_version'),
+ Method(Peer, 'get_address', 'p.address'),
Method(Peer, 'is_incoming', 'p.is_incoming',
boolean=True,
),
Method(Peer, 'is_encrypted', 'p.is_encrypted',
boolean=True,
),
- Method(Peer, 'get_options_str', 'p.get_options_str'),
+ Method(Peer, 'get_options_str', 'p.options_str'),
Method(Peer, 'get_client_version', 'p.client_version'),
- Method(Peer, 'get_up_total', 'p.get_up_total'),
+ Method(Peer, 'get_up_total', 'p.up_total'),
# MODIFIERS
]
diff --git a/libs/rtorrent/rpc/__init__.py b/libs/rtorrent/rpc/__init__.py
index 607d409..e294a72 100755
--- a/libs/rtorrent/rpc/__init__.py
+++ b/libs/rtorrent/rpc/__init__.py
@@ -38,13 +38,13 @@ def get_varname(rpc_call):
r = re.search(
"([ptdf]\.|system\.|get\_|is\_|set\_)+([^=]*)", rpc_call, re.I)
if r:
- return(r.groups()[-1])
+ return(r.groups()[-1].replace(".","_"))
else:
return(None)
def _handle_unavailable_rpc_method(method, rt_obj):
- msg = "Method isn't available."
+ msg = "Method " + str(method) + " isn't available."
if rt_obj.connection._get_client_version_tuple() < method.min_version:
msg = "This method is only available in " \
"RTorrent version v{0} or later".format(
@@ -91,7 +91,7 @@ class Method:
def _get_method_type(self):
"""Determine whether method is a modifier or a retriever"""
- if self.method_name[:4] == "set_": return('m') # modifier
+ if self.method_name[:4] == "set_" or self.method_name[-4:] == ".set": return('m') # modifier
else:
return('r') # retriever
diff --git a/libs/rtorrent/torrent.py b/libs/rtorrent/torrent.py
index bd6bb68..f4f1406 100755
--- a/libs/rtorrent/torrent.py
+++ b/libs/rtorrent/torrent.py
@@ -139,7 +139,7 @@ class Torrent:
results = m.call()[0] # only sent one call, only need first result
offset_method_index = retriever_methods.index(
- rtorrent.rpc.find_method("f.get_offset"))
+ rtorrent.rpc.find_method("f.offset"))
# make a list of the offsets of all the files, sort appropriately
offset_list = sorted([r[offset_method_index] for r in results])
@@ -168,7 +168,7 @@ class Torrent:
"""
m = rtorrent.rpc.Multicall(self)
self.multicall_add(m, "d.try_stop")
- self.multicall_add(m, "d.set_directory", d)
+ self.multicall_add(m, "d.directory.set", d)
self.directory = m.call()[-1]
@@ -181,7 +181,7 @@ class Torrent:
"""
m = rtorrent.rpc.Multicall(self)
self.multicall_add(m, "d.try_stop")
- self.multicall_add(m, "d.set_directory_base", d)
+ self.multicall_add(m, "d.directory_base.set", d)
def start(self):
"""Start the torrent"""
@@ -304,7 +304,7 @@ class Torrent:
m = rtorrent.rpc.Multicall(self)
field = "custom{0}".format(key)
- self.multicall_add(m, "d.get_{0}".format(field))
+ self.multicall_add(m, "d.{0}".format(field))
setattr(self, field, m.call()[-1])
return (getattr(self, field))
@@ -326,7 +326,7 @@ class Torrent:
self._assert_custom_key_valid(key)
m = rtorrent.rpc.Multicall(self)
- self.multicall_add(m, "d.set_custom{0}".format(key), value)
+ self.multicall_add(m, "d.custom{0}.set".format(key), value)
return(m.call()[-1])
@@ -355,7 +355,7 @@ class Torrent:
@note: Variable where the result for this method is stored Torrent.hash_checking_queued"""
m = rtorrent.rpc.Multicall(self)
- self.multicall_add(m, "d.get_hashing")
+ self.multicall_add(m, "d.hashing")
self.multicall_add(m, "d.is_hash_checking")
results = m.call()
@@ -397,86 +397,86 @@ methods = [
Method(Torrent, 'is_hash_checking', 'd.is_hash_checking',
boolean=True,
),
- Method(Torrent, 'get_peers_max', 'd.get_peers_max'),
- Method(Torrent, 'get_tracker_focus', 'd.get_tracker_focus'),
- Method(Torrent, 'get_skip_total', 'd.get_skip_total'),
- Method(Torrent, 'get_state', 'd.get_state'),
- Method(Torrent, 'get_peer_exchange', 'd.get_peer_exchange'),
- Method(Torrent, 'get_down_rate', 'd.get_down_rate'),
- Method(Torrent, 'get_connection_seed', 'd.get_connection_seed'),
- Method(Torrent, 'get_uploads_max', 'd.get_uploads_max'),
- Method(Torrent, 'get_priority_str', 'd.get_priority_str'),
+ Method(Torrent, 'get_peers_max', 'd.peers_max'),
+ Method(Torrent, 'get_tracker_focus', 'd.tracker_focus'),
+ Method(Torrent, 'get_skip_total', 'd.skip.total'),
+ Method(Torrent, 'get_state', 'd.state'),
+ Method(Torrent, 'get_peer_exchange', 'd.peer_exchange'),
+ Method(Torrent, 'get_down_rate', 'd.down.rate'),
+ Method(Torrent, 'get_connection_seed', 'd.connection_seed'),
+ Method(Torrent, 'get_uploads_max', 'd.uploads_max'),
+ Method(Torrent, 'get_priority_str', 'd.priority_str'),
Method(Torrent, 'is_open', 'd.is_open',
boolean=True,
),
- Method(Torrent, 'get_peers_min', 'd.get_peers_min'),
- Method(Torrent, 'get_peers_complete', 'd.get_peers_complete'),
- Method(Torrent, 'get_tracker_numwant', 'd.get_tracker_numwant'),
- Method(Torrent, 'get_connection_current', 'd.get_connection_current'),
- Method(Torrent, 'is_complete', 'd.get_complete',
+ Method(Torrent, 'get_peers_min', 'd.peers_min'),
+ Method(Torrent, 'get_peers_complete', 'd.peers_complete'),
+ Method(Torrent, 'get_tracker_numwant', 'd.tracker_numwant'),
+ Method(Torrent, 'get_connection_current', 'd.connection_current'),
+ Method(Torrent, 'is_complete', 'd.complete',
boolean=True,
),
- Method(Torrent, 'get_peers_connected', 'd.get_peers_connected'),
- Method(Torrent, 'get_chunk_size', 'd.get_chunk_size'),
- Method(Torrent, 'get_state_counter', 'd.get_state_counter'),
- Method(Torrent, 'get_base_filename', 'd.get_base_filename'),
- Method(Torrent, 'get_state_changed', 'd.get_state_changed'),
- Method(Torrent, 'get_peers_not_connected', 'd.get_peers_not_connected'),
- Method(Torrent, 'get_directory', 'd.get_directory'),
+ Method(Torrent, 'get_peers_connected', 'd.peers_connected'),
+ Method(Torrent, 'get_chunk_size', 'd.chunk_size'),
+ Method(Torrent, 'get_state_counter', 'd.state_counter'),
+ Method(Torrent, 'get_base_filename', 'd.base_filename'),
+ Method(Torrent, 'get_state_changed', 'd.state_changed'),
+ Method(Torrent, 'get_peers_not_connected', 'd.peers_not_connected'),
+ Method(Torrent, 'get_directory', 'd.directory'),
Method(Torrent, 'is_incomplete', 'd.incomplete',
boolean=True,
),
- Method(Torrent, 'get_tracker_size', 'd.get_tracker_size'),
+ Method(Torrent, 'get_tracker_size', 'd.tracker_size'),
Method(Torrent, 'is_multi_file', 'd.is_multi_file',
boolean=True,
),
- Method(Torrent, 'get_local_id', 'd.get_local_id'),
- Method(Torrent, 'get_ratio', 'd.get_ratio',
+ Method(Torrent, 'get_local_id', 'd.local_id'),
+ Method(Torrent, 'get_ratio', 'd.ratio',
post_process_func=lambda x: x / 1000.0,
),
- Method(Torrent, 'get_loaded_file', 'd.get_loaded_file'),
- Method(Torrent, 'get_max_file_size', 'd.get_max_file_size'),
- Method(Torrent, 'get_size_chunks', 'd.get_size_chunks'),
+ Method(Torrent, 'get_loaded_file', 'd.loaded_file'),
+ Method(Torrent, 'get_max_file_size', 'd.max_file_size'),
+ Method(Torrent, 'get_size_chunks', 'd.size_chunks'),
Method(Torrent, 'is_pex_active', 'd.is_pex_active',
boolean=True,
),
- Method(Torrent, 'get_hashing', 'd.get_hashing'),
- Method(Torrent, 'get_bitfield', 'd.get_bitfield'),
- Method(Torrent, 'get_local_id_html', 'd.get_local_id_html'),
- Method(Torrent, 'get_connection_leech', 'd.get_connection_leech'),
- Method(Torrent, 'get_peers_accounted', 'd.get_peers_accounted'),
- Method(Torrent, 'get_message', 'd.get_message'),
+ Method(Torrent, 'get_hashing', 'd.hashing'),
+ Method(Torrent, 'get_bitfield', 'd.bitfield'),
+ Method(Torrent, 'get_local_id_html', 'd.local_id_html'),
+ Method(Torrent, 'get_connection_leech', 'd.connection_leech'),
+ Method(Torrent, 'get_peers_accounted', 'd.peers_accounted'),
+ Method(Torrent, 'get_message', 'd.message'),
Method(Torrent, 'is_active', 'd.is_active',
boolean=True,
),
- Method(Torrent, 'get_size_bytes', 'd.get_size_bytes'),
- Method(Torrent, 'get_ignore_commands', 'd.get_ignore_commands'),
- Method(Torrent, 'get_creation_date', 'd.get_creation_date'),
- Method(Torrent, 'get_base_path', 'd.get_base_path'),
- Method(Torrent, 'get_left_bytes', 'd.get_left_bytes'),
- Method(Torrent, 'get_size_files', 'd.get_size_files'),
- Method(Torrent, 'get_size_pex', 'd.get_size_pex'),
+ Method(Torrent, 'get_size_bytes', 'd.size_bytes'),
+ Method(Torrent, 'get_ignore_commands', 'd.ignore_commands'),
+ Method(Torrent, 'get_creation_date', 'd.creation_date'),
+ Method(Torrent, 'get_base_path', 'd.base_path'),
+ Method(Torrent, 'get_left_bytes', 'd.left_bytes'),
+ Method(Torrent, 'get_size_files', 'd.size_files'),
+ Method(Torrent, 'get_size_pex', 'd.size_pex'),
Method(Torrent, 'is_private', 'd.is_private',
boolean=True,
),
- Method(Torrent, 'get_max_size_pex', 'd.get_max_size_pex'),
- Method(Torrent, 'get_num_chunks_hashed', 'd.get_chunks_hashed',
+ Method(Torrent, 'get_max_size_pex', 'd.max_size_pex'),
+ Method(Torrent, 'get_num_chunks_hashed', 'd.chunks_hashed',
aliases=("get_chunks_hashed",)),
Method(Torrent, 'get_num_chunks_wanted', 'd.wanted_chunks'),
- Method(Torrent, 'get_priority', 'd.get_priority'),
- Method(Torrent, 'get_skip_rate', 'd.get_skip_rate'),
- Method(Torrent, 'get_completed_bytes', 'd.get_completed_bytes'),
- Method(Torrent, 'get_name', 'd.get_name'),
- Method(Torrent, 'get_completed_chunks', 'd.get_completed_chunks'),
- Method(Torrent, 'get_throttle_name', 'd.get_throttle_name'),
- Method(Torrent, 'get_free_diskspace', 'd.get_free_diskspace'),
- Method(Torrent, 'get_directory_base', 'd.get_directory_base'),
- Method(Torrent, 'get_hashing_failed', 'd.get_hashing_failed'),
- Method(Torrent, 'get_tied_to_file', 'd.get_tied_to_file'),
- Method(Torrent, 'get_down_total', 'd.get_down_total'),
- Method(Torrent, 'get_bytes_done', 'd.get_bytes_done'),
- Method(Torrent, 'get_up_rate', 'd.get_up_rate'),
- Method(Torrent, 'get_up_total', 'd.get_up_total'),
+ Method(Torrent, 'get_priority', 'd.priority'),
+ Method(Torrent, 'get_skip_rate', 'd.skip.rate'),
+ Method(Torrent, 'get_completed_bytes', 'd.completed_bytes'),
+ Method(Torrent, 'get_name', 'd.name'),
+ Method(Torrent, 'get_completed_chunks', 'd.completed_chunks'),
+ Method(Torrent, 'get_throttle_name', 'd.throttle_name'),
+ Method(Torrent, 'get_free_diskspace', 'd.free_diskspace'),
+ Method(Torrent, 'get_directory_base', 'd.directory_base'),
+ Method(Torrent, 'get_hashing_failed', 'd.hashing_failed'),
+ Method(Torrent, 'get_tied_to_file', 'd.tied_to_file'),
+ Method(Torrent, 'get_down_total', 'd.down.total'),
+ Method(Torrent, 'get_bytes_done', 'd.bytes_done'),
+ Method(Torrent, 'get_up_rate', 'd.up.rate'),
+ Method(Torrent, 'get_up_total', 'd.up.total'),
Method(Torrent, 'is_accepting_seeders', 'd.accepting_seeders',
boolean=True,
),
@@ -490,28 +490,28 @@ methods = [
boolean=True,
),
Method(Torrent, "get_time_started", "d.timestamp.started"),
- Method(Torrent, "get_custom1", "d.get_custom1"),
- Method(Torrent, "get_custom2", "d.get_custom2"),
- Method(Torrent, "get_custom3", "d.get_custom3"),
- Method(Torrent, "get_custom4", "d.get_custom4"),
- Method(Torrent, "get_custom5", "d.get_custom5"),
+ Method(Torrent, "get_custom1", "d.custom1"),
+ Method(Torrent, "get_custom2", "d.custom2"),
+ Method(Torrent, "get_custom3", "d.custom3"),
+ Method(Torrent, "get_custom4", "d.custom4"),
+ Method(Torrent, "get_custom5", "d.custom5"),
# MODIFIERS
- Method(Torrent, 'set_uploads_max', 'd.set_uploads_max'),
- Method(Torrent, 'set_tied_to_file', 'd.set_tied_to_file'),
- Method(Torrent, 'set_tracker_numwant', 'd.set_tracker_numwant'),
- Method(Torrent, 'set_priority', 'd.set_priority'),
- Method(Torrent, 'set_peers_max', 'd.set_peers_max'),
- Method(Torrent, 'set_hashing_failed', 'd.set_hashing_failed'),
- Method(Torrent, 'set_message', 'd.set_message'),
- Method(Torrent, 'set_throttle_name', 'd.set_throttle_name'),
- Method(Torrent, 'set_peers_min', 'd.set_peers_min'),
- Method(Torrent, 'set_ignore_commands', 'd.set_ignore_commands'),
- Method(Torrent, 'set_max_file_size', 'd.set_max_file_size'),
- Method(Torrent, 'set_custom5', 'd.set_custom5'),
- Method(Torrent, 'set_custom4', 'd.set_custom4'),
- Method(Torrent, 'set_custom2', 'd.set_custom2'),
- Method(Torrent, 'set_custom1', 'd.set_custom1'),
- Method(Torrent, 'set_custom3', 'd.set_custom3'),
- Method(Torrent, 'set_connection_current', 'd.set_connection_current'),
+ Method(Torrent, 'set_uploads_max', 'd.uploads_max.set'),
+ Method(Torrent, 'set_tied_to_file', 'd.tied_to_file.set'),
+ Method(Torrent, 'set_tracker_numwant', 'd.tracker_numwant.set'),
+ Method(Torrent, 'set_priority', 'd.priority.set'),
+ Method(Torrent, 'set_peers_max', 'd.peers_max.set'),
+ Method(Torrent, 'set_hashing_failed', 'd.hashing_failed.set'),
+ Method(Torrent, 'set_message', 'd.message.set'),
+ Method(Torrent, 'set_throttle_name', 'd.throttle_name.set'),
+ Method(Torrent, 'set_peers_min', 'd.peers_min.set'),
+ Method(Torrent, 'set_ignore_commands', 'd.ignore_commands.set'),
+ Method(Torrent, 'set_max_file_size', 'd.max_file_size.set'),
+ Method(Torrent, 'set_custom5', 'd.custom5.set'),
+ Method(Torrent, 'set_custom4', 'd.custom4.set'),
+ Method(Torrent, 'set_custom2', 'd.custom2.set'),
+ Method(Torrent, 'set_custom1', 'd.custom1.set'),
+ Method(Torrent, 'set_custom3', 'd.custom3.set'),
+ Method(Torrent, 'set_connection_current', 'd.connection_current.set'),
]
diff --git a/libs/rtorrent/tracker.py b/libs/rtorrent/tracker.py
index 81af2e4..03cec4b 100755
--- a/libs/rtorrent/tracker.py
+++ b/libs/rtorrent/tracker.py
@@ -70,17 +70,17 @@ class Tracker:
methods = [
# RETRIEVERS
Method(Tracker, 'is_enabled', 't.is_enabled', boolean=True),
- Method(Tracker, 'get_id', 't.get_id'),
- Method(Tracker, 'get_scrape_incomplete', 't.get_scrape_incomplete'),
+ Method(Tracker, 'get_id', 't.id'),
+ Method(Tracker, 'get_scrape_incomplete', 't.scrape_incomplete'),
Method(Tracker, 'is_open', 't.is_open', boolean=True),
- Method(Tracker, 'get_min_interval', 't.get_min_interval'),
- Method(Tracker, 'get_scrape_downloaded', 't.get_scrape_downloaded'),
- Method(Tracker, 'get_group', 't.get_group'),
- Method(Tracker, 'get_scrape_time_last', 't.get_scrape_time_last'),
- Method(Tracker, 'get_type', 't.get_type'),
- Method(Tracker, 'get_normal_interval', 't.get_normal_interval'),
- Method(Tracker, 'get_url', 't.get_url'),
- Method(Tracker, 'get_scrape_complete', 't.get_scrape_complete',
+ Method(Tracker, 'get_min_interval', 't.min_interval'),
+ Method(Tracker, 'get_scrape_downloaded', 't.scrape_downloaded'),
+ Method(Tracker, 'get_group', 't.group'),
+ Method(Tracker, 'get_scrape_time_last', 't.scrape_time_last'),
+ Method(Tracker, 'get_type', 't.type'),
+ Method(Tracker, 'get_normal_interval', 't.normal_interval'),
+ Method(Tracker, 'get_url', 't.url'),
+ Method(Tracker, 'get_scrape_complete', 't.scrape_complete',
min_version=(0, 8, 9),
),
Method(Tracker, 'get_activity_time_last', 't.activity_time_last',
@@ -134,5 +134,5 @@ methods = [
),
# MODIFIERS
- Method(Tracker, 'set_enabled', 't.set_enabled'),
+ Method(Tracker, 'set_enabled', 't.is_enabled.set'),
]
diff --git a/libs/subliminal/core.py b/libs/subliminal/core.py
index 6661968..5cb4a96 100755
--- a/libs/subliminal/core.py
+++ b/libs/subliminal/core.py
@@ -32,7 +32,8 @@ __all__ = ['SERVICES', 'LANGUAGE_INDEX', 'SERVICE_INDEX', 'SERVICE_CONFIDENCE',
'create_list_tasks', 'create_download_tasks', 'consume_task', 'matching_confidence',
'key_subtitles', 'group_by_video']
logger = logging.getLogger(__name__)
-SERVICES = ['opensubtitles', 'bierdopje', 'subswiki', 'subtitulos', 'thesubdb', 'addic7ed', 'tvsubtitles', 'subscenter']
+SERVICES = ['opensubtitles', 'bierdopje', 'subswiki', 'subtitulos', 'thesubdb', 'addic7ed', 'tvsubtitles',
+ 'subscenter', 'wizdom']
LANGUAGE_INDEX, SERVICE_INDEX, SERVICE_CONFIDENCE, MATCHING_CONFIDENCE = range(4)
diff --git a/libs/subliminal/services/subscenter.py b/libs/subliminal/services/subscenter.py
index 9a5511c..258edad 100644
--- a/libs/subliminal/services/subscenter.py
+++ b/libs/subliminal/services/subscenter.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2012 Ofir Brukner
+# Copyright 2012 Ofir123
#
# This file is part of subliminal.
#
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with subliminal. If not, see .
from . import ServiceBase
-from ..exceptions import ServiceError
+from ..exceptions import DownloadFailedError, ServiceError
from ..language import language_set
from ..subtitles import get_subtitle_path, ResultSubtitle
from ..videos import Episode, Movie
@@ -30,7 +30,7 @@ logger = logging.getLogger(__name__)
class Subscenter(ServiceBase):
- server = 'http://www.subscenter.co/he/'
+ server = 'http://www.subscenter.info/he/'
api_based = False
languages = language_set(['he'])
videos = [Episode, Movie]
@@ -110,10 +110,11 @@ class Subscenter(ServiceBase):
# Read the item.
subtitle_id = subtitle_item['id']
subtitle_key = subtitle_item['key']
+ subtitle_version = subtitle_item['h_version']
release = subtitle_item['subtitle_version']
subtitle_path = get_subtitle_path(filepath, language_object, self.config.multi)
download_link = self.server_url + 'subtitle/download/{0}/{1}/?v={2}&key={3}'.format(
- language_code, subtitle_id, release, subtitle_key)
+ language_code, subtitle_id, subtitle_version, subtitle_key)
# Add the release and increment downloaded count if we already have the subtitle.
if subtitle_id in subtitles:
logger.debug('Found additional release {0} for subtitle {1}'.format(
@@ -128,7 +129,11 @@ class Subscenter(ServiceBase):
return subtitles.values()
def download(self, subtitle):
- self.download_zip_file(subtitle.link, subtitle.path)
+ try:
+ self.download_zip_file(subtitle.link, subtitle.path)
+ except DownloadFailedError:
+ # If no zip file was retrieved, daily downloads limit has exceeded.
+ raise ServiceError('Daily limit exceeded')
return subtitle
diff --git a/libs/subliminal/services/wizdom.py b/libs/subliminal/services/wizdom.py
new file mode 100644
index 0000000..675dccf
--- /dev/null
+++ b/libs/subliminal/services/wizdom.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+# Copyright 2017 Ofir123
+#
+# This file is part of subliminal.
+#
+# subliminal is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# subliminal is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with subliminal. If not, see .
+from . import ServiceBase
+from ..exceptions import ServiceError
+from ..language import language_set
+from ..subtitles import get_subtitle_path, ResultSubtitle
+from ..videos import Episode, Movie
+from ..utils import to_unicode
+import bisect
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+class Wizdom(ServiceBase):
+ server = 'http://wizdom.xyz'
+ api_based = True
+ languages = language_set(['he'])
+ videos = [Episode, Movie]
+ require_video = False
+
+ _tmdb_api_key = 'a51ee051bcd762543373903de296e0a3'
+
+ def _search_imdb_id(self, title, year, is_movie):
+ """Search the IMDB ID for the given `title` and `year`.
+
+ :param str title: title to search for.
+ :param int year: year to search for (or 0 if not relevant).
+ :param bool is_movie: If True, IMDB ID will be searched for in TMDB instead of Wizdom.
+ :return: the IMDB ID for the given title and year (or None if not found).
+ :rtype: str
+ """
+ # make the search
+ logger.info('Searching IMDB ID for %r%r', title, '' if not year else ' ({})'.format(year))
+ category = 'movie' if is_movie else 'tv'
+ title = title.replace('\'', '')
+ # get TMDB ID first
+ r = self.session.get('http://api.tmdb.org/3/search/{}?api_key={}&query={}{}&language=en'.format(
+ category, self._tmdb_api_key, title, '' if not year else '&year={}'.format(year)))
+ r.raise_for_status()
+ tmdb_results = r.json().get('results')
+ if tmdb_results:
+ tmdb_id = tmdb_results[0].get('id')
+ if tmdb_id:
+ # get actual IMDB ID from TMDB
+ r = self.session.get('http://api.tmdb.org/3/{}/{}{}?api_key={}&language=en'.format(
+ category, tmdb_id, '' if is_movie else '/external_ids', self._tmdb_api_key))
+ r.raise_for_status()
+ return str(r.json().get('imdb_id', '')) or None
+ return None
+
+ def list_checked(self, video, languages):
+ series = None
+ season = None
+ episode = None
+ title = video.title
+ imdb_id = video.imdbid
+ year = video.year
+ if isinstance(video, Episode):
+ series = video.series
+ season = video.season
+ episode = video.episode
+ return self.query(video.path or video.release, languages, series, season,
+ episode, title, imdb_id, year)
+
+ def query(self, filepath, languages=None, series=None, season=None, episode=None, title=None, imdbid=None,
+ year=None):
+ logger.debug(u'Getting subtitles for {0} season {1} episode {2} with languages {3}'.format(
+ series, season, episode, languages))
+ # search for the IMDB ID if needed
+ is_movie = not (series and season and episode)
+ if is_movie and not title:
+ raise ServiceError('One or more parameters are missing')
+ # for TV series, we need the series IMDB ID, and not the specific episode ID
+ imdb_id = imdbid or self._search_imdb_id(title, year, is_movie)
+
+ # search
+ logger.debug(u'Using IMDB ID {0}'.format(imdb_id))
+ url = 'http://json.{}/{}.json'.format(self.server_url, imdb_id)
+
+ # get the list of subtitles
+ logger.debug('Getting the list of subtitles')
+ r = self.session.get(url)
+ r.raise_for_status()
+ try:
+ results = r.json()
+ except ValueError:
+ return {}
+
+ # filter irrelevant results
+ if not is_movie:
+ results = results.get('subs', {}).get(str(season), {}).get(str(episode), [])
+ else:
+ results = results.get('subs', [])
+
+ # loop over results
+ subtitles = dict()
+ for result in results:
+ language_object = self.get_language('heb')
+ subtitle_id = result['id']
+ release = result['version']
+ subtitle_path = get_subtitle_path(filepath, language_object, self.config.multi)
+ download_link = 'http://zip.{}/{}.zip'.format(self.server_url, subtitle_id)
+ # add the release and increment downloaded count if we already have the subtitle
+ if subtitle_id in subtitles:
+ logger.debug(u'Found additional release {0} for subtitle {1}'.format(release, subtitle_id))
+ bisect.insort_left(subtitles[subtitle_id].releases, release) # deterministic order
+ subtitles[subtitle_id].downloaded += 1
+ continue
+ # otherwise create it
+ subtitle = ResultSubtitle(subtitle_path, language_object, self.__class__.__name__.lower(),
+ download_link, release=to_unicode(release))
+ logger.debug(u'Found subtitle {0}'.format(subtitle))
+ subtitles[subtitle_id] = subtitle
+
+ return subtitles.values()
+
+ def download(self, subtitle):
+ self.download_zip_file(subtitle.link, subtitle.path)
+ return subtitle
+
+
+Service = Wizdom
diff --git a/libs/xmpp/transports.py b/libs/xmpp/transports.py
index f3d1316..bf59266 100644
--- a/libs/xmpp/transports.py
+++ b/libs/xmpp/transports.py
@@ -27,7 +27,7 @@ Transports are stackable so you - f.e. TLS use HTPPROXYsocket or TCPsocket as mo
Also exception 'error' is defined to allow capture of this module specific exceptions.
"""
-import socket, select, base64, dispatcher, sys
+import socket, ssl, select, base64, dispatcher, sys
from simplexml import ustr
from client import PlugIn
from protocol import *
@@ -312,9 +312,9 @@ class TLS(PlugIn):
""" Immidiatedly switch socket to TLS mode. Used internally."""
""" Here we should switch pending_data to hint mode."""
tcpsock = self._owner.Connection
- tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
- tcpsock._sslIssuer = tcpsock._sslObj.issuer()
- tcpsock._sslServer = tcpsock._sslObj.server()
+ tcpsock._sslObj = ssl.wrap_socket(tcpsock._sock, None, None)
+ tcpsock._sslIssuer = tcpsock._sslObj.getpeercert().get('issuer')
+ tcpsock._sslServer = tcpsock._sslObj.getpeercert().get('server')
tcpsock._recv = tcpsock._sslObj.read
tcpsock._send = tcpsock._sslObj.write