Merge branch 'refs/heads/develop'
This commit is contained in:
@@ -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')
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 []
|
||||||
|
|||||||
@@ -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')}),
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)&u=md5(username)">/getkey/?p=md5(password)&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 %}
|
||||||
|
|||||||
Reference in New Issue
Block a user