Merge branch 'refs/heads/develop' into tv

Conflicts:
	couchpotato/core/media/movie/_base/main.py
	couchpotato/core/providers/torrent/bitsoup/main.py
	couchpotato/core/providers/torrent/iptorrents/main.py
	couchpotato/core/providers/torrent/sceneaccess/main.py
	couchpotato/core/providers/torrent/torrentleech/main.py
	couchpotato/core/providers/torrent/torrentshack/main.py
This commit is contained in:
Ruud
2014-01-11 13:55:12 +01:00
99 changed files with 7125 additions and 3838 deletions
+4
View File
@@ -55,6 +55,10 @@ class Core(Plugin):
if not Env.get('desktop'):
self.signalHandler()
# Set default urlopen timeout
import socket
socket.setdefaulttimeout(30)
def md5Password(self, value):
return md5(value) if value else ''
+3 -1
View File
@@ -13,6 +13,7 @@ class Downloader(Provider):
protocol = []
http_time_between_calls = 0
status_support = True
torrent_sources = [
'http://torrage.com/torrent/%s.torrent',
@@ -69,7 +70,7 @@ class Downloader(Provider):
return
def getAllDownloadStatus(self, ids):
return
return []
def _removeFailed(self, release_download):
if self.isDisabled(manual = True, data = {}):
@@ -133,6 +134,7 @@ class Downloader(Provider):
def downloadReturnId(self, download_id):
return {
'downloader': self.getName(),
'status_support': self.status_support,
'id': download_id
}
@@ -11,6 +11,7 @@ log = CPLog(__name__)
class Blackhole(Downloader):
protocol = ['nzb', 'torrent', 'torrent_magnet']
status_support = False
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
+34 -35
View File
@@ -91,51 +91,50 @@ class Deluge(Downloader):
log.debug('Checking Deluge download status.')
if not self.connect():
return False
return []
release_downloads = ReleaseDownloadList(self)
queue = self.drpc.get_alltorrents()
queue = self.drpc.get_alltorrents(ids)
if not queue:
log.debug('Nothing in queue or error')
return False
return []
for torrent_id in queue:
torrent = queue[torrent_id]
if torrent['hash'] in ids:
log.debug('name=%s / id=%s / save_path=%s / move_completed_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / stop_ratio=%s / is_seed=%s / is_finished=%s / paused=%s', (torrent['name'], torrent['hash'], torrent['save_path'], torrent['move_completed_path'], torrent['hash'], torrent['progress'], torrent['state'], torrent['eta'], torrent['ratio'], torrent['stop_ratio'], torrent['is_seed'], torrent['is_finished'], torrent['paused']))
log.debug('name=%s / id=%s / save_path=%s / move_completed_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / stop_ratio=%s / is_seed=%s / is_finished=%s / paused=%s', (torrent['name'], torrent['hash'], torrent['save_path'], torrent['move_completed_path'], torrent['hash'], torrent['progress'], torrent['state'], torrent['eta'], torrent['ratio'], torrent['stop_ratio'], torrent['is_seed'], torrent['is_finished'], torrent['paused']))
# Deluge has no easy way to work out if a torrent is stalled or failing.
#status = 'failed'
status = 'busy'
if torrent['is_seed'] and tryFloat(torrent['ratio']) < tryFloat(torrent['stop_ratio']):
# We have torrent['seeding_time'] to work out what the seeding time is, but we do not
# have access to the downloader seed_time, as with deluge we have no way to pass it
# when the torrent is added. So Deluge will only look at the ratio.
# See above comment in download().
status = 'seeding'
elif torrent['is_seed'] and torrent['is_finished'] and torrent['paused'] and torrent['state'] == 'Paused':
status = 'completed'
# Deluge has no easy way to work out if a torrent is stalled or failing.
#status = 'failed'
status = 'busy'
if torrent['is_seed'] and tryFloat(torrent['ratio']) < tryFloat(torrent['stop_ratio']):
# We have torrent['seeding_time'] to work out what the seeding time is, but we do not
# have access to the downloader seed_time, as with deluge we have no way to pass it
# when the torrent is added. So Deluge will only look at the ratio.
# See above comment in download().
status = 'seeding'
elif torrent['is_seed'] and torrent['is_finished'] and torrent['paused'] and torrent['state'] == 'Paused':
status = 'completed'
download_dir = sp(torrent['save_path'])
if torrent['move_on_completed']:
download_dir = torrent['move_completed_path']
download_dir = sp(torrent['save_path'])
if torrent['move_on_completed']:
download_dir = torrent['move_completed_path']
torrent_files = []
for file_item in torrent['files']:
torrent_files.append(sp(os.path.join(download_dir, file_item['path'])))
torrent_files = []
for file_item in torrent['files']:
torrent_files.append(sp(os.path.join(download_dir, file_item['path'])))
release_downloads.append({
'id': torrent['hash'],
'name': torrent['name'],
'status': status,
'original_status': torrent['state'],
'seed_ratio': torrent['ratio'],
'timeleft': str(timedelta(seconds = torrent['eta'])),
'folder': sp(download_dir if len(torrent_files) == 1 else os.path.join(download_dir, torrent['name'])),
'files': '|'.join(torrent_files),
})
release_downloads.append({
'id': torrent['hash'],
'name': torrent['name'],
'status': status,
'original_status': torrent['state'],
'seed_ratio': torrent['ratio'],
'timeleft': str(timedelta(seconds = torrent['eta'])),
'folder': sp(download_dir if len(torrent_files) == 1 else os.path.join(download_dir, torrent['name'])),
'files': '|'.join(torrent_files),
})
return release_downloads
@@ -209,11 +208,11 @@ class DelugeRPC(object):
return torrent_id
def get_alltorrents(self):
def get_alltorrents(self, ids):
ret = False
try:
self.connect()
ret = self.client.core.get_torrents_status({}, {}).get()
ret = self.client.core.get_torrents_status({'id': ids}, {}).get()
except Exception, err:
log.error('Failed to get all torrents: %s %s', (err, traceback.format_exc()))
finally:
@@ -25,6 +25,13 @@ config = [{
'default': 'localhost:6789',
'description': 'Hostname with port. Usually <strong>localhost:6789</strong>',
},
{
'name': 'ssl',
'default': 0,
'type': 'bool',
'advanced': True,
'description': 'Use HyperText Transfer Protocol Secure, or <strong>https</strong>',
},
{
'name': 'username',
'default': 'nzbget',
+6 -6
View File
@@ -17,7 +17,7 @@ class NZBGet(Downloader):
protocol = ['nzb']
url = 'http://%(username)s:%(password)s@%(host)s/xmlrpc'
url = '%(protocol)s://%(username)s:%(password)s@%(host)s/xmlrpc'
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
@@ -29,7 +29,7 @@ class NZBGet(Downloader):
log.info('Sending "%s" to NZBGet.', data.get('name'))
url = self.url % {'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')}
url = self.url % {'protocol': 'https' if self.conf('ssl') else 'http', 'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')}
nzb_name = ss('%s.nzb' % self.createNzbName(data, media))
rpc = xmlrpclib.ServerProxy(url)
@@ -71,7 +71,7 @@ class NZBGet(Downloader):
log.debug('Checking NZBGet download status.')
url = self.url % {'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')}
url = self.url % {'protocol': 'https' if self.conf('ssl') else 'http', 'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')}
rpc = xmlrpclib.ServerProxy(url)
try:
@@ -81,13 +81,13 @@ class NZBGet(Downloader):
log.info('Successfully connected to NZBGet, but unable to send a message')
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False
return []
except xmlrpclib.ProtocolError, e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:
log.error('Protocol Error: %s', e)
return False
return []
# Get NZBGet data
try:
@@ -97,7 +97,7 @@ class NZBGet(Downloader):
history = rpc.history()
except:
log.error('Failed getting data: %s', traceback.format_exc(1))
return False
return []
release_downloads = ReleaseDownloadList(self)
@@ -32,7 +32,7 @@ class NZBVortex(Downloader):
# Send the nzb
try:
nzb_filename = self.createFileName(data, filedata, media)
self.call('nzb/add', params = {'file': (nzb_filename, filedata)}, multipart = True)
self.call('nzb/add', files = {'file': (nzb_filename, filedata)})
time.sleep(10)
raw_statuses = self.call('nzb')
@@ -117,10 +117,9 @@ class NZBVortex(Downloader):
params = tryUrlencode(parameters)
url = cleanHost(self.conf('host')) + 'api/' + call
url_opener = urllib2.build_opener(HTTPSHandler())
try:
data = self.urlopen('%s?%s' % (url, params), opener = url_opener, *args, **kwargs)
data = self.urlopen('%s?%s' % (url, params), *args, **kwargs)
if data:
return json.loads(data)
@@ -142,10 +141,9 @@ class NZBVortex(Downloader):
if not self.api_level:
url = cleanHost(self.conf('host')) + 'api/app/apilevel'
url_opener = urllib2.build_opener(HTTPSHandler())
try:
data = self.urlopen(url, opener = url_opener, show_error = False)
data = self.urlopen(url, show_error = False)
self.api_level = float(json.loads(data).get('apilevel'))
except URLError, e:
if hasattr(e, 'code') and e.code == 403:
@@ -11,6 +11,7 @@ class Pneumatic(Downloader):
protocol = ['nzb']
strm_syntax = 'plugin://plugin.program.pneumatic/?mode=strm&type=add_file&nzb=%s&nzbname=%s'
status_support = False
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
@@ -147,7 +147,7 @@ class rTorrent(Downloader):
log.debug('Checking rTorrent download status.')
if not self.connect():
return False
return []
try:
torrents = self.rt.get_torrents()
@@ -182,7 +182,7 @@ class rTorrent(Downloader):
except Exception, err:
log.error('Failed to get status from rTorrent: %s', err)
return False
return []
def pause(self, release_download, pause = True):
if not self.connect():
+3 -3
View File
@@ -43,7 +43,7 @@ class Sabnzbd(Downloader):
try:
if nzb_filename and req_params.get('mode') is 'addfile':
sab_data = self.call(req_params, params = {'nzbfile': (ss(nzb_filename), filedata)}, multipart = True)
sab_data = self.call(req_params, files = {'nzbfile': (ss(nzb_filename), filedata)})
else:
sab_data = self.call(req_params)
except URLError:
@@ -75,7 +75,7 @@ class Sabnzbd(Downloader):
})
except:
log.error('Failed getting queue: %s', traceback.format_exc(1))
return False
return []
# Go through history items
try:
@@ -85,7 +85,7 @@ class Sabnzbd(Downloader):
})
except:
log.error('Failed getting history json: %s', traceback.format_exc(1))
return False
return []
release_downloads = ReleaseDownloadList(self)
@@ -11,7 +11,7 @@ log = CPLog(__name__)
class Synology(Downloader):
protocol = ['nzb', 'torrent', 'torrent_magnet']
log = CPLog(__name__)
status_support = False
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
@@ -88,7 +88,7 @@ class Transmission(Downloader):
log.debug('Checking Transmission download status.')
if not self.connect():
return False
return []
release_downloads = ReleaseDownloadList(self)
@@ -99,7 +99,7 @@ class Transmission(Downloader):
queue = self.trpc.get_alltorrents(return_params)
if not (queue and queue.get('torrents')):
log.debug('Nothing in queue or error')
return False
return []
for torrent in queue['torrents']:
if torrent['hashString'] in ids:
+36 -37
View File
@@ -24,6 +24,16 @@ class uTorrent(Downloader):
protocol = ['torrent', 'torrent_magnet']
utorrent_api = None
status_flags = {
'STARTED' : 1,
'CHECKING' : 2,
'CHECK-START' : 4,
'CHECKED' : 8,
'ERROR' : 16,
'PAUSED' : 32,
'QUEUED' : 64,
'LOADED' : 128
}
def connect(self):
# Load host from config and split out port.
@@ -40,7 +50,7 @@ class uTorrent(Downloader):
if not media: media = {}
if not data: data = {}
log.debug('Sending "%s" (%s) to uTorrent.', (data.get('name'), data.get('protocol')))
log.debug("Sending '%s' (%s) to uTorrent.", (data.get('name'), data.get('protocol')))
if not self.connect():
return False
@@ -75,7 +85,7 @@ class uTorrent(Downloader):
torrent_hash = re.findall('urn:btih:([\w]{32,40})', data.get('url'))[0].upper()
torrent_params['trackers'] = '%0D%0A%0D%0A'.join(self.torrent_trackers)
else:
info = bdecode(filedata)["info"]
info = bdecode(filedata)['info']
torrent_hash = sha1(benc(info)).hexdigest().upper()
torrent_filename = self.createFileName(data, filedata, media)
@@ -110,23 +120,23 @@ class uTorrent(Downloader):
log.debug('Checking uTorrent download status.')
if not self.connect():
return False
return []
release_downloads = ReleaseDownloadList(self)
data = self.utorrent_api.get_status()
if not data:
log.error('Error getting data from uTorrent')
return False
return []
queue = json.loads(data)
if queue.get('error'):
log.error('Error getting data from uTorrent: %s', queue.get('error'))
return False
return []
if not queue.get('torrents'):
log.debug('Nothing in queue')
return False
return []
# Get torrents
for torrent in queue['torrents']:
@@ -140,21 +150,10 @@ class uTorrent(Downloader):
except:
log.debug('Failed getting files from torrent: %s', torrent[2])
status_flags = {
"STARTED" : 1,
"CHECKING" : 2,
"CHECK-START" : 4,
"CHECKED" : 8,
"ERROR" : 16,
"PAUSED" : 32,
"QUEUED" : 64,
"LOADED" : 128
}
status = 'busy'
if (torrent[1] & status_flags["STARTED"] or torrent[1] & status_flags["QUEUED"]) and torrent[4] == 1000:
if (torrent[1] & self.status_flags['STARTED'] or torrent[1] & self.status_flags['QUEUED']) and torrent[4] == 1000:
status = 'seeding'
elif (torrent[1] & status_flags["ERROR"]):
elif (torrent[1] & self.status_flags['ERROR']):
status = 'failed'
elif torrent[4] == 1000:
status = 'completed'
@@ -224,7 +223,7 @@ class uTorrentAPI(object):
if time.time() > self.last_time + 1800:
self.last_time = time.time()
self.token = self.get_token()
request = urllib2.Request(self.url + "?token=" + self.token + "&" + action, data)
request = urllib2.Request(self.url + '?token=' + self.token + '&' + action, data)
try:
open_request = self.opener.open(request)
response = open_request.read()
@@ -244,52 +243,52 @@ class uTorrentAPI(object):
return False
def get_token(self):
request = self.opener.open(self.url + "token.html")
token = re.findall("<div.*?>(.*?)</", request.read())[0]
request = self.opener.open(self.url + 'token.html')
token = re.findall('<div.*?>(.*?)</', request.read())[0]
return token
def add_torrent_uri(self, filename, torrent, add_folder = False):
action = "action=add-url&s=%s" % urllib.quote(torrent)
action = 'action=add-url&s=%s' % urllib.quote(torrent)
if add_folder:
action += "&path=%s" % urllib.quote(filename)
action += '&path=%s' % urllib.quote(filename)
return self._request(action)
def add_torrent_file(self, filename, filedata, add_folder = False):
action = "action=add-file"
action = 'action=add-file'
if add_folder:
action += "&path=%s" % urllib.quote(filename)
return self._request(action, {"torrent_file": (ss(filename), filedata)})
action += '&path=%s' % urllib.quote(filename)
return self._request(action, {'torrent_file': (ss(filename), filedata)})
def set_torrent(self, hash, params):
action = "action=setprops&hash=%s" % hash
action = 'action=setprops&hash=%s' % hash
for k, v in params.iteritems():
action += "&s=%s&v=%s" % (k, v)
action += '&s=%s&v=%s' % (k, v)
return self._request(action)
def pause_torrent(self, hash, pause = True):
if pause:
action = "action=pause&hash=%s" % hash
action = 'action=pause&hash=%s' % hash
else:
action = "action=unpause&hash=%s" % hash
action = 'action=unpause&hash=%s' % hash
return self._request(action)
def stop_torrent(self, hash):
action = "action=stop&hash=%s" % hash
action = 'action=stop&hash=%s' % hash
return self._request(action)
def remove_torrent(self, hash, remove_data = False):
if remove_data:
action = "action=removedata&hash=%s" % hash
action = 'action=removedata&hash=%s' % hash
else:
action = "action=remove&hash=%s" % hash
action = 'action=remove&hash=%s' % hash
return self._request(action)
def get_status(self):
action = "list=1"
action = 'list=1'
return self._request(action)
def get_settings(self):
action = "action=getsettings"
action = 'action=getsettings'
settings_dict = {}
try:
utorrent_settings = json.loads(self._request(action))
@@ -321,5 +320,5 @@ class uTorrentAPI(object):
return self._request(action)
def get_files(self, hash):
action = "action=getfiles&hash=%s" % hash
action = 'action=getfiles&hash=%s' % hash
return self._request(action)
+8
View File
@@ -60,9 +60,17 @@ def sp(path, *args):
path = os.path.normcase(os.path.normpath(ss(path, *args)))
# Remove any trailing path separators
if path != os.path.sep:
path = path.rstrip(os.path.sep)
# Add a trailing separator in case it is a root folder on windows (crashes guessit)
if len(path) == 2 and path[1] == ':':
path = path + os.path.sep
# Replace *NIX ambiguous '//' at the beginning of a path with '/' (crashes guessit)
path = re.sub('^//', '/', path)
return path
def ek(original, *args):
+5 -1
View File
@@ -2,7 +2,7 @@ from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss
from couchpotato.core.logger import CPLog
import collections
import hashlib
import os.path
import os
import platform
import random
import re
@@ -219,3 +219,7 @@ def splitString(str, split_on = ',', clean = True):
def dictIsSubset(a, b):
return all([k in b and b[k] == v for k, v in a.items()])
def isSubFolder(sub_folder, base_folder):
# Returns True is sub_folder is the same as or in base_folder
return base_folder.rstrip(os.path.sep) + os.path.sep in sub_folder.rstrip(os.path.sep) + os.path.sep
@@ -35,6 +35,7 @@ class MovieBase(MovieTypeBase):
'params': {
'id': {'desc': 'Movie ID(s) you want to edit.', 'type': 'int (comma separated)'},
'profile_id': {'desc': 'ID of quality profile you want the edit the movie to.'},
'category_id': {'desc': 'ID of category you want the add the movie in. If empty will use no category.'},
'default_title': {'desc': 'Movie title to use for searches. Has to be one of the titles returned by movie.search.'},
}
})
@@ -283,6 +283,10 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
return True
else:
# Don't allow movies with years to far in the future
if year is not None and year > now_year + 1:
return False
# For movies before 1972
if not dates or dates.get('theater', 0) < 0 or dates.get('dvd', 0) < 0:
return True
@@ -16,14 +16,14 @@ class Boxcar(Notification):
try:
message = message.strip()
params = {
data = {
'email': self.conf('email'),
'notification[from_screen_name]': self.default_title,
'notification[message]': toUnicode(message),
'notification[from_remote_service_id]': int(time.time()),
}
self.urlopen(self.url, params = params)
self.urlopen(self.url, data = data)
except:
log.error('Check your email and added services on boxcar.io')
return False
+1 -1
View File
@@ -26,7 +26,7 @@ class Prowl(Notification):
}
try:
self.urlopen(self.urls['api'], headers = headers, params = data, multipart = True, show_error = False)
self.urlopen(self.urls['api'], headers = headers, data = data, show_error = False)
log.info('Prowl notifications sent.')
return True
except:
@@ -29,7 +29,7 @@ class Pushalot(Notification):
}
try:
self.urlopen(self.urls['api'], headers = headers, params = data, multipart = True, show_error = False)
self.urlopen(self.urls['api'], headers = headers, data = data, show_error = False)
return True
except:
log.error('PushAlot failed: %s', traceback.format_exc())
@@ -74,9 +74,9 @@ class Pushbullet(Notification):
}
if cache:
return self.getJsonData(self.url % method, headers = headers, params = kwargs)
return self.getJsonData(self.url % method, headers = headers, data = kwargs)
else:
data = self.urlopen(self.url % method, headers = headers, params = kwargs)
data = self.urlopen(self.url % method, headers = headers, data = kwargs)
return json.loads(data)
except Exception, ex:
+1 -1
View File
@@ -35,7 +35,7 @@ class Trakt(Notification):
def call(self, method_url, post_data):
try:
response = self.getJsonData(self.urls['base'] % method_url, params = post_data, cache_timeout = 1)
response = self.getJsonData(self.urls['base'] % method_url, data = post_data, cache_timeout = 1)
if response:
if response.get('status') == "success":
log.info('Successfully called Trakt')
+10 -17
View File
@@ -7,6 +7,7 @@ import json
import socket
import traceback
import urllib
import requests
log = CPLog(__name__)
@@ -167,22 +168,18 @@ class XBMC(Notification):
# manually fake expected response array
return [{'result': 'Error'}]
except URLError, e:
if isinstance(e.reason, socket.timeout):
log.info('Couldn\'t send request to XBMC, assuming it\'s turned off')
return [{'result': 'Error'}]
else:
log.error('Failed sending non-JSON-type request to XBMC: %s', traceback.format_exc())
return [{'result': 'Error'}]
except requests.exceptions.Timeout:
log.info2('Couldn\'t send request to XBMC, assuming it\'s turned off')
return [{'result': 'Error'}]
except:
log.error('Failed sending non-JSON-type request to XBMC: %s', traceback.format_exc())
return [{'result': 'Error'}]
def request(self, host, requests):
def request(self, host, do_requests):
server = 'http://%s/jsonrpc' % host
data = []
for req in requests:
for req in do_requests:
method, kwargs = req
data.append({
'method': method,
@@ -202,17 +199,13 @@ class XBMC(Notification):
try:
log.debug('Sending request to %s: %s', (host, data))
response = self.getJsonData(server, headers = headers, params = data, timeout = 3, show_error = False)
response = self.getJsonData(server, headers = headers, data = data, timeout = 3, show_error = False)
log.debug('Returned from request %s: %s', (host, response))
return response
except URLError, e:
if isinstance(e.reason, socket.timeout):
log.info('Couldn\'t send request to XBMC, assuming it\'s turned off')
return []
else:
log.error('Failed sending request to XBMC: %s', traceback.format_exc())
return []
except requests.exceptions.Timeout:
log.info2('Couldn\'t send request to XBMC, assuming it\'s turned off')
return []
except:
log.error('Failed sending request to XBMC: %s', traceback.format_exc())
return []
+31 -52
View File
@@ -1,19 +1,15 @@
from StringIO import StringIO
from couchpotato.core.event import fireEvent, addEvent
from couchpotato.core.helpers.encoding import tryUrlencode, ss, toSafeString, \
from couchpotato.core.helpers.encoding import ss, toSafeString, \
toUnicode, sp
from couchpotato.core.helpers.variable import getExt, md5, isLocalIP
from couchpotato.core.logger import CPLog
from couchpotato.environment import Env
from multipartpost import MultipartPostHandler
import requests
from tornado import template
from tornado.web import StaticFileHandler
from urlparse import urlparse
import cookielib
import glob
import gzip
import inspect
import math
import os.path
import re
import time
@@ -39,6 +35,7 @@ class Plugin(object):
http_time_between_calls = 0
http_failed_request = {}
http_failed_disabled = {}
http_opener = requests.Session()
def __new__(typ, *args, **kwargs):
new_plugin = super(Plugin, typ).__new__(typ)
@@ -106,7 +103,9 @@ class Plugin(object):
f.close()
os.chmod(path, Env.getPermission('file'))
except Exception, e:
log.error('Unable writing to file "%s": %s', (path, e))
log.error('Unable writing to file "%s": %s', (path, traceback.format_exc()))
if os.path.isfile(path):
os.remove(path)
def makeDir(self, path):
path = ss(path)
@@ -120,11 +119,11 @@ class Plugin(object):
return False
# http request
def urlopen(self, url, timeout = 30, params = None, headers = None, opener = None, multipart = False, show_error = True):
def urlopen(self, url, timeout = 30, data = None, headers = None, files = None, show_error = True, return_raw = False):
url = urllib2.quote(ss(url), safe = "%/:=&?~#+!$,;'@()*[]")
if not headers: headers = {}
if not params: params = {}
if not data: data = {}
# Fill in some headers
parsed_url = urlparse(url)
@@ -137,6 +136,8 @@ class Plugin(object):
headers['Connection'] = headers.get('Connection', 'keep-alive')
headers['Cache-Control'] = headers.get('Cache-Control', 'max-age=0')
r = self.http_opener
# Don't try for failed requests
if self.http_failed_disabled.get(host, 0) > 0:
if self.http_failed_disabled[host] > (time.time() - 900):
@@ -152,45 +153,18 @@ class Plugin(object):
self.wait(host)
try:
# Make sure opener has the correct headers
if opener:
opener.add_headers = headers
kwargs = {
'headers': headers,
'data': data if len(data) > 0 else None,
'timeout': timeout,
'files': files,
}
method = 'post' if len(data) > 0 or files else 'get'
if multipart:
log.info('Opening multipart url: %s, params: %s', (url, [x for x in params.iterkeys()] if isinstance(params, dict) else 'with data'))
request = urllib2.Request(url, params, headers)
log.info('Opening url: %s %s, data: %s', (method, url, [x for x in data.iterkeys()] if isinstance(data, dict) else 'with data'))
response = r.request(method, url, verify = False, **kwargs)
if opener:
opener.add_handler(MultipartPostHandler())
else:
cookies = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), MultipartPostHandler)
response = opener.open(request, timeout = timeout)
else:
log.info('Opening url: %s, params: %s', (url, [x for x in params.iterkeys()] if isinstance(params, dict) else 'with data'))
if isinstance(params, (str, unicode)) and len(params) > 0:
data = params
else:
data = tryUrlencode(params) if len(params) > 0 else None
request = urllib2.Request(url, data, headers)
if opener:
response = opener.open(request, timeout = timeout)
else:
response = urllib2.urlopen(request, timeout = timeout)
# unzip if needed
if response.info().get('Content-Encoding') == 'gzip':
buf = StringIO(response.read())
f = gzip.GzipFile(fileobj = buf)
data = f.read()
f.close()
else:
data = response.read()
response.close()
data = response.content if return_raw else response.text
self.http_failed_request[host] = 0
except IOError:
@@ -218,15 +192,19 @@ class Plugin(object):
return data
def wait(self, host = ''):
if self.http_time_between_calls == 0:
return
now = time.time()
last_use = self.http_last_use.get(host, 0)
if last_use > 0:
wait = math.ceil(last_use - now + self.http_time_between_calls)
wait = (last_use - now) + self.http_time_between_calls
if wait > 0:
log.debug('Waiting for %s, %d seconds', (self.getName(), wait))
time.sleep(last_use - now + self.http_time_between_calls)
if wait > 0:
log.debug('Waiting for %s, %d seconds', (self.getName(), wait))
time.sleep(wait)
def beforeCall(self, handler):
self.isRunning('%s.%s' % (self.getName(), handler.__name__))
@@ -269,18 +247,19 @@ class Plugin(object):
try:
cache_timeout = 300
if kwargs.get('cache_timeout'):
if kwargs.has_key('cache_timeout'):
cache_timeout = kwargs.get('cache_timeout')
del kwargs['cache_timeout']
data = self.urlopen(url, **kwargs)
if data:
if data and cache_timeout > 0:
self.setCache(cache_key, data, timeout = cache_timeout)
return data
except:
if not kwargs.get('show_error', True):
raise
log.error('Failed getting cache: %s', (traceback.format_exc()))
return ''
def setCache(self, cache_key, value, timeout = 300):
+1 -1
View File
@@ -93,7 +93,7 @@ class FileManager(Plugin):
return dest
try:
filedata = self.urlopen(url, **urlopen_kwargs)
filedata = self.urlopen(url, return_raw = True, **urlopen_kwargs)
except:
log.error('Failed downloading file %s: %s', (url, traceback.format_exc()))
return False
+1
View File
@@ -314,6 +314,7 @@ class QualityPlugin(Plugin):
'Movie.Name.1999.DVDRip-Group': 'dvdrip',
'Movie.Name.1999.DVD-Rip-Group': 'dvdrip',
'Movie.Name.1999.DVD-R-Group': 'dvdr',
'Movie.Name.Camelie.1999.720p.BluRay.x264-Group': '720p',
}
correct = 0
+5 -4
View File
@@ -247,13 +247,13 @@ class Release(Plugin):
'files': {}
}), manual = True)
if success:
if success == True:
db.expunge_all()
rel = db.query(Relea).filter_by(id = id).first() # Get release again @RuudBurger why do we need to get it again??
fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Successfully snatched "%s"' % item['name'])
return {
'success': success
'success': success == True
}
def download(self, data, media, manual = False):
@@ -266,20 +266,21 @@ class Release(Plugin):
# Test to see if any downloaders are enabled for this type
downloader_enabled = fireEvent('download.enabled', manual, data, single = True)
if not downloader_enabled:
log.info('Tried to download, but none of the "%s" downloaders are enabled or gave an error', (data.get('protocol')))
log.info('Tried to download, but none of the "%s" downloaders are enabled or gave an error', data.get('protocol'))
return False
# Download NZB or torrent file
filedata = None
if data.get('download') and (ismethod(data.get('download')) or isfunction(data.get('download'))):
filedata = data.get('download')(url = data.get('url'), nzb_id = data.get('id'))
log.info('Tried to download, but the "%s" provider gave an error', data.get('protocol'))
if filedata == 'try_next':
return filedata
# Send NZB or torrent file to downloader
download_result = fireEvent('download', data = data, media = media, manual = manual, filedata = filedata, single = True)
if not download_result:
log.info('Tried to download, but the "%s" downloader gave an error', (data.get('protocol')))
log.info('Tried to download, but the "%s" downloader gave an error', data.get('protocol'))
return False
log.debug('Downloader result: %s', download_result)
+26 -14
View File
@@ -3,7 +3,7 @@ from couchpotato.api import addApiView
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
from couchpotato.core.helpers.encoding import toUnicode, ss, sp
from couchpotato.core.helpers.variable import getExt, mergeDicts, getTitle, \
getImdb, link, symlink, tryInt, splitString, fnEscape
getImdb, link, symlink, tryInt, splitString, fnEscape, isSubFolder
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.core.settings.model import Library, File, Profile, Release, \
@@ -125,7 +125,7 @@ class Renamer(Plugin):
return
else:
for item in no_process:
if '%s%s' % (base_folder, os.path.sep) in item:
if isSubFolder(item, base_folder):
log.error('To protect your data, the media libraries can\'t be inside of or the same as the "from" folder.')
return
@@ -157,13 +157,13 @@ class Renamer(Plugin):
if media_folder:
for item in no_process:
if '%s%s' % (media_folder, os.path.sep) in item:
if isSubFolder(item, media_folder):
log.error('To protect your data, the media libraries can\'t be inside of or the same as the provided media folder.')
return
# Make sure a checkSnatched marked all downloads/seeds as such
if not release_download and self.conf('run_every') > 0:
fireEvent('renamer.check_snatched')
self.checkSnatched(fire_scan = False)
self.renaming_started = True
@@ -508,7 +508,10 @@ class Renamer(Plugin):
os.remove(src)
parent_dir = os.path.dirname(src)
if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and not '%s%s' % (parent_dir, os.path.sep) in [destination, media_folder] and not '%s%s' % (base_folder, os.path.sep) in parent_dir:
if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and \
not isSubFolder(destination, parent_dir) and not isSubFolder(media_folder, parent_dir) and \
not isSubFolder(parent_dir, base_folder):
delete_folders.append(parent_dir)
except:
@@ -575,7 +578,7 @@ class Renamer(Plugin):
# Break if CP wants to shut down
if self.shuttingDown():
break
self.renaming_started = False
def getRenameExtras(self, extra_type = '', replacements = None, folder_name = '', file_name = '', destination = '', group = None, current_file = '', remove_multiple = False):
@@ -806,7 +809,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
except:
loge('Couldn\'t remove empty directory %s: %s', (folder, traceback.format_exc()))
def checkSnatched(self):
def checkSnatched(self, fire_scan = True):
if self.checking_snatched:
log.debug('Already checking snatched')
@@ -829,20 +832,29 @@ Remove it if you want it to be renamed (again, or at least let it try again)
# Collect all download information with the download IDs from the releases
download_ids = []
no_status_support = []
try:
for rel in rels:
rel_dict = rel.to_dict({'info': {}})
if rel_dict['info'].get('download_id') and rel_dict['info'].get('download_downloader'):
download_ids.append({'id': rel_dict['info']['download_id'], 'downloader': rel_dict['info']['download_downloader']})
ds = rel_dict['info'].get('download_status_support')
if ds == False or ds == 'False':
no_status_support.append(ss(rel_dict['info'].get('download_downloader')))
except:
log.error('Error getting download IDs from database')
self.checking_snatched = False
return False
release_downloads = fireEvent('download.status', download_ids, merge = True)
release_downloads = fireEvent('download.status', download_ids, merge = True) if download_ids else []
if len(no_status_support) > 0:
log.debug('Download status functionality is not implemented for one of the active downloaders: %s', no_status_support)
if not release_downloads:
log.debug('Download status functionality is not implemented for any active downloaders.')
fireEvent('renamer.scan')
if fire_scan:
self.scan()
self.checking_snatched = False
return True
@@ -982,7 +994,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
if release_download['scan']:
if release_download['pause'] and self.conf('file_action') == 'link':
fireEvent('download.pause', release_download = release_download, pause = True, single = True)
fireEvent('renamer.scan', release_download = release_download)
self.scan(release_download = release_download)
if release_download['pause'] and self.conf('file_action') == 'link':
fireEvent('download.pause', release_download = release_download, pause = False, single = True)
if release_download['process_complete']:
@@ -993,8 +1005,8 @@ Remove it if you want it to be renamed (again, or at least let it try again)
# Ask the downloader to process the item
fireEvent('download.process_complete', release_download = release_download, single = True)
if scan_required:
fireEvent('renamer.scan')
if fire_scan and (scan_required or len(no_status_support) > 0):
self.scan()
self.checking_snatched = False
return True
@@ -1044,7 +1056,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
return release_download['id'] and release_download['downloader'] and release_download['folder']
def movieInFromFolder(self, media_folder):
return media_folder and '%s%s' % (sp(self.conf('from')), os.path.sep) in sp(media_folder) or not media_folder
return media_folder and isSubFolder(media_folder, sp(self.conf('from'))) or not media_folder
def extractFiles(self, folder = None, media_folder = None, files = None, cleanup = False):
if not files: files = []
+2 -1
View File
@@ -80,7 +80,8 @@ class Scanner(Plugin):
'hdtv': ['hdtv']
}
clean = '[ _\,\.\(\)\[\]\-](extended.cut|directors.cut|french|swedisch|danish|dutch|swesub|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|video_ts|audio_ts|480p|480i|576p|576i|720p|720i|1080p|1080i|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|cd[1-9]|\[.*\])([ _\,\.\(\)\[\]\-]|$)'
clean = '[ _\,\.\(\)\[\]\-]?(extended.cut|directors.cut|french|swedisch|danish|dutch|swesub|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip' \
'|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|video_ts|audio_ts|480p|480i|576p|576i|720p|720i|1080p|1080i|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|cd[1-9]|\[.*\])([ _\,\.\(\)\[\]\-]|$)'
multipart_regex = [
'[ _\.-]+cd[ _\.-]*([0-9a-d]+)', #*cd1
'[ _\.-]+dvd[ _\.-]*([0-9a-d]+)', #*dvd1
@@ -59,7 +59,7 @@ config = [{
{
'name': 'automation_charts_boxoffice',
'type': 'bool',
'label': 'Box offce TOP 10',
'label': 'Box office TOP 10',
'description': 'IMDB Box office <a href="http://www.imdb.com/chart/">TOP 10</a> chart',
'default': True,
},
+11 -19
View File
@@ -5,12 +5,10 @@ from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
from urlparse import urlparse
import cookielib
import json
import re
import time
import traceback
import urllib2
import xml.etree.ElementTree as XMLTree
log = CPLog(__name__)
@@ -95,7 +93,7 @@ class Provider(Plugin):
def getHTMLData(self, url, **kwargs):
cache_key = '%s%s' % (md5(url), md5('%s' % kwargs.get('params', {})))
cache_key = '%s%s' % (md5(url), md5('%s' % kwargs.get('data', {})))
return self.getCache(cache_key, url, **kwargs)
@@ -111,8 +109,7 @@ class YarrProvider(Provider):
sizeMb = ['mb', 'mib']
sizeKb = ['kb', 'kib']
login_opener = None
last_login_check = 0
last_login_check = None
def __init__(self):
addEvent('provider.enabled_protocols', self.getEnabledProtocol)
@@ -131,35 +128,30 @@ class YarrProvider(Provider):
# Check if we are still logged in every hour
now = time.time()
if self.login_opener and self.last_login_check < (now - 3600):
if self.last_login_check and self.last_login_check < (now - 3600):
try:
output = self.urlopen(self.urls['login_check'], opener = self.login_opener)
output = self.urlopen(self.urls['login_check'])
if self.loginCheckSuccess(output):
self.last_login_check = now
return True
else:
self.login_opener = None
except:
self.login_opener = None
except: pass
self.last_login_check = None
if self.login_opener:
if self.last_login_check:
return True
try:
cookiejar = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
output = self.urlopen(self.urls['login'], params = self.getLoginParams(), opener = opener)
output = self.urlopen(self.urls['login'], data = self.getLoginParams())
if self.loginSuccess(output):
self.last_login_check = now
self.login_opener = opener
return True
error = 'unknown'
except:
error = traceback.format_exc()
self.login_opener = None
self.last_login_check = None
log.error('Failed to login %s: %s', (self.getName(), error))
return False
@@ -173,12 +165,12 @@ class YarrProvider(Provider):
try:
if not self.login():
log.error('Failed downloading from %s', self.getName())
return self.urlopen(url, opener = self.login_opener)
return self.urlopen(url)
except:
log.error('Failed downloading from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
return ''
return {}
def download(self, url = '', nzb_id = ''):
try:
@@ -32,14 +32,17 @@ class Movie(ModifierBase):
'poster': [],
'backdrop': [],
'poster_original': [],
'backdrop_original': []
'backdrop_original': [],
'actors': {}
},
'runtime': 0,
'plot': '',
'tagline': '',
'imdb': '',
'genres': [],
'mpaa': None
'mpaa': None,
'actors': [],
'actor_roles': {}
}
def __init__(self):
@@ -74,7 +74,7 @@ class CouchPotatoApi(MovieProvider):
return True
def getInfo(self, identifier = None):
def getInfo(self, identifier = None, **kwargs):
if not identifier:
return
@@ -97,7 +97,7 @@ class CouchPotatoApi(MovieProvider):
if not ignore: ignore = []
if not movies: movies = []
suggestions = self.getJsonData(self.urls['suggest'], params = {
suggestions = self.getJsonData(self.urls['suggest'], data = {
'movies': ','.join(movies),
'ignore': ','.join(ignore),
}, headers = self.getRequestHeaders())
@@ -46,7 +46,7 @@ class OMDBAPI(MovieProvider):
return []
def getInfo(self, identifier = None):
def getInfo(self, identifier = None, **kwargs):
if not identifier:
return {}
@@ -88,10 +88,6 @@ class OMDBAPI(MovieProvider):
year = tryInt(movie.get('Year', ''))
actors = {}
for actor in splitString(movie.get('Actors', '')):
actors[actor] = '' #omdb does not return actor roles
movie_data = {
'type': 'movie',
'via_imdb': True,
@@ -113,7 +109,7 @@ class OMDBAPI(MovieProvider):
'genres': splitString(movie.get('Genre', '')),
'directors': splitString(movie.get('Director', '')),
'writers': splitString(movie.get('Writer', '')),
'actor_roles': actors,
'actors': splitString(movie.get('Actors', '')),
}
movie_data = dict((k, v) for k, v in movie_data.iteritems() if v)
except:
@@ -11,8 +11,8 @@ log = CPLog(__name__)
class TheMovieDb(MovieProvider):
def __init__(self):
addEvent('info.search', self.search, priority = 2)
addEvent('movie.search', self.search, priority = 2)
#addEvent('info.search', self.search, priority = 2)
#addEvent('movie.search', self.search, priority = 2)
addEvent('movie.info', self.getInfo, priority = 2)
addEvent('movie.info_by_tmdb', self.getInfo)
@@ -45,7 +45,7 @@ class TheMovieDb(MovieProvider):
nr = 0
for movie in raw:
results.append(self.parseMovie(movie, with_titles = False))
results.append(self.parseMovie(movie, extended = False))
nr += 1
if nr == limit:
@@ -61,7 +61,7 @@ class TheMovieDb(MovieProvider):
return results
def getInfo(self, identifier = None):
def getInfo(self, identifier = None, extended = True):
if not identifier:
return {}
@@ -73,14 +73,14 @@ class TheMovieDb(MovieProvider):
try:
log.debug('Getting info: %s', cache_key)
movie = tmdb3.Movie(identifier)
result = self.parseMovie(movie)
result = self.parseMovie(movie, extended = extended)
self.setCache(cache_key, result)
except:
pass
return result
def parseMovie(self, movie, with_titles = True):
def parseMovie(self, movie, extended = True):
cache_key = 'tmdb.cache.%s' % movie.id
movie_data = self.getCache(cache_key)
@@ -97,6 +97,7 @@ class TheMovieDb(MovieProvider):
#'backdrop': [backdrop] if backdrop else [],
'poster_original': [poster_original] if poster_original else [],
'backdrop_original': [backdrop_original] if backdrop_original else [],
'actors': {}
}
# Genres
@@ -112,12 +113,13 @@ class TheMovieDb(MovieProvider):
# Gather actors data
actors = {}
for cast_item in movie.cast:
try:
actors[toUnicode(cast_item.name)] = toUnicode(cast_item.character)
images['actor %s' % toUnicode(cast_item.name)] = self.getImage(cast_item, type = 'profile', size = 'original')
except:
log.debug('Error getting cast info for %s: %s', (cast_item, traceback.format_exc()))
if extended:
for cast_item in movie.cast:
try:
actors[toUnicode(cast_item.name)] = toUnicode(cast_item.character)
images['actors'][toUnicode(cast_item.name)] = self.getImage(cast_item, type = 'profile', size = 'original')
except:
log.debug('Error getting cast info for %s: %s', (cast_item, traceback.format_exc()))
movie_data = {
'type': 'movie',
@@ -139,7 +141,7 @@ class TheMovieDb(MovieProvider):
movie_data = dict((k, v) for k, v in movie_data.iteritems() if v)
# Add alternative names
if with_titles:
if extended:
movie_data['titles'].append(movie.originaltitle)
for alt in movie.alternate_titles:
alt_name = alt.title
@@ -98,9 +98,9 @@ class XBMC(MetaDataBase):
if role_name:
role = SubElement(actor, 'role')
role.text = toUnicode(role_name)
if movie_info['images'].get('actor %s' % actor_name, ''):
if movie_info['images']['actors'].get(actor_name):
thumb = SubElement(actor, 'thumb')
thumb.text = toUnicode(movie_info['images'].get('actor %s' % actor_name))
thumb.text = toUnicode(movie_info['images']['actors'].get(actor_name))
# Directors
for director_name in movie_info.get('directors', []):
@@ -85,13 +85,13 @@ class Base(NZBProvider):
def download(self, url = '', nzb_id = ''):
params = {
data = {
'action': 'nzb',
nzb_id: 'on'
}
try:
return self.urlopen(url, params = params, show_error = False)
return self.urlopen(url, data = data, show_error = False)
except:
log.error('Failed getting nzb from %s: %s', (self.getName(), traceback.format_exc()))
@@ -165,6 +165,7 @@ class Base(NZBProvider, RSS):
# Get final redirected url
log.debug('Checking %s for redirects.', url)
req = urllib2.Request(url)
req.add_header('User-Agent', self.user_agent)
res = urllib2.urlopen(req)
finalurl = res.geturl()
if finalurl != url:
@@ -34,7 +34,7 @@ class Base(TorrentProvider):
url = "%s&%s" % (self.urls['search'], query)
data = self.getHTMLData(url, opener = self.login_opener)
data = self.getHTMLData(url)
if data:
# Remove BiT-HDTV's output garbage so outdated BS4 versions successfully parse the HTML
@@ -71,10 +71,10 @@ class Base(TorrentProvider):
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
return tryUrlencode({
return {
'username': self.conf('username'),
'password': self.conf('password'),
})
}
def getMoreInfo(self, item):
full_description = self.getCache('bithdtv.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
@@ -116,4 +116,4 @@ class Episode(EpisodeProvider, Base):
'search': fireEvent('library.query', media['library'], single = True),
'cat': 10 # Episode cat
})
return query
return query
@@ -1,5 +1,4 @@
from bs4 import BeautifulSoup
from couchpotato.core.helpers.encoding import tryUrlencode
from couchpotato.core.helpers.variable import tryInt
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.torrent.base import TorrentProvider
@@ -23,7 +22,7 @@ class HDBits(TorrentProvider):
def _search(self, movie, quality, results):
data = self.getJsonData(self.urls['search'] % movie['library']['identifier'], opener = self.login_opener)
data = self.getJsonData(self.urls['search'] % movie['library']['identifier'])
if data:
try:
@@ -42,15 +41,17 @@ class HDBits(TorrentProvider):
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
data = self.getHTMLData('https://hdbits.org/login')
data = self.getHTMLData('https://hdbits.org/login', cache_timeout = 0)
bs = BeautifulSoup(data)
secret = bs.find('input', attrs = {'name': 'lol'})['value']
return tryUrlencode({
return {
'uname': self.conf('username'),
'password': self.conf('password'),
'returnto': '/',
'lol': secret
})
}
def loginSuccess(self, output):
return '/logout.php' in output.lower()
@@ -42,7 +42,7 @@ class ILoveTorrents(TorrentProvider):
search_url = self.urls['search'] % (movieTitle, page, cats[0])
page += 1
data = self.getHTMLData(search_url, opener = self.login_opener)
data = self.getHTMLData(search_url)
if data:
try:
soup = BeautifulSoup(data)
@@ -96,11 +96,11 @@ class ILoveTorrents(TorrentProvider):
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
return tryUrlencode({
return {
'username': self.conf('username'),
'password': self.conf('password'),
'submit': 'Welcome to ILT',
})
}
def getMoreInfo(self, item):
cache_key = 'ilt.%s' % item['id']
@@ -109,7 +109,7 @@ class ILoveTorrents(TorrentProvider):
if not description:
try:
full_description = self.getHTMLData(item['detail_url'], opener = self.login_opener)
full_description = self.getHTMLData(item['detail_url'])
html = BeautifulSoup(full_description)
nfo_pre = html.find('td', attrs = {'class':'main'}).findAll('table')[1]
description = toUnicode(nfo_pre.text) if nfo_pre else ''
@@ -44,7 +44,7 @@ class Base(TorrentProvider):
})
url = '%s?json=noredirect&%s' % (self.urls['torrent'], tryUrlencode(params))
res = self.getJsonData(url, opener = self.login_opener)
res = self.getJsonData(url)
try:
if not 'Movies' in res:
@@ -167,13 +167,13 @@ class Base(TorrentProvider):
return self.unicodeToASCII(self.htmlToUnicode(text))
def getLoginParams(self):
return tryUrlencode({
return {
'username': self.conf('username'),
'password': self.conf('password'),
'passkey': self.conf('passkey'),
'keeplogged': '1',
'login': 'Login'
})
}
def loginSuccess(self, output):
try:
@@ -211,4 +211,4 @@ class Movie(MovieProvider, Base):
'tc': {'Source': ['TC']},
'ts': {'Source': ['TS']},
'cam': {'Source': ['CAM']}
}
}
@@ -35,7 +35,7 @@ class TorrentBytes(TorrentProvider):
def _searchOnTitle(self, title, movie, quality, results):
url = self.urls['search'] % (tryUrlencode('%s %s' % (title.replace(':', ''), movie['library']['year'])), self.getCatId(quality['identifier'])[0])
data = self.getHTMLData(url, opener = self.login_opener)
data = self.getHTMLData(url)
if data:
html = BeautifulSoup(data)
@@ -69,11 +69,11 @@ class TorrentBytes(TorrentProvider):
log.error('Failed to parsing %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
return tryUrlencode({
return {
'username': self.conf('username'),
'password': self.conf('password'),
'login': 'submit',
})
}
def loginSuccess(self, output):
return 'logout.php' in output.lower() or 'Welcome' in output.lower()
@@ -1,4 +1,3 @@
from couchpotato.core.helpers.encoding import tryUrlencode
from couchpotato.core.helpers.variable import tryInt
from couchpotato.core.logger import CPLog
from couchpotato.core.event import fireEvent
@@ -31,7 +30,7 @@ class Base(TorrentProvider):
query = self.buildUrl(media)
params = {
data = {
'/browse.php?': None,
'cata': 'yes',
'jxt': 8,
@@ -39,7 +38,7 @@ class Base(TorrentProvider):
'search': query,
}
data = self.getJsonData(self.urls['search'], params = params, opener = self.login_opener)
data = self.getJsonData(self.urls['search'], data = data)
try: torrents = data.get('Fs', [])[0].get('Cn', {}).get('torrents', [])
except: return
@@ -55,11 +54,13 @@ class Base(TorrentProvider):
})
def getLoginParams(self):
return tryUrlencode({
return {
'username': self.conf('username'),
'password': self.conf('password'),
'submit.x': 18,
'submit.y': 11,
'submit': 'submit',
})
}
def loginSuccess(self, output):
return 'Password not correct' not in output
@@ -25,7 +25,7 @@ class UserscriptBase(Plugin):
result = fireEvent('movie.search', q = '%s %s' % (name, year), limit = 1, merge = True)
if len(result) > 0:
movie = fireEvent('movie.info', identifier = result[0].get('imdb'), merge = True)
movie = fireEvent('movie.info', identifier = result[0].get('imdb'), extended = False, merge = True)
return movie
else:
return None
@@ -54,7 +54,7 @@ class UserscriptBase(Plugin):
return self.getInfo(getImdb(data))
def getInfo(self, identifier):
return fireEvent('movie.info', identifier = identifier, merge = True)
return fireEvent('movie.info', identifier = identifier, extended = False, merge = True)
def getInclude(self):
return self.includes
@@ -8,4 +8,4 @@ class IMDB(UserscriptBase):
includes = ['*://*.imdb.com/title/tt*', '*://imdb.com/title/tt*']
def getMovie(self, url):
return fireEvent('movie.info', identifier = getImdb(url), merge = True)
return self.getInfo(getImdb(url))
@@ -9,7 +9,7 @@ class TMDB(UserscriptBase):
def getMovie(self, url):
match = re.search('(?P<id>\d+)', url)
movie = fireEvent('movie.info_by_tmdb', identifier = match.group('id'), merge = True)
movie = fireEvent('movie.info_by_tmdb', identifier = match.group('id'), extended = False, merge = True)
if movie['imdb']:
return self.getInfo(movie['imdb'])