Merge branch 'refs/heads/develop' into tv
This commit is contained in:
commit
7410288781
124 files changed
+1678
-595
No files matched your search
@@ -15,6 +15,7 @@ log = CPLog(__name__)
|
|||||||
views = {}
|
views = {}
|
||||||
template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates'))
|
template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates'))
|
||||||
|
|
||||||
|
|
||||||
class BaseHandler(RequestHandler):
|
class BaseHandler(RequestHandler):
|
||||||
|
|
||||||
def get_current_user(self):
|
def get_current_user(self):
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ class Core(Plugin):
|
|||||||
def signalHandler(self):
|
def signalHandler(self):
|
||||||
if Env.get('daemonized'): return
|
if Env.get('daemonized'): return
|
||||||
|
|
||||||
def signal_handler(signal, frame):
|
def signal_handler(*args, **kwargs):
|
||||||
fireEvent('app.shutdown', single = True)
|
fireEvent('app.shutdown', single = True)
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|||||||
@@ -57,13 +57,12 @@ class ClientScript(Plugin):
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
urls = {'style': {}, 'script': {}}
|
urls = {'style': {}, 'script': {}}
|
||||||
minified = {'style': {}, 'script': {}}
|
minified = {'style': {}, 'script': {}}
|
||||||
paths = {'style': {}, 'script': {}}
|
paths = {'style': {}, 'script': {}}
|
||||||
comment = {
|
comment = {
|
||||||
'style': '/*** %s:%d ***/\n',
|
'style': '/*** %s:%d ***/\n',
|
||||||
'script': '// %s:%d\n'
|
'script': '// %s:%d\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
html = {
|
html = {
|
||||||
@@ -95,7 +94,6 @@ class ClientScript(Plugin):
|
|||||||
else:
|
else:
|
||||||
self.registerStyle(core_url, file_path, position = 'front')
|
self.registerStyle(core_url, file_path, position = 'front')
|
||||||
|
|
||||||
|
|
||||||
def minify(self):
|
def minify(self):
|
||||||
|
|
||||||
# Create cache dir
|
# Create cache dir
|
||||||
@@ -129,7 +127,7 @@ class ClientScript(Plugin):
|
|||||||
data = cssmin(data)
|
data = cssmin(data)
|
||||||
data = data.replace('../images/', '../static/images/')
|
data = data.replace('../images/', '../static/images/')
|
||||||
data = data.replace('../fonts/', '../static/fonts/')
|
data = data.replace('../fonts/', '../static/fonts/')
|
||||||
data = data.replace('../../static/', '../static/') # Replace inside plugins
|
data = data.replace('../../static/', '../static/') # Replace inside plugins
|
||||||
|
|
||||||
raw.append({'file': file_path, 'date': int(os.path.getmtime(file_path)), 'data': data})
|
raw.append({'file': file_path, 'date': int(os.path.getmtime(file_path)), 'data': data})
|
||||||
|
|
||||||
@@ -192,6 +190,7 @@ class ClientScript(Plugin):
|
|||||||
|
|
||||||
prefix_properties = ['border-radius', 'transform', 'transition', 'box-shadow']
|
prefix_properties = ['border-radius', 'transform', 'transition', 'box-shadow']
|
||||||
prefix_tags = ['ms', 'moz', 'webkit']
|
prefix_tags = ['ms', 'moz', 'webkit']
|
||||||
|
|
||||||
def prefix(self, data):
|
def prefix(self, data):
|
||||||
|
|
||||||
trimmed_data = re.sub('(\t|\n|\r)+', '', data)
|
trimmed_data = re.sub('(\t|\n|\r)+', '', data)
|
||||||
|
|||||||
@@ -164,14 +164,14 @@ class BaseUpdater(Plugin):
|
|||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
|
|
||||||
version = self.getVersion()
|
current_version = self.getVersion()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'last_check': self.last_check,
|
'last_check': self.last_check,
|
||||||
'update_version': self.update_version,
|
'update_version': self.update_version,
|
||||||
'version': version,
|
'version': current_version,
|
||||||
'repo_name': '%s/%s' % (self.repo_user, self.repo_name),
|
'repo_name': '%s/%s' % (self.repo_user, self.repo_name),
|
||||||
'branch': version.get('branch', self.branch),
|
'branch': current_version.get('branch', self.branch),
|
||||||
}
|
}
|
||||||
|
|
||||||
def getVersion(self):
|
def getVersion(self):
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ var UpdaterBase = new Class({
|
|||||||
initialize: function(){
|
initialize: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
App.addEvent('load', self.info.bind(self, 2000))
|
App.addEvent('load', self.info.bind(self, 2000));
|
||||||
App.addEvent('unload', function(){
|
App.addEvent('unload', function(){
|
||||||
if(self.timer)
|
if(self.timer)
|
||||||
clearTimeout(self.timer);
|
clearTimeout(self.timer);
|
||||||
@@ -66,7 +66,7 @@ var UpdaterBase = new Class({
|
|||||||
|
|
||||||
var changelog = 'https://github.com/'+data.repo_name+'/compare/'+data.version.hash+'...'+data.branch;
|
var changelog = 'https://github.com/'+data.repo_name+'/compare/'+data.version.hash+'...'+data.branch;
|
||||||
if(data.update_version.changelog)
|
if(data.update_version.changelog)
|
||||||
changelog = data.update_version.changelog + '#' + data.version.hash+'...'+data.update_version.hash
|
changelog = data.update_version.changelog + '#' + data.version.hash+'...'+data.update_version.hash;
|
||||||
|
|
||||||
self.message = new Element('div.message.update').adopt(
|
self.message = new Element('div.message.update').adopt(
|
||||||
new Element('span', {
|
new Element('span', {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ class Database(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
addApiView('database.list_documents', self.listDocuments)
|
addApiView('database.list_documents', self.listDocuments)
|
||||||
|
addApiView('database.reindex', self.reindex)
|
||||||
|
addApiView('database.compact', self.compact)
|
||||||
addApiView('database.document.update', self.updateDocument)
|
addApiView('database.document.update', self.updateDocument)
|
||||||
addApiView('database.document.delete', self.deleteDocument)
|
addApiView('database.document.delete', self.deleteDocument)
|
||||||
|
|
||||||
@@ -114,9 +116,36 @@ class Database(object):
|
|||||||
results[key] = []
|
results[key] = []
|
||||||
results[key].append(document)
|
results[key].append(document)
|
||||||
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def reindex(self, **kwargs):
|
||||||
|
|
||||||
|
success = True
|
||||||
|
try:
|
||||||
|
db = self.getDB()
|
||||||
|
db.reindex()
|
||||||
|
except:
|
||||||
|
log.error('Failed index: %s', traceback.format_exc())
|
||||||
|
success = False
|
||||||
|
|
||||||
|
return {
|
||||||
|
'success': success
|
||||||
|
}
|
||||||
|
|
||||||
|
def compact(self, **kwargs):
|
||||||
|
|
||||||
|
success = True
|
||||||
|
try:
|
||||||
|
db = self.getDB()
|
||||||
|
db.compact()
|
||||||
|
except:
|
||||||
|
log.error('Failed compact: %s', traceback.format_exc())
|
||||||
|
success = False
|
||||||
|
|
||||||
|
return {
|
||||||
|
'success': success
|
||||||
|
}
|
||||||
|
|
||||||
def migrate(self):
|
def migrate(self):
|
||||||
|
|
||||||
from couchpotato import Env
|
from couchpotato import Env
|
||||||
@@ -181,7 +210,7 @@ class Database(object):
|
|||||||
migrate_data[ml][p[0]] = [migrate_data[ml][p[0]]]
|
migrate_data[ml][p[0]] = [migrate_data[ml][p[0]]]
|
||||||
migrate_data[ml][p[0]].append(columns)
|
migrate_data[ml][p[0]].append(columns)
|
||||||
|
|
||||||
c.close()
|
conn.close()
|
||||||
|
|
||||||
log.info('Getting data took %s', time.time() - migrate_start)
|
log.info('Getting data took %s', time.time() - migrate_start)
|
||||||
|
|
||||||
@@ -297,6 +326,11 @@ class Database(object):
|
|||||||
releaseinfos = migrate_data['releaseinfo']
|
releaseinfos = migrate_data['releaseinfo']
|
||||||
for x in releaseinfos:
|
for x in releaseinfos:
|
||||||
info = releaseinfos[x]
|
info = releaseinfos[x]
|
||||||
|
|
||||||
|
# Skip if release doesn't exist for this info
|
||||||
|
if not migrate_data['release'].get(info.get('release_id')):
|
||||||
|
continue
|
||||||
|
|
||||||
if not migrate_data['release'][info.get('release_id')].get('info'):
|
if not migrate_data['release'][info.get('release_id')].get('info'):
|
||||||
migrate_data['release'][info.get('release_id')]['info'] = {}
|
migrate_data['release'][info.get('release_id')]['info'] = {}
|
||||||
|
|
||||||
@@ -438,7 +472,6 @@ class Database(object):
|
|||||||
log.info('Total migration took %s', time.time() - migrate_start)
|
log.info('Total migration took %s', time.time() - migrate_start)
|
||||||
log.info('=' * 30)
|
log.info('=' * 30)
|
||||||
|
|
||||||
|
|
||||||
# rename old database
|
# rename old database
|
||||||
log.info('Renaming old database to %s ', old_db + '.old')
|
log.info('Renaming old database to %s ', old_db + '.old')
|
||||||
os.rename(old_db, old_db + '.old')
|
os.rename(old_db, old_db + '.old')
|
||||||
|
|||||||
@@ -24,17 +24,21 @@ class Downloader(Provider):
|
|||||||
]
|
]
|
||||||
|
|
||||||
torrent_trackers = [
|
torrent_trackers = [
|
||||||
'http://tracker.publicbt.com/announce',
|
|
||||||
'udp://tracker.istole.it:80/announce',
|
'udp://tracker.istole.it:80/announce',
|
||||||
'udp://fr33domtracker.h33t.com:3310/announce',
|
|
||||||
'http://tracker.istole.it/announce',
|
'http://tracker.istole.it/announce',
|
||||||
'http://tracker.ccc.de/announce',
|
'udp://fr33domtracker.h33t.com:3310/announce',
|
||||||
|
'http://tracker.publicbt.com/announce',
|
||||||
'udp://tracker.publicbt.com:80/announce',
|
'udp://tracker.publicbt.com:80/announce',
|
||||||
|
'http://tracker.ccc.de/announce',
|
||||||
'udp://tracker.ccc.de:80/announce',
|
'udp://tracker.ccc.de:80/announce',
|
||||||
'http://exodus.desync.com/announce',
|
'http://exodus.desync.com/announce',
|
||||||
'http://exodus.desync.com:6969/announce',
|
'http://exodus.desync.com:6969/announce',
|
||||||
'http://tracker.publichd.eu/announce',
|
'http://tracker.publichd.eu/announce',
|
||||||
|
'udp://tracker.publichd.eu:80/announce',
|
||||||
'http://tracker.openbittorrent.com/announce',
|
'http://tracker.openbittorrent.com/announce',
|
||||||
|
'udp://tracker.openbittorrent.com/announce',
|
||||||
|
'udp://tracker.openbittorrent.com:80/announce',
|
||||||
|
'udp://open.demonii.com:1337/announce',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -184,6 +188,7 @@ class Downloader(Provider):
|
|||||||
def pause(self, release_download, pause):
|
def pause(self, release_download, pause):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class ReleaseDownloadList(list):
|
class ReleaseDownloadList(list):
|
||||||
|
|
||||||
provider = None
|
provider = None
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ class NZBGet(Downloader):
|
|||||||
'timeleft': timeleft,
|
'timeleft': timeleft,
|
||||||
})
|
})
|
||||||
|
|
||||||
for nzb in queue: # 'Parameters' is not passed in rpc.postqueue
|
for nzb in queue: # 'Parameters' is not passed in rpc.postqueue
|
||||||
if nzb['NZBID'] in ids:
|
if nzb['NZBID'] in ids:
|
||||||
log.debug('Found %s in NZBGet postprocessing queue', nzb['NZBFilename'])
|
log.debug('Found %s in NZBGet postprocessing queue', nzb['NZBFilename'])
|
||||||
release_downloads.append({
|
release_downloads.append({
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ log = CPLog(__name__)
|
|||||||
|
|
||||||
autoload = 'qBittorrent'
|
autoload = 'qBittorrent'
|
||||||
|
|
||||||
|
|
||||||
class qBittorrent(Downloader):
|
class qBittorrent(Downloader):
|
||||||
|
|
||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
@@ -107,25 +108,24 @@ class qBittorrent(Downloader):
|
|||||||
for torrent in torrents:
|
for torrent in torrents:
|
||||||
if torrent.hash in ids:
|
if torrent.hash in ids:
|
||||||
torrent.update_general() # get extra info
|
torrent.update_general() # get extra info
|
||||||
|
torrent_filelist = torrent.get_files()
|
||||||
|
|
||||||
torrent_files = []
|
torrent_files = []
|
||||||
t_files = torrent.get_files()
|
torrent_dir = os.path.join(torrent.save_path, torrent.name)
|
||||||
|
|
||||||
check_dir = os.path.join(torrent.save_path, torrent.name)
|
if os.path.isdir(torrent_dir):
|
||||||
if os.path.isdir(check_dir):
|
torrent.save_path = torrent_dir
|
||||||
torrent.save_path = check_dir
|
|
||||||
|
|
||||||
if len(t_files) > 1 and os.path.isdir(torrent.save_path): # multi file torrent
|
if len(torrent_filelist) > 1 and os.path.isdir(torrent_dir): # multi file torrent, path.isdir check makes sure we're not in the root download folder
|
||||||
for root, _, files in os.walk(torrent.save_path):
|
for root, _, files in os.walk(torrent.save_path):
|
||||||
for f in files:
|
for f in files:
|
||||||
p = os.path.join(root, f)
|
torrent_files.append(sp(os.path.join(root, f)))
|
||||||
if os.path.isfile(p):
|
|
||||||
torrent_files.append(sp(p))
|
|
||||||
|
|
||||||
else: # multi or single file placed directly in torrent.save_path
|
else: # multi or single file placed directly in torrent.save_path
|
||||||
for f in t_files:
|
for f in torrent_filelist:
|
||||||
p = os.path.join(torrent.save_path, f.name)
|
file_path = os.path.join(torrent.save_path, f.name)
|
||||||
if os.path.isfile(p):
|
if os.path.isfile(file_path):
|
||||||
torrent_files.append(sp(p))
|
torrent_files.append(sp(file_path))
|
||||||
|
|
||||||
release_downloads.append({
|
release_downloads.append({
|
||||||
'id': torrent.hash,
|
'id': torrent.hash,
|
||||||
|
|||||||
@@ -78,10 +78,10 @@ class rTorrent(Downloader):
|
|||||||
|
|
||||||
self.error_msg = ''
|
self.error_msg = ''
|
||||||
try:
|
try:
|
||||||
self.rt._verify_conn()
|
self.rt._verify_conn()
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.error_msg = e.message
|
self.error_msg = e.message
|
||||||
self.rt = None
|
self.rt = None
|
||||||
|
|
||||||
return self.rt
|
return self.rt
|
||||||
|
|
||||||
@@ -94,44 +94,6 @@ class rTorrent(Downloader):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateProviderGroup(self, name, data):
|
|
||||||
if data.get('seed_time'):
|
|
||||||
log.info('seeding time ignored, not supported')
|
|
||||||
|
|
||||||
if not name:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not self.connect():
|
|
||||||
return False
|
|
||||||
|
|
||||||
views = self.rt.get_views()
|
|
||||||
|
|
||||||
if name not in views:
|
|
||||||
self.rt.create_group(name)
|
|
||||||
|
|
||||||
group = self.rt.get_group(name)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if data.get('seed_ratio'):
|
|
||||||
ratio = int(float(data.get('seed_ratio')) * 100)
|
|
||||||
log.debug('Updating provider ratio to %s, group name: %s', (ratio, name))
|
|
||||||
|
|
||||||
# Explicitly set all group options to ensure it is setup correctly
|
|
||||||
group.set_upload('1M')
|
|
||||||
group.set_min(ratio)
|
|
||||||
group.set_max(ratio)
|
|
||||||
group.set_command('d.stop')
|
|
||||||
group.enable()
|
|
||||||
else:
|
|
||||||
# Reset group action and disable it
|
|
||||||
group.set_command()
|
|
||||||
group.disable()
|
|
||||||
except MethodError as err:
|
|
||||||
log.error('Unable to set group options: %s', err.msg)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def download(self, data = None, media = None, filedata = None):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
@@ -142,10 +104,6 @@ class rTorrent(Downloader):
|
|||||||
if not self.connect():
|
if not self.connect():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
group_name = 'cp_' + data.get('provider').lower()
|
|
||||||
if not self.updateProviderGroup(group_name, data):
|
|
||||||
return False
|
|
||||||
|
|
||||||
torrent_params = {}
|
torrent_params = {}
|
||||||
if self.conf('label'):
|
if self.conf('label'):
|
||||||
torrent_params['label'] = self.conf('label')
|
torrent_params['label'] = self.conf('label')
|
||||||
@@ -186,9 +144,6 @@ class rTorrent(Downloader):
|
|||||||
if self.conf('directory'):
|
if self.conf('directory'):
|
||||||
torrent.set_directory(self.conf('directory'))
|
torrent.set_directory(self.conf('directory'))
|
||||||
|
|
||||||
# Set Ratio Group
|
|
||||||
torrent.set_visible(group_name)
|
|
||||||
|
|
||||||
# Start torrent
|
# Start torrent
|
||||||
if not self.conf('paused', default = 0):
|
if not self.conf('paused', default = 0):
|
||||||
torrent.start()
|
torrent.start()
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ class Transmission(Downloader):
|
|||||||
log.debug('Requesting Transmission to remove the torrent %s%s.', (release_download['name'], ' and cleanup the downloaded files' if delete_files else ''))
|
log.debug('Requesting Transmission to remove the torrent %s%s.', (release_download['name'], ' and cleanup the downloaded files' if delete_files else ''))
|
||||||
return self.trpc.remove_torrent(release_download['id'], delete_files)
|
return self.trpc.remove_torrent(release_download['id'], delete_files)
|
||||||
|
|
||||||
|
|
||||||
class TransmissionRPC(object):
|
class TransmissionRPC(object):
|
||||||
|
|
||||||
"""TransmissionRPC lite library"""
|
"""TransmissionRPC lite library"""
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ class uTorrent(Downloader):
|
|||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
utorrent_api = None
|
utorrent_api = None
|
||||||
status_flags = {
|
status_flags = {
|
||||||
'STARTED' : 1,
|
'STARTED': 1,
|
||||||
'CHECKING' : 2,
|
'CHECKING': 2,
|
||||||
'CHECK-START' : 4,
|
'CHECK-START': 4,
|
||||||
'CHECKED' : 8,
|
'CHECKED': 8,
|
||||||
'ERROR' : 16,
|
'ERROR': 16,
|
||||||
'PAUSED' : 32,
|
'PAUSED': 32,
|
||||||
'QUEUED' : 64,
|
'QUEUED': 64,
|
||||||
'LOADED' : 128
|
'LOADED': 128
|
||||||
}
|
}
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from urllib import unquote
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from couchpotato.core.helpers.encoding import toUnicode
|
from couchpotato.core.helpers.encoding import toUnicode
|
||||||
from couchpotato.core.helpers.variable import natsortKey, tryInt
|
from couchpotato.core.helpers.variable import natsortKey
|
||||||
|
|
||||||
|
|
||||||
def getParams(params):
|
def getParams(params):
|
||||||
@@ -44,6 +44,7 @@ def getParams(params):
|
|||||||
return dictToList(temp)
|
return dictToList(temp)
|
||||||
|
|
||||||
non_decimal = re.compile(r'[^\d.]+')
|
non_decimal = re.compile(r'[^\d.]+')
|
||||||
|
|
||||||
def dictToList(params):
|
def dictToList(params):
|
||||||
|
|
||||||
if type(params) is dict:
|
if type(params) is dict:
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ def tryFloat(s):
|
|||||||
return float(s)
|
return float(s)
|
||||||
except: return 0
|
except: return 0
|
||||||
|
|
||||||
|
|
||||||
def natsortKey(string_):
|
def natsortKey(string_):
|
||||||
"""See http://www.codinghorror.com/blog/archives/001018.html"""
|
"""See http://www.codinghorror.com/blog/archives/001018.html"""
|
||||||
return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]
|
return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]
|
||||||
@@ -247,9 +248,6 @@ def getTitle(media_dict):
|
|||||||
except:
|
except:
|
||||||
log.error('Could not get title for %s', getIdentifier(media_dict))
|
log.error('Could not get title for %s', getIdentifier(media_dict))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
log.error('Could not get title for %s', getIdentifier(media_dict))
|
|
||||||
return None
|
|
||||||
except:
|
except:
|
||||||
log.error('Could not get title for library item: %s', media_dict)
|
log.error('Could not get title for library item: %s', media_dict)
|
||||||
return None
|
return None
|
||||||
@@ -296,8 +294,11 @@ def isSubFolder(sub_folder, base_folder):
|
|||||||
# Returns True if sub_folder is the same as or inside base_folder
|
# Returns True if sub_folder is the same as or inside base_folder
|
||||||
return base_folder and sub_folder and ss(os.path.normpath(base_folder).rstrip(os.path.sep) + os.path.sep) in ss(os.path.normpath(sub_folder).rstrip(os.path.sep) + os.path.sep)
|
return base_folder and sub_folder and ss(os.path.normpath(base_folder).rstrip(os.path.sep) + os.path.sep) in ss(os.path.normpath(sub_folder).rstrip(os.path.sep) + os.path.sep)
|
||||||
|
|
||||||
|
|
||||||
# From SABNZBD
|
# From SABNZBD
|
||||||
re_password = [re.compile(r'(.+){{([^{}]+)}}$'), re.compile(r'(.+)\s+password\s*=\s*(.+)$', re.I)]
|
re_password = [re.compile(r'(.+){{([^{}]+)}}$'), re.compile(r'(.+)\s+password\s*=\s*(.+)$', re.I)]
|
||||||
|
|
||||||
|
|
||||||
def scanForPassword(name):
|
def scanForPassword(name):
|
||||||
m = None
|
m = None
|
||||||
for reg in re_password:
|
for reg in re_password:
|
||||||
|
|||||||
@@ -12,19 +12,22 @@ log = CPLog(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class Loader(object):
|
class Loader(object):
|
||||||
plugins = {}
|
|
||||||
providers = {}
|
def __init__(self):
|
||||||
modules = {}
|
self.plugins = {}
|
||||||
|
self.providers = {}
|
||||||
|
self.modules = {}
|
||||||
|
self.paths = {}
|
||||||
|
|
||||||
def preload(self, root = ''):
|
def preload(self, root = ''):
|
||||||
core = os.path.join(root, 'couchpotato', 'core')
|
core = os.path.join(root, 'couchpotato', 'core')
|
||||||
|
|
||||||
self.paths = {
|
self.paths.update({
|
||||||
'core': (0, 'couchpotato.core._base', os.path.join(core, '_base')),
|
'core': (0, 'couchpotato.core._base', os.path.join(core, '_base')),
|
||||||
'plugin': (1, 'couchpotato.core.plugins', os.path.join(core, 'plugins')),
|
'plugin': (1, 'couchpotato.core.plugins', os.path.join(core, 'plugins')),
|
||||||
'notifications': (20, 'couchpotato.core.notifications', os.path.join(core, 'notifications')),
|
'notifications': (20, 'couchpotato.core.notifications', os.path.join(core, 'notifications')),
|
||||||
'downloaders': (20, 'couchpotato.core.downloaders', os.path.join(core, 'downloaders')),
|
'downloaders': (20, 'couchpotato.core.downloaders', os.path.join(core, 'downloaders')),
|
||||||
}
|
})
|
||||||
|
|
||||||
# Add media to loader
|
# Add media to loader
|
||||||
self.addPath(root, ['couchpotato', 'core', 'media'], 25, recursive = True)
|
self.addPath(root, ['couchpotato', 'core', 'media'], 25, recursive = True)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from couchpotato import get_db, CPLog
|
|||||||
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
||||||
from couchpotato.core.helpers.encoding import toUnicode
|
from couchpotato.core.helpers.encoding import toUnicode
|
||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from .main import Library
|
from .main import Library
|
||||||
|
|
||||||
|
|
||||||
def autoload():
|
def autoload():
|
||||||
return Library()
|
return Library()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from .main import Matcher
|
from .main import Matcher
|
||||||
|
|
||||||
|
|
||||||
def autoload():
|
def autoload():
|
||||||
return Matcher()
|
return Matcher()
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ from couchpotato.core.helpers.encoding import simplifyString"""
|
|||||||
|
|
||||||
|
|
||||||
class TitleIndex(TreeBasedIndex):
|
class TitleIndex(TreeBasedIndex):
|
||||||
_version = 1
|
_version = 2
|
||||||
|
|
||||||
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
||||||
from string import ascii_letters
|
from string import ascii_letters
|
||||||
@@ -113,14 +113,14 @@ from couchpotato.core.helpers.encoding import toUnicode, simplifyString"""
|
|||||||
return self.simplify(key)
|
return self.simplify(key)
|
||||||
|
|
||||||
def make_key_value(self, data):
|
def make_key_value(self, data):
|
||||||
if data.get('_t') == 'media' and data.get('title') is not None:
|
if data.get('_t') == 'media' and data.get('title') is not None and len(data.get('title')) > 0:
|
||||||
return self.simplify(data['title']), None
|
return self.simplify(data['title']), None
|
||||||
|
|
||||||
def simplify(self, title):
|
def simplify(self, title):
|
||||||
|
|
||||||
title = toUnicode(title)
|
title = toUnicode(title)
|
||||||
|
|
||||||
nr_prefix = '' if title[0] in ascii_letters else '#'
|
nr_prefix = '' if title and len(title) > 0 and title[0] in ascii_letters else '#'
|
||||||
title = simplifyString(title)
|
title = simplifyString(title)
|
||||||
|
|
||||||
for prefix in ['the ']:
|
for prefix in ['the ']:
|
||||||
@@ -132,7 +132,7 @@ from couchpotato.core.helpers.encoding import toUnicode, simplifyString"""
|
|||||||
|
|
||||||
|
|
||||||
class StartsWithIndex(TreeBasedIndex):
|
class StartsWithIndex(TreeBasedIndex):
|
||||||
_version = 1
|
_version = 2
|
||||||
|
|
||||||
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
custom_header = """from CodernityDB.tree_index import TreeBasedIndex
|
||||||
from string import ascii_letters
|
from string import ascii_letters
|
||||||
@@ -158,4 +158,4 @@ from couchpotato.core.helpers.encoding import toUnicode, simplifyString"""
|
|||||||
title = title[len(prefix):]
|
title = title[len(prefix):]
|
||||||
break
|
break
|
||||||
|
|
||||||
return str(title[0] if title[0] in ascii_letters else '#').lower()
|
return str(title[0] if title and len(title) > 0 and title[0] in ascii_letters else '#').lower()
|
||||||
@@ -132,10 +132,10 @@ class MediaPlugin(MediaBase):
|
|||||||
if media:
|
if media:
|
||||||
|
|
||||||
# Attach category
|
# Attach category
|
||||||
if media.get('category_id'):
|
try: media['category'] = db.get('id', media.get('category_id'))
|
||||||
media['category'] = db.get('id', media.get('category_id'))
|
except: pass
|
||||||
|
|
||||||
media['releases'] = list(fireEvent('release.for_media', media['_id'], single = True))
|
media['releases'] = fireEvent('release.for_media', media['_id'], single = True)
|
||||||
|
|
||||||
return media
|
return media
|
||||||
|
|
||||||
@@ -222,7 +222,6 @@ class MediaPlugin(MediaBase):
|
|||||||
del filter_by['media_status']
|
del filter_by['media_status']
|
||||||
del filter_by['release_status']
|
del filter_by['release_status']
|
||||||
|
|
||||||
|
|
||||||
# Filter by combining ids
|
# Filter by combining ids
|
||||||
for x in filter_by:
|
for x in filter_by:
|
||||||
media_ids = [n for n in media_ids if n in filter_by[x]]
|
media_ids = [n for n in media_ids if n in filter_by[x]]
|
||||||
@@ -281,7 +280,7 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
for media_type in fireEvent('media.types', merge = True):
|
for media_type in fireEvent('media.types', merge = True):
|
||||||
def tempList(*args, **kwargs):
|
def tempList(*args, **kwargs):
|
||||||
return self.listView(types = media_type, *args, **kwargs)
|
return self.listView(types = media_type, **kwargs)
|
||||||
addApiView('%s.list' % media_type, tempList)
|
addApiView('%s.list' % media_type, tempList)
|
||||||
|
|
||||||
def availableChars(self, types = None, status = None, release_status = None):
|
def availableChars(self, types = None, status = None, release_status = None):
|
||||||
@@ -350,7 +349,7 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
for media_type in fireEvent('media.types', merge = True):
|
for media_type in fireEvent('media.types', merge = True):
|
||||||
def tempChar(*args, **kwargs):
|
def tempChar(*args, **kwargs):
|
||||||
return self.charView(types = media_type, *args, **kwargs)
|
return self.charView(types = media_type, **kwargs)
|
||||||
addApiView('%s.available_chars' % media_type, tempChar)
|
addApiView('%s.available_chars' % media_type, tempChar)
|
||||||
|
|
||||||
def delete(self, media_id, delete_from = None):
|
def delete(self, media_id, delete_from = None):
|
||||||
@@ -366,7 +365,7 @@ class MediaPlugin(MediaBase):
|
|||||||
deleted = True
|
deleted = True
|
||||||
else:
|
else:
|
||||||
|
|
||||||
media_releases = list(fireEvent('release.for_media', media['_id'], single = True))
|
media_releases = fireEvent('release.for_media', media['_id'], single = True)
|
||||||
|
|
||||||
total_releases = len(media_releases)
|
total_releases = len(media_releases)
|
||||||
total_deleted = 0
|
total_deleted = 0
|
||||||
@@ -382,9 +381,8 @@ class MediaPlugin(MediaBase):
|
|||||||
if release.get('status') == 'done':
|
if release.get('status') == 'done':
|
||||||
db.delete(release)
|
db.delete(release)
|
||||||
total_deleted += 1
|
total_deleted += 1
|
||||||
new_media_status = 'active'
|
|
||||||
|
|
||||||
if total_releases == total_deleted:
|
if (total_releases == total_deleted and media['status'] != 'active') or (delete_from == 'wanted' and media['status'] == 'active'):
|
||||||
db.delete(media)
|
db.delete(media)
|
||||||
deleted = True
|
deleted = True
|
||||||
elif new_media_status:
|
elif new_media_status:
|
||||||
@@ -432,7 +430,7 @@ class MediaPlugin(MediaBase):
|
|||||||
move_to_wanted = True
|
move_to_wanted = True
|
||||||
|
|
||||||
profile = db.get('id', m['profile_id'])
|
profile = db.get('id', m['profile_id'])
|
||||||
media_releases = list(fireEvent('release.for_media', m['_id'], single = True))
|
media_releases = fireEvent('release.for_media', m['_id'], single = True)
|
||||||
|
|
||||||
for q_identifier in profile['qualities']:
|
for q_identifier in profile['qualities']:
|
||||||
index = profile['qualities'].index(q_identifier)
|
index = profile['qualities'].index(q_identifier)
|
||||||
|
|||||||
@@ -244,10 +244,16 @@ class YarrProvider(Provider):
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def getCatId(self, identifier):
|
def getCatId(self, quality = None):
|
||||||
|
if not quality: quality = {}
|
||||||
|
identifier = quality.get('identifier')
|
||||||
|
|
||||||
|
want_3d = False
|
||||||
|
if quality.get('custom'):
|
||||||
|
want_3d = quality['custom'].get('3d')
|
||||||
|
|
||||||
for ids, qualities in self.cat_ids:
|
for ids, qualities in self.cat_ids:
|
||||||
if identifier in qualities:
|
if identifier in qualities or (want_3d and '3d' in qualities):
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
if self.cat_backup_id:
|
if self.cat_backup_id:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Base(NZBProvider):
|
|||||||
'search': 'https://www.binsearch.info/index.php?%s',
|
'search': 'https://www.binsearch.info/index.php?%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 4 # Seconds
|
http_time_between_calls = 4 # Seconds
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ class Base(NZBProvider):
|
|||||||
try:
|
try:
|
||||||
|
|
||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
main_table = html.find('table', attrs = {'id':'r2'})
|
main_table = html.find('table', attrs = {'id': 'r2'})
|
||||||
|
|
||||||
if not main_table:
|
if not main_table:
|
||||||
return
|
return
|
||||||
@@ -36,11 +36,11 @@ class Base(NZBProvider):
|
|||||||
items = main_table.find_all('tr')
|
items = main_table.find_all('tr')
|
||||||
|
|
||||||
for row in items:
|
for row in items:
|
||||||
title = row.find('span', attrs = {'class':'s'})
|
title = row.find('span', attrs = {'class': 's'})
|
||||||
|
|
||||||
if not title: continue
|
if not title: continue
|
||||||
|
|
||||||
nzb_id = row.find('input', attrs = {'type':'checkbox'})['name']
|
nzb_id = row.find('input', attrs = {'type': 'checkbox'})['name']
|
||||||
info = row.find('span', attrs = {'class':'d'})
|
info = row.find('span', attrs = {'class':'d'})
|
||||||
size_match = re.search('size:.(?P<size>[0-9\.]+.[GMB]+)', info.text)
|
size_match = re.search('size:.(?P<size>[0-9\.]+.[GMB]+)', info.text)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Base(NZBProvider, RSS):
|
|||||||
'search': 'https://www.nzbclub.com/nzbfeeds.aspx?%s',
|
'search': 'https://www.nzbclub.com/nzbfeeds.aspx?%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 4 #seconds
|
http_time_between_calls = 4 # seconds
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class Base(NZBProvider, RSS):
|
|||||||
def getMoreInfo(self, item):
|
def getMoreInfo(self, item):
|
||||||
full_description = self.getCache('nzbclub.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
full_description = self.getCache('nzbclub.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
||||||
html = BeautifulSoup(full_description)
|
html = BeautifulSoup(full_description)
|
||||||
nfo_pre = html.find('pre', attrs = {'class':'nfo'})
|
nfo_pre = html.find('pre', attrs = {'class': 'nfo'})
|
||||||
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
||||||
|
|
||||||
item['description'] = description
|
item['description'] = description
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class Base(NZBProvider, RSS):
|
|||||||
nfo_url = re.search('href=\"(?P<nfo>.+)\" ', item['description']).group('nfo')
|
nfo_url = re.search('href=\"(?P<nfo>.+)\" ', item['description']).group('nfo')
|
||||||
full_description = self.getCache('nzbindex.%s' % item['id'], url = nfo_url, cache_timeout = 25920000)
|
full_description = self.getCache('nzbindex.%s' % item['id'], url = nfo_url, cache_timeout = 25920000)
|
||||||
html = BeautifulSoup(full_description)
|
html = BeautifulSoup(full_description)
|
||||||
item['description'] = toUnicode(html.find('pre', attrs = {'id':'nfo0'}).text)
|
item['description'] = toUnicode(html.find('pre', attrs = {'id': 'nfo0'}).text)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Base(NZBProvider, RSS):
|
|||||||
'detail_url': 'https://omgwtfnzbs.org/details.php?id=%s',
|
'detail_url': 'https://omgwtfnzbs.org/details.php?id=%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
cat_ids = [
|
cat_ids = [
|
||||||
([15], ['dvdrip']),
|
([15], ['dvdrip']),
|
||||||
@@ -42,7 +42,7 @@ class Base(NZBProvider, RSS):
|
|||||||
q = '%s %s' % (title, movie['info']['year'])
|
q = '%s %s' % (title, movie['info']['year'])
|
||||||
params = tryUrlencode({
|
params = tryUrlencode({
|
||||||
'search': q,
|
'search': q,
|
||||||
'catid': ','.join([str(x) for x in self.getCatId(quality['identifier'])]),
|
'catid': ','.join([str(x) for x in self.getCatId(quality)]),
|
||||||
'user': self.conf('username', default = ''),
|
'user': self.conf('username', default = ''),
|
||||||
'api': self.conf('api_key', default = ''),
|
'api': self.conf('api_key', default = ''),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Searches for movies only - BiT-HDTV's subcategory and resolution search filters appear to be broken
|
# Searches for movies only - BiT-HDTV's subcategory and resolution search filters appear to be broken
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ class Base(TorrentProvider):
|
|||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result_table = html.find('table', attrs = {'width' : '750', 'class' : ''})
|
result_table = html.find('table', attrs = {'width': '750', 'class': ''})
|
||||||
if result_table is None:
|
if result_table is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class Base(TorrentProvider):
|
|||||||
def getMoreInfo(self, item):
|
def getMoreInfo(self, item):
|
||||||
full_description = self.getCache('bithdtv.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
full_description = self.getCache('bithdtv.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
||||||
html = BeautifulSoup(full_description)
|
html = BeautifulSoup(full_description)
|
||||||
nfo_pre = html.find('table', attrs = {'class':'detail'})
|
nfo_pre = html.find('table', attrs = {'class': 'detail'})
|
||||||
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
||||||
|
|
||||||
item['description'] = description
|
item['description'] = description
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Base(TorrentProvider):
|
|||||||
'baseurl': 'https://www.bitsoup.me/%s',
|
'baseurl': 'https://www.bitsoup.me/%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
def _searchOnTitle(self, title, movie, quality, results):
|
def _searchOnTitle(self, title, movie, quality, results):
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ class Base(TorrentProvider):
|
|||||||
})
|
})
|
||||||
url = "%s&%s" % (self.urls['search'], arguments)
|
url = "%s&%s" % (self.urls['search'], arguments)
|
||||||
|
|
||||||
url = self.urls['search'] % self.buildUrl(media, quality)
|
url = self.urls['search'] % self.buildUrl(movie, quality)
|
||||||
data = self.getHTMLData(url)
|
data = self.getHTMLData(url)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
@@ -74,7 +74,6 @@ class Base(TorrentProvider):
|
|||||||
except:
|
except:
|
||||||
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
|
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
|
||||||
|
|
||||||
|
|
||||||
def getLoginParams(self):
|
def getLoginParams(self):
|
||||||
return {
|
return {
|
||||||
'username': self.conf('username'),
|
'username': self.conf('username'),
|
||||||
@@ -82,7 +81,6 @@ class Base(TorrentProvider):
|
|||||||
'ssl': 'yes',
|
'ssl': 'yes',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def loginSuccess(self, output):
|
def loginSuccess(self, output):
|
||||||
return 'logout.php' in output.lower()
|
return 'logout.php' in output.lower()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class Base(TorrentProvider):
|
|||||||
'api': 'https://hdbits.org/api/torrents'
|
'api': 'https://hdbits.org/api/torrents'
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
def _post_query(self, **params):
|
def _post_query(self, **params):
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ class Base(TorrentProvider):
|
|||||||
'name': result['name'],
|
'name': result['name'],
|
||||||
'url': self.urls['download'] % (result['id'], self.conf('passkey')),
|
'url': self.urls['download'] % (result['id'], self.conf('passkey')),
|
||||||
'detail_url': self.urls['detail'] % result['id'],
|
'detail_url': self.urls['detail'] % result['id'],
|
||||||
'size': tryInt(result['size'])/1024/1024,
|
'size': tryInt(result['size']) / 1024 / 1024,
|
||||||
'seeders': tryInt(result['seeders']),
|
'seeders': tryInt(result['seeders']),
|
||||||
'leechers': tryInt(result['leechers'])
|
'leechers': tryInt(result['leechers'])
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ class Base(TorrentProvider):
|
|||||||
}
|
}
|
||||||
|
|
||||||
cat_ids = [
|
cat_ids = [
|
||||||
(['41'], ['720p', '1080p', 'brrip']),
|
(['41'], ['720p', '1080p', 'brrip']),
|
||||||
(['19'], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
|
(['19'], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
|
||||||
(['20'], ['dvdr'])
|
(['20'], ['dvdr'])
|
||||||
]
|
]
|
||||||
|
|
||||||
cat_backup_id = 200
|
cat_backup_id = 200
|
||||||
@@ -36,7 +36,7 @@ class Base(TorrentProvider):
|
|||||||
|
|
||||||
page = 0
|
page = 0
|
||||||
total_pages = 1
|
total_pages = 1
|
||||||
cats = self.getCatId(quality['identifier'])
|
cats = self.getCatId(quality)
|
||||||
|
|
||||||
while page < total_pages:
|
while page < total_pages:
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ class Base(TorrentProvider):
|
|||||||
return confirmed + trusted + vip + moderated
|
return confirmed + trusted + vip + moderated
|
||||||
|
|
||||||
id = re.search('id=(?P<id>\d+)&', link).group('id')
|
id = re.search('id=(?P<id>\d+)&', link).group('id')
|
||||||
url = self.urls['download'] % (download)
|
url = self.urls['download'] % download
|
||||||
|
|
||||||
fileSize = self.parseSize(result.select('td.rowhead')[5].text)
|
fileSize = self.parseSize(result.select('td.rowhead')[5].text)
|
||||||
results.append({
|
results.append({
|
||||||
@@ -113,7 +113,7 @@ class Base(TorrentProvider):
|
|||||||
try:
|
try:
|
||||||
full_description = self.getHTMLData(item['detail_url'])
|
full_description = self.getHTMLData(item['detail_url'])
|
||||||
html = BeautifulSoup(full_description)
|
html = BeautifulSoup(full_description)
|
||||||
nfo_pre = html.find('td', attrs = {'class':'main'}).findAll('table')[1]
|
nfo_pre = html.find('td', attrs = {'class': 'main'}).findAll('table')[1]
|
||||||
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
||||||
except:
|
except:
|
||||||
log.error('Failed getting more info for %s', item['name'])
|
log.error('Failed getting more info for %s', item['name'])
|
||||||
|
|||||||
@@ -18,21 +18,21 @@ class Base(TorrentProvider):
|
|||||||
'base_url': 'https://www.iptorrents.com',
|
'base_url': 'https://www.iptorrents.com',
|
||||||
'login': 'https://www.iptorrents.com/torrents/',
|
'login': 'https://www.iptorrents.com/torrents/',
|
||||||
'login_check': 'https://www.iptorrents.com/inbox.php',
|
'login_check': 'https://www.iptorrents.com/inbox.php',
|
||||||
'search': 'https://www.iptorrents.com/torrents/?l%d=1%s&q=%s&qf=ti&p=%d',
|
'search': 'https://www.iptorrents.com/torrents/?%s%%s&q=%s&qf=ti&p=%%d',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
cat_backup_id = None
|
cat_backup_id = None
|
||||||
|
|
||||||
def buildUrl(self, title, media, quality):
|
def buildUrl(self, title, media, quality):
|
||||||
return self._buildUrl(title.replace(':', ''), quality['identifier'])
|
return self._buildUrl(title.replace(':', ''), quality)
|
||||||
|
|
||||||
def _buildUrl(self, query, quality_identifier):
|
def _buildUrl(self, query, quality):
|
||||||
|
|
||||||
cat_ids = self.getCatId(quality_identifier)
|
cat_ids = self.getCatId(quality)
|
||||||
|
|
||||||
if not cat_ids:
|
if not cat_ids:
|
||||||
log.warning('Unable to find category ids for identifier "%s"', quality_identifier)
|
log.warning('Unable to find category ids for identifier "%s"', quality.get('identifier'))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self.urls['search'] % ("&".join(("l%d=" % x) for x in cat_ids), tryUrlencode(query).replace('%', '%%'))
|
return self.urls['search'] % ("&".join(("l%d=" % x) for x in cat_ids), tryUrlencode(query).replace('%', '%%'))
|
||||||
@@ -53,14 +53,14 @@ class Base(TorrentProvider):
|
|||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
page_nav = html.find('span', attrs = {'class' : 'page_nav'})
|
page_nav = html.find('span', attrs = {'class': 'page_nav'})
|
||||||
if page_nav:
|
if page_nav:
|
||||||
next_link = page_nav.find("a", text = "Next")
|
next_link = page_nav.find("a", text = "Next")
|
||||||
if next_link:
|
if next_link:
|
||||||
final_page_link = next_link.previous_sibling.previous_sibling
|
final_page_link = next_link.previous_sibling.previous_sibling
|
||||||
pages = int(final_page_link.string)
|
pages = int(final_page_link.string)
|
||||||
|
|
||||||
result_table = html.find('table', attrs = {'class' : 'torrents'})
|
result_table = html.find('table', attrs = {'class': 'torrents'})
|
||||||
|
|
||||||
if not result_table or 'nothing found!' in data.lower():
|
if not result_table or 'nothing found!' in data.lower():
|
||||||
return
|
return
|
||||||
@@ -80,8 +80,8 @@ class Base(TorrentProvider):
|
|||||||
torrent_download_url = self.urls['base_url'] + (result.find_all('td')[3].find('a'))['href'].replace(' ', '.')
|
torrent_download_url = self.urls['base_url'] + (result.find_all('td')[3].find('a'))['href'].replace(' ', '.')
|
||||||
torrent_details_url = self.urls['base_url'] + torrent['href']
|
torrent_details_url = self.urls['base_url'] + torrent['href']
|
||||||
torrent_size = self.parseSize(result.find_all('td')[5].string)
|
torrent_size = self.parseSize(result.find_all('td')[5].string)
|
||||||
torrent_seeders = tryInt(result.find('td', attrs = {'class' : 'ac t_seeders'}).string)
|
torrent_seeders = tryInt(result.find('td', attrs = {'class': 'ac t_seeders'}).string)
|
||||||
torrent_leechers = tryInt(result.find('td', attrs = {'class' : 'ac t_leechers'}).string)
|
torrent_leechers = tryInt(result.find('td', attrs = {'class': 'ac t_leechers'}).string)
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
'id': torrent_id,
|
'id': torrent_id,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Base(TorrentMagnetProvider):
|
|||||||
(['dvd'], ['dvdr']),
|
(['dvd'], ['dvdr']),
|
||||||
]
|
]
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
cat_backup_id = None
|
cat_backup_id = None
|
||||||
|
|
||||||
proxy_list = [
|
proxy_list = [
|
||||||
@@ -42,7 +42,7 @@ class Base(TorrentMagnetProvider):
|
|||||||
|
|
||||||
if data:
|
if data:
|
||||||
|
|
||||||
cat_ids = self.getCatId(quality['identifier'])
|
cat_ids = self.getCatId(quality)
|
||||||
table_order = ['name', 'size', None, 'age', 'seeds', 'leechers']
|
table_order = ['name', 'size', None, 'age', 'seeds', 'leechers']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ log = CPLog(__name__)
|
|||||||
class Base(TorrentProvider):
|
class Base(TorrentProvider):
|
||||||
|
|
||||||
urls = {
|
urls = {
|
||||||
'domain': 'https://tls.passthepopcorn.me',
|
'domain': 'https://tls.passthepopcorn.me',
|
||||||
'detail': 'https://tls.passthepopcorn.me/torrents.php?torrentid=%s',
|
'detail': 'https://tls.passthepopcorn.me/torrents.php?torrentid=%s',
|
||||||
'torrent': 'https://tls.passthepopcorn.me/torrents.php',
|
'torrent': 'https://tls.passthepopcorn.me/torrents.php',
|
||||||
'login': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
'login': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
||||||
'login_check': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
'login_check': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
||||||
'search': 'https://tls.passthepopcorn.me/search/%s/0/7/%d'
|
'search': 'https://tls.passthepopcorn.me/search/%s/0/7/%d'
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 2
|
http_time_between_calls = 2
|
||||||
@@ -136,23 +136,23 @@ class Base(TorrentProvider):
|
|||||||
|
|
||||||
def htmlToUnicode(self, text):
|
def htmlToUnicode(self, text):
|
||||||
def fixup(m):
|
def fixup(m):
|
||||||
text = m.group(0)
|
txt = m.group(0)
|
||||||
if text[:2] == "&#":
|
if txt[:2] == "&#":
|
||||||
# character reference
|
# character reference
|
||||||
try:
|
try:
|
||||||
if text[:3] == "&#x":
|
if txt[:3] == "&#x":
|
||||||
return unichr(int(text[3:-1], 16))
|
return unichr(int(txt[3:-1], 16))
|
||||||
else:
|
else:
|
||||||
return unichr(int(text[2:-1]))
|
return unichr(int(txt[2:-1]))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# named entity
|
# named entity
|
||||||
try:
|
try:
|
||||||
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
|
txt = unichr(htmlentitydefs.name2codepoint[txt[1:-1]])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
return text # leave as is
|
return txt # leave as is
|
||||||
return re.sub("&#?\w+;", fixup, six.u('%s') % text)
|
return re.sub("&#?\w+;", fixup, six.u('%s') % text)
|
||||||
|
|
||||||
def unicodeToASCII(self, text):
|
def unicodeToASCII(self, text):
|
||||||
@@ -164,11 +164,11 @@ class Base(TorrentProvider):
|
|||||||
|
|
||||||
def getLoginParams(self):
|
def getLoginParams(self):
|
||||||
return {
|
return {
|
||||||
'username': self.conf('username'),
|
'username': self.conf('username'),
|
||||||
'password': self.conf('password'),
|
'password': self.conf('password'),
|
||||||
'passkey': self.conf('passkey'),
|
'passkey': self.conf('passkey'),
|
||||||
'keeplogged': '1',
|
'keeplogged': '1',
|
||||||
'login': 'Login'
|
'login': 'Login'
|
||||||
}
|
}
|
||||||
|
|
||||||
def loginSuccess(self, output):
|
def loginSuccess(self, output):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class Base(TorrentMagnetProvider):
|
|||||||
query = self.buildUrl(media)
|
query = self.buildUrl(media)
|
||||||
|
|
||||||
params = tryUrlencode({
|
params = tryUrlencode({
|
||||||
'page':'torrents',
|
'page': 'torrents',
|
||||||
'search': query,
|
'search': query,
|
||||||
'active': 1,
|
'active': 1,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class Base(TorrentProvider):
|
|||||||
'download': 'https://www.sceneaccess.eu/%s',
|
'download': 'https://www.sceneaccess.eu/%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
@@ -33,16 +33,16 @@ class Base(TorrentProvider):
|
|||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resultsTable = html.find('table', attrs = {'id' : 'torrents-table'})
|
resultsTable = html.find('table', attrs = {'id': 'torrents-table'})
|
||||||
if resultsTable is None:
|
if resultsTable is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
entries = resultsTable.find_all('tr', attrs = {'class' : 'tt_row'})
|
entries = resultsTable.find_all('tr', attrs = {'class': 'tt_row'})
|
||||||
for result in entries:
|
for result in entries:
|
||||||
|
|
||||||
link = result.find('td', attrs = {'class' : 'ttr_name'}).find('a')
|
link = result.find('td', attrs = {'class': 'ttr_name'}).find('a')
|
||||||
url = result.find('td', attrs = {'class' : 'td_dl'}).find('a')
|
url = result.find('td', attrs = {'class': 'td_dl'}).find('a')
|
||||||
leechers = result.find('td', attrs = {'class' : 'ttr_leechers'}).find('a')
|
leechers = result.find('td', attrs = {'class': 'ttr_leechers'}).find('a')
|
||||||
torrent_id = link['href'].replace('details?id=', '')
|
torrent_id = link['href'].replace('details?id=', '')
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
@@ -50,8 +50,8 @@ class Base(TorrentProvider):
|
|||||||
'name': link['title'],
|
'name': link['title'],
|
||||||
'url': self.urls['download'] % url['href'],
|
'url': self.urls['download'] % url['href'],
|
||||||
'detail_url': self.urls['detail'] % torrent_id,
|
'detail_url': self.urls['detail'] % torrent_id,
|
||||||
'size': self.parseSize(result.find('td', attrs = {'class' : 'ttr_size'}).contents[0]),
|
'size': self.parseSize(result.find('td', attrs = {'class': 'ttr_size'}).contents[0]),
|
||||||
'seeders': tryInt(result.find('td', attrs = {'class' : 'ttr_seeders'}).find('a').string),
|
'seeders': tryInt(result.find('td', attrs = {'class': 'ttr_seeders'}).find('a').string),
|
||||||
'leechers': tryInt(leechers.string) if leechers else 0,
|
'leechers': tryInt(leechers.string) if leechers else 0,
|
||||||
'get_more_info': self.getMoreInfo,
|
'get_more_info': self.getMoreInfo,
|
||||||
})
|
})
|
||||||
@@ -62,7 +62,7 @@ class Base(TorrentProvider):
|
|||||||
def getMoreInfo(self, item):
|
def getMoreInfo(self, item):
|
||||||
full_description = self.getCache('sceneaccess.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
full_description = self.getCache('sceneaccess.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
||||||
html = BeautifulSoup(full_description)
|
html = BeautifulSoup(full_description)
|
||||||
nfo_pre = html.find('div', attrs = {'id':'details_table'})
|
nfo_pre = html.find('div', attrs = {'id': 'details_table'})
|
||||||
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
||||||
|
|
||||||
item['description'] = description
|
item['description'] = description
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class Base(TorrentMagnetProvider):
|
|||||||
|
|
||||||
page = 0
|
page = 0
|
||||||
total_pages = 1
|
total_pages = 1
|
||||||
cats = self.getCatId(quality['identifier'])
|
cats = self.getCatId(quality)
|
||||||
|
|
||||||
base_search_url = self.urls['search'] % self.getDomain()
|
base_search_url = self.urls['search'] % self.getDomain()
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class Base(TorrentMagnetProvider):
|
|||||||
def getMoreInfo(self, item):
|
def getMoreInfo(self, item):
|
||||||
full_description = self.getCache('tpb.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
full_description = self.getCache('tpb.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
||||||
html = BeautifulSoup(full_description)
|
html = BeautifulSoup(full_description)
|
||||||
nfo_pre = html.find('div', attrs = {'class':'nfo'})
|
nfo_pre = html.find('div', attrs = {'class': 'nfo'})
|
||||||
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
||||||
|
|
||||||
item['description'] = description
|
item['description'] = description
|
||||||
|
|||||||
@@ -31,19 +31,19 @@ class Base(TorrentProvider):
|
|||||||
([20], ['dvdr']),
|
([20], ['dvdr']),
|
||||||
]
|
]
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
cat_backup_id = None
|
cat_backup_id = None
|
||||||
|
|
||||||
def _searchOnTitle(self, title, movie, quality, results):
|
def _searchOnTitle(self, title, movie, quality, results):
|
||||||
|
|
||||||
url = self.urls['search'] % (tryUrlencode('%s %s' % (title.replace(':', ''), movie['info']['year'])), self.getCatId(quality['identifier'])[0])
|
url = self.urls['search'] % (tryUrlencode('%s %s' % (title.replace(':', ''), movie['info']['year'])), self.getCatId(quality)[0])
|
||||||
data = self.getHTMLData(url)
|
data = self.getHTMLData(url)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result_table = html.find('table', attrs = {'border' : '1'})
|
result_table = html.find('table', attrs = {'border': '1'})
|
||||||
if not result_table:
|
if not result_table:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ class Base(TorrentProvider):
|
|||||||
for result in entries[1:]:
|
for result in entries[1:]:
|
||||||
cells = result.find_all('td')
|
cells = result.find_all('td')
|
||||||
|
|
||||||
link = cells[1].find('a', attrs = {'class' : 'index'})
|
link = cells[1].find('a', attrs = {'class': 'index'})
|
||||||
|
|
||||||
full_id = link['href'].replace('details.php?id=', '')
|
full_id = link['href'].replace('details.php?id=', '')
|
||||||
torrent_id = full_id[:6]
|
torrent_id = full_id[:6]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class Base(TorrentProvider):
|
|||||||
'download': 'http://www.td.af/download.php/%s/%s',
|
'download': 'http://www.td.af/download.php/%s/%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
|
|||||||
'download': 'http://www.torrentleech.org%s',
|
'download': 'http://www.torrentleech.org%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
cat_backup_id = None
|
cat_backup_id = None
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
@@ -34,7 +34,7 @@ class Base(TorrentProvider):
|
|||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result_table = html.find('table', attrs = {'id' : 'torrenttable'})
|
result_table = html.find('table', attrs = {'id': 'torrenttable'})
|
||||||
if not result_table:
|
if not result_table:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -42,9 +42,9 @@ class Base(TorrentProvider):
|
|||||||
|
|
||||||
for result in entries[1:]:
|
for result in entries[1:]:
|
||||||
|
|
||||||
link = result.find('td', attrs = {'class' : 'name'}).find('a')
|
link = result.find('td', attrs = {'class': 'name'}).find('a')
|
||||||
url = result.find('td', attrs = {'class' : 'quickdownload'}).find('a')
|
url = result.find('td', attrs = {'class': 'quickdownload'}).find('a')
|
||||||
details = result.find('td', attrs = {'class' : 'name'}).find('a')
|
details = result.find('td', attrs = {'class': 'name'}).find('a')
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
'id': link['href'].replace('/torrent/', ''),
|
'id': link['href'].replace('/torrent/', ''),
|
||||||
@@ -52,8 +52,8 @@ class Base(TorrentProvider):
|
|||||||
'url': self.urls['download'] % url['href'],
|
'url': self.urls['download'] % url['href'],
|
||||||
'detail_url': self.urls['download'] % details['href'],
|
'detail_url': self.urls['download'] % details['href'],
|
||||||
'size': self.parseSize(result.find_all('td')[4].string),
|
'size': self.parseSize(result.find_all('td')[4].string),
|
||||||
'seeders': tryInt(result.find('td', attrs = {'class' : 'seeders'}).string),
|
'seeders': tryInt(result.find('td', attrs = {'class': 'seeders'}).string),
|
||||||
'leechers': tryInt(result.find('td', attrs = {'class' : 'leechers'}).string),
|
'leechers': tryInt(result.find('td', attrs = {'class': 'leechers'}).string),
|
||||||
})
|
})
|
||||||
|
|
||||||
except:
|
except:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
|
|||||||
'download': 'https://torrentshack.net/%s',
|
'download': 'https://torrentshack.net/%s',
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
|
||||||
def _search(self, media, quality, results):
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
@@ -32,16 +32,16 @@ class Base(TorrentProvider):
|
|||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result_table = html.find('table', attrs = {'id' : 'torrent_table'})
|
result_table = html.find('table', attrs = {'id': 'torrent_table'})
|
||||||
if not result_table:
|
if not result_table:
|
||||||
return
|
return
|
||||||
|
|
||||||
entries = result_table.find_all('tr', attrs = {'class' : 'torrent'})
|
entries = result_table.find_all('tr', attrs = {'class': 'torrent'})
|
||||||
|
|
||||||
for result in entries:
|
for result in entries:
|
||||||
|
|
||||||
link = result.find('span', attrs = {'class' : 'torrent_name_link'}).parent
|
link = result.find('span', attrs = {'class': 'torrent_name_link'}).parent
|
||||||
url = result.find('td', attrs = {'class' : 'torrent_td'}).find('a')
|
url = result.find('td', attrs = {'class': 'torrent_td'}).find('a')
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
'id': link['href'].replace('torrents.php?torrentid=', ''),
|
'id': link['href'].replace('torrents.php?torrentid=', ''),
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import re
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||||
|
from couchpotato.core.helpers.rss import RSS
|
||||||
|
from couchpotato.core.helpers.variable import tryInt, splitString
|
||||||
|
from couchpotato.core.logger import CPLog
|
||||||
|
from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
log = CPLog(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Base(TorrentMagnetProvider, RSS):
|
||||||
|
|
||||||
|
urls = {
|
||||||
|
'detail': 'https://torrentz.eu/%s',
|
||||||
|
'search': 'https://torrentz.eu/feed?q=%s',
|
||||||
|
'verified_search': 'https://torrentz.eu/feed_verified?q=%s'
|
||||||
|
}
|
||||||
|
|
||||||
|
http_time_between_calls = 0
|
||||||
|
|
||||||
|
def _search(self, media, quality, results):
|
||||||
|
|
||||||
|
search_url = self.urls['verified_search'] if self.conf('verified_only') else self.urls['search']
|
||||||
|
|
||||||
|
# Create search parameters
|
||||||
|
search_params = self.buildUrl(media)
|
||||||
|
|
||||||
|
smin = quality.get('size_min')
|
||||||
|
smax = quality.get('size_max')
|
||||||
|
if smin and smax:
|
||||||
|
search_params += ' size %sm - %sm' % (smin, smax)
|
||||||
|
|
||||||
|
min_seeds = tryInt(self.conf('minimal_seeds'))
|
||||||
|
if min_seeds:
|
||||||
|
search_params += ' seed > %s' % (min_seeds - 1)
|
||||||
|
|
||||||
|
rss_data = self.getRSSData(search_url % search_params)
|
||||||
|
|
||||||
|
if rss_data:
|
||||||
|
try:
|
||||||
|
|
||||||
|
for result in rss_data:
|
||||||
|
|
||||||
|
name = self.getTextElement(result, 'title')
|
||||||
|
detail_url = self.getTextElement(result, 'link')
|
||||||
|
description = self.getTextElement(result, 'description')
|
||||||
|
|
||||||
|
magnet = splitString(detail_url, '/')[-1]
|
||||||
|
magnet_url = 'magnet:?xt=urn:btih:%s&dn=%s&tr=%s' % (magnet.upper(), tryUrlencode(name), tryUrlencode('udp://tracker.openbittorrent.com/announce'))
|
||||||
|
|
||||||
|
reg = re.search('Size: (?P<size>\d+) MB Seeds: (?P<seeds>[\d,]+) Peers: (?P<peers>[\d,]+)', six.text_type(description))
|
||||||
|
size = reg.group('size')
|
||||||
|
seeds = reg.group('seeds').replace(',', '')
|
||||||
|
peers = reg.group('peers').replace(',', '')
|
||||||
|
|
||||||
|
results.append({
|
||||||
|
'id': magnet,
|
||||||
|
'name': six.text_type(name),
|
||||||
|
'url': magnet_url,
|
||||||
|
'detail_url': detail_url,
|
||||||
|
'size': tryInt(size),
|
||||||
|
'seeders': tryInt(seeds),
|
||||||
|
'leechers': tryInt(peers),
|
||||||
|
})
|
||||||
|
|
||||||
|
except:
|
||||||
|
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
|
||||||
|
|
||||||
|
|
||||||
|
config = [{
|
||||||
|
'name': 'torrentz',
|
||||||
|
'groups': [
|
||||||
|
{
|
||||||
|
'tab': 'searcher',
|
||||||
|
'list': 'torrent_providers',
|
||||||
|
'name': 'Torrentz',
|
||||||
|
'description': 'Torrentz is a free, fast and powerful meta-search engine. <a href="https://torrentz.eu/">Torrentz</a>',
|
||||||
|
'wizard': True,
|
||||||
|
'options': [
|
||||||
|
{
|
||||||
|
'name': 'enabled',
|
||||||
|
'type': 'enabler',
|
||||||
|
'default': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'verified_only',
|
||||||
|
'type': 'bool',
|
||||||
|
'default': True,
|
||||||
|
'advanced': True,
|
||||||
|
'description': 'Only search verified releases',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'minimal_seeds',
|
||||||
|
'type': 'int',
|
||||||
|
'default': 1,
|
||||||
|
'advanced': True,
|
||||||
|
'description': 'Only return releases with minimal X seeds',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'seed_ratio',
|
||||||
|
'label': 'Seed ratio',
|
||||||
|
'type': 'float',
|
||||||
|
'default': 1,
|
||||||
|
'description': 'Will not be (re)moved until this seed ratio is met.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'seed_time',
|
||||||
|
'label': 'Seed time',
|
||||||
|
'type': 'int',
|
||||||
|
'default': 40,
|
||||||
|
'description': 'Will not be (re)moved until this seed time (in hours) is met.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'extra_score',
|
||||||
|
'advanced': True,
|
||||||
|
'label': 'Extra Score',
|
||||||
|
'type': 'int',
|
||||||
|
'default': 0,
|
||||||
|
'description': 'Starting score for each release found via this provider.',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
@@ -16,7 +16,7 @@ class Base(TorrentProvider):
|
|||||||
'detail': '%s/api/movie.json?id=%s'
|
'detail': '%s/api/movie.json?id=%s'
|
||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 #seconds
|
http_time_between_calls = 1 # seconds
|
||||||
|
|
||||||
proxy_list = [
|
proxy_list = [
|
||||||
'http://yify.unlocktorrent.com',
|
'http://yify.unlocktorrent.com',
|
||||||
@@ -81,7 +81,7 @@ config = [{
|
|||||||
{
|
{
|
||||||
'name': 'enabled',
|
'name': 'enabled',
|
||||||
'type': 'enabler',
|
'type': 'enabler',
|
||||||
'default': 0
|
'default': False
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'domain',
|
'name': 'domain',
|
||||||
|
|||||||
@@ -6,12 +6,11 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-bottom: 4px solid transparent;
|
|
||||||
transition: all .4s cubic-bezier(0.9,0,0.1,1);
|
transition: all .4s cubic-bezier(0.9,0,0.1,1);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
border: 1px solid transparent;
|
border: 0 solid transparent;
|
||||||
border-width: 0 0 4px;
|
border-bottom-width: 4px;
|
||||||
}
|
}
|
||||||
.search_form:hover {
|
.search_form:hover {
|
||||||
border-color: #047792;
|
border-color: #047792;
|
||||||
@@ -49,7 +48,6 @@
|
|||||||
color: #FFF;
|
color: #FFF;
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 10px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
padding: 0 40px 0 10px;
|
padding: 0 40px 0 10px;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Block.Search = new Class({
|
|||||||
'keyup': self.keyup.bind(self),
|
'keyup': self.keyup.bind(self),
|
||||||
'focus': function(){
|
'focus': function(){
|
||||||
if(focus_timer) clearTimeout(focus_timer);
|
if(focus_timer) clearTimeout(focus_timer);
|
||||||
self.el.addClass('focused')
|
self.el.addClass('focused');
|
||||||
if(this.get('value'))
|
if(this.get('value'))
|
||||||
self.hideResults(false)
|
self.hideResults(false)
|
||||||
},
|
},
|
||||||
@@ -57,17 +57,17 @@ Block.Search = new Class({
|
|||||||
(e).preventDefault();
|
(e).preventDefault();
|
||||||
|
|
||||||
if(self.last_q === ''){
|
if(self.last_q === ''){
|
||||||
self.input.blur()
|
self.input.blur();
|
||||||
self.last_q = null;
|
self.last_q = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
self.last_q = '';
|
self.last_q = '';
|
||||||
self.input.set('value', '');
|
self.input.set('value', '');
|
||||||
self.input.focus()
|
self.input.focus();
|
||||||
|
|
||||||
self.media = {}
|
self.media = {};
|
||||||
self.results.empty()
|
self.results.empty();
|
||||||
self.el.removeClass('filled')
|
self.el.removeClass('filled')
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -92,16 +92,16 @@ Block.Search = new Class({
|
|||||||
self.hidden = bool;
|
self.hidden = bool;
|
||||||
},
|
},
|
||||||
|
|
||||||
keyup: function(e){
|
keyup: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.el[self.q() ? 'addClass' : 'removeClass']('filled')
|
self.el[self.q() ? 'addClass' : 'removeClass']('filled');
|
||||||
|
|
||||||
if(self.q() != self.last_q){
|
if(self.q() != self.last_q){
|
||||||
if(self.api_request && self.api_request.isRunning())
|
if(self.api_request && self.api_request.isRunning())
|
||||||
self.api_request.cancel();
|
self.api_request.cancel();
|
||||||
|
|
||||||
if(self.autocomplete_timer) clearTimeout(self.autocomplete_timer)
|
if(self.autocomplete_timer) clearTimeout(self.autocomplete_timer);
|
||||||
self.autocomplete_timer = self.autocomplete.delay(300, self)
|
self.autocomplete_timer = self.autocomplete.delay(300, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ Block.Search = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if(!self.q()){
|
if(!self.q()){
|
||||||
self.hideResults(true)
|
self.hideResults(true);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ Block.Search = new Class({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
self.fill(q, cache)
|
self.fill(q, cache);
|
||||||
|
|
||||||
self.last_q = q;
|
self.last_q = q;
|
||||||
|
|
||||||
@@ -148,31 +148,31 @@ Block.Search = new Class({
|
|||||||
fill: function(q, json){
|
fill: function(q, json){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.cache[q] = json
|
self.cache[q] = json;
|
||||||
|
|
||||||
self.media = {}
|
self.media = {};
|
||||||
self.results.empty()
|
self.results.empty();
|
||||||
|
|
||||||
Object.each(json, function(media, type){
|
Object.each(json, function(media){
|
||||||
if(typeOf(media) == 'array'){
|
if(typeOf(media) == 'array'){
|
||||||
Object.each(media, function(m){
|
Object.each(media, function(m){
|
||||||
|
|
||||||
var m = new Block.Search[m.type.capitalize() + 'Item'](m);
|
var m = new Block.Search[m.type.capitalize() + 'Item'](m);
|
||||||
$(m).inject(self.results)
|
$(m).inject(self.results);
|
||||||
self.media[m.imdb || 'r-'+Math.floor(Math.random()*10000)] = m
|
self.media[m.imdb || 'r-'+Math.floor(Math.random()*10000)] = m;
|
||||||
|
|
||||||
if(q == m.imdb)
|
if(q == m.imdb)
|
||||||
m.showOptions()
|
m.showOptions()
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// Calculate result heights
|
// Calculate result heights
|
||||||
var w = window.getSize(),
|
var w = window.getSize(),
|
||||||
rc = self.result_container.getCoordinates();
|
rc = self.result_container.getCoordinates();
|
||||||
|
|
||||||
self.results.setStyle('max-height', (w.y - rc.top - 50) + 'px')
|
self.results.setStyle('max-height', (w.y - rc.top - 50) + 'px');
|
||||||
self.mask.fade('out')
|
self.mask.fade('out')
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ log = CPLog(__name__)
|
|||||||
|
|
||||||
class Searcher(SearcherBase):
|
class Searcher(SearcherBase):
|
||||||
|
|
||||||
|
# noinspection PyMissingConstructor
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addEvent('searcher.protocols', self.getSearchProtocols)
|
addEvent('searcher.protocols', self.getSearchProtocols)
|
||||||
addEvent('searcher.contains_other_quality', self.containsOtherQuality)
|
addEvent('searcher.contains_other_quality', self.containsOtherQuality)
|
||||||
|
addEvent('searcher.correct_3d', self.correct3D)
|
||||||
addEvent('searcher.correct_year', self.correctYear)
|
addEvent('searcher.correct_year', self.correctYear)
|
||||||
addEvent('searcher.correct_name', self.correctName)
|
addEvent('searcher.correct_name', self.correctName)
|
||||||
addEvent('searcher.correct_words', self.correctWords)
|
addEvent('searcher.correct_words', self.correctWords)
|
||||||
@@ -123,6 +125,17 @@ class Searcher(SearcherBase):
|
|||||||
|
|
||||||
return not (found.get(preferred_quality['identifier']) and len(found) == 1)
|
return not (found.get(preferred_quality['identifier']) and len(found) == 1)
|
||||||
|
|
||||||
|
def correct3D(self, nzb, preferred_quality = None):
|
||||||
|
if not preferred_quality: preferred_quality = {}
|
||||||
|
if not preferred_quality.get('custom'): return
|
||||||
|
|
||||||
|
threed = preferred_quality['custom'].get('3d')
|
||||||
|
|
||||||
|
# Try guessing via quality tags
|
||||||
|
guess = fireEvent('quality.guess', [nzb.get('name')], single = True)
|
||||||
|
|
||||||
|
return threed == guess.get('is_3d')
|
||||||
|
|
||||||
def correctYear(self, haystack, year, year_range):
|
def correctYear(self, haystack, year, year_range):
|
||||||
|
|
||||||
if not isinstance(haystack, (list, tuple, set)):
|
if not isinstance(haystack, (list, tuple, set)):
|
||||||
@@ -183,7 +196,7 @@ class Searcher(SearcherBase):
|
|||||||
req = splitString(req_set, '&')
|
req = splitString(req_set, '&')
|
||||||
req_match += len(list(set(rel_words) & set(req))) == len(req)
|
req_match += len(list(set(rel_words) & set(req))) == len(req)
|
||||||
|
|
||||||
if len(required_words) > 0 and req_match == 0:
|
if len(required_words) > 0 and req_match == 0:
|
||||||
log.info2('Wrong: Required word missing: %s', rel_name)
|
log.info2('Wrong: Required word missing: %s', rel_name)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ var MovieList = new Class({
|
|||||||
self.filter = self.options.filter || {
|
self.filter = self.options.filter || {
|
||||||
'starts_with': null,
|
'starts_with': null,
|
||||||
'search': null
|
'search': null
|
||||||
}
|
};
|
||||||
|
|
||||||
self.el = new Element('div.movies').adopt(
|
self.el = new Element('div.movies').adopt(
|
||||||
self.title = self.options.title ? new Element('h2', {
|
self.title = self.options.title ? new Element('h2', {
|
||||||
@@ -52,7 +52,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
self.getMovies();
|
self.getMovies();
|
||||||
|
|
||||||
App.on('movie.added', self.movieAdded.bind(self))
|
App.on('movie.added', self.movieAdded.bind(self));
|
||||||
App.on('movie.deleted', self.movieDeleted.bind(self))
|
App.on('movie.deleted', self.movieDeleted.bind(self))
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ var MovieList = new Class({
|
|||||||
if(self.options.load_more)
|
if(self.options.load_more)
|
||||||
self.scrollspy = new ScrollSpy({
|
self.scrollspy = new ScrollSpy({
|
||||||
min: function(){
|
min: function(){
|
||||||
var c = self.load_more.getCoordinates()
|
var c = self.load_more.getCoordinates();
|
||||||
return c.top - window.document.getSize().y - 300
|
return c.top - window.document.getSize().y - 300
|
||||||
},
|
},
|
||||||
onEnter: self.loadMore.bind(self)
|
onEnter: self.loadMore.bind(self)
|
||||||
@@ -179,7 +179,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
m.fireEvent('injected');
|
m.fireEvent('injected');
|
||||||
|
|
||||||
self.movies.include(m)
|
self.movies.include(m);
|
||||||
self.movies_added[movie._id] = true;
|
self.movies_added[movie._id] = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ var MovieList = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
var chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
var chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
|
||||||
self.el.addClass('with_navigation')
|
self.el.addClass('with_navigation');
|
||||||
|
|
||||||
self.navigation = new Element('div.alph_nav').adopt(
|
self.navigation = new Element('div.alph_nav').adopt(
|
||||||
self.mass_edit_form = new Element('div.mass_edit_form').adopt(
|
self.mass_edit_form = new Element('div.mass_edit_form').adopt(
|
||||||
@@ -242,7 +242,7 @@ var MovieList = new Class({
|
|||||||
this.addClass(a);
|
this.addClass(a);
|
||||||
|
|
||||||
el.inject(el.getParent(), 'top');
|
el.inject(el.getParent(), 'top');
|
||||||
el.getSiblings().hide()
|
el.getSiblings().hide();
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
el.getSiblings().setStyle('display', null);
|
el.getSiblings().setStyle('display', null);
|
||||||
}, 100)
|
}, 100)
|
||||||
@@ -286,7 +286,7 @@ var MovieList = new Class({
|
|||||||
'status': self.options.status
|
'status': self.options.status
|
||||||
}, self.filter),
|
}, self.filter),
|
||||||
'onSuccess': function(json){
|
'onSuccess': function(json){
|
||||||
available_chars = json.chars
|
available_chars = json.chars;
|
||||||
|
|
||||||
available_chars.each(function(c){
|
available_chars.each(function(c){
|
||||||
self.letters[c.capitalize()].addClass('available')
|
self.letters[c.capitalize()].addClass('available')
|
||||||
@@ -300,7 +300,7 @@ var MovieList = new Class({
|
|||||||
self.navigation_alpha = new Element('ul.numbers', {
|
self.navigation_alpha = new Element('ul.numbers', {
|
||||||
'events': {
|
'events': {
|
||||||
'click:relay(li.available)': function(e, el){
|
'click:relay(li.available)': function(e, el){
|
||||||
self.activateLetter(el.get('data-letter'))
|
self.activateLetter(el.get('data-letter'));
|
||||||
self.getMovies(true)
|
self.getMovies(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,7 +318,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
// All
|
// All
|
||||||
self.letters['all'] = new Element('li.letter_all.available.active', {
|
self.letters['all'] = new Element('li.letter_all.available.active', {
|
||||||
'text': 'ALL',
|
'text': 'ALL'
|
||||||
}).inject(self.navigation_alpha);
|
}).inject(self.navigation_alpha);
|
||||||
|
|
||||||
// Chars
|
// Chars
|
||||||
@@ -334,7 +334,7 @@ var MovieList = new Class({
|
|||||||
if (self.options.menu.length > 0)
|
if (self.options.menu.length > 0)
|
||||||
self.options.menu.each(function(menu_item){
|
self.options.menu.each(function(menu_item){
|
||||||
self.navigation_menu.addLink(menu_item);
|
self.navigation_menu.addLink(menu_item);
|
||||||
})
|
});
|
||||||
else
|
else
|
||||||
self.navigation_menu.hide();
|
self.navigation_menu.hide();
|
||||||
|
|
||||||
@@ -347,15 +347,15 @@ var MovieList = new Class({
|
|||||||
movies = self.movies.length;
|
movies = self.movies.length;
|
||||||
self.movies.each(function(movie){
|
self.movies.each(function(movie){
|
||||||
selected += movie.isSelected() ? 1 : 0
|
selected += movie.isSelected() ? 1 : 0
|
||||||
})
|
});
|
||||||
|
|
||||||
var indeterminate = selected > 0 && selected < movies,
|
var indeterminate = selected > 0 && selected < movies,
|
||||||
checked = selected == movies && selected > 0;
|
checked = selected == movies && selected > 0;
|
||||||
|
|
||||||
self.mass_edit_select.set('indeterminate', indeterminate)
|
self.mass_edit_select.set('indeterminate', indeterminate);
|
||||||
|
|
||||||
self.mass_edit_select_class[checked ? 'check' : 'uncheck']()
|
self.mass_edit_select_class[checked ? 'check' : 'uncheck']();
|
||||||
self.mass_edit_select_class.element[indeterminate ? 'addClass' : 'removeClass']('indeterminate')
|
self.mass_edit_select_class.element[indeterminate ? 'addClass' : 'removeClass']('indeterminate');
|
||||||
|
|
||||||
self.mass_edit_selected.set('text', selected);
|
self.mass_edit_selected.set('text', selected);
|
||||||
},
|
},
|
||||||
@@ -371,7 +371,7 @@ var MovieList = new Class({
|
|||||||
'events': {
|
'events': {
|
||||||
'click': function(e){
|
'click': function(e){
|
||||||
(e).preventDefault();
|
(e).preventDefault();
|
||||||
this.set('text', 'Deleting..')
|
this.set('text', 'Deleting..');
|
||||||
Api.request('media.delete', {
|
Api.request('media.delete', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': ids.join(','),
|
'id': ids.join(','),
|
||||||
@@ -383,7 +383,7 @@ var MovieList = new Class({
|
|||||||
var erase_movies = [];
|
var erase_movies = [];
|
||||||
self.movies.each(function(movie){
|
self.movies.each(function(movie){
|
||||||
if (movie.isSelected()){
|
if (movie.isSelected()){
|
||||||
$(movie).destroy()
|
$(movie).destroy();
|
||||||
erase_movies.include(movie);
|
erase_movies.include(movie);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -410,7 +410,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
changeQualitySelected: function(){
|
changeQualitySelected: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
var ids = self.getSelectedMovies()
|
var ids = self.getSelectedMovies();
|
||||||
|
|
||||||
Api.request('movie.edit', {
|
Api.request('movie.edit', {
|
||||||
'data': {
|
'data': {
|
||||||
@@ -423,11 +423,11 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
refreshSelected: function(){
|
refreshSelected: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
var ids = self.getSelectedMovies()
|
var ids = self.getSelectedMovies();
|
||||||
|
|
||||||
Api.request('media.refresh', {
|
Api.request('media.refresh', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': ids.join(','),
|
'id': ids.join(',')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -435,7 +435,7 @@ var MovieList = new Class({
|
|||||||
getSelectedMovies: function(){
|
getSelectedMovies: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var ids = []
|
var ids = [];
|
||||||
self.movies.each(function(movie){
|
self.movies.each(function(movie){
|
||||||
if (movie.isSelected())
|
if (movie.isSelected())
|
||||||
ids.include(movie.get('_id'))
|
ids.include(movie.get('_id'))
|
||||||
@@ -459,11 +459,11 @@ var MovieList = new Class({
|
|||||||
reset: function(){
|
reset: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.movies = []
|
self.movies = [];
|
||||||
if(self.mass_edit_select)
|
if(self.mass_edit_select)
|
||||||
self.calculateSelected()
|
self.calculateSelected();
|
||||||
if(self.navigation_alpha)
|
if(self.navigation_alpha)
|
||||||
self.navigation_alpha.getElements('.active').removeClass('active')
|
self.navigation_alpha.getElements('.active').removeClass('active');
|
||||||
|
|
||||||
self.offset = 0;
|
self.offset = 0;
|
||||||
if(self.scrollspy){
|
if(self.scrollspy){
|
||||||
@@ -475,7 +475,7 @@ var MovieList = new Class({
|
|||||||
activateLetter: function(letter){
|
activateLetter: function(letter){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.reset()
|
self.reset();
|
||||||
|
|
||||||
self.letters[letter || 'all'].addClass('active');
|
self.letters[letter || 'all'].addClass('active');
|
||||||
self.filter.starts_with = letter;
|
self.filter.starts_with = letter;
|
||||||
@@ -487,7 +487,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
self.el
|
self.el
|
||||||
.removeClass(self.current_view+'_list')
|
.removeClass(self.current_view+'_list')
|
||||||
.addClass(new_view+'_list')
|
.addClass(new_view+'_list');
|
||||||
|
|
||||||
self.current_view = new_view;
|
self.current_view = new_view;
|
||||||
Cookie.write(self.options.identifier+'_view2', new_view, {duration: 1000});
|
Cookie.write(self.options.identifier+'_view2', new_view, {duration: 1000});
|
||||||
@@ -504,9 +504,9 @@ var MovieList = new Class({
|
|||||||
if(self.search_timer) clearTimeout(self.search_timer);
|
if(self.search_timer) clearTimeout(self.search_timer);
|
||||||
self.search_timer = (function(){
|
self.search_timer = (function(){
|
||||||
var search_value = self.navigation_search_input.get('value');
|
var search_value = self.navigation_search_input.get('value');
|
||||||
if (search_value == self.last_search_value) return
|
if (search_value == self.last_search_value) return;
|
||||||
|
|
||||||
self.reset()
|
self.reset();
|
||||||
|
|
||||||
self.activateLetter();
|
self.activateLetter();
|
||||||
self.filter.search = search_value;
|
self.filter.search = search_value;
|
||||||
@@ -563,7 +563,7 @@ var MovieList = new Class({
|
|||||||
|
|
||||||
if(self.loader_first){
|
if(self.loader_first){
|
||||||
var lf = self.loader_first;
|
var lf = self.loader_first;
|
||||||
self.loader_first.addClass('hide')
|
self.loader_first.addClass('hide');
|
||||||
self.loader_first = null;
|
self.loader_first = null;
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
lf.destroy();
|
lf.destroy();
|
||||||
@@ -603,10 +603,10 @@ var MovieList = new Class({
|
|||||||
var is_empty = self.movies.length == 0 && (self.total_movies == 0 || self.total_movies === undefined);
|
var is_empty = self.movies.length == 0 && (self.total_movies == 0 || self.total_movies === undefined);
|
||||||
|
|
||||||
if(self.title)
|
if(self.title)
|
||||||
self.title[is_empty ? 'hide' : 'show']()
|
self.title[is_empty ? 'hide' : 'show']();
|
||||||
|
|
||||||
if(self.description)
|
if(self.description)
|
||||||
self.description.setStyle('display', [is_empty ? 'none' : ''])
|
self.description.setStyle('display', [is_empty ? 'none' : '']);
|
||||||
|
|
||||||
if(is_empty && self.options.on_empty_element){
|
if(is_empty && self.options.on_empty_element){
|
||||||
self.options.on_empty_element.inject(self.loader_first || self.title || self.movie_list, 'after');
|
self.options.on_empty_element.inject(self.loader_first || self.title || self.movie_list, 'after');
|
||||||
|
|||||||
@@ -60,22 +60,6 @@ var MovieAction = new Class({
|
|||||||
'z-index': '1'
|
'z-index': '1'
|
||||||
}
|
}
|
||||||
}).inject(self.movie, 'top').fade('hide');
|
}).inject(self.movie, 'top').fade('hide');
|
||||||
//self.positionMask();
|
|
||||||
},
|
|
||||||
|
|
||||||
positionMask: function(){
|
|
||||||
var self = this,
|
|
||||||
movie = $(self.movie),
|
|
||||||
s = movie.getSize()
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
return self.mask.setStyles({
|
|
||||||
'width': s.x,
|
|
||||||
'height': s.y
|
|
||||||
}).position({
|
|
||||||
'relativeTo': movie
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toElement: function(){
|
toElement: function(){
|
||||||
@@ -122,7 +106,7 @@ MA.Release = new Class({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(!self.movie.data.releases || self.movie.data.releases.length == 0)
|
if(!self.movie.data.releases || self.movie.data.releases.length == 0)
|
||||||
self.el.hide()
|
self.el.hide();
|
||||||
else
|
else
|
||||||
self.showHelper();
|
self.showHelper();
|
||||||
|
|
||||||
@@ -164,7 +148,7 @@ MA.Release = new Class({
|
|||||||
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'})
|
||||||
).inject(self.release_container)
|
).inject(self.release_container);
|
||||||
|
|
||||||
if(self.movie.data.releases)
|
if(self.movie.data.releases)
|
||||||
self.movie.data.releases.each(function(release){
|
self.movie.data.releases.each(function(release){
|
||||||
@@ -186,13 +170,13 @@ MA.Release = new Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create release
|
// Create release
|
||||||
var item = new Element('div', {
|
release['el'] = new Element('div', {
|
||||||
'class': 'item '+release.status,
|
'class': 'item '+release.status,
|
||||||
'id': 'release_'+release._id
|
'id': 'release_'+release._id
|
||||||
}).adopt(
|
}).adopt(
|
||||||
new Element('span.name', {'text': release_name, 'title': release_name}),
|
new Element('span.name', {'text': release_name, 'title': release_name}),
|
||||||
new Element('span.status', {'text': release.status, 'class': 'release_status '+release.status}),
|
new Element('span.status', {'text': release.status, 'class': 'release_status '+release.status}),
|
||||||
new Element('span.quality', {'text': quality.label || 'n/a'}),
|
new Element('span.quality', {'text': quality.label + (release.is_3d ? ' 3D' : '') || 'n/a'}),
|
||||||
new Element('span.size', {'text': info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}),
|
new Element('span.size', {'text': info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}),
|
||||||
new Element('span.age', {'text': self.get(release, 'age')}),
|
new Element('span.age', {'text': self.get(release, 'age')}),
|
||||||
new Element('span.score', {'text': self.get(release, 'score')}),
|
new Element('span.score', {'text': self.get(release, 'score')}),
|
||||||
@@ -219,7 +203,6 @@ MA.Release = new Class({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
).inject(self.release_container);
|
).inject(self.release_container);
|
||||||
release['el'] = item;
|
|
||||||
|
|
||||||
if(release.status == 'ignored' || release.status == 'failed' || release.status == 'snatched'){
|
if(release.status == 'ignored' || release.status == 'failed' || release.status == 'snatched'){
|
||||||
if(!self.last_release || (self.last_release && self.last_release.status != 'snatched' && release.status == 'snatched'))
|
if(!self.last_release || (self.last_release && self.last_release.status != 'snatched' && release.status == 'snatched'))
|
||||||
@@ -242,13 +225,13 @@ MA.Release = new Class({
|
|||||||
status_el.set('text', new_status);
|
status_el.set('text', new_status);
|
||||||
|
|
||||||
if(!q && (new_status == 'snatched' || new_status == 'seeding' || new_status == 'done'))
|
if(!q && (new_status == 'snatched' || new_status == 'seeding' || new_status == 'done'))
|
||||||
var q = self.addQuality(release.quality_id);
|
q = self.addQuality(release.quality_id);
|
||||||
|
|
||||||
if(q && !q.hasClass(new_status)) {
|
if(q && !q.hasClass(new_status)) {
|
||||||
q.removeClass(release.status).addClass(new_status);
|
q.removeClass(release.status).addClass(new_status);
|
||||||
q.set('title', q.get('title').replace(release.status, new_status));
|
q.set('title', q.get('title').replace(release.status, new_status));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
App.on('release.update_status', update_handle);
|
App.on('release.update_status', update_handle);
|
||||||
|
|
||||||
@@ -391,12 +374,11 @@ MA.Release = new Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
ignore: function(release){
|
ignore: function(release){
|
||||||
var self = this;
|
|
||||||
|
|
||||||
Api.request('release.ignore', {
|
Api.request('release.ignore', {
|
||||||
'data': {
|
'data': {
|
||||||
'id': release._id
|
'id': release._id
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -456,7 +438,7 @@ MA.Trailer = new Class({
|
|||||||
watch: function(offset){
|
watch: function(offset){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var data_url = 'https://gdata.youtube.com/feeds/videos?vq="{title}" {year} trailer&max-results=1&alt=json-in-script&orderby=relevance&sortorder=descending&format=5&fmt=18'
|
var data_url = 'https://gdata.youtube.com/feeds/videos?vq="{title}" {year} trailer&max-results=1&alt=json-in-script&orderby=relevance&sortorder=descending&format=5&fmt=18';
|
||||||
var url = data_url.substitute({
|
var url = data_url.substitute({
|
||||||
'title': encodeURI(self.getTitle()),
|
'title': encodeURI(self.getTitle()),
|
||||||
'year': self.get('year'),
|
'year': self.get('year'),
|
||||||
@@ -515,7 +497,7 @@ MA.Trailer = new Class({
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
self.player.addEventListener('onStateChange', change_quality);
|
self.player.addEventListener('onStateChange', change_quality);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -532,7 +514,7 @@ MA.Trailer = new Class({
|
|||||||
$(self.movie).setStyle('height', null);
|
$(self.movie).setStyle('height', null);
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
self.container.destroy()
|
self.container.destroy();
|
||||||
self.close_button.destroy();
|
self.close_button.destroy();
|
||||||
}, 1800)
|
}, 1800)
|
||||||
}
|
}
|
||||||
@@ -661,7 +643,7 @@ MA.Edit = new Class({
|
|||||||
self.movie.slide('out');
|
self.movie.slide('out');
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
});
|
||||||
|
|
||||||
MA.Refresh = new Class({
|
MA.Refresh = new Class({
|
||||||
|
|
||||||
@@ -847,7 +829,7 @@ MA.Files = new Class({
|
|||||||
new Element('div.item.head').adopt(
|
new Element('div.item.head').adopt(
|
||||||
new Element('span.name', {'text': 'File'}),
|
new Element('span.name', {'text': 'File'}),
|
||||||
new Element('span.type', {'text': 'Type'})
|
new Element('span.type', {'text': 'Type'})
|
||||||
).inject(self.files_container)
|
).inject(self.files_container);
|
||||||
|
|
||||||
if(self.movie.data.releases)
|
if(self.movie.data.releases)
|
||||||
Array.each(self.movie.data.releases, function(release){
|
Array.each(self.movie.data.releases, function(release){
|
||||||
|
|||||||
@@ -398,7 +398,6 @@
|
|||||||
|
|
||||||
.movies .data .quality span {
|
.movies .data .quality span {
|
||||||
padding: 2px 3px;
|
padding: 2px 3px;
|
||||||
font-weight: bold;
|
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@@ -451,7 +450,6 @@
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
display: block;
|
|
||||||
width: auto;
|
width: auto;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
display: none;
|
display: none;
|
||||||
@@ -833,7 +831,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.movies .alph_nav .search input {
|
.movies .alph_nav .search input {
|
||||||
padding: 6px 5px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -841,7 +838,6 @@
|
|||||||
background: none;
|
background: none;
|
||||||
color: #444;
|
color: #444;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 10px;
|
|
||||||
padding: 0 10px 0 30px;
|
padding: 0 10px 0 30px;
|
||||||
border-bottom: 1px solid rgba(0,0,0,.08);
|
border-bottom: 1px solid rgba(0,0,0,.08);
|
||||||
}
|
}
|
||||||
@@ -1043,7 +1039,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.movies .progress > div .percentage {
|
.movies .progress > div .percentage {
|
||||||
font-weight: bold;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ var Movie = new Class({
|
|||||||
addEvents: function(){
|
addEvents: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.global_events = {}
|
self.global_events = {};
|
||||||
|
|
||||||
// Do refresh with new data
|
// Do refresh with new data
|
||||||
self.global_events['movie.update'] = function(notification){
|
self.global_events['movie.update'] = function(notification){
|
||||||
@@ -32,7 +32,7 @@ var Movie = new Class({
|
|||||||
self.busy(false);
|
self.busy(false);
|
||||||
self.removeView();
|
self.removeView();
|
||||||
self.update.delay(2000, self, notification);
|
self.update.delay(2000, self, notification);
|
||||||
}
|
};
|
||||||
App.on('movie.update', self.global_events['movie.update']);
|
App.on('movie.update', self.global_events['movie.update']);
|
||||||
|
|
||||||
// Add spinner on load / search
|
// Add spinner on load / search
|
||||||
@@ -40,20 +40,20 @@ var Movie = new Class({
|
|||||||
self.global_events[listener] = function(notification){
|
self.global_events[listener] = function(notification){
|
||||||
if(notification.data && (self.data._id == notification.data._id || (typeOf(notification.data._id) == 'array' && notification.data._id.indexOf(self.data._id) > -1)))
|
if(notification.data && (self.data._id == notification.data._id || (typeOf(notification.data._id) == 'array' && notification.data._id.indexOf(self.data._id) > -1)))
|
||||||
self.busy(true);
|
self.busy(true);
|
||||||
}
|
};
|
||||||
App.on(listener, self.global_events[listener]);
|
App.on(listener, self.global_events[listener]);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Remove spinner
|
// Remove spinner
|
||||||
self.global_events['movie.searcher.ended'] = function(notification){
|
self.global_events['movie.searcher.ended'] = function(notification){
|
||||||
if(notification.data && self.data._id == notification.data._id)
|
if(notification.data && self.data._id == notification.data._id)
|
||||||
self.busy(false)
|
self.busy(false)
|
||||||
}
|
};
|
||||||
App.on('movie.searcher.ended', self.global_events['movie.searcher.ended']);
|
App.on('movie.searcher.ended', self.global_events['movie.searcher.ended']);
|
||||||
|
|
||||||
// Reload when releases have updated
|
// Reload when releases have updated
|
||||||
self.global_events['release.update_status'] = function(notification){
|
self.global_events['release.update_status'] = function(notification){
|
||||||
var data = notification.data
|
var data = notification.data;
|
||||||
if(data && self.data._id == data.movie_id){
|
if(data && self.data._id == data.movie_id){
|
||||||
|
|
||||||
if(!self.data.releases)
|
if(!self.data.releases)
|
||||||
@@ -62,7 +62,7 @@ var Movie = new Class({
|
|||||||
self.data.releases.push({'quality': data.quality, 'status': data.status});
|
self.data.releases.push({'quality': data.quality, 'status': data.status});
|
||||||
self.updateReleases();
|
self.updateReleases();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
App.on('release.update_status', self.global_events['release.update_status']);
|
App.on('release.update_status', self.global_events['release.update_status']);
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ var Movie = new Class({
|
|||||||
|
|
||||||
self.el.destroy();
|
self.el.destroy();
|
||||||
delete self.list.movies_added[self.get('id')];
|
delete self.list.movies_added[self.get('id')];
|
||||||
self.list.movies.erase(self)
|
self.list.movies.erase(self);
|
||||||
|
|
||||||
self.list.checkIfEmpty();
|
self.list.checkIfEmpty();
|
||||||
|
|
||||||
@@ -117,18 +117,6 @@ var Movie = new Class({
|
|||||||
}).inject(self.el, 'top').fade('hide');
|
}).inject(self.el, 'top').fade('hide');
|
||||||
},
|
},
|
||||||
|
|
||||||
positionMask: function(){
|
|
||||||
var self = this,
|
|
||||||
s = self.el.getSize()
|
|
||||||
|
|
||||||
return self.mask.setStyles({
|
|
||||||
'width': s.x,
|
|
||||||
'height': s.y
|
|
||||||
}).position({
|
|
||||||
'relativeTo': self.el
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function(notification){
|
update: function(notification){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@@ -197,7 +185,7 @@ var Movie = new Class({
|
|||||||
if(self.profile.data)
|
if(self.profile.data)
|
||||||
self.profile.getTypes().each(function(type){
|
self.profile.getTypes().each(function(type){
|
||||||
|
|
||||||
var q = self.addQuality(type.get('quality'));
|
var q = self.addQuality(type.get('quality'), type.get('3d'));
|
||||||
if((type.finish == true || type.get('finish')) && !q.hasClass('finish')){
|
if((type.finish == true || type.get('finish')) && !q.hasClass('finish')){
|
||||||
q.addClass('finish');
|
q.addClass('finish');
|
||||||
q.set('title', q.get('title') + ' Will finish searching for this movie if this quality is found.')
|
q.set('title', q.get('title') + ' Will finish searching for this movie if this quality is found.')
|
||||||
@@ -209,7 +197,7 @@ var Movie = new Class({
|
|||||||
self.updateReleases();
|
self.updateReleases();
|
||||||
|
|
||||||
Object.each(self.options.actions, function(action, key){
|
Object.each(self.options.actions, function(action, key){
|
||||||
self.action[key.toLowerCase()] = action = new self.options.actions[key](self)
|
self.action[key.toLowerCase()] = action = new self.options.actions[key](self);
|
||||||
if(action.el)
|
if(action.el)
|
||||||
self.actions.adopt(action)
|
self.actions.adopt(action)
|
||||||
});
|
});
|
||||||
@@ -222,11 +210,11 @@ var Movie = new Class({
|
|||||||
|
|
||||||
self.data.releases.each(function(release){
|
self.data.releases.each(function(release){
|
||||||
|
|
||||||
var q = self.quality.getElement('.q_'+ release.quality),
|
var q = self.quality.getElement('.q_'+ release.quality+(release.is_3d ? '.is_3d' : ':not(.is_3d)')),
|
||||||
status = release.status;
|
status = release.status;
|
||||||
|
|
||||||
if(!q && (status == 'snatched' || status == 'seeding' || status == 'done'))
|
if(!q && (status == 'snatched' || status == 'seeding' || status == 'done'))
|
||||||
var q = self.addQuality(release.quality)
|
q = self.addQuality(release.quality, release.is_3d || false);
|
||||||
|
|
||||||
if (q && !q.hasClass(status)){
|
if (q && !q.hasClass(status)){
|
||||||
q.addClass(status);
|
q.addClass(status);
|
||||||
@@ -236,13 +224,13 @@ var Movie = new Class({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addQuality: function(quality){
|
addQuality: function(quality, is_3d){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var q = Quality.getQuality(quality);
|
var q = Quality.getQuality(quality);
|
||||||
return new Element('span', {
|
return new Element('span', {
|
||||||
'text': q.label,
|
'text': q.label + (is_3d ? ' 3D' : ''),
|
||||||
'class': 'q_'+q.identifier,
|
'class': 'q_'+q.identifier + (is_3d ? ' is_3d' : ''),
|
||||||
'title': ''
|
'title': ''
|
||||||
}).inject(self.quality);
|
}).inject(self.quality);
|
||||||
|
|
||||||
@@ -252,9 +240,9 @@ var Movie = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if(self.data.title)
|
if(self.data.title)
|
||||||
return self.getUnprefixedTitle(self.data.title)
|
return self.getUnprefixedTitle(self.data.title);
|
||||||
else if(self.data.info.titles.length > 0)
|
else if(self.data.info.titles.length > 0)
|
||||||
return self.getUnprefixedTitle(self.data.info.titles[0])
|
return self.getUnprefixedTitle(self.data.info.titles[0]);
|
||||||
|
|
||||||
return 'Unknown movie'
|
return 'Unknown movie'
|
||||||
},
|
},
|
||||||
@@ -275,12 +263,12 @@ var Movie = new Class({
|
|||||||
self.el.addEvent('outerClick', function(){
|
self.el.addEvent('outerClick', function(){
|
||||||
self.removeView();
|
self.removeView();
|
||||||
self.slide('out')
|
self.slide('out')
|
||||||
})
|
});
|
||||||
el.show();
|
el.show();
|
||||||
self.data_container.addClass('hide_right');
|
self.data_container.addClass('hide_right');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.el.removeEvents('outerClick')
|
self.el.removeEvents('outerClick');
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
if(self.el)
|
if(self.el)
|
||||||
@@ -297,7 +285,7 @@ var Movie = new Class({
|
|||||||
if(self.el)
|
if(self.el)
|
||||||
self.el
|
self.el
|
||||||
.removeClass(self.view+'_view')
|
.removeClass(self.view+'_view')
|
||||||
.addClass(new_view+'_view')
|
.addClass(new_view+'_view');
|
||||||
|
|
||||||
self.view = new_view;
|
self.view = new_view;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Block.Search.MovieItem = new Class({
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
|
|
||||||
if(info.titles)
|
if(info.titles)
|
||||||
info.titles.each(function(title){
|
info.titles.each(function(title){
|
||||||
@@ -132,19 +132,19 @@ Block.Search.MovieItem = new Class({
|
|||||||
|
|
||||||
if(!self.options_el.hasClass('set')){
|
if(!self.options_el.hasClass('set')){
|
||||||
|
|
||||||
if(self.info.in_library){
|
if(info.in_library){
|
||||||
var in_library = [];
|
var in_library = [];
|
||||||
(self.info.in_library.releases || []).each(function(release){
|
(info.in_library.releases || []).each(function(release){
|
||||||
in_library.include(release.quality)
|
in_library.include(release.quality)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.options_el.grab(
|
self.options_el.grab(
|
||||||
new Element('div', {
|
new Element('div', {
|
||||||
'class': self.info.in_wanted && self.info.in_wanted.profile_id || in_library ? 'in_library_wanted' : ''
|
'class': info.in_wanted && info.in_wanted.profile_id || in_library ? 'in_library_wanted' : ''
|
||||||
}).adopt(
|
}).adopt(
|
||||||
self.info.in_wanted && self.info.in_wanted.profile_id ? new Element('span.in_wanted', {
|
info.in_wanted && info.in_wanted.profile_id ? new Element('span.in_wanted', {
|
||||||
'text': 'Already in wanted list: ' + Quality.getProfile(self.info.in_wanted.profile_id).get('label')
|
'text': 'Already in wanted list: ' + Quality.getProfile(info.in_wanted.profile_id).get('label')
|
||||||
}) : (in_library ? new Element('span.in_library', {
|
}) : (in_library ? new Element('span.in_library', {
|
||||||
'text': 'Already in library: ' + in_library.join(', ')
|
'text': 'Already in library: ' + in_library.join(', ')
|
||||||
}) : null),
|
}) : null),
|
||||||
@@ -172,7 +172,7 @@ Block.Search.MovieItem = new Class({
|
|||||||
new Element('option', {
|
new Element('option', {
|
||||||
'text': alt.title
|
'text': alt.title
|
||||||
}).inject(self.title_select)
|
}).inject(self.title_select)
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
// Fill categories
|
// Fill categories
|
||||||
@@ -215,9 +215,9 @@ Block.Search.MovieItem = new Class({
|
|||||||
loadingMask: function(){
|
loadingMask: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.mask = new Element('div.mask').inject(self.el).fade('hide')
|
self.mask = new Element('div.mask').inject(self.el).fade('hide');
|
||||||
|
|
||||||
createSpinner(self.mask)
|
createSpinner(self.mask);
|
||||||
self.mask.fade('in')
|
self.mask.fade('in')
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
from .main import Charts
|
||||||
|
|
||||||
|
|
||||||
|
def autoload():
|
||||||
|
return Charts()
|
||||||
|
|
||||||
|
|
||||||
|
config = [{
|
||||||
|
'name': 'charts',
|
||||||
|
'groups': [
|
||||||
|
{
|
||||||
|
'label': 'Charts',
|
||||||
|
'description': 'Displays selected charts on the home page',
|
||||||
|
'type': 'list',
|
||||||
|
'name': 'charts_providers',
|
||||||
|
'tab': 'display',
|
||||||
|
'options': [
|
||||||
|
{
|
||||||
|
'name': 'max_items',
|
||||||
|
'default': 5,
|
||||||
|
'type': 'int',
|
||||||
|
'description': 'Maximum number of items displayed from each chart.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'update_interval',
|
||||||
|
'default': 12,
|
||||||
|
'type': 'int',
|
||||||
|
'advanced': True,
|
||||||
|
'description': '(hours)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}]
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
from couchpotato import tryInt
|
||||||
|
from couchpotato.core.logger import CPLog
|
||||||
|
from couchpotato.api import addApiView
|
||||||
|
from couchpotato.core.event import addEvent,fireEvent
|
||||||
|
from couchpotato.core.plugins.base import Plugin
|
||||||
|
|
||||||
|
|
||||||
|
log = CPLog(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Charts(Plugin):
|
||||||
|
|
||||||
|
update_in_progress = False
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
addApiView('charts.view', self.automationView)
|
||||||
|
addEvent('app.load', self.setCrons)
|
||||||
|
|
||||||
|
def setCrons(self):
|
||||||
|
fireEvent('schedule.interval', 'charts.update_cache', self.updateViewCache, hours = self.conf('update_interval', default = 12))
|
||||||
|
|
||||||
|
def automationView(self, force_update = False, **kwargs):
|
||||||
|
|
||||||
|
if force_update:
|
||||||
|
charts = self.updateViewCache()
|
||||||
|
else:
|
||||||
|
charts = self.getCache('charts_cached')
|
||||||
|
if not charts:
|
||||||
|
charts = self.updateViewCache()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'count': len(charts),
|
||||||
|
'charts': charts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def updateViewCache(self):
|
||||||
|
|
||||||
|
if self.update_in_progress:
|
||||||
|
while self.update_in_progress:
|
||||||
|
time.sleep(1)
|
||||||
|
catched_charts = self.getCache('charts_cached')
|
||||||
|
if catched_charts:
|
||||||
|
return catched_charts
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.update_in_progress = True
|
||||||
|
charts = fireEvent('automation.get_chart_list', merge = True)
|
||||||
|
self.setCache('charts_cached', charts, timeout = 7200 * tryInt(self.conf('update_interval', default = 12)))
|
||||||
|
except:
|
||||||
|
log.error('Failed refreshing charts')
|
||||||
|
|
||||||
|
self.update_in_progress = False
|
||||||
|
|
||||||
|
return charts
|
||||||
@@ -0,0 +1,261 @@
|
|||||||
|
.charts {
|
||||||
|
clear: both;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts > h2 {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart {
|
||||||
|
display: inline-block;
|
||||||
|
width: 50%;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .refresh {
|
||||||
|
clear:both;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .refresh .refreshing {
|
||||||
|
display: block;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .refresh a {
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
display: none;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: -40px;
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .refresh a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts p.no_charts_enabled {
|
||||||
|
padding: 0.7em 1em;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart h3 a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.charts .chart .media_result {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 960px) {
|
||||||
|
.charts .chart {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 600px) {
|
||||||
|
.charts .chart {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data {
|
||||||
|
left: 150px;
|
||||||
|
background: #4e5969;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info {
|
||||||
|
top: 10px;
|
||||||
|
left: 15px;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info h2 {
|
||||||
|
white-space: normal;
|
||||||
|
max-height: 120px;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info .rating,
|
||||||
|
.charts .chart .media_result .data .info .genres,
|
||||||
|
.charts .chart .media_result .data .info .year {
|
||||||
|
position: static;
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info .year {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info .rating {
|
||||||
|
font-size: 20px;
|
||||||
|
float: right;
|
||||||
|
margin-top: -20px;
|
||||||
|
}
|
||||||
|
.charts .chart .media_result .data .info .rating:before {
|
||||||
|
content: "\e031";
|
||||||
|
font-family: 'Elusive-Icons';
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0 5px 0 0;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info .genres {
|
||||||
|
font-size: 11px;
|
||||||
|
font-style: italic;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info .plot {
|
||||||
|
display: block;
|
||||||
|
font-size: 11px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: justify;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
top: 64px;
|
||||||
|
position: absolute;
|
||||||
|
background: #4e5969;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all .4s ease-in-out;
|
||||||
|
padding: 0 3px 10px 0;
|
||||||
|
}
|
||||||
|
.charts .chart .media_result .data:before {
|
||||||
|
bottom: 0;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 10px;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 10px;
|
||||||
|
position: absolute;
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
rgba(78, 89, 105, 1) 0%,
|
||||||
|
rgba(78, 89, 105, 0) 100%
|
||||||
|
);
|
||||||
|
z-index: 3;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data .info .plot.full {
|
||||||
|
top: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .data {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .options {
|
||||||
|
left: 150px;
|
||||||
|
}
|
||||||
|
.charts .chart .media_result .options select[name=title] { width: 100%; }
|
||||||
|
.charts .chart .media_result .options select[name=profile] { width: 100%; }
|
||||||
|
.charts .chart .media_result .options select[name=category] { width: 100%; }
|
||||||
|
|
||||||
|
.charts .chart .media_result .button {
|
||||||
|
position: absolute;
|
||||||
|
margin: 2px 0 0 0;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.charts .chart .media_result .thumbnail {
|
||||||
|
width: 100px;
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .chart_number {
|
||||||
|
color: white;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
padding: 10px;
|
||||||
|
font: bold 2em/1em Helvetica, Sans-Serif;
|
||||||
|
width: 50px;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
border-left: 8px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result.chart_in_wanted .chart_number {
|
||||||
|
border-color: rgba(0, 255, 40, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result.chart_in_library .chart_number {
|
||||||
|
border-color: rgba(0, 202, 32, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.charts .chart .media_result .actions {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
display: none;
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
.charts .chart .media_result:hover .actions {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.charts .chart .media_result:hover h2 .title {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.charts .chart .media_result .data.open .actions {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.charts .chart .media_result .actions a {
|
||||||
|
margin-left: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.toggle_menu {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle_menu a {
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
float: left;
|
||||||
|
color: rgba(255,255,255,.6);
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.0666667);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle_menu a:hover {
|
||||||
|
border-color: #047792;
|
||||||
|
border-width: 4px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle_menu a.active {
|
||||||
|
border-bottom: 4px solid #04bce6;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle_menu a:last-child {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle_menu h2 {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
var Charts = new Class({
|
||||||
|
|
||||||
|
Implements: [Options, Events],
|
||||||
|
|
||||||
|
initialize: function(options){
|
||||||
|
var self = this;
|
||||||
|
self.setOptions(options);
|
||||||
|
|
||||||
|
self.create();
|
||||||
|
},
|
||||||
|
|
||||||
|
create: function(){
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.el = new Element('div.charts').adopt(
|
||||||
|
self.el_no_charts_enabled = new Element('p.no_charts_enabled', {
|
||||||
|
'html': 'Hey, it looks like you have no charts enabled at the moment. If you\'d like some great movie suggestions you can go to <a href="' + App.createUrl('settings/display') + '">settings</a> and turn on some charts of your choice.'
|
||||||
|
}),
|
||||||
|
self.el_refresh_container = new Element('div.refresh').adopt(
|
||||||
|
self.el_refresh_link = new Element('a.refresh.icon2', {
|
||||||
|
'href': '#',
|
||||||
|
'events': {
|
||||||
|
'click': function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
self.el.getChildren('div.chart').destroy();
|
||||||
|
self.el_refreshing_text.show();
|
||||||
|
self.el_refresh_link.hide();
|
||||||
|
self.api_request = Api.request('charts.view', {
|
||||||
|
'data': { 'force_update': 1 },
|
||||||
|
'onComplete': self.fill.bind(self)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
self.el_refreshing_text = new Element('span.refreshing', {
|
||||||
|
'text': 'Refreshing charts...'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if( Cookie.read('suggestions_charts_menu_selected') === 'charts')
|
||||||
|
self.el.show();
|
||||||
|
else
|
||||||
|
self.el.hide();
|
||||||
|
|
||||||
|
self.api_request = Api.request('charts.view', {
|
||||||
|
'onComplete': self.fill.bind(self)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.fireEvent.delay(0, self, 'created');
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
fill: function(json){
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.el_refreshing_text.hide();
|
||||||
|
self.el_refresh_link.show();
|
||||||
|
|
||||||
|
if(!json || json.count == 0){
|
||||||
|
self.el_no_charts_enabled.show();
|
||||||
|
self.el_refresh_link.show();
|
||||||
|
self.el_refreshing_text.hide();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.el_no_charts_enabled.hide();
|
||||||
|
|
||||||
|
json.charts.sort(function(a, b) {
|
||||||
|
return a.order - b.order;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.each(json.charts, function(chart){
|
||||||
|
|
||||||
|
var c = new Element('div.chart').grab(
|
||||||
|
new Element('h3').grab( new Element('a', {
|
||||||
|
'text': chart.name,
|
||||||
|
'href': chart.url
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
var it = 1;
|
||||||
|
|
||||||
|
Object.each(chart.list, function(movie){
|
||||||
|
|
||||||
|
var m = new Block.Search.MovieItem(movie, {
|
||||||
|
'onAdded': function(){
|
||||||
|
self.afterAdded(m, movie)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var in_database_class = movie.in_wanted ? 'chart_in_wanted' : (movie.in_library ? 'chart_in_library' : ''),
|
||||||
|
in_database_title = movie.in_wanted ? 'Movie in wanted list' : (movie.in_library ? 'Movie in library' : '');
|
||||||
|
|
||||||
|
m.el
|
||||||
|
.addClass(in_database_class)
|
||||||
|
.grab(
|
||||||
|
new Element('div.chart_number', {
|
||||||
|
'text': it++,
|
||||||
|
'title': in_database_title
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
m.data_container.grab(
|
||||||
|
new Element('div.actions').adopt(
|
||||||
|
new Element('a.add.icon2', {
|
||||||
|
'title': 'Add movie with your default quality',
|
||||||
|
'data-add': movie.imdb,
|
||||||
|
'events': {
|
||||||
|
'click': m.showOptions.bind(m)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
$(new MA.IMDB(m)),
|
||||||
|
$(new MA.Trailer(m, {
|
||||||
|
'height': 150
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
m.data_container.removeEvents('click');
|
||||||
|
|
||||||
|
var plot = false;
|
||||||
|
if(m.info.plot && m.info.plot.length > 0)
|
||||||
|
plot = m.info.plot;
|
||||||
|
|
||||||
|
// Add rating
|
||||||
|
m.info_container.adopt(
|
||||||
|
m.rating = m.info.rating && m.info.rating.imdb && m.info.rating.imdb.length == 2 && parseFloat(m.info.rating.imdb[0]) > 0 ? new Element('span.rating', {
|
||||||
|
'text': parseFloat(m.info.rating.imdb[0]),
|
||||||
|
'title': parseInt(m.info.rating.imdb[1]) + ' votes'
|
||||||
|
}) : null,
|
||||||
|
m.genre = m.info.genres && m.info.genres.length > 0 ? new Element('span.genres', {
|
||||||
|
'text': m.info.genres.slice(0, 3).join(', ')
|
||||||
|
}) : null,
|
||||||
|
m.plot = plot ? new Element('span.plot', {
|
||||||
|
'text': plot,
|
||||||
|
'events': {
|
||||||
|
'click': function(){
|
||||||
|
this.toggleClass('full')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) : null
|
||||||
|
);
|
||||||
|
|
||||||
|
$(m).inject(c);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
c.inject(self.el);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fireEvent('loaded');
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
afterAdded: function(m){
|
||||||
|
|
||||||
|
$(m).getElement('div.chart_number')
|
||||||
|
.addClass('chart_in_wanted')
|
||||||
|
.set('title', 'Movie in wanted list');
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
toElement: function(){
|
||||||
|
return this.el;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
@@ -13,6 +13,7 @@ log = CPLog(__name__)
|
|||||||
class Automation(AutomationBase):
|
class Automation(AutomationBase):
|
||||||
|
|
||||||
enabled_option = 'automation_enabled'
|
enabled_option = 'automation_enabled'
|
||||||
|
chart_enabled_option = 'chart_display_enabled'
|
||||||
http_time_between_calls = 2
|
http_time_between_calls = 2
|
||||||
|
|
||||||
interval = 1800
|
interval = 1800
|
||||||
@@ -20,6 +21,7 @@ class Automation(AutomationBase):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addEvent('automation.get_movies', self._getMovies)
|
addEvent('automation.get_movies', self._getMovies)
|
||||||
|
addEvent('automation.get_chart_list', self._getChartList)
|
||||||
|
|
||||||
def _getMovies(self):
|
def _getMovies(self):
|
||||||
|
|
||||||
@@ -34,6 +36,13 @@ class Automation(AutomationBase):
|
|||||||
|
|
||||||
return self.getIMDBids()
|
return self.getIMDBids()
|
||||||
|
|
||||||
|
def _getChartList(self):
|
||||||
|
|
||||||
|
if not (self.conf(self.chart_enabled_option) or self.conf(self.chart_enabled_option) is None):
|
||||||
|
return
|
||||||
|
|
||||||
|
return self.getChartList()
|
||||||
|
|
||||||
def search(self, name, year = None, imdb_only = False):
|
def search(self, name, year = None, imdb_only = False):
|
||||||
|
|
||||||
prop_name = 'automation.cached.%s.%s' % (name, year)
|
prop_name = 'automation.cached.%s.%s' % (name, year)
|
||||||
@@ -94,5 +103,9 @@ class Automation(AutomationBase):
|
|||||||
def getIMDBids(self):
|
def getIMDBids(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def getChartList(self):
|
||||||
|
# Example return: [ {'name': 'Display name of list', 'url': 'http://example.com/', 'order': 1, 'list': []} ]
|
||||||
|
return
|
||||||
|
|
||||||
def canCheck(self):
|
def canCheck(self):
|
||||||
return time.time() > self.last_checked + self.interval
|
return time.time() > self.last_checked + self.interval
|
||||||
@@ -14,6 +14,8 @@ class Bluray(Automation, RSS):
|
|||||||
interval = 1800
|
interval = 1800
|
||||||
rss_url = 'http://www.blu-ray.com/rss/newreleasesfeed.xml'
|
rss_url = 'http://www.blu-ray.com/rss/newreleasesfeed.xml'
|
||||||
backlog_url = 'http://www.blu-ray.com/movies/movies.php?show=newreleases&page=%s'
|
backlog_url = 'http://www.blu-ray.com/movies/movies.php?show=newreleases&page=%s'
|
||||||
|
display_url = 'http://www.blu-ray.com/movies/movies.php?show=newreleases'
|
||||||
|
chart_order = 1
|
||||||
|
|
||||||
def getIMDBids(self):
|
def getIMDBids(self):
|
||||||
|
|
||||||
@@ -62,7 +64,7 @@ class Bluray(Automation, RSS):
|
|||||||
name = self.getTextElement(movie, 'title').lower().split('blu-ray')[0].strip('(').rstrip()
|
name = self.getTextElement(movie, 'title').lower().split('blu-ray')[0].strip('(').rstrip()
|
||||||
year = self.getTextElement(movie, 'description').split('|')[1].strip('(').strip()
|
year = self.getTextElement(movie, 'description').split('|')[1].strip('(').strip()
|
||||||
|
|
||||||
if not name.find('/') == -1: # make sure it is not a double movie release
|
if not name.find('/') == -1: # make sure it is not a double movie release
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if tryInt(year) < self.getMinimal('year'):
|
if tryInt(year) < self.getMinimal('year'):
|
||||||
@@ -77,6 +79,32 @@ class Bluray(Automation, RSS):
|
|||||||
return movies
|
return movies
|
||||||
|
|
||||||
|
|
||||||
|
def getChartList(self):
|
||||||
|
# Nearly identical to 'getIMDBids', but we don't care about minimalMovie and return all movie data (not just id)
|
||||||
|
movie_list = {'name': 'Blu-ray.com - New Releases', 'url': self.display_url, 'order': self.chart_order, 'list': []}
|
||||||
|
max_items = int(self.conf('max_items', section='charts', default=5))
|
||||||
|
rss_movies = self.getRSSData(self.rss_url)
|
||||||
|
|
||||||
|
for movie in rss_movies:
|
||||||
|
name = self.getTextElement(movie, 'title').lower().split('blu-ray')[0].strip('(').rstrip()
|
||||||
|
year = self.getTextElement(movie, 'description').split('|')[1].strip('(').strip()
|
||||||
|
|
||||||
|
if not name.find('/') == -1: # make sure it is not a double movie release
|
||||||
|
continue
|
||||||
|
|
||||||
|
movie = self.search(name, year)
|
||||||
|
|
||||||
|
if movie:
|
||||||
|
movie_list['list'].append( movie )
|
||||||
|
if len(movie_list['list']) >= max_items:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not movie_list['list']:
|
||||||
|
return
|
||||||
|
|
||||||
|
return [ movie_list ]
|
||||||
|
|
||||||
|
|
||||||
config = [{
|
config = [{
|
||||||
'name': 'bluray',
|
'name': 'bluray',
|
||||||
'groups': [
|
'groups': [
|
||||||
@@ -101,5 +129,19 @@ config = [{
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'tab': 'display',
|
||||||
|
'list': 'charts_providers',
|
||||||
|
'name': 'bluray_charts_display',
|
||||||
|
'label': 'Blu-ray.com',
|
||||||
|
'description': 'Display <a href="http://www.blu-ray.com/movies/movies.php?show=newreleases">new releases</a> from Blu-ray.com',
|
||||||
|
'options': [
|
||||||
|
{
|
||||||
|
'name': 'chart_display_enabled',
|
||||||
|
'default': True,
|
||||||
|
'type': 'enabler',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}]
|
}]
|
||||||
@@ -46,7 +46,10 @@ class Goodfilms(Automation):
|
|||||||
break
|
break
|
||||||
|
|
||||||
for movie in this_watch_list:
|
for movie in this_watch_list:
|
||||||
movies.append({ 'title': movie['data-film-title'], 'year': movie['data-film-year'] })
|
movies.append({
|
||||||
|
'title': movie['data-film-title'],
|
||||||
|
'year': movie['data-film-year']
|
||||||
|
})
|
||||||
|
|
||||||
if not 'next page' in data.lower():
|
if not 'next page' in data.lower():
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -105,6 +105,16 @@ class IMDBAutomation(IMDBBase):
|
|||||||
'top250': 'http://www.imdb.com/chart/top',
|
'top250': 'http://www.imdb.com/chart/top',
|
||||||
'boxoffice': 'http://www.imdb.com/chart/',
|
'boxoffice': 'http://www.imdb.com/chart/',
|
||||||
}
|
}
|
||||||
|
chart_names = {
|
||||||
|
'theater': 'IMDB - Movies in Theaters',
|
||||||
|
'top250': 'IMDB - Top 250 Movies',
|
||||||
|
'boxoffice': 'IMDB - Box Office',
|
||||||
|
}
|
||||||
|
chart_order = {
|
||||||
|
'theater': 2,
|
||||||
|
'top250': 4,
|
||||||
|
'boxoffice': 3,
|
||||||
|
}
|
||||||
|
|
||||||
first_table = ['boxoffice']
|
first_table = ['boxoffice']
|
||||||
|
|
||||||
@@ -144,6 +154,46 @@ class IMDBAutomation(IMDBBase):
|
|||||||
return movies
|
return movies
|
||||||
|
|
||||||
|
|
||||||
|
def getChartList(self):
|
||||||
|
# Nearly identical to 'getIMDBids', but we don't care about minimalMovie and return all movie data (not just id)
|
||||||
|
movie_lists = []
|
||||||
|
max_items = int(self.conf('max_items', section='charts', default=5))
|
||||||
|
|
||||||
|
for url in self.chart_urls:
|
||||||
|
if self.conf('chart_display_%s' % url):
|
||||||
|
movie_list = {'name': self.chart_names[url], 'url': self.chart_urls[url], 'order': self.chart_order[url], 'list': []}
|
||||||
|
data = self.getHTMLData(self.chart_urls[url])
|
||||||
|
if data:
|
||||||
|
html = BeautifulSoup(data)
|
||||||
|
|
||||||
|
try:
|
||||||
|
result_div = html.find('div', attrs = {'id': 'main'})
|
||||||
|
|
||||||
|
try:
|
||||||
|
if url in self.first_table:
|
||||||
|
table = result_div.find('table')
|
||||||
|
result_div = table if table else result_div
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
imdb_ids = getImdb(str(result_div), multiple = True)
|
||||||
|
|
||||||
|
for imdb_id in imdb_ids[0:max_items]:
|
||||||
|
info = self.getInfo(imdb_id)
|
||||||
|
movie_list['list'].append(info)
|
||||||
|
|
||||||
|
if self.shuttingDown():
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
log.error('Failed loading IMDB chart results from %s: %s', (url, traceback.format_exc()))
|
||||||
|
|
||||||
|
if movie_list['list']:
|
||||||
|
movie_lists.append(movie_list)
|
||||||
|
|
||||||
|
|
||||||
|
return movie_lists
|
||||||
|
|
||||||
|
|
||||||
config = [{
|
config = [{
|
||||||
'name': 'imdb',
|
'name': 'imdb',
|
||||||
'groups': [
|
'groups': [
|
||||||
@@ -206,5 +256,40 @@ config = [{
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'tab': 'display',
|
||||||
|
'list': 'charts_providers',
|
||||||
|
'name': 'imdb_charts_display',
|
||||||
|
'label': 'IMDB',
|
||||||
|
'description': 'Display movies from IMDB Charts',
|
||||||
|
'options': [
|
||||||
|
{
|
||||||
|
'name': 'chart_display_enabled',
|
||||||
|
'default': True,
|
||||||
|
'type': 'enabler',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'chart_display_theater',
|
||||||
|
'type': 'bool',
|
||||||
|
'label': 'In Theaters',
|
||||||
|
'description': 'New Movies <a href="http://www.imdb.com/movies-in-theaters/">In-Theaters</a> chart',
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'chart_display_top250',
|
||||||
|
'type': 'bool',
|
||||||
|
'label': 'TOP 250',
|
||||||
|
'description': 'IMDB <a href="http://www.imdb.com/chart/top/">TOP 250</a> chart',
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'chart_display_boxoffice',
|
||||||
|
'type': 'bool',
|
||||||
|
'label': 'Box office TOP 10',
|
||||||
|
'description': 'IMDB Box office <a href="http://www.imdb.com/chart/">TOP 10</a> chart',
|
||||||
|
'default': True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}]
|
}]
|
||||||
@@ -50,7 +50,10 @@ class Letterboxd(Automation):
|
|||||||
|
|
||||||
for movie in soup.find_all('a', attrs = {'class': 'frame'}):
|
for movie in soup.find_all('a', attrs = {'class': 'frame'}):
|
||||||
match = removeEmpty(self.pattern.split(movie['title']))
|
match = removeEmpty(self.pattern.split(movie['title']))
|
||||||
movies.append({'title': match[0], 'year': match[1] })
|
movies.append({
|
||||||
|
'title': match[0],
|
||||||
|
'year': match[1]
|
||||||
|
})
|
||||||
|
|
||||||
return movies
|
return movies
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ class MovieResultModifier(Plugin):
|
|||||||
if media.get('status') == 'active':
|
if media.get('status') == 'active':
|
||||||
temp['in_wanted'] = media
|
temp['in_wanted'] = media
|
||||||
|
|
||||||
|
try: temp['in_wanted']['profile'] = db.get('id', media['profile_id'])
|
||||||
|
except: temp['in_wanted']['profile'] = {'label': ''}
|
||||||
|
|
||||||
for release in fireEvent('release.for_media', media['_id'], single = True):
|
for release in fireEvent('release.for_media', media['_id'], single = True):
|
||||||
if release.get('status') == 'done':
|
if release.get('status') == 'done':
|
||||||
if not temp['in_library']:
|
if not temp['in_library']:
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class TheMovieDb(MovieProvider):
|
|||||||
if not result:
|
if not result:
|
||||||
try:
|
try:
|
||||||
log.debug('Getting info: %s', cache_key)
|
log.debug('Getting info: %s', cache_key)
|
||||||
|
# noinspection PyArgumentList
|
||||||
movie = tmdb3.Movie(identifier)
|
movie = tmdb3.Movie(identifier)
|
||||||
try: exists = movie.title is not None
|
try: exists = movie.title is not None
|
||||||
except: exists = False
|
except: exists = False
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ class BiTHDTV(MovieProvider, Base):
|
|||||||
def buildUrl(self, media):
|
def buildUrl(self, media):
|
||||||
query = tryUrlencode({
|
query = tryUrlencode({
|
||||||
'search': fireEvent('library.query', media, single = True),
|
'search': fireEvent('library.query', media, single = True),
|
||||||
'cat': 7 # Movie cat
|
'cat': 7 # Movie cat
|
||||||
})
|
})
|
||||||
return query
|
return query
|
||||||
@@ -11,6 +11,7 @@ autoload = 'Bitsoup'
|
|||||||
|
|
||||||
class Bitsoup(MovieProvider, Base):
|
class Bitsoup(MovieProvider, Base):
|
||||||
cat_ids = [
|
cat_ids = [
|
||||||
|
([17], ['3d']),
|
||||||
([41], ['720p', '1080p']),
|
([41], ['720p', '1080p']),
|
||||||
([20], ['dvdr']),
|
([20], ['dvdr']),
|
||||||
([19], ['brrip', 'dvdrip']),
|
([19], ['brrip', 'dvdrip']),
|
||||||
@@ -23,6 +24,6 @@ class Bitsoup(MovieProvider, Base):
|
|||||||
fireEvent('library.query', media, include_year = False, single = True),
|
fireEvent('library.query', media, include_year = False, single = True),
|
||||||
media['info']['year']
|
media['info']['year']
|
||||||
),
|
),
|
||||||
'cat': self.getCatId(quality['identifier'])[0],
|
'cat': self.getCatId(quality)[0],
|
||||||
})
|
})
|
||||||
return query
|
return query
|
||||||
@@ -10,6 +10,7 @@ autoload = 'IPTorrents'
|
|||||||
class IPTorrents(MovieProvider, Base):
|
class IPTorrents(MovieProvider, Base):
|
||||||
|
|
||||||
cat_ids = [
|
cat_ids = [
|
||||||
|
([87], ['3d']),
|
||||||
([48], ['720p', '1080p', 'bd50']),
|
([48], ['720p', '1080p', 'bd50']),
|
||||||
([72], ['cam', 'ts', 'tc', 'r5', 'scr']),
|
([72], ['cam', 'ts', 'tc', 'r5', 'scr']),
|
||||||
([7], ['dvdrip', 'brrip']),
|
([7], ['dvdrip', 'brrip']),
|
||||||
@@ -19,4 +20,4 @@ class IPTorrents(MovieProvider, Base):
|
|||||||
def buildUrl(self, title, media, quality):
|
def buildUrl(self, title, media, quality):
|
||||||
query = '%s %s' % (title.replace(':', ''), media['info']['year'])
|
query = '%s %s' % (title.replace(':', ''), media['info']['year'])
|
||||||
|
|
||||||
return self._buildUrl(query, quality['identifier'])
|
return self._buildUrl(query, quality)
|
||||||
@@ -10,29 +10,29 @@ autoload = 'PassThePopcorn'
|
|||||||
class PassThePopcorn(MovieProvider, Base):
|
class PassThePopcorn(MovieProvider, Base):
|
||||||
|
|
||||||
quality_search_params = {
|
quality_search_params = {
|
||||||
'bd50': {'media': 'Blu-ray', 'format': 'BD50'},
|
'bd50': {'media': 'Blu-ray', 'format': 'BD50'},
|
||||||
'1080p': {'resolution': '1080p'},
|
'1080p': {'resolution': '1080p'},
|
||||||
'720p': {'resolution': '720p'},
|
'720p': {'resolution': '720p'},
|
||||||
'brrip': {'media': 'Blu-ray'},
|
'brrip': {'media': 'Blu-ray'},
|
||||||
'dvdr': {'resolution': 'anysd'},
|
'dvdr': {'resolution': 'anysd'},
|
||||||
'dvdrip': {'media': 'DVD'},
|
'dvdrip': {'media': 'DVD'},
|
||||||
'scr': {'media': 'DVD-Screener'},
|
'scr': {'media': 'DVD-Screener'},
|
||||||
'r5': {'media': 'R5'},
|
'r5': {'media': 'R5'},
|
||||||
'tc': {'media': 'TC'},
|
'tc': {'media': 'TC'},
|
||||||
'ts': {'media': 'TS'},
|
'ts': {'media': 'TS'},
|
||||||
'cam': {'media': 'CAM'}
|
'cam': {'media': 'CAM'}
|
||||||
}
|
}
|
||||||
|
|
||||||
post_search_filters = {
|
post_search_filters = {
|
||||||
'bd50': {'Codec': ['BD50']},
|
'bd50': {'Codec': ['BD50']},
|
||||||
'1080p': {'Resolution': ['1080p']},
|
'1080p': {'Resolution': ['1080p']},
|
||||||
'720p': {'Resolution': ['720p']},
|
'720p': {'Resolution': ['720p']},
|
||||||
'brrip': {'Source': ['Blu-ray'], 'Quality': ['High Definition'], 'Container': ['!ISO']},
|
'brrip': {'Source': ['Blu-ray'], 'Quality': ['High Definition'], 'Container': ['!ISO']},
|
||||||
'dvdr': {'Codec': ['DVD5', 'DVD9']},
|
'dvdr': {'Codec': ['DVD5', 'DVD9']},
|
||||||
'dvdrip': {'Source': ['DVD'], 'Codec': ['!DVD5', '!DVD9']},
|
'dvdrip': {'Source': ['DVD'], 'Codec': ['!DVD5', '!DVD9']},
|
||||||
'scr': {'Source': ['DVD-Screener']},
|
'scr': {'Source': ['DVD-Screener']},
|
||||||
'r5': {'Source': ['R5']},
|
'r5': {'Source': ['R5']},
|
||||||
'tc': {'Source': ['TC']},
|
'tc': {'Source': ['TC']},
|
||||||
'ts': {'Source': ['TS']},
|
'ts': {'Source': ['TS']},
|
||||||
'cam': {'Source': ['CAM']}
|
'cam': {'Source': ['CAM']}
|
||||||
}
|
}
|
||||||
@@ -18,10 +18,8 @@ class SceneAccess(MovieProvider, Base):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def buildUrl(self, media, quality):
|
def buildUrl(self, media, quality):
|
||||||
url = self.urls['search'] % (
|
cat_id = self.getCatId(quality)[0]
|
||||||
self.getCatId(quality['identifier'])[0],
|
url = self.urls['search'] % (cat_id, cat_id)
|
||||||
self.getCatId(quality['identifier'])[0]
|
|
||||||
)
|
|
||||||
|
|
||||||
arguments = tryUrlencode({
|
arguments = tryUrlencode({
|
||||||
'search': fireEvent('library.query', media, single = True),
|
'search': fireEvent('library.query', media, single = True),
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ autoload = 'ThePirateBay'
|
|||||||
class ThePirateBay(MovieProvider, Base):
|
class ThePirateBay(MovieProvider, Base):
|
||||||
|
|
||||||
cat_ids = [
|
cat_ids = [
|
||||||
([207], ['720p', '1080p']),
|
([209], ['3d']),
|
||||||
([201], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
|
([207], ['720p', '1080p']),
|
||||||
([201, 207], ['brrip']),
|
([201], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
|
||||||
([202], ['dvdr'])
|
([201, 207], ['brrip']),
|
||||||
|
([202], ['dvdr'])
|
||||||
]
|
]
|
||||||
|
|
||||||
def buildUrl(self, media, page, cats):
|
def buildUrl(self, media, page, cats):
|
||||||
|
|||||||
@@ -16,5 +16,6 @@ class TorrentDay(MovieProvider, Base):
|
|||||||
([3], ['dvdr']),
|
([3], ['dvdr']),
|
||||||
([5], ['bd50']),
|
([5], ['bd50']),
|
||||||
]
|
]
|
||||||
|
|
||||||
def buildUrl(self, media):
|
def buildUrl(self, media):
|
||||||
return fireEvent('library.query', media, single = True)
|
return fireEvent('library.query', media, single = True)
|
||||||
@@ -24,5 +24,5 @@ class TorrentLeech(MovieProvider, Base):
|
|||||||
def buildUrl(self, media, quality):
|
def buildUrl(self, media, quality):
|
||||||
return (
|
return (
|
||||||
tryUrlencode(fireEvent('library.query', media, single = True)),
|
tryUrlencode(fireEvent('library.query', media, single = True)),
|
||||||
self.getCatId(quality['identifier'])[0]
|
self.getCatId(quality)[0]
|
||||||
)
|
)
|
||||||
@@ -31,6 +31,6 @@ class TorrentShack(MovieProvider, Base):
|
|||||||
|
|
||||||
def buildUrl(self, media, quality):
|
def buildUrl(self, media, quality):
|
||||||
query = (tryUrlencode(fireEvent('library.query', media, single = True)),
|
query = (tryUrlencode(fireEvent('library.query', media, single = True)),
|
||||||
self.getCatId(quality['identifier'])[0],
|
self.getCatId(quality)[0],
|
||||||
self.getSceneOnly())
|
self.getSceneOnly())
|
||||||
return query
|
return query
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||||
|
from couchpotato.core.logger import CPLog
|
||||||
|
from couchpotato.core.event import fireEvent
|
||||||
|
from couchpotato.core.media._base.providers.torrent.torrentz import Base
|
||||||
|
from couchpotato.core.media.movie.providers.base import MovieProvider
|
||||||
|
|
||||||
|
log = CPLog(__name__)
|
||||||
|
|
||||||
|
autoload = 'Torrentz'
|
||||||
|
|
||||||
|
|
||||||
|
class Torrentz(MovieProvider, Base):
|
||||||
|
|
||||||
|
def buildUrl(self, media):
|
||||||
|
return tryUrlencode('"%s"' % fireEvent('library.query', media, single = True))
|
||||||
@@ -52,7 +52,7 @@ class HDTrailers(TrailerProvider):
|
|||||||
return result_data
|
return result_data
|
||||||
|
|
||||||
def findViaAlternative(self, group):
|
def findViaAlternative(self, group):
|
||||||
results = {'480p':[], '720p':[], '1080p':[]}
|
results = {'480p': [], '720p': [], '1080p': []}
|
||||||
|
|
||||||
movie_name = getTitle(group)
|
movie_name = getTitle(group)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from couchpotato.core.media._base.providers.userscript.base import UserscriptBase
|
||||||
|
|
||||||
|
autoload = 'FilmCentrum'
|
||||||
|
|
||||||
|
|
||||||
|
class FilmCentrum(UserscriptBase):
|
||||||
|
|
||||||
|
includes = ['*://filmcentrum.nl/films/*']
|
||||||
@@ -143,14 +143,17 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
|
|
||||||
ret = False
|
ret = False
|
||||||
|
|
||||||
|
index = 0
|
||||||
for q_identifier in profile.get('qualities'):
|
for q_identifier in profile.get('qualities'):
|
||||||
index = profile['qualities'].index(q_identifier)
|
|
||||||
quality_custom = {
|
quality_custom = {
|
||||||
'quality': q_identifier,
|
'quality': q_identifier,
|
||||||
'finish': profile['finish'][index],
|
'finish': profile['finish'][index],
|
||||||
'wait_for': profile['wait_for'][index]
|
'wait_for': profile['wait_for'][index],
|
||||||
|
'3d': profile['3d'][index] if profile.get('3d') else False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
|
||||||
if not self.conf('always_search') and not self.couldBeReleased(q_identifier in pre_releases, release_dates, movie['info']['year']):
|
if not self.conf('always_search') and not self.couldBeReleased(q_identifier in pre_releases, release_dates, movie['info']['year']):
|
||||||
too_early_to_search.append(q_identifier)
|
too_early_to_search.append(q_identifier)
|
||||||
continue
|
continue
|
||||||
@@ -168,6 +171,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
quality = fireEvent('quality.single', identifier = q_identifier, single = True)
|
quality = fireEvent('quality.single', identifier = q_identifier, single = True)
|
||||||
log.info('Search for %s in %s', (default_title, quality['label']))
|
log.info('Search for %s in %s', (default_title, quality['label']))
|
||||||
|
|
||||||
|
# Extend quality with profile customs
|
||||||
|
quality['custom'] = quality_custom
|
||||||
|
|
||||||
results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or []
|
results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or []
|
||||||
if len(results) == 0:
|
if len(results) == 0:
|
||||||
log.debug('Nothing found for %s in %s', (default_title, quality['label']))
|
log.debug('Nothing found for %s in %s', (default_title, quality['label']))
|
||||||
@@ -221,13 +227,17 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
if not fireEvent('searcher.correct_words', nzb['name'], media, single = True):
|
if not fireEvent('searcher.correct_words', nzb['name'], media, single = True):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
preferred_quality = fireEvent('quality.single', identifier = quality['identifier'], single = True)
|
preferred_quality = quality if quality else fireEvent('quality.single', identifier = quality['identifier'], single = True)
|
||||||
|
|
||||||
# Contains lower quality string
|
# Contains lower quality string
|
||||||
if fireEvent('searcher.contains_other_quality', nzb, movie_year = media['info']['year'], preferred_quality = preferred_quality, single = True):
|
if fireEvent('searcher.contains_other_quality', nzb, movie_year = media['info']['year'], preferred_quality = preferred_quality, single = True):
|
||||||
log.info2('Wrong: %s, looking for %s', (nzb['name'], quality['label']))
|
log.info2('Wrong: %s, looking for %s', (nzb['name'], quality['label']))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Contains lower quality string
|
||||||
|
if not fireEvent('searcher.correct_3d', nzb, preferred_quality = preferred_quality, single = True):
|
||||||
|
log.info2('Wrong: %s, %slooking for %s in 3D', (nzb['name'], ('' if preferred_quality['custom'].get('3d') else 'NOT '), quality['label']))
|
||||||
|
return False
|
||||||
|
|
||||||
# File to small
|
# File to small
|
||||||
if nzb['size'] and tryInt(preferred_quality['size_min']) > tryInt(nzb['size']):
|
if nzb['size'] and tryInt(preferred_quality['size_min']) > tryInt(nzb['size']):
|
||||||
@@ -239,7 +249,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
log.info2('Wrong: "%s" is too large to be %s. %sMB instead of the maximum of %sMB.', (nzb['name'], preferred_quality['label'], nzb['size'], preferred_quality['size_max']))
|
log.info2('Wrong: "%s" is too large to be %s. %sMB instead of the maximum of %sMB.', (nzb['name'], preferred_quality['label'], nzb['size'], preferred_quality['size_max']))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# Provider specific functions
|
# Provider specific functions
|
||||||
get_more = nzb.get('get_more_info')
|
get_more = nzb.get('get_more_info')
|
||||||
if get_more:
|
if get_more:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
.suggestions {
|
.suggestions {
|
||||||
|
clear: both;
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.suggestions > h2 {
|
.suggestions > h2 {
|
||||||
@@ -91,7 +94,6 @@
|
|||||||
padding: 0 3px 10px 0;
|
padding: 0 3px 10px 0;
|
||||||
}
|
}
|
||||||
.suggestions .media_result .data:before {
|
.suggestions .media_result .data:before {
|
||||||
bottom: 0;
|
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
|
|||||||
@@ -42,11 +42,10 @@ var SuggestList = new Class({
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).grab(
|
});
|
||||||
new Element('h2', {
|
|
||||||
'text': 'You might like these'
|
var cookie_menu_select = Cookie.read('suggestions_charts_menu_selected');
|
||||||
})
|
if( cookie_menu_select === 'suggestions' || cookie_menu_select === null ) self.el.show(); else self.el.hide();
|
||||||
);
|
|
||||||
|
|
||||||
self.api_request = Api.request('suggestion.view', {
|
self.api_request = Api.request('suggestion.view', {
|
||||||
'onComplete': self.fill.bind(self)
|
'onComplete': self.fill.bind(self)
|
||||||
@@ -116,7 +115,7 @@ var SuggestList = new Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) : null
|
}) : null
|
||||||
)
|
);
|
||||||
|
|
||||||
$(m).inject(self.el);
|
$(m).inject(self.el);
|
||||||
|
|
||||||
@@ -150,4 +149,4 @@ var SuggestList = new Class({
|
|||||||
return this.el;
|
return this.el;
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
});
|
||||||
@@ -131,7 +131,7 @@ class CoreNotifier(Notification):
|
|||||||
|
|
||||||
for message in messages:
|
for message in messages:
|
||||||
if message.get('time') > last_check:
|
if message.get('time') > last_check:
|
||||||
message['sticky'] = True # Always sticky core messages
|
message['sticky'] = True # Always sticky core messages
|
||||||
|
|
||||||
message_type = 'core.message.important' if message.get('important') else 'core.message'
|
message_type = 'core.message.important' if message.get('important') else 'core.message'
|
||||||
fireEvent(message_type, message = message.get('message'), data = message)
|
fireEvent(message_type, message = message.get('message'), data = message)
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ var NotificationBase = new Class({
|
|||||||
App.addEvent('load', self.addTestButtons.bind(self));
|
App.addEvent('load', self.addTestButtons.bind(self));
|
||||||
|
|
||||||
// Notification bar
|
// Notification bar
|
||||||
self.notifications = []
|
self.notifications = [];
|
||||||
App.addEvent('load', function(){
|
App.addEvent('load', function(){
|
||||||
|
|
||||||
App.block.notification = new Block.Menu(self, {
|
App.block.notification = new Block.Menu(self, {
|
||||||
'button_class': 'icon2.eye-open',
|
'button_class': 'icon2.eye-open',
|
||||||
'class': 'notification_menu',
|
'class': 'notification_menu',
|
||||||
'onOpen': self.markAsRead.bind(self)
|
'onOpen': self.markAsRead.bind(self)
|
||||||
})
|
});
|
||||||
$(App.block.notification).inject(App.getBlock('search'), 'after');
|
$(App.block.notification).inject(App.getBlock('search'), 'after');
|
||||||
self.badge = new Element('div.badge').inject(App.block.notification, 'top').hide();
|
self.badge = new Element('div.badge').inject(App.block.notification, 'top').hide();
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ var NotificationBase = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var added = new Date();
|
var added = new Date();
|
||||||
added.setTime(result.added*1000)
|
added.setTime(result.added*1000);
|
||||||
|
|
||||||
result.el = App.getBlock('notification').addLink(
|
result.el = App.getBlock('notification').addLink(
|
||||||
new Element('span.'+(result.read ? 'read' : '' )).adopt(
|
new Element('span.'+(result.read ? 'read' : '' )).adopt(
|
||||||
@@ -51,7 +51,7 @@ var NotificationBase = new Class({
|
|||||||
self.notifications.include(result);
|
self.notifications.include(result);
|
||||||
|
|
||||||
if((result.data.important !== undefined || result.data.sticky !== undefined) && !result.read){
|
if((result.data.important !== undefined || result.data.sticky !== undefined) && !result.read){
|
||||||
var sticky = true
|
var sticky = true;
|
||||||
App.trigger('message', [result.message, sticky, result])
|
App.trigger('message', [result.message, sticky, result])
|
||||||
}
|
}
|
||||||
else if(!result.read){
|
else if(!result.read){
|
||||||
@@ -62,7 +62,7 @@ var NotificationBase = new Class({
|
|||||||
|
|
||||||
setBadge: function(value){
|
setBadge: function(value){
|
||||||
var self = this;
|
var self = this;
|
||||||
self.badge.set('text', value)
|
self.badge.set('text', value);
|
||||||
self.badge[value ? 'show' : 'hide']()
|
self.badge[value ? 'show' : 'hide']()
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -73,9 +73,9 @@ var NotificationBase = new Class({
|
|||||||
if(!force_ids) {
|
if(!force_ids) {
|
||||||
var rn = self.notifications.filter(function(n){
|
var rn = self.notifications.filter(function(n){
|
||||||
return !n.read && n.data.important === undefined
|
return !n.read && n.data.important === undefined
|
||||||
})
|
});
|
||||||
|
|
||||||
var ids = []
|
var ids = [];
|
||||||
rn.each(function(n){
|
rn.each(function(n){
|
||||||
ids.include(n._id)
|
ids.include(n._id)
|
||||||
})
|
})
|
||||||
@@ -106,7 +106,7 @@ var NotificationBase = new Class({
|
|||||||
'onSuccess': function(json){
|
'onSuccess': function(json){
|
||||||
self.processData(json, true)
|
self.processData(json, true)
|
||||||
}
|
}
|
||||||
}).send()
|
}).send();
|
||||||
|
|
||||||
setInterval(function(){
|
setInterval(function(){
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ var NotificationBase = new Class({
|
|||||||
|
|
||||||
stopPoll: function(){
|
stopPoll: function(){
|
||||||
if(this.request)
|
if(this.request)
|
||||||
this.request.cancel()
|
this.request.cancel();
|
||||||
this.stopped = true;
|
this.stopped = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ var NotificationBase = new Class({
|
|||||||
App.trigger(result._t || result.type, [result]);
|
App.trigger(result._t || result.type, [result]);
|
||||||
if(result.message && result.read === undefined && !init)
|
if(result.message && result.read === undefined && !init)
|
||||||
self.showMessage(result.message);
|
self.showMessage(result.message);
|
||||||
})
|
});
|
||||||
|
|
||||||
if(json.result.length > 0)
|
if(json.result.length > 0)
|
||||||
self.last_id = json.result.getLast().message_id
|
self.last_id = json.result.getLast().message_id
|
||||||
@@ -180,11 +180,11 @@ var NotificationBase = new Class({
|
|||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
var hide_message = function(){
|
var hide_message = function(){
|
||||||
new_message.addClass('hide')
|
new_message.addClass('hide');
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
new_message.destroy();
|
new_message.destroy();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
};
|
||||||
|
|
||||||
if(sticky)
|
if(sticky)
|
||||||
new_message.grab(
|
new_message.grab(
|
||||||
@@ -206,7 +206,7 @@ var NotificationBase = new Class({
|
|||||||
addTestButtons: function(){
|
addTestButtons: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var setting_page = App.getPage('Settings')
|
var setting_page = App.getPage('Settings');
|
||||||
setting_page.addEvent('create', function(){
|
setting_page.addEvent('create', function(){
|
||||||
Object.each(setting_page.tabs.notifications.groups, self.addTestButton.bind(self))
|
Object.each(setting_page.tabs.notifications.groups, self.addTestButton.bind(self))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ config = [{
|
|||||||
'name': 'smtp_server',
|
'name': 'smtp_server',
|
||||||
'label': 'SMTP server',
|
'label': 'SMTP server',
|
||||||
},
|
},
|
||||||
{ 'name': 'smtp_port',
|
{
|
||||||
|
'name': 'smtp_port',
|
||||||
'label': 'SMTP server port',
|
'label': 'SMTP server port',
|
||||||
'default': '25',
|
'default': '25',
|
||||||
'type': 'int',
|
'type': 'int',
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ class Growl(Notification):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Growl, self).__init__()
|
super(Growl, self).__init__()
|
||||||
|
|
||||||
|
self.growl = None
|
||||||
|
|
||||||
if self.isEnabled():
|
if self.isEnabled():
|
||||||
addEvent('app.load', self.register)
|
addEvent('app.load', self.register)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ autoload = 'NMJ'
|
|||||||
|
|
||||||
class NMJ(Notification):
|
class NMJ(Notification):
|
||||||
|
|
||||||
|
# noinspection PyMissingConstructor
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addEvent('renamer.after', self.addToLibrary)
|
addEvent('renamer.after', self.addToLibrary)
|
||||||
addApiView(self.testNotifyName(), self.test)
|
addApiView(self.testNotifyName(), self.test)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Pushalot(Notification):
|
|||||||
}
|
}
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
'Content-type': 'application/x-www-form-urlencoded'
|
'Content-type': 'application/x-www-form-urlencoded'
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class Pushover(Notification):
|
|||||||
'token': self.app_token,
|
'token': self.app_token,
|
||||||
'message': toUnicode(message),
|
'message': toUnicode(message),
|
||||||
'priority': self.conf('priority'),
|
'priority': self.conf('priority'),
|
||||||
|
'sound': self.conf('sound'),
|
||||||
}
|
}
|
||||||
|
|
||||||
if data and data.get('identifier'):
|
if data and data.get('identifier'):
|
||||||
@@ -33,10 +34,9 @@ class Pushover(Notification):
|
|||||||
'url_title': toUnicode('%s on IMDb' % getTitle(data)),
|
'url_title': toUnicode('%s on IMDb' % getTitle(data)),
|
||||||
})
|
})
|
||||||
|
|
||||||
http_handler.request('POST',
|
http_handler.request('POST', '/1/messages.json',
|
||||||
"/1/messages.json",
|
headers = {'Content-type': 'application/x-www-form-urlencoded'},
|
||||||
headers = {'Content-type': 'application/x-www-form-urlencoded'},
|
body = tryUrlencode(api_data)
|
||||||
body = tryUrlencode(api_data)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
response = http_handler.getresponse()
|
response = http_handler.getresponse()
|
||||||
@@ -83,6 +83,11 @@ config = [{
|
|||||||
'advanced': True,
|
'advanced': True,
|
||||||
'description': 'Also send message when movie is snatched.',
|
'description': 'Also send message when movie is snatched.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'sound',
|
||||||
|
'advanced': True,
|
||||||
|
'description': 'Define <a href="https://pushover.net/api%23sounds" target="_blank">custom sound</a> for Pushover alert.'
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ var TwitterNotification = new Class({
|
|||||||
).inject(fieldset.getElement('.test_button'), 'before');
|
).inject(fieldset.getElement('.test_button'), 'before');
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class XBMC(Notification):
|
|||||||
self.use_json_notifications[host] = False
|
self.use_json_notifications[host] = False
|
||||||
|
|
||||||
# send the text message
|
# send the text message
|
||||||
resp = self.notifyXBMCnoJSON(host, {'title':self.default_title, 'message':message})
|
resp = self.notifyXBMCnoJSON(host, {'title': self.default_title, 'message': message})
|
||||||
for r in resp:
|
for r in resp:
|
||||||
if r.get('result') and r['result'] == 'OK':
|
if r.get('result') and r['result'] == 'OK':
|
||||||
log.debug('Message delivered successfully!')
|
log.debug('Message delivered successfully!')
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ class Automation(Plugin):
|
|||||||
prop_name = 'automation.added.%s' % imdb_id
|
prop_name = 'automation.added.%s' % imdb_id
|
||||||
added = Env.prop(prop_name, default = False)
|
added = Env.prop(prop_name, default = False)
|
||||||
if not added:
|
if not added:
|
||||||
added_movie = fireEvent('movie.add', params = {'identifier': imdb_id}, force_readd = False, search_after = False, update_library = True, single = True)
|
added_movie = fireEvent('movie.add', params = {'identifier': imdb_id}, force_readd = False, search_after = False, update_after = True, single = True)
|
||||||
if added_movie:
|
if added_movie:
|
||||||
movie_ids.append(added_movie['id'])
|
movie_ids.append(added_movie['_id'])
|
||||||
Env.prop(prop_name, True)
|
Env.prop(prop_name, True)
|
||||||
|
|
||||||
for movie_id in movie_ids:
|
for movie_id in movie_ids:
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ class Plugin(object):
|
|||||||
http_failed_disabled = {}
|
http_failed_disabled = {}
|
||||||
http_opener = requests.Session()
|
http_opener = requests.Session()
|
||||||
|
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
new_plugin = super(Plugin, typ).__new__(typ)
|
new_plugin = super(Plugin, cls).__new__(cls)
|
||||||
new_plugin.registerPlugin()
|
new_plugin.registerPlugin()
|
||||||
|
|
||||||
return new_plugin
|
return new_plugin
|
||||||
@@ -329,7 +329,7 @@ class Plugin(object):
|
|||||||
elif data.get('password'):
|
elif data.get('password'):
|
||||||
tag += '{{%s}}' % data.get('password')
|
tag += '{{%s}}' % data.get('password')
|
||||||
|
|
||||||
max_length = 127 - len(tag) # Some filesystems don't support 128+ long filenames
|
max_length = 127 - len(tag) # Some filesystems don't support 128+ long filenames
|
||||||
return '%s%s' % (toSafeString(toUnicode(release_name)[:max_length]), tag)
|
return '%s%s' % (toSafeString(toUnicode(release_name)[:max_length]), tag)
|
||||||
|
|
||||||
def createFileName(self, data, filedata, media):
|
def createFileName(self, data, filedata, media):
|
||||||
@@ -349,6 +349,7 @@ class Plugin(object):
|
|||||||
now = time.time()
|
now = time.time()
|
||||||
file_too_new = False
|
file_too_new = False
|
||||||
|
|
||||||
|
file_time = []
|
||||||
for cur_file in files:
|
for cur_file in files:
|
||||||
|
|
||||||
# File got removed while checking
|
# File got removed while checking
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ if os.name == 'nt':
|
|||||||
raise ImportError("Missing the win32file module, which is a part of the prerequisite \
|
raise ImportError("Missing the win32file module, which is a part of the prerequisite \
|
||||||
pywin32 package. You can get it from http://sourceforge.net/projects/pywin32/files/pywin32/")
|
pywin32 package. You can get it from http://sourceforge.net/projects/pywin32/files/pywin32/")
|
||||||
else:
|
else:
|
||||||
import win32file #@UnresolvedImport
|
# noinspection PyUnresolvedReferences
|
||||||
|
import win32file
|
||||||
|
|
||||||
autoload = 'FileBrowser'
|
autoload = 'FileBrowser'
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#category_ordering li .handle {
|
#category_ordering li .handle {
|
||||||
background: url('../../static/profile_plugin/handle.png') center;
|
background: url('../../images/handle.png') center;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ var CategoryListBase = new Class({
|
|||||||
setup: function(categories){
|
setup: function(categories){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.categories = []
|
self.categories = [];
|
||||||
Array.each(categories, self.createCategory.bind(self));
|
Array.each(categories, self.createCategory.bind(self));
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -17,7 +17,7 @@ var CategoryListBase = new Class({
|
|||||||
addSettings: function(){
|
addSettings: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.settings = App.getPage('Settings')
|
self.settings = App.getPage('Settings');
|
||||||
self.settings.addEvent('create', function(){
|
self.settings.addEvent('create', function(){
|
||||||
var tab = self.settings.createSubTab('category', {
|
var tab = self.settings.createSubTab('category', {
|
||||||
'label': 'Categories',
|
'label': 'Categories',
|
||||||
@@ -31,7 +31,7 @@ var CategoryListBase = new Class({
|
|||||||
self.createList();
|
self.createList();
|
||||||
self.createOrdering();
|
self.createOrdering();
|
||||||
|
|
||||||
})
|
});
|
||||||
|
|
||||||
// Add categories in renamer
|
// Add categories in renamer
|
||||||
self.settings.addEvent('create', function(){
|
self.settings.addEvent('create', function(){
|
||||||
@@ -97,9 +97,9 @@ var CategoryListBase = new Class({
|
|||||||
createCategory: function(data){
|
createCategory: function(data){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var data = data || {'id': randomString()}
|
var data = data || {'id': randomString()};
|
||||||
var category = new Category(data)
|
var category = new Category(data);
|
||||||
self.categories.include(category)
|
self.categories.include(category);
|
||||||
|
|
||||||
return category;
|
return category;
|
||||||
},
|
},
|
||||||
@@ -108,7 +108,7 @@ var CategoryListBase = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var category_list;
|
var category_list;
|
||||||
var group = self.settings.createGroup({
|
self.settings.createGroup({
|
||||||
'label': 'Category ordering'
|
'label': 'Category ordering'
|
||||||
}).adopt(
|
}).adopt(
|
||||||
new Element('.ctrlHolder#category_ordering').adopt(
|
new Element('.ctrlHolder#category_ordering').adopt(
|
||||||
@@ -118,7 +118,7 @@ var CategoryListBase = new Class({
|
|||||||
'html': 'Change the order the categories are in the dropdown list.<br />First one will be default.'
|
'html': 'Change the order the categories are in the dropdown list.<br />First one will be default.'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).inject(self.content)
|
).inject(self.content);
|
||||||
|
|
||||||
Array.each(self.categories, function(category){
|
Array.each(self.categories, function(category){
|
||||||
new Element('li', {'data-id': category.data._id}).adopt(
|
new Element('li', {'data-id': category.data._id}).adopt(
|
||||||
@@ -145,7 +145,7 @@ var CategoryListBase = new Class({
|
|||||||
|
|
||||||
var ids = [];
|
var ids = [];
|
||||||
|
|
||||||
self.category_sortable.list.getElements('li').each(function(el, nr){
|
self.category_sortable.list.getElements('li').each(function(el){
|
||||||
ids.include(el.get('data-id'));
|
ids.include(el.get('data-id'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ var CategoryListBase = new Class({
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
});
|
||||||
|
|
||||||
window.CategoryList = new CategoryListBase();
|
window.CategoryList = new CategoryListBase();
|
||||||
|
|
||||||
@@ -235,8 +235,6 @@ var Category = new Class({
|
|||||||
if(self.save_timer) clearTimeout(self.save_timer);
|
if(self.save_timer) clearTimeout(self.save_timer);
|
||||||
self.save_timer = (function(){
|
self.save_timer = (function(){
|
||||||
|
|
||||||
var data = self.getData();
|
|
||||||
|
|
||||||
Api.request('category.save', {
|
Api.request('category.save', {
|
||||||
'data': self.getData(),
|
'data': self.getData(),
|
||||||
'useSpinner': true,
|
'useSpinner': true,
|
||||||
@@ -257,7 +255,7 @@ var Category = new Class({
|
|||||||
getData: function(){
|
getData: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var data = {
|
return {
|
||||||
'id' : self.data._id,
|
'id' : self.data._id,
|
||||||
'label' : self.el.getElement('.category_label input').get('value'),
|
'label' : self.el.getElement('.category_label input').get('value'),
|
||||||
'required' : self.el.getElement('.category_required input').get('value'),
|
'required' : self.el.getElement('.category_required input').get('value'),
|
||||||
@@ -265,8 +263,6 @@ var Category = new Class({
|
|||||||
'ignored' : self.el.getElement('.category_ignored input').get('value'),
|
'ignored' : self.el.getElement('.category_ignored input').get('value'),
|
||||||
'destination': self.data.destination
|
'destination': self.data.destination
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
|
||||||
},
|
},
|
||||||
|
|
||||||
del: function(){
|
del: function(){
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ class Dashboard(Plugin):
|
|||||||
if coming_soon:
|
if coming_soon:
|
||||||
|
|
||||||
# Don't list older movies
|
# Don't list older movies
|
||||||
if ((not late and (media['info']['year'] >= now_year-1) and (not eta.get('dvd') and not eta.get('theater') or eta.get('dvd') and eta.get('dvd') > (now - 2419200))) or
|
if ((not late and (media['info']['year'] >= now_year - 1) and (not eta.get('dvd') and not eta.get('theater') or eta.get('dvd') and eta.get('dvd') > (now - 2419200))) or
|
||||||
(late and ((media['info']['year'] < now_year-1) or ((eta.get('dvd', 0) > 0 or eta.get('theater')) and eta.get('dvd') < (now - 2419200))))):
|
(late and (media['info']['year'] < now_year - 1 or (eta.get('dvd', 0) > 0 or eta.get('theater')) and eta.get('dvd') < (now - 2419200)))):
|
||||||
medias.append(media)
|
medias.append(media)
|
||||||
|
|
||||||
if len(medias) >= limit:
|
if len(medias) >= limit:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import time
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from couchpotato import get_db
|
from couchpotato import get_db
|
||||||
@@ -64,7 +63,7 @@ class FileManager(Plugin):
|
|||||||
def download(self, url = '', dest = None, overwrite = False, urlopen_kwargs = None):
|
def download(self, url = '', dest = None, overwrite = False, urlopen_kwargs = None):
|
||||||
if not urlopen_kwargs: urlopen_kwargs = {}
|
if not urlopen_kwargs: urlopen_kwargs = {}
|
||||||
|
|
||||||
if not dest: # to Cache
|
if not dest: # to Cache
|
||||||
dest = os.path.join(Env.get('cache_dir'), '%s.%s' % (md5(url), getExt(url)))
|
dest = os.path.join(Env.get('cache_dir'), '%s.%s' % (md5(url), getExt(url)))
|
||||||
|
|
||||||
if not overwrite and os.path.isfile(dest):
|
if not overwrite and os.path.isfile(dest):
|
||||||
|
|||||||
@@ -67,14 +67,14 @@ class Logging(Plugin):
|
|||||||
if x is nr:
|
if x is nr:
|
||||||
current_path = path
|
current_path = path
|
||||||
|
|
||||||
log = ''
|
log_content = ''
|
||||||
if current_path:
|
if current_path:
|
||||||
f = open(current_path, 'r')
|
f = open(current_path, 'r')
|
||||||
log = f.read()
|
log_content = f.read()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'success': True,
|
'success': True,
|
||||||
'log': toUnicode(log),
|
'log': toUnicode(log_content),
|
||||||
'total': total,
|
'total': total,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 150%;
|
line-height: 150%;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-family: Lucida Console, Monaco, Nimbus Mono L;
|
font-family: Lucida Console, Monaco, Nimbus Mono L, monospace, serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page.log .container .error {
|
.page.log .container .error {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Page.Log = new Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).inject(nav);
|
}).inject(nav);
|
||||||
};
|
}
|
||||||
|
|
||||||
new Element('li', {
|
new Element('li', {
|
||||||
'text': 'clear',
|
'text': 'clear',
|
||||||
@@ -63,7 +63,6 @@ Page.Log = new Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
addColors: function(text){
|
addColors: function(text){
|
||||||
var self = this;
|
|
||||||
|
|
||||||
text = text
|
text = text
|
||||||
.replace(/&/g, '&')
|
.replace(/&/g, '&')
|
||||||
@@ -74,9 +73,9 @@ Page.Log = new Class({
|
|||||||
.replace(/\u001b\[36m/gi, '</span><span class="debug">')
|
.replace(/\u001b\[36m/gi, '</span><span class="debug">')
|
||||||
.replace(/\u001b\[33m/gi, '</span><span class="debug">')
|
.replace(/\u001b\[33m/gi, '</span><span class="debug">')
|
||||||
.replace(/\u001b\[0m\n/gi, '</div><div class="time">')
|
.replace(/\u001b\[0m\n/gi, '</div><div class="time">')
|
||||||
.replace(/\u001b\[0m/gi, '</span><span>')
|
.replace(/\u001b\[0m/gi, '</span><span>');
|
||||||
|
|
||||||
return '<div class="time">' + text + '</div>';
|
return '<div class="time">' + text + '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
});
|
||||||
@@ -160,7 +160,7 @@ class Manage(Plugin):
|
|||||||
except:
|
except:
|
||||||
log.error('Failed updating library: %s', (traceback.format_exc()))
|
log.error('Failed updating library: %s', (traceback.format_exc()))
|
||||||
|
|
||||||
while True and not self.shuttingDown():
|
while self.in_progress and len(self.in_progress) > 0 and not self.shuttingDown():
|
||||||
|
|
||||||
delete_me = {}
|
delete_me = {}
|
||||||
|
|
||||||
@@ -171,14 +171,12 @@ class Manage(Plugin):
|
|||||||
for delete in delete_me:
|
for delete in delete_me:
|
||||||
del self.in_progress[delete]
|
del self.in_progress[delete]
|
||||||
|
|
||||||
if len(self.in_progress) == 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
fireEvent('notify.frontend', type = 'manage.updating', data = False)
|
fireEvent('notify.frontend', type = 'manage.updating', data = False)
|
||||||
self.in_progress = False
|
self.in_progress = False
|
||||||
|
|
||||||
|
# noinspection PyDefaultArgument
|
||||||
def createAddToLibrary(self, folder, added_identifiers = []):
|
def createAddToLibrary(self, folder, added_identifiers = []):
|
||||||
|
|
||||||
def addToLibrary(group, total_found, to_go):
|
def addToLibrary(group, total_found, to_go):
|
||||||
@@ -219,7 +217,7 @@ class Manage(Plugin):
|
|||||||
pr = self.in_progress[folder]
|
pr = self.in_progress[folder]
|
||||||
pr['to_go'] -= 1
|
pr['to_go'] -= 1
|
||||||
|
|
||||||
avg = (time.time() - pr['started'])/(pr['total'] - pr['to_go'])
|
avg = (time.time() - pr['started']) / (pr['total'] - pr['to_go'])
|
||||||
pr['eta'] = tryInt(avg * pr['to_go'])
|
pr['eta'] = tryInt(avg * pr['to_go'])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ class ProfilePlugin(Plugin):
|
|||||||
'core': kwargs.get('core', False),
|
'core': kwargs.get('core', False),
|
||||||
'qualities': [],
|
'qualities': [],
|
||||||
'wait_for': [],
|
'wait_for': [],
|
||||||
'finish': []
|
'finish': [],
|
||||||
|
'3d': []
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update types
|
# Update types
|
||||||
@@ -88,6 +89,7 @@ class ProfilePlugin(Plugin):
|
|||||||
profile['qualities'].append(type.get('quality'))
|
profile['qualities'].append(type.get('quality'))
|
||||||
profile['wait_for'].append(tryInt(type.get('wait_for')))
|
profile['wait_for'].append(tryInt(type.get('wait_for')))
|
||||||
profile['finish'].append((tryInt(type.get('finish')) == 1) if order > 0 else True)
|
profile['finish'].append((tryInt(type.get('finish')) == 1) if order > 0 else True)
|
||||||
|
profile['3d'].append(tryInt(type.get('3d')))
|
||||||
order += 1
|
order += 1
|
||||||
|
|
||||||
id = kwargs.get('id')
|
id = kwargs.get('id')
|
||||||
@@ -184,6 +186,14 @@ class ProfilePlugin(Plugin):
|
|||||||
}, {
|
}, {
|
||||||
'label': 'SD',
|
'label': 'SD',
|
||||||
'qualities': ['dvdrip', 'dvdr']
|
'qualities': ['dvdrip', 'dvdr']
|
||||||
|
}, {
|
||||||
|
'label': 'Prefer 3D HD',
|
||||||
|
'qualities': ['1080p', '720p', '720p', '1080p'],
|
||||||
|
'3d': [True, True]
|
||||||
|
}, {
|
||||||
|
'label': '3D HD',
|
||||||
|
'qualities': ['1080p', '720p'],
|
||||||
|
'3d': [True, True]
|
||||||
}]
|
}]
|
||||||
|
|
||||||
# Create default quality profile
|
# Create default quality profile
|
||||||
@@ -197,12 +207,15 @@ class ProfilePlugin(Plugin):
|
|||||||
'order': order,
|
'order': order,
|
||||||
'qualities': profile.get('qualities'),
|
'qualities': profile.get('qualities'),
|
||||||
'finish': [],
|
'finish': [],
|
||||||
'wait_for': []
|
'wait_for': [],
|
||||||
|
'3d': []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
threed = profile.get('3d', [])
|
||||||
for q in profile.get('qualities'):
|
for q in profile.get('qualities'):
|
||||||
pro['finish'].append(True)
|
pro['finish'].append(True)
|
||||||
pro['wait_for'].append(0)
|
pro['wait_for'].append(0)
|
||||||
|
pro['3d'].append(threed.pop() if threed else False)
|
||||||
|
|
||||||
db.insert(pro)
|
db.insert(pro)
|
||||||
order += 1
|
order += 1
|
||||||
|
|||||||
@@ -29,11 +29,10 @@
|
|||||||
|
|
||||||
.profile .qualities {
|
.profile .qualities {
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
padding-top: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile .formHint {
|
.profile .formHint {
|
||||||
width: 250px !important;
|
width: 210px !important;
|
||||||
vertical-align: top !important;
|
vertical-align: top !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
padding-left: 3px !important;
|
padding-left: 3px !important;
|
||||||
@@ -78,21 +77,55 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.profile .quality_type select {
|
.profile .quality_type select {
|
||||||
width: 186px;
|
width: 120px;
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile .types li.is_empty .check, .profile .types li.is_empty .delete, .profile .types li.is_empty .handle {
|
.profile .types li.is_empty .check,
|
||||||
|
.profile .types li.is_empty .delete,
|
||||||
|
.profile .types li.is_empty .handle,
|
||||||
|
.profile .types li.is_empty .check_label {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.profile .types .type label {
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
float: none;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-right: 20px;
|
||||||
|
text-shadow: none;
|
||||||
|
vertical-align: bottom;
|
||||||
|
padding: 0;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
.profile .types .type label .check {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.profile .types .type label .check_label {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .types .type .threed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .types .type.allow_3d .threed {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.profile .types .type .handle {
|
.profile .types .type .handle {
|
||||||
background: url('../../static/profile_plugin/handle.png') center;
|
background: url('../../images/handle.png') center;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
cursor: -webkit-grab;
|
|
||||||
cursor: -moz-grab;
|
cursor: -moz-grab;
|
||||||
|
cursor: -webkit-grab;
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@@ -106,6 +139,9 @@
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #fd5353;
|
color: #fd5353;
|
||||||
}
|
}
|
||||||
|
.profile .types .type:not(.allow_3d) .delete {
|
||||||
|
margin-left: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
.profile .types .type:hover:not(.is_empty) .delete {
|
.profile .types .type:hover:not(.is_empty) .delete {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
@@ -144,7 +180,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#profile_ordering li .handle {
|
#profile_ordering li .handle {
|
||||||
background: url('../../static/profile_plugin/handle.png') center;
|
background: url('../../images/handle.png') center;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ var Profile = new Class({
|
|||||||
data.types.include({
|
data.types.include({
|
||||||
'quality': quality,
|
'quality': quality,
|
||||||
'finish': data.finish[nr] || false,
|
'finish': data.finish[nr] || false,
|
||||||
|
'3d': data['3d'] ? data['3d'][nr] || false : false,
|
||||||
'wait_for': data.wait_for[nr] || 0
|
'wait_for': data.wait_for[nr] || 0
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -99,7 +100,7 @@ var Profile = new Class({
|
|||||||
'onComplete': function(json){
|
'onComplete': function(json){
|
||||||
if(json.success){
|
if(json.success){
|
||||||
self.data = json.profile;
|
self.data = json.profile;
|
||||||
self.type_container.getElement('li:first-child input[type=checkbox]')
|
self.type_container.getElement('li:first-child input.finish[type=checkbox]')
|
||||||
.set('checked', true)
|
.set('checked', true)
|
||||||
.getParent().addClass('checked');
|
.getParent().addClass('checked');
|
||||||
}
|
}
|
||||||
@@ -118,16 +119,17 @@ var Profile = new Class({
|
|||||||
'label' : self.el.getElement('.quality_label input').get('value'),
|
'label' : self.el.getElement('.quality_label input').get('value'),
|
||||||
'wait_for' : self.el.getElement('.wait_for input').get('value'),
|
'wait_for' : self.el.getElement('.wait_for input').get('value'),
|
||||||
'types': []
|
'types': []
|
||||||
}
|
};
|
||||||
|
|
||||||
Array.each(self.type_container.getElements('.type'), function(type){
|
Array.each(self.type_container.getElements('.type'), function(type){
|
||||||
if(!type.hasClass('deleted') && type.getElement('select').get('value') != -1)
|
if(!type.hasClass('deleted') && type.getElement('select').get('value') != -1)
|
||||||
data.types.include({
|
data.types.include({
|
||||||
'quality': type.getElement('select').get('value'),
|
'quality': type.getElement('select').get('value'),
|
||||||
'finish': +type.getElement('input[type=checkbox]').checked,
|
'finish': +type.getElement('input.finish[type=checkbox]').checked,
|
||||||
|
'3d': +type.getElement('input.3d[type=checkbox]').checked,
|
||||||
'wait_for': 0
|
'wait_for': 0
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
@@ -240,6 +242,7 @@ Profile.Type = new Class({
|
|||||||
|
|
||||||
self.addEvent('change', function(){
|
self.addEvent('change', function(){
|
||||||
self.el[self.qualities.get('value') == '-1' ? 'addClass' : 'removeClass']('is_empty');
|
self.el[self.qualities.get('value') == '-1' ? 'addClass' : 'removeClass']('is_empty');
|
||||||
|
self.el[Quality.getQuality(self.qualities.get('value')).allow_3d ? 'addClass': 'removeClass']('allow_3d');
|
||||||
self.deleted = self.qualities.get('value') == '-1';
|
self.deleted = self.qualities.get('value') == '-1';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -250,24 +253,40 @@ Profile.Type = new Class({
|
|||||||
var data = self.data;
|
var data = self.data;
|
||||||
|
|
||||||
self.el = new Element('li.type').adopt(
|
self.el = new Element('li.type').adopt(
|
||||||
new Element('span.quality_type').adopt(
|
new Element('span.quality_type').grab(
|
||||||
self.fillQualities()
|
self.fillQualities()
|
||||||
),
|
),
|
||||||
new Element('span.finish').adopt(
|
self.finish_container = new Element('label.finish').adopt(
|
||||||
self.finish = new Element('input.inlay.finish[type=checkbox]', {
|
new Element('span.finish').grab(
|
||||||
'checked': data.finish !== undefined ? data.finish : 1,
|
self.finish = new Element('input.inlay.finish[type=checkbox]', {
|
||||||
'events': {
|
'checked': data.finish !== undefined ? data.finish : 1,
|
||||||
'change': function(e){
|
'events': {
|
||||||
if(self.el == self.el.getParent().getElement(':first-child')){
|
'change': function(){
|
||||||
self.finish_class.check();
|
if(self.el == self.el.getParent().getElement(':first-child')){
|
||||||
alert('Top quality always finishes the search')
|
self.finish_class.check();
|
||||||
return;
|
alert('Top quality always finishes the search');
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.fireEvent('change');
|
self.fireEvent('change');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
),
|
||||||
|
new Element('span.check_label[text=finish]')
|
||||||
|
),
|
||||||
|
self['3d_container'] = new Element('label.threed').adopt(
|
||||||
|
new Element('span.3d').grab(
|
||||||
|
self['3d'] = new Element('input.inlay.3d[type=checkbox]', {
|
||||||
|
'checked': data['3d'] !== undefined ? data['3d'] : 0,
|
||||||
|
'events': {
|
||||||
|
'change': function(){
|
||||||
|
self.fireEvent('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
new Element('span.check_label[text=3D]')
|
||||||
),
|
),
|
||||||
new Element('span.delete.icon2', {
|
new Element('span.delete.icon2', {
|
||||||
'events': {
|
'events': {
|
||||||
@@ -279,7 +298,11 @@ Profile.Type = new Class({
|
|||||||
|
|
||||||
self.el[self.data.quality ? 'removeClass' : 'addClass']('is_empty');
|
self.el[self.data.quality ? 'removeClass' : 'addClass']('is_empty');
|
||||||
|
|
||||||
|
if(self.data.quality && Quality.getQuality(self.data.quality).allow_3d)
|
||||||
|
self.el.addClass('allow_3d');
|
||||||
|
|
||||||
self.finish_class = new Form.Check(self.finish);
|
self.finish_class = new Form.Check(self.finish);
|
||||||
|
self['3d_class'] = new Form.Check(self['3d']);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -290,7 +313,7 @@ Profile.Type = new Class({
|
|||||||
'events': {
|
'events': {
|
||||||
'change': self.fireEvent.bind(self, 'change')
|
'change': self.fireEvent.bind(self, 'change')
|
||||||
}
|
}
|
||||||
}).adopt(
|
}).grab(
|
||||||
new Element('option', {
|
new Element('option', {
|
||||||
'text': '+ Add another quality',
|
'text': '+ Add another quality',
|
||||||
'value': -1
|
'value': -1
|
||||||
@@ -300,7 +323,8 @@ Profile.Type = new Class({
|
|||||||
Object.each(Quality.qualities, function(q){
|
Object.each(Quality.qualities, function(q){
|
||||||
new Element('option', {
|
new Element('option', {
|
||||||
'text': q.label,
|
'text': q.label,
|
||||||
'value': q.identifier
|
'value': q.identifier,
|
||||||
|
'data-allow_3d': q.allow_3d
|
||||||
}).inject(self.qualities)
|
}).inject(self.qualities)
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -316,6 +340,7 @@ Profile.Type = new Class({
|
|||||||
return {
|
return {
|
||||||
'quality': self.qualities.get('value'),
|
'quality': self.qualities.get('value'),
|
||||||
'finish': +self.finish.checked,
|
'finish': +self.finish.checked,
|
||||||
|
'3d': +self['3d'].checked,
|
||||||
'wait_for': 0
|
'wait_for': 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -338,4 +363,4 @@ Profile.Type = new Class({
|
|||||||
return this.el;
|
return this.el;
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
});
|
||||||
@@ -21,9 +21,9 @@ 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, 'allow_3d': True, 'size': (15000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25'], 'allow': ['1080p'], 'ext':[], 'tags': ['bdmv', 'certificate', ('complete', 'bluray')]},
|
||||||
{'identifier': '1080p', 'hd': True, 'size': (4000, 20000), 'label': '1080p', 'width': 1920, 'height': 1080, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts'], 'tags': ['m2ts', 'x264', 'h264']},
|
{'identifier': '1080p', 'hd': True, 'allow_3d': True, 'size': (4000, 20000), 'label': '1080p', 'width': 1920, 'height': 1080, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts'], 'tags': ['m2ts', 'x264', 'h264']},
|
||||||
{'identifier': '720p', 'hd': True, 'size': (3000, 10000), 'label': '720p', 'width': 1280, 'height': 720, 'alternative': [], 'allow': [], 'ext':['mkv', 'ts'], 'tags': ['x264', 'h264']},
|
{'identifier': '720p', 'hd': True, 'allow_3d': True, 'size': (3000, 10000), 'label': '720p', 'width': 1280, 'height': 720, 'alternative': [], 'allow': [], 'ext':['mkv', 'ts'], 'tags': ['x264', 'h264']},
|
||||||
{'identifier': 'brrip', 'hd': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p', '1080p'], 'ext':[], 'tags': ['hdtv', 'hdrip', 'webdl', ('web', 'dl')]},
|
{'identifier': 'brrip', 'hd': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p', '1080p'], 'ext':[], 'tags': ['hdtv', 'hdrip', 'webdl', ('web', 'dl')]},
|
||||||
{'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': ['br2dvd'], 'allow': [], 'ext':['iso', 'img', 'vob'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts', ('dvd', 'r')]},
|
{'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': ['br2dvd'], 'allow': [], 'ext':['iso', 'img', 'vob'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts', ('dvd', 'r')]},
|
||||||
{'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'width': 720, 'alternative': [], 'allow': [], 'ext':[], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]},
|
{'identifier': 'dvdrip', 'size': (600, 2400), 'label': 'DVD-Rip', 'width': 720, 'alternative': [], 'allow': [], 'ext':[], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]},
|
||||||
@@ -34,6 +34,11 @@ class QualityPlugin(Plugin):
|
|||||||
{'identifier': 'cam', 'size': (600, 1000), 'label': 'Cam', 'alternative': ['camrip', 'hdcam'], 'allow': [], 'ext':[]}
|
{'identifier': 'cam', 'size': (600, 1000), 'label': 'Cam', 'alternative': ['camrip', 'hdcam'], 'allow': [], 'ext':[]}
|
||||||
]
|
]
|
||||||
pre_releases = ['cam', 'ts', 'tc', 'r5', 'scr']
|
pre_releases = ['cam', 'ts', 'tc', 'r5', 'scr']
|
||||||
|
threed_tags = {
|
||||||
|
'hsbs': [('half', 'sbs')],
|
||||||
|
'fsbs': [('full', 'sbs')],
|
||||||
|
'3d': [],
|
||||||
|
}
|
||||||
|
|
||||||
cached_qualities = None
|
cached_qualities = None
|
||||||
cached_order = None
|
cached_order = None
|
||||||
@@ -58,6 +63,7 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
addEvent('app.test', self.doTest)
|
addEvent('app.test', self.doTest)
|
||||||
|
|
||||||
|
self.order = []
|
||||||
self.addOrder()
|
self.addOrder()
|
||||||
|
|
||||||
def addOrder(self):
|
def addOrder(self):
|
||||||
@@ -185,14 +191,19 @@ class QualityPlugin(Plugin):
|
|||||||
# Start with 0
|
# Start with 0
|
||||||
score = {}
|
score = {}
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
score[quality.get('identifier')] = 0
|
score[quality.get('identifier')] = {
|
||||||
|
'score': 0,
|
||||||
|
'3d': {}
|
||||||
|
}
|
||||||
|
|
||||||
for cur_file in files:
|
for cur_file in files:
|
||||||
words = re.split('\W+', cur_file.lower())
|
words = re.split('\W+', cur_file.lower())
|
||||||
|
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
contains_score = self.containsTagScore(quality, words, cur_file)
|
contains_score = self.containsTagScore(quality, words, cur_file)
|
||||||
self.calcScore(score, quality, contains_score)
|
threedscore = self.contains3D(quality, words, cur_file) if quality.get('allow_3d') else (0, None)
|
||||||
|
|
||||||
|
self.calcScore(score, quality, contains_score, threedscore)
|
||||||
|
|
||||||
# Try again with loose testing
|
# Try again with loose testing
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
@@ -208,10 +219,13 @@ class QualityPlugin(Plugin):
|
|||||||
if not has_non_zero:
|
if not has_non_zero:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
heighest_quality = max(score, key = score.get)
|
heighest_quality = max(score, key = lambda p: score[p]['score'])
|
||||||
if heighest_quality:
|
if heighest_quality:
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
if quality.get('identifier') == heighest_quality:
|
if quality.get('identifier') == heighest_quality:
|
||||||
|
quality['is_3d'] = False
|
||||||
|
if score[heighest_quality].get('3d'):
|
||||||
|
quality['is_3d'] = True
|
||||||
return self.setCache(cache_key, quality)
|
return self.setCache(cache_key, quality)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@@ -234,12 +248,12 @@ class QualityPlugin(Plugin):
|
|||||||
qualities = [qualities] if isinstance(qualities, (str, unicode)) else qualities
|
qualities = [qualities] if isinstance(qualities, (str, unicode)) else qualities
|
||||||
|
|
||||||
for alt in qualities:
|
for alt in qualities:
|
||||||
if (isinstance(alt, tuple)):
|
if isinstance(alt, tuple):
|
||||||
if len(set(words) & set(alt)) == len(alt):
|
if len(set(words) & set(alt)) == len(alt):
|
||||||
log.debug('Found %s via %s %s in %s', (quality['identifier'], tag_type, quality.get(tag_type), cur_file))
|
log.debug('Found %s via %s %s in %s', (quality['identifier'], tag_type, quality.get(tag_type), cur_file))
|
||||||
score += points.get(tag_type)
|
score += points.get(tag_type)
|
||||||
|
|
||||||
if (isinstance(alt, (str, unicode)) and ss(alt.lower()) in cur_file.lower()):
|
if isinstance(alt, (str, unicode)) and ss(alt.lower()) in cur_file.lower():
|
||||||
log.debug('Found %s via %s %s in %s', (quality['identifier'], tag_type, quality.get(tag_type), cur_file))
|
log.debug('Found %s via %s %s in %s', (quality['identifier'], tag_type, quality.get(tag_type), cur_file))
|
||||||
score += points.get(tag_type) / 2
|
score += points.get(tag_type) / 2
|
||||||
|
|
||||||
@@ -255,6 +269,23 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
|
def contains3D(self, quality, words, cur_file = ''):
|
||||||
|
cur_file = ss(cur_file)
|
||||||
|
|
||||||
|
for key in self.threed_tags:
|
||||||
|
tags = self.threed_tags.get(key, [])
|
||||||
|
|
||||||
|
for tag in tags:
|
||||||
|
if (isinstance(tag, tuple) and '.'.join(tag) in '.'.join(words)) or (isinstance(tag, (str, unicode)) and ss(tag.lower()) in cur_file.lower()):
|
||||||
|
log.debug('Found %s in %s', (tag, cur_file))
|
||||||
|
return 1, key
|
||||||
|
|
||||||
|
if list(set([key]) & set(words)):
|
||||||
|
log.debug('Found %s in %s', (tag, cur_file))
|
||||||
|
return 1, key
|
||||||
|
|
||||||
|
return 0, None
|
||||||
|
|
||||||
def guessLooseScore(self, quality, extra = None):
|
def guessLooseScore(self, quality, extra = None):
|
||||||
|
|
||||||
score = 0
|
score = 0
|
||||||
@@ -277,9 +308,16 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
def calcScore(self, score, quality, add_score):
|
def calcScore(self, score, quality, add_score, threedscore = (0, None)):
|
||||||
|
|
||||||
score[quality['identifier']] += add_score
|
score[quality['identifier']]['score'] += add_score
|
||||||
|
|
||||||
|
threedscore, threedtag = threedscore
|
||||||
|
if threedscore and threedtag:
|
||||||
|
if threedscore not in score[quality['identifier']]['3d']:
|
||||||
|
score[quality['identifier']]['3d'][threedtag] = 0
|
||||||
|
|
||||||
|
score[quality['identifier']]['3d'][threedtag] += threedscore
|
||||||
|
|
||||||
# Set order for allow calculation (and cache)
|
# Set order for allow calculation (and cache)
|
||||||
if not self.cached_order:
|
if not self.cached_order:
|
||||||
@@ -289,7 +327,7 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
if add_score != 0:
|
if add_score != 0:
|
||||||
for allow in quality.get('allow', []):
|
for allow in quality.get('allow', []):
|
||||||
score[allow] -= 40 if self.cached_order[allow] < self.cached_order[quality['identifier']] else 5
|
score[allow]['score'] -= 40 if self.cached_order[allow] < self.cached_order[quality['identifier']] else 5
|
||||||
|
|
||||||
def doTest(self):
|
def doTest(self):
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ var QualityBase = new Class({
|
|||||||
|
|
||||||
self.qualities = data.qualities;
|
self.qualities = data.qualities;
|
||||||
|
|
||||||
self.profiles = []
|
self.profiles = [];
|
||||||
Array.each(data.profiles, self.createProfilesClass.bind(self));
|
Array.each(data.profiles, self.createProfilesClass.bind(self));
|
||||||
|
|
||||||
App.addEvent('load', self.addSettings.bind(self))
|
App.addEvent('load', self.addSettings.bind(self))
|
||||||
@@ -37,7 +37,7 @@ var QualityBase = new Class({
|
|||||||
addSettings: function(){
|
addSettings: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.settings = App.getPage('Settings')
|
self.settings = App.getPage('Settings');
|
||||||
self.settings.addEvent('create', function(){
|
self.settings.addEvent('create', function(){
|
||||||
var tab = self.settings.createSubTab('profile', {
|
var tab = self.settings.createSubTab('profile', {
|
||||||
'label': 'Quality',
|
'label': 'Quality',
|
||||||
@@ -91,9 +91,9 @@ var QualityBase = new Class({
|
|||||||
createProfilesClass: function(data){
|
createProfilesClass: function(data){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var data = data || {'id': randomString()}
|
var data = data || {'id': randomString()};
|
||||||
var profile = new Profile(data)
|
var profile = new Profile(data);
|
||||||
self.profiles.include(profile)
|
self.profiles.include(profile);
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
},
|
},
|
||||||
@@ -102,7 +102,7 @@ var QualityBase = new Class({
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var profile_list;
|
var profile_list;
|
||||||
var group = self.settings.createGroup({
|
self.settings.createGroup({
|
||||||
'label': 'Profile Defaults',
|
'label': 'Profile Defaults',
|
||||||
'description': '(Needs refresh \'' +(App.isMac() ? 'CMD+R' : 'F5')+ '\' after editing)'
|
'description': '(Needs refresh \'' +(App.isMac() ? 'CMD+R' : 'F5')+ '\' after editing)'
|
||||||
}).adopt(
|
}).adopt(
|
||||||
@@ -113,7 +113,7 @@ var QualityBase = new Class({
|
|||||||
'html': 'Change the order the profiles are in the dropdown list. Uncheck to hide it completely.<br />First one will be default.'
|
'html': 'Change the order the profiles are in the dropdown list. Uncheck to hide it completely.<br />First one will be default.'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
).inject(self.content)
|
).inject(self.content);
|
||||||
|
|
||||||
Array.each(self.profiles, function(profile){
|
Array.each(self.profiles, function(profile){
|
||||||
var check;
|
var check;
|
||||||
@@ -175,14 +175,14 @@ var QualityBase = new Class({
|
|||||||
'description': 'Edit the minimal and maximum sizes (in MB) for each quality.',
|
'description': 'Edit the minimal and maximum sizes (in MB) for each quality.',
|
||||||
'advanced': true,
|
'advanced': true,
|
||||||
'name': 'sizes'
|
'name': 'sizes'
|
||||||
}).inject(self.content)
|
}).inject(self.content);
|
||||||
|
|
||||||
|
|
||||||
new Element('div.item.head.ctrlHolder').adopt(
|
new Element('div.item.head.ctrlHolder').adopt(
|
||||||
new Element('span.label', {'text': 'Quality'}),
|
new Element('span.label', {'text': 'Quality'}),
|
||||||
new Element('span.min', {'text': 'Min'}),
|
new Element('span.min', {'text': 'Min'}),
|
||||||
new Element('span.max', {'text': 'Max'})
|
new Element('span.max', {'text': 'Max'})
|
||||||
).inject(group)
|
).inject(group);
|
||||||
|
|
||||||
Array.each(self.qualities, function(quality){
|
Array.each(self.qualities, function(quality){
|
||||||
new Element('div.ctrlHolder.item').adopt(
|
new Element('div.ctrlHolder.item').adopt(
|
||||||
|
|||||||
Loaded 100 of 124 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user