Merge branch 'refs/heads/develop'

This commit is contained in:
Ruud
2012-04-28 23:14:18 +02:00
26 changed files with 123 additions and 47 deletions
+18
View File
@@ -1,6 +1,8 @@
from couchpotato.api import api_docs, api_docs_missing from couchpotato.api import api_docs, api_docs_missing
from couchpotato.core.auth import requires_auth from couchpotato.core.auth import requires_auth
from couchpotato.core.event import fireEvent from couchpotato.core.event import fireEvent
from couchpotato.core.helpers.request import getParams, jsonified
from couchpotato.core.helpers.variable import md5
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.environment import Env from couchpotato.environment import Env
from flask.app import Flask from flask.app import Flask
@@ -51,6 +53,22 @@ def apiDocs():
del api_docs_missing[''] del api_docs_missing['']
return render_template('api.html', fireEvent = fireEvent, routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing)) return render_template('api.html', fireEvent = fireEvent, routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing))
@web.route('getkey/')
def getApiKey():
api = None
params = getParams()
username = Env.setting('username')
password = Env.setting('password')
if (params.get('u') == md5(username) or not username) and (params.get('p') == password or not password):
api = Env.setting('api_key')
return jsonified({
'success': api is not None,
'api_key': api
})
@app.errorhandler(404) @app.errorhandler(404)
def page_not_found(error): def page_not_found(error):
index_url = url_for('web.index') index_url = url_for('web.index')
+1 -1
View File
@@ -55,7 +55,7 @@ config = [{
'name': 'api_key', 'name': 'api_key',
'default': uuid4().hex, 'default': uuid4().hex,
'readonly': 1, 'readonly': 1,
'description': 'Let 3rd party app do stuff. <a target="_self" href="/docs/">Docs</a>', 'description': 'Let 3rd party app do stuff. <a target="_self" href="../../docs/">Docs</a>',
}, },
{ {
'name': 'debug', 'name': 'debug',
+2 -1
View File
@@ -96,7 +96,8 @@ class BaseUpdater(Plugin):
'last_check': self.last_check, 'last_check': self.last_check,
'update_version': self.update_version, 'update_version': self.update_version,
'version': self.getVersion(), 'version': self.getVersion(),
'repo_name': '%s/%s' % (self.repo_user, self.repo_name) 'repo_name': '%s/%s' % (self.repo_user, self.repo_name),
'branch': self.branch,
} }
def check(self): def check(self):
@@ -79,6 +79,8 @@ var UpdaterBase = new Class({
if(json.success){ if(json.success){
App.restart('Please wait while CouchPotato is being updated with more awesome stuff.', 'Updating'); App.restart('Please wait while CouchPotato is being updated with more awesome stuff.', 'Updating');
App.checkAvailable.delay(500, App); App.checkAvailable.delay(500, App);
if(self.message)
self.message.destroy();
} }
} }
}); });
+2 -2
View File
@@ -56,7 +56,7 @@ class CoreNotifier(Notification):
addEvent('library.update_finish', lambda data: fireEvent('notify.frontend', type = 'library.update', data = data)) addEvent('library.update_finish', lambda data: fireEvent('notify.frontend', type = 'library.update', data = data))
def markAsRead(self): def markAsRead(self):
ids = getParam('ids').split(',') ids = [x.strip() for x in getParam('ids').split(',')]
db = get_session() db = get_session()
@@ -78,7 +78,7 @@ class CoreNotifier(Notification):
q = db.query(Notif) q = db.query(Notif)
if limit_offset: if limit_offset:
splt = limit_offset.split(',') splt = [x.strip() for x in limit_offset.split(',')]
limit = splt[0] limit = splt[0]
offset = 0 if len(splt) is 1 else splt[1] offset = 0 if len(splt) is 1 else splt[1]
q = q.limit(limit).offset(offset) q = q.limit(limit).offset(offset)
@@ -11,7 +11,7 @@ class NotifyMyAndroid(Notification):
if self.isDisabled(): return if self.isDisabled(): return
nma = pynma.PyNMA() nma = pynma.PyNMA()
keys = self.conf('api_key').split(',') keys = [x.strip() for x in self.conf('api_key').split(',')]
nma.addkey(keys) nma.addkey(keys)
nma.developerkey(self.conf('dev_key')) nma.developerkey(self.conf('dev_key'))
@@ -10,7 +10,7 @@ class NotifyMyWP(Notification):
def notify(self, message = '', data = {}): def notify(self, message = '', data = {}):
if self.isDisabled(): return if self.isDisabled(): return
keys = self.conf('api_key').split(',') keys = [x.strip() for x in self.conf('api_key').split(',')]
p = PyNMWP(keys, self.conf('dev_key')) p = PyNMWP(keys, self.conf('dev_key'))
response = p.push(application = self.default_title, event = message, description = message, priority = self.conf('priority'), batch_mode = len(keys) > 1) response = p.push(application = self.default_title, event = message, description = message, priority = self.conf('priority'), batch_mode = len(keys) > 1)
+1 -1
View File
@@ -77,6 +77,6 @@ class Manage(Plugin):
def directories(self): def directories(self):
try: try:
return self.conf('library', default = '').split('::') return [x.strip() for x in self.conf('library', default = '').split('::')]
except: except:
return [] return []
+3 -3
View File
@@ -139,7 +139,7 @@ class MoviePlugin(Plugin):
if limit_offset: if limit_offset:
splt = limit_offset.split(',') splt = [x.strip() for x in limit_offset.split(',')]
limit = splt[0] limit = splt[0]
offset = 0 if len(splt) is 1 else splt[1] offset = 0 if len(splt) is 1 else splt[1]
q2 = q2.limit(limit).offset(offset) q2 = q2.limit(limit).offset(offset)
@@ -324,7 +324,7 @@ class MoviePlugin(Plugin):
available_status = fireEvent('status.get', 'available', single = True) available_status = fireEvent('status.get', 'available', single = True)
ids = params.get('id').split(',') ids = [x.strip() for x in params.get('id').split(',')]
for movie_id in ids: for movie_id in ids:
m = db.query(Movie).filter_by(id = movie_id).first() m = db.query(Movie).filter_by(id = movie_id).first()
@@ -356,7 +356,7 @@ class MoviePlugin(Plugin):
params = getParams() params = getParams()
ids = params.get('id').split(',') ids = [x.strip() for x in params.get('id').split(',')]
for movie_id in ids: for movie_id in ids:
self.delete(movie_id) self.delete(movie_id)
@@ -279,7 +279,8 @@
border: 0; border: 0;
} }
.movies .options .table .provider { .movies .options .table .provider {
width: 130px; width: 120px;
text-overflow: ellipsis;
} }
.movies .options .table .name { .movies .options .table .name {
width: 350px; width: 350px;
@@ -290,6 +291,8 @@
.movies .options .table.files .name { width: 605px; } .movies .options .table.files .name { width: 605px; }
.movies .options .table .type { width: 130px; } .movies .options .table .type { width: 130px; }
.movies .options .table .is_available { width: 90px; } .movies .options .table .is_available { width: 90px; }
.movies .options .table .age,
.movies .options .table .size { width: 40px; }
.movies .options .table a { .movies .options .table a {
width: 30px !important; width: 30px !important;
@@ -270,8 +270,9 @@ var ReleaseAction = new Class({
// Header // Header
new Element('div.item.head').adopt( new Element('div.item.head').adopt(
new Element('span.name', {'text': 'Release name'}), new Element('span.name', {'text': 'Release name'}),
new Element('span.status', {'text': 'Status'}),
new Element('span.quality', {'text': 'Quality'}), new Element('span.quality', {'text': 'Quality'}),
new Element('span.size', {'text': 'Size (MB)'}), new Element('span.size', {'text': 'Size'}),
new Element('span.age', {'text': 'Age'}), new Element('span.age', {'text': 'Age'}),
new Element('span.score', {'text': 'Score'}), new Element('span.score', {'text': 'Score'}),
new Element('span.provider', {'text': 'Provider'}) new Element('span.provider', {'text': 'Provider'})
@@ -288,9 +289,10 @@ var ReleaseAction = new Class({
} catch(e){} } catch(e){}
new Element('div', { new Element('div', {
'class': 'item ' + status.identifier 'class': 'item'
}).adopt( }).adopt(
new Element('span.name', {'text': self.get(release, 'name'), 'title': self.get(release, 'name')}), new Element('span.name', {'text': self.get(release, 'name'), 'title': self.get(release, 'name')}),
new Element('span.status', {'text': status.identifier, 'class': 'release_status '+status.identifier}),
new Element('span.quality', {'text': quality.get('label')}), new Element('span.quality', {'text': quality.get('label')}),
new Element('span.size', {'text': (self.get(release, 'size') || 'unknown')}), new Element('span.size', {'text': (self.get(release, 'size') || 'unknown')}),
new Element('span.age', {'text': self.get(release, 'age')}), new Element('span.age', {'text': self.get(release, 'age')}),
+5 -6
View File
@@ -18,7 +18,7 @@ class QualityPlugin(Plugin):
qualities = [ qualities = [
{'identifier': 'bd50', 'hd': True, 'size': (15000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25'], 'allow': ['1080p'], 'ext':[], 'tags': ['bdmv', 'certificate', ('complete', 'bluray')]}, {'identifier': 'bd50', 'hd': True, 'size': (15000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25'], 'allow': ['1080p'], 'ext':[], 'tags': ['bdmv', 'certificate', ('complete', 'bluray')]},
{'identifier': '1080p', 'hd': True, 'size': (5000, 20000), 'label': '1080P', 'width': 1920, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts']}, {'identifier': '1080p', 'hd': True, 'size': (5000, 20000), 'label': '1080P', 'width': 1920, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts']},
{'identifier': '720p', 'hd': True, 'size': (3500, 10000), 'label': '720P', 'width': 1280, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts']}, {'identifier': '720p', 'hd': True, 'size': (3500, 10000), 'label': '720P', 'width': 1280, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts', 'ts']},
{'identifier': 'brrip', 'hd': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p'], 'ext':['avi']}, {'identifier': 'brrip', 'hd': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p'], 'ext':['avi']},
{'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': [], 'allow': [], 'ext':['iso', 'img'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts']}, {'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': [], 'allow': [], 'ext':['iso', 'img'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts']},
{'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'alternative': ['dvdrip'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']}, {'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'alternative': ['dvdrip'], 'allow': [], 'ext':['avi', 'mpg', 'mpeg']},
@@ -161,26 +161,25 @@ class QualityPlugin(Plugin):
for cur_file in files: for cur_file in files:
size = (os.path.getsize(cur_file) / 1024 / 1024) if os.path.isfile(cur_file) else 0 size = (os.path.getsize(cur_file) / 1024 / 1024) if os.path.isfile(cur_file) else 0
words = re.split('\W+', cur_file.lower()) words = re.split('\W+', cur_file.lower())
safe_cur_file = toSafeString(cur_file)
for quality in self.all(): for quality in self.all():
# Check tags # Check tags
if quality['identifier'] in words: if quality['identifier'] in words:
log.debug('Found via identifier "%s" in %s' % (quality['identifier'], safe_cur_file)) log.debug('Found via identifier "%s" in %s' % (quality['identifier'], cur_file))
return self.setCache(hash, quality) return self.setCache(hash, quality)
if list(set(quality.get('alternative', [])) & set(words)): if list(set(quality.get('alternative', [])) & set(words)):
log.debug('Found %s via alt %s in %s' % (quality['identifier'], quality.get('alternative'), safe_cur_file)) log.debug('Found %s via alt %s in %s' % (quality['identifier'], quality.get('alternative'), cur_file))
return self.setCache(hash, quality) return self.setCache(hash, quality)
for tag in quality.get('tags', []): for tag in quality.get('tags', []):
if isinstance(tag, tuple) and '.'.join(tag) in '.'.join(words): if isinstance(tag, tuple) and '.'.join(tag) in '.'.join(words):
log.debug('Found %s via tag %s in %s' % (quality['identifier'], quality.get('tags'), safe_cur_file)) log.debug('Found %s via tag %s in %s' % (quality['identifier'], quality.get('tags'), cur_file))
return self.setCache(hash, quality) return self.setCache(hash, quality)
if list(set(quality.get('tags', [])) & set(words)): if list(set(quality.get('tags', [])) & set(words)):
log.debug('Found %s via tag %s in %s' % (quality['identifier'], quality.get('tags'), safe_cur_file)) log.debug('Found %s via tag %s in %s' % (quality['identifier'], quality.get('tags'), cur_file))
return self.setCache(hash, quality) return self.setCache(hash, quality)
# Check on unreliable stuff # Check on unreliable stuff
+3 -3
View File
@@ -328,7 +328,7 @@ class Renamer(Plugin):
try: try:
os.remove(src) os.remove(src)
except: except:
log.error('Failed removing %s: %s', (src, traceback.format_exc())) log.error('Failed removing %s: %s' % (src, traceback.format_exc()))
# Remove matching releases # Remove matching releases
for release in remove_releases: for release in remove_releases:
@@ -336,14 +336,14 @@ class Renamer(Plugin):
try: try:
db.delete(release) db.delete(release)
except: except:
log.error('Failed removing %s: %s', (release.identifier, traceback.format_exc())) log.error('Failed removing %s: %s' % (release.identifier, traceback.format_exc()))
if group['dirname'] and group['parentdir']: if group['dirname'] and group['parentdir']:
try: try:
log.info('Deleting folder: %s' % group['parentdir']) log.info('Deleting folder: %s' % group['parentdir'])
self.deleteEmptyFolder(group['parentdir']) self.deleteEmptyFolder(group['parentdir'])
except: except:
log.error('Failed removing %s: %s', (group['parentdir'], traceback.format_exc())) log.error('Failed removing %s: %s' % (group['parentdir'], traceback.format_exc()))
# Search for trailers etc # Search for trailers etc
fireEventAsync('renamer.after', group) fireEventAsync('renamer.after', group)
+5 -2
View File
@@ -31,7 +31,7 @@ class Scanner(Plugin):
ignored_in_path = ['_unpack', '_failed_', '_unknown_', '_exists_', '.appledouble', '.appledb', '.appledesktop', os.path.sep + '._', '.ds_store', 'cp.cpnfo'] #unpacking, smb-crap, hidden files ignored_in_path = ['_unpack', '_failed_', '_unknown_', '_exists_', '.appledouble', '.appledb', '.appledesktop', os.path.sep + '._', '.ds_store', 'cp.cpnfo'] #unpacking, smb-crap, hidden files
ignore_names = ['extract', 'extracting', 'extracted', 'movie', 'movies', 'film', 'films', 'download', 'downloads', 'video_ts', 'audio_ts', 'bdmv', 'certificate'] ignore_names = ['extract', 'extracting', 'extracted', 'movie', 'movies', 'film', 'films', 'download', 'downloads', 'video_ts', 'audio_ts', 'bdmv', 'certificate']
extensions = { extensions = {
'movie': ['mkv', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'm2ts', 'iso', 'img', 'mdf'], 'movie': ['mkv', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'm2ts', 'iso', 'img', 'mdf', 'ts'],
'movie_extra': ['mds'], 'movie_extra': ['mds'],
'dvd': ['vts_*', 'vob'], 'dvd': ['vts_*', 'vob'],
'nfo': ['nfo', 'txt', 'tag'], 'nfo': ['nfo', 'txt', 'tag'],
@@ -165,6 +165,9 @@ class Scanner(Plugin):
for file_path in files: for file_path in files:
if not os.path.exists(file_path):
continue
# Remove ignored files # Remove ignored files
if self.isSampleFile(file_path): if self.isSampleFile(file_path):
leftovers.append(file_path) leftovers.append(file_path)
@@ -263,7 +266,7 @@ class Scanner(Plugin):
file_too_new = tryInt(time.time() - file_time) file_too_new = tryInt(time.time() - file_time)
break break
if file_too_new and not Env.get('dev'): if file_too_new:
log.info('Files seem to be still unpacking or just unpacked (created on %s), ignoring for now: %s' % (time.ctime(file_time), identifier)) log.info('Files seem to be still unpacking or just unpacked (created on %s), ignoring for now: %s' % (time.ctime(file_time), identifier))
continue continue
+1 -1
View File
@@ -40,7 +40,7 @@ def nameScore(name, year):
# Contains preferred word # Contains preferred word
nzb_words = re.split('\W+', simplifyString(name)) nzb_words = re.split('\W+', simplifyString(name))
preferred_words = Env.setting('preferred_words', section = 'searcher').split(',') preferred_words = [x.strip() for x in Env.setting('preferred_words', section = 'searcher').split(',')]
for word in preferred_words: for word in preferred_words:
if word.strip() and word.strip().lower() in nzb_words: if word.strip() and word.strip().lower() in nzb_words:
score = score + 100 score = score + 100
+18 -7
View File
@@ -123,7 +123,11 @@ class Searcher(Plugin):
for nzb in sorted_results: for nzb in sorted_results:
return self.download(data = nzb, movie = movie) downloaded = self.download(data = nzb, movie = movie)
if downloaded:
return True
else:
break
else: else:
log.info('Better quality (%s) already available or snatched for %s' % (quality_type['quality']['label'], default_title)) log.info('Better quality (%s) already available or snatched for %s' % (quality_type['quality']['label'], default_title))
fireEvent('movie.restatus', movie['id']) fireEvent('movie.restatus', movie['id'])
@@ -190,19 +194,26 @@ class Searcher(Plugin):
log.info('Wrong: Outside retention, age is %s, needs %s or lower: %s' % (nzb['age'], retention, nzb['name'])) log.info('Wrong: Outside retention, age is %s, needs %s or lower: %s' % (nzb['age'], retention, nzb['name']))
return False return False
nzb_words = re.split('\W+', simplifyString(nzb['name'])) movie_name = simplifyString(nzb['name'])
required_words = self.conf('required_words').split(',') nzb_words = re.split('\W+', movie_name)
required_words = [x.strip() for x in self.conf('required_words').split(',')]
if self.conf('required_words') and not list(set(nzb_words) & set(required_words)): if self.conf('required_words') and not list(set(nzb_words) & set(required_words)):
log.info("NZB doesn't contain any of the required words.") log.info("NZB doesn't contain any of the required words.")
return False return False
ignored_words = self.conf('ignored_words').split(',') ignored_words = [x.strip() for x in self.conf('ignored_words').split(',')]
blacklisted = list(set(nzb_words) & set(ignored_words)) blacklisted = list(set(nzb_words) & set(ignored_words))
if self.conf('ignored_words') and blacklisted: if self.conf('ignored_words') and blacklisted:
log.info("Wrong: '%s' blacklisted words: %s" % (nzb['name'], ", ".join(blacklisted))) log.info("Wrong: '%s' blacklisted words: %s" % (nzb['name'], ", ".join(blacklisted)))
return False return False
pron_tags = ['xxx', 'sex', 'anal', 'tits', 'fuck', 'porn', 'orgy', 'milf', 'boobs']
for p_tag in pron_tags:
if p_tag in movie_name:
log.info('Wrong: %s, probably pr0n' % (nzb['name']))
return False
#qualities = fireEvent('quality.all', single = True) #qualities = fireEvent('quality.all', single = True)
preferred_quality = fireEvent('quality.single', identifier = quality['identifier'], single = True) preferred_quality = fireEvent('quality.single', identifier = quality['identifier'], single = True)
@@ -313,10 +324,10 @@ class Searcher(Plugin):
check_movie = fireEvent('scanner.name_year', check_name, single = True) check_movie = fireEvent('scanner.name_year', check_name, single = True)
try: try:
check_words = re.split('\W+', check_movie.get('name', '')) check_words = filter(None, re.split('\W+', check_movie.get('name', '')))
movie_words = re.split('\W+', simplifyString(movie_name)) movie_words = filter(None, re.split('\W+', simplifyString(movie_name)))
if len(list(set(check_words) - set(movie_words))) == 0: if len(check_words) > 0 and len(movie_words) > 0 and len(list(set(check_words) - set(movie_words))) == 0:
return True return True
except: except:
pass pass
+6 -2
View File
@@ -65,9 +65,13 @@ class YarrProvider(Provider):
def belongsTo(self, url, host = None): def belongsTo(self, url, host = None):
try: try:
hostname = urlparse(url).hostname hostname = urlparse(url).hostname
download_url = host if host else self.urls['download'] if host and hostname in host:
if hostname in download_url:
return self return self
else:
for url_type in self.urls:
download_url = self.urls[url_type]
if hostname in download_url:
return self
except: except:
log.debug('Url % s doesn\'t belong to %s' % (url, self.getName())) log.debug('Url % s doesn\'t belong to %s' % (url, self.getName()))
@@ -20,19 +20,41 @@ config = [{
}, },
{ {
'name': 'meta_nfo', 'name': 'meta_nfo',
'label': 'NFO',
'default': True, 'default': True,
'type': 'bool', 'type': 'bool',
}, },
{
'name': 'meta_nfo_name',
'label': 'NFO filename',
'default': '%s.nfo',
'advanced': True,
'description': '<strong>%s</strong> is the rootname of the movie. For example "/path/to/movie cd1.mkv" will be "/path/to/movie"'
},
{ {
'name': 'meta_fanart', 'name': 'meta_fanart',
'label': 'Fanart',
'default': True, 'default': True,
'type': 'bool', 'type': 'bool',
}, },
{
'name': 'meta_fanart_name',
'label': 'Fanart filename',
'default': '%s-fanart.jpg',
'advanced': True,
},
{ {
'name': 'meta_thumbnail', 'name': 'meta_thumbnail',
'label': 'Thumbnail',
'default': True, 'default': True,
'type': 'bool', 'type': 'bool',
}, },
{
'name': 'meta_thumbnail_name',
'label': 'Thumbnail filename',
'default': '%s.tbn',
'advanced': True,
},
], ],
}, },
], ],
@@ -15,13 +15,13 @@ class XBMC(MetaDataBase):
return os.path.join(data['destination_dir'], data['filename']) return os.path.join(data['destination_dir'], data['filename'])
def getFanartName(self, root): def getFanartName(self, root):
return '%s-fanart.jpg' % root return self.conf('meta_fanart_name') % root
def getThumbnailName(self, root): def getThumbnailName(self, root):
return '%s.tbn' % root return self.conf('meta_thumbnail_name') % root
def getNfoName(self, root): def getNfoName(self, root):
return '%s.nfo' % root return self.conf('meta_nfo_name') % root
def getNfo(self, movie_info = {}, data = {}): def getNfo(self, movie_info = {}, data = {}):
nfoxml = Element('movie') nfoxml = Element('movie')
@@ -27,6 +27,7 @@ class CouchPotatoApi(MovieProvider):
def getReleaseDate(self, identifier = None): def getReleaseDate(self, identifier = None):
if identifier is None: return {}
try: try:
headers = {'X-CP-Version': fireEvent('app.version', single = True)} headers = {'X-CP-Version': fireEvent('app.version', single = True)}
data = self.urlopen((self.api_url % ('eta')) + (identifier + '/'), headers = headers) data = self.urlopen((self.api_url % ('eta')) + (identifier + '/'), headers = headers)
@@ -27,7 +27,7 @@ class IMDBAPI(MovieProvider):
name_year = fireEvent('scanner.name_year', q, single = True) name_year = fireEvent('scanner.name_year', q, single = True)
if not name_year.get('name'): if not q or not name_year.get('name'):
return [] return []
cache_key = 'imdbapi.cache.%s' % q cache_key = 'imdbapi.cache.%s' % q
@@ -45,6 +45,9 @@ class IMDBAPI(MovieProvider):
def getInfo(self, identifier = None): def getInfo(self, identifier = None):
if not identifier:
return {}
cache_key = 'imdbapi.cache.%s' % identifier cache_key = 'imdbapi.cache.%s' % identifier
cached = self.getCache(cache_key, self.urls['info'] % identifier) cached = self.getCache(cache_key, self.urls['info'] % identifier)
@@ -89,7 +89,7 @@ class Newzbin(NZBProvider, RSS):
title = self.getTextElement(nzb, "title") title = self.getTextElement(nzb, "title")
if 'error' in title.lower(): continue if 'error' in title.lower(): continue
REPORT_NS = 'http://www.newzbin.com/DTD/2007/feeds/report/'; REPORT_NS = 'http://www.newzbin2.es/DTD/2007/feeds/report/';
# Add attributes to name # Add attributes to name
try: try:
@@ -157,9 +157,9 @@ class Newznab(NZBProvider, RSS):
def getHosts(self): def getHosts(self):
uses = str(self.conf('use')).split(',') uses = [x.strip() for x in str(self.conf('use')).split(',')]
hosts = self.conf('host').split(',') hosts = [x.strip() for x in self.conf('host').split(',')]
api_keys = self.conf('api_key').split(',') api_keys = [x.strip() for x in self.conf('api_key').split(',')]
list = [] list = []
for nr in range(len(hosts)): for nr in range(len(hosts)):
+4 -4
View File
@@ -13,10 +13,10 @@ log = CPLog(__name__)
class Nzbs(NZBProvider, RSS): class Nzbs(NZBProvider, RSS):
urls = { urls = {
'download': 'http://nzbs.org/index.php?action=getnzb&nzbid=%s%s', 'download': 'https://nzbs.org/index.php?action=getnzb&nzbid=%s%s',
'nfo': 'http://nzbs.org/index.php?action=view&nzbid=%s&nfo=1', 'nfo': 'https://nzbs.org/index.php?action=view&nzbid=%s&nfo=1',
'detail': 'http://nzbs.org/index.php?action=view&nzbid=%s', 'detail': 'https://nzbs.org/index.php?action=view&nzbid=%s',
'api': 'http://nzbs.org/rss.php', 'api': 'https://nzbs.org/rss.php',
} }
cat_ids = [ cat_ids = [
@@ -17,6 +17,7 @@ class KickAssTorrents(TorrentProvider):
'test': 'http://www.kat.ph/', 'test': 'http://www.kat.ph/',
'detail': 'http://www.kat.ph/%s-t%s.html', 'detail': 'http://www.kat.ph/%s-t%s.html',
'search': 'http://www.kat.ph/%s-i%s/', 'search': 'http://www.kat.ph/%s-i%s/',
'download': 'http://torcache.net/',
} }
cat_ids = [ cat_ids = [
@@ -127,7 +128,7 @@ class KickAssTorrents(TorrentProvider):
return tryInt(age) return tryInt(age)
def download(self, url = '', nzb_id = ''): def download(self, url = '', nzb_id = ''):
compressed_data = super(KickAssTorrents, self).download(url = url, nzb_id = nzb_id) compressed_data = self.urlopen(url = url, headers = {'Referer': 'http://kat.ph/'})
compressedstream = StringIO.StringIO(compressed_data) compressedstream = StringIO.StringIO(compressed_data)
gzipper = gzip.GzipFile(fileobj = compressedstream) gzipper = gzip.GzipFile(fileobj = compressedstream)
+6
View File
@@ -18,6 +18,12 @@
<br /> <br />
You can also use the API over another domain using JSONP, the callback function should be in 'callback_func' You can also use the API over another domain using JSONP, the callback function should be in 'callback_func'
<pre><a href="{{ fireEvent('app.api_url', single = True)|safe }}/updater.info/?callback_func=myfunction">{{ fireEvent('app.api_url', single = True)|safe }}/updater.info/?callback_func=myfunction</a></pre> <pre><a href="{{ fireEvent('app.api_url', single = True)|safe }}/updater.info/?callback_func=myfunction">{{ fireEvent('app.api_url', single = True)|safe }}/updater.info/?callback_func=myfunction</a></pre>
<br />
<br />
Get the API key:
<pre><a href="/getkey/?p=md5(password)&amp;u=md5(username)">/getkey/?p=md5(password)&amp;u=md5(username)</a></pre>
Will return {"api_key": "XXXXXXXXXX", "success": true}. When username or password is empty you don't need to md5 it.
<br />
</div> </div>
{% for route in routes %} {% for route in routes %}