Browse Source

Merge pull request #1 from CouchPotato/develop

Develop
pull/7236/head
Filip Andre Larsen Tomren 8 years ago
committed by GitHub
parent
commit
1c5c15efdb
  1. 2
      couchpotato/core/downloaders/utorrent.py
  2. 14
      couchpotato/core/media/_base/providers/torrent/torrentday.py
  3. 62
      couchpotato/core/media/_base/providers/torrent/yts.py
  4. 54
      couchpotato/core/media/movie/providers/automation/kinepolis.py
  5. 48
      couchpotato/core/media/movie/providers/automation/moviemeter.py
  6. 72
      couchpotato/core/media/movie/providers/automation/movies_io.py
  7. 47
      couchpotato/core/media/movie/providers/info/omdbapi.py
  8. 9
      couchpotato/core/media/movie/providers/userscript/filmstarts.py
  9. 34
      couchpotato/core/notifications/script.py
  10. 2
      couchpotato/core/plugins/log/static/log.js
  11. 2
      couchpotato/core/plugins/subtitle.py
  12. 2
      couchpotato/static/scripts/combined.plugins.min.js
  13. 50
      libs/rtorrent/__init__.py
  14. 28
      libs/rtorrent/file.py
  15. 26
      libs/rtorrent/peer.py
  16. 6
      libs/rtorrent/rpc/__init__.py
  17. 168
      libs/rtorrent/torrent.py
  18. 22
      libs/rtorrent/tracker.py
  19. 3
      libs/subliminal/core.py
  20. 15
      libs/subliminal/services/subscenter.py
  21. 138
      libs/subliminal/services/wizdom.py
  22. 8
      libs/xmpp/transports.py

2
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'

14
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': '<a href="https://classic.torrentday.com/" target="_blank">TorrentDay</a>',
'description': '<a href="https://www.torrentday.com/" target="_blank">TorrentDay</a>',
'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': [

62
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

54
couchpotato/core/media/movie/providers/automation/kinepolis.py

@ -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',
},
],
},
],
}]

48
couchpotato/core/media/movie/providers/automation/moviemeter.py

@ -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',
},
],
},
],
}]

72
couchpotato/core/media/movie/providers/automation/movies_io.py

@ -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 <a href="http://movies.io" target="_blank">Movies.io</a> 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'],
},
],
},
],
}]

47
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',
},
],
},
],
}]

9
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)

34
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',

2
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 <strong>FILL IN</strong> the dots.'

2
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)

2
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 <strong>FILL IN</strong> the dots."
})), textarea = new Element("textarea", {

50
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)

28
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,
),

26
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
]

6
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

168
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'),
]

22
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'),
]

3
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)

15
libs/subliminal/services/subscenter.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2012 Ofir Brukner <ofirbrukner@gmail.com>
# Copyright 2012 Ofir123 <ofirbrukner@gmail.com>
#
# 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 <http://www.gnu.org/licenses/>.
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

138
libs/subliminal/services/wizdom.py

@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Ofir123 <ofirbrukner@gmail.com>
#
# 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 <http://www.gnu.org/licenses/>.
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

8
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

Loading…
Cancel
Save