Spring cleanup

This commit is contained in:
Ruud
2014-03-29 23:44:14 +01:00
parent 83c5d701b3
commit 99e77e409a
98 changed files with 469 additions and 489 deletions
+5 -4
View File
@@ -15,6 +15,7 @@ log = CPLog(__name__)
views = {}
template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates'))
class BaseHandler(RequestHandler):
def get_current_user(self):
@@ -54,7 +55,7 @@ def get_db():
# Web view
def index():
return template_loader.load('index.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env)
return template_loader.load('index.thtml').generate(sep = os.sep, fireEvent = fireEvent, Env = Env)
addView('', index)
@@ -66,14 +67,14 @@ def apiDocs():
del api_docs['']
del api_docs_missing['']
return template_loader.load('api.html').generate(fireEvent = fireEvent, routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing), Env = Env)
return template_loader.load('api.thtml').generate(fireEvent = fireEvent, routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing), Env = Env)
addView('docs', apiDocs)
# Database debug manager
def databaseManage():
return template_loader.load('database.html').generate(fireEvent = fireEvent, Env = Env)
return template_loader.load('database.thtml').generate(fireEvent = fireEvent, Env = Env)
addView('database', databaseManage)
@@ -107,7 +108,7 @@ class LoginHandler(BaseHandler):
if self.get_current_user():
self.redirect(Env.get('web_base'))
else:
self.write(template_loader.load('login.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env))
self.write(template_loader.load('login.thtml').generate(sep = os.sep, fireEvent = fireEvent, Env = Env))
def post(self, *args, **kwargs):
+1 -1
View File
@@ -189,7 +189,7 @@ class Core(Plugin):
def signalHandler(self):
if Env.get('daemonized'): return
def signal_handler(signal, frame):
def signal_handler(*args, **kwargs):
fireEvent('app.shutdown', single = True)
signal.signal(signal.SIGINT, signal_handler)
+4 -5
View File
@@ -57,13 +57,12 @@ class ClientScript(Plugin):
],
}
urls = {'style': {}, 'script': {}}
minified = {'style': {}, 'script': {}}
paths = {'style': {}, 'script': {}}
comment = {
'style': '/*** %s:%d ***/\n',
'script': '// %s:%d\n'
'style': '/*** %s:%d ***/\n',
'script': '// %s:%d\n'
}
html = {
@@ -95,7 +94,6 @@ class ClientScript(Plugin):
else:
self.registerStyle(core_url, file_path, position = 'front')
def minify(self):
# Create cache dir
@@ -129,7 +127,7 @@ class ClientScript(Plugin):
data = cssmin(data)
data = data.replace('../images/', '../static/images/')
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})
@@ -192,6 +190,7 @@ class ClientScript(Plugin):
prefix_properties = ['border-radius', 'transform', 'transition', 'box-shadow']
prefix_tags = ['ms', 'moz', 'webkit']
def prefix(self, data):
trimmed_data = re.sub('(\t|\n|\r)+', '', data)
+3 -3
View File
@@ -164,14 +164,14 @@ class BaseUpdater(Plugin):
def info(self):
version = self.getVersion()
current_version = self.getVersion()
return {
'last_check': self.last_check,
'update_version': self.update_version,
'version': version,
'version': current_version,
'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):
@@ -5,7 +5,7 @@ var UpdaterBase = new Class({
initialize: function(){
var self = this;
App.addEvent('load', self.info.bind(self, 2000))
App.addEvent('load', self.info.bind(self, 2000));
App.addEvent('unload', function(){
if(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;
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(
new Element('span', {
-2
View File
@@ -116,7 +116,6 @@ class Database(object):
results[key] = []
results[key].append(document)
return results
def reindex(self, **kwargs):
@@ -473,7 +472,6 @@ class Database(object):
log.info('Total migration took %s', time.time() - migrate_start)
log.info('=' * 30)
# rename old database
log.info('Renaming old database to %s ', old_db + '.old')
os.rename(old_db, old_db + '.old')
+1
View File
@@ -188,6 +188,7 @@ class Downloader(Provider):
def pause(self, release_download, pause):
return
class ReleaseDownloadList(list):
provider = None
+1 -1
View File
@@ -146,7 +146,7 @@ class NZBGet(Downloader):
'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:
log.debug('Found %s in NZBGet postprocessing queue', nzb['NZBFilename'])
release_downloads.append({
@@ -14,6 +14,7 @@ log = CPLog(__name__)
autoload = 'qBittorrent'
class qBittorrent(Downloader):
protocol = ['torrent', 'torrent_magnet']
+3 -3
View File
@@ -78,10 +78,10 @@ class rTorrent(Downloader):
self.error_msg = ''
try:
self.rt._verify_conn()
self.rt._verify_conn()
except AssertionError as e:
self.error_msg = e.message
self.rt = None
self.error_msg = e.message
self.rt = None
return self.rt
@@ -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 ''))
return self.trpc.remove_torrent(release_download['id'], delete_files)
class TransmissionRPC(object):
"""TransmissionRPC lite library"""
+8 -8
View File
@@ -29,14 +29,14 @@ class uTorrent(Downloader):
protocol = ['torrent', 'torrent_magnet']
utorrent_api = None
status_flags = {
'STARTED' : 1,
'CHECKING' : 2,
'CHECK-START' : 4,
'CHECKED' : 8,
'ERROR' : 16,
'PAUSED' : 32,
'QUEUED' : 64,
'LOADED' : 128
'STARTED': 1,
'CHECKING': 2,
'CHECK-START': 4,
'CHECKED': 8,
'ERROR': 16,
'PAUSED': 32,
'QUEUED': 64,
'LOADED': 128
}
def connect(self):
+2 -1
View File
@@ -2,7 +2,7 @@ from urllib import unquote
import re
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):
@@ -44,6 +44,7 @@ def getParams(params):
return dictToList(temp)
non_decimal = re.compile(r'[^\d.]+')
def dictToList(params):
if type(params) is dict:
+4 -3
View File
@@ -216,6 +216,7 @@ def tryFloat(s):
return float(s)
except: return 0
def natsortKey(string_):
"""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_)]
@@ -247,9 +248,6 @@ def getTitle(media_dict):
except:
log.error('Could not get title for %s', getIdentifier(media_dict))
return None
log.error('Could not get title for %s', getIdentifier(media_dict))
return None
except:
log.error('Could not get title for library item: %s', media_dict)
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
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
re_password = [re.compile(r'(.+){{([^{}]+)}}$'), re.compile(r'(.+)\s+password\s*=\s*(.+)$', re.I)]
def scanForPassword(name):
m = None
for reg in re_password:
+8 -5
View File
@@ -12,19 +12,22 @@ log = CPLog(__name__)
class Loader(object):
plugins = {}
providers = {}
modules = {}
def __init__(self):
self.plugins = {}
self.providers = {}
self.modules = {}
self.paths = {}
def preload(self, root = ''):
core = os.path.join(root, 'couchpotato', 'core')
self.paths = {
self.paths.update({
'core': (0, 'couchpotato.core._base', os.path.join(core, '_base')),
'plugin': (1, 'couchpotato.core.plugins', os.path.join(core, 'plugins')),
'notifications': (20, 'couchpotato.core.notifications', os.path.join(core, 'notifications')),
'downloaders': (20, 'couchpotato.core.downloaders', os.path.join(core, 'downloaders')),
}
})
# Add media to loader
self.addPath(root, ['couchpotato', 'core', 'media'], 25, recursive = True)
+1
View File
@@ -5,6 +5,7 @@ from couchpotato import get_db, CPLog
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
from couchpotato.core.helpers.encoding import toUnicode
from couchpotato.core.plugins.base import Plugin
import six
log = CPLog(__name__)
@@ -1,5 +1,6 @@
from .main import Library
def autoload():
return Library()
@@ -1,5 +1,6 @@
from .main import Matcher
def autoload():
return Matcher()
+3 -5
View File
@@ -222,7 +222,6 @@ class MediaPlugin(MediaBase):
del filter_by['media_status']
del filter_by['release_status']
# Filter by combining ids
for x in filter_by:
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):
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)
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):
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)
def delete(self, media_id, delete_from = None):
@@ -382,9 +381,8 @@ class MediaPlugin(MediaBase):
if release.get('status') == 'done':
db.delete(release)
total_deleted += 1
new_media_status = 'active'
if total_releases == total_deleted:
if total_releases == total_deleted and media['status'] != 'active':
db.delete(media)
deleted = True
elif new_media_status:
@@ -18,7 +18,7 @@ class Base(NZBProvider):
'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):
@@ -28,7 +28,7 @@ class Base(NZBProvider):
try:
html = BeautifulSoup(data)
main_table = html.find('table', attrs = {'id':'r2'})
main_table = html.find('table', attrs = {'id': 'r2'})
if not main_table:
return
@@ -36,11 +36,11 @@ class Base(NZBProvider):
items = main_table.find_all('tr')
for row in items:
title = row.find('span', attrs = {'class':'s'})
title = row.find('span', attrs = {'class': 's'})
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'})
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',
}
http_time_between_calls = 4 #seconds
http_time_between_calls = 4 # seconds
def _search(self, media, quality, results):
@@ -55,7 +55,7 @@ class Base(NZBProvider, RSS):
def getMoreInfo(self, item):
full_description = self.getCache('nzbclub.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
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 ''
item['description'] = description
@@ -91,7 +91,7 @@ class Base(NZBProvider, RSS):
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)
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:
pass
@@ -20,7 +20,7 @@ class Base(NZBProvider, RSS):
'detail_url': 'https://omgwtfnzbs.org/details.php?id=%s',
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
cat_ids = [
([15], ['dvdrip']),
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
}
# 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):
@@ -40,7 +40,7 @@ class Base(TorrentProvider):
html = BeautifulSoup(data)
try:
result_table = html.find('table', attrs = {'width' : '750', 'class' : ''})
result_table = html.find('table', attrs = {'width': '750', 'class': ''})
if result_table is None:
return
@@ -74,7 +74,7 @@ class Base(TorrentProvider):
def getMoreInfo(self, item):
full_description = self.getCache('bithdtv.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
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 ''
item['description'] = description
@@ -20,7 +20,7 @@ class Base(TorrentProvider):
'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):
@@ -30,7 +30,7 @@ class Base(TorrentProvider):
})
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)
if data:
@@ -74,7 +74,6 @@ class Base(TorrentProvider):
except:
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
def getLoginParams(self):
return {
'username': self.conf('username'),
@@ -82,7 +81,6 @@ class Base(TorrentProvider):
'ssl': 'yes',
}
def loginSuccess(self, output):
return 'logout.php' in output.lower()
@@ -19,7 +19,7 @@ class Base(TorrentProvider):
'api': 'https://hdbits.org/api/torrents'
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
def _post_query(self, **params):
@@ -56,7 +56,7 @@ class Base(TorrentProvider):
'name': result['name'],
'url': self.urls['download'] % (result['id'], self.conf('passkey')),
'detail_url': self.urls['detail'] % result['id'],
'size': tryInt(result['size'])/1024/1024,
'size': tryInt(result['size']) / 1024 / 1024,
'seeders': tryInt(result['seeders']),
'leechers': tryInt(result['leechers'])
})
@@ -23,9 +23,9 @@ class Base(TorrentProvider):
}
cat_ids = [
(['41'], ['720p', '1080p', 'brrip']),
(['19'], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
(['20'], ['dvdr'])
(['41'], ['720p', '1080p', 'brrip']),
(['19'], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
(['20'], ['dvdr'])
]
cat_backup_id = 200
@@ -79,7 +79,7 @@ class Base(TorrentProvider):
return confirmed + trusted + vip + moderated
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)
results.append({
@@ -113,7 +113,7 @@ class Base(TorrentProvider):
try:
full_description = self.getHTMLData(item['detail_url'])
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 ''
except:
log.error('Failed getting more info for %s', item['name'])
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
'search': 'https://www.iptorrents.com/torrents/?l%d=1%s&q=%s&qf=ti&p=%d',
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
cat_backup_id = None
def buildUrl(self, title, media, quality):
@@ -53,14 +53,14 @@ class Base(TorrentProvider):
html = BeautifulSoup(data)
try:
page_nav = html.find('span', attrs = {'class' : 'page_nav'})
page_nav = html.find('span', attrs = {'class': 'page_nav'})
if page_nav:
next_link = page_nav.find("a", text = "Next")
if next_link:
final_page_link = next_link.previous_sibling.previous_sibling
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():
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_details_url = self.urls['base_url'] + torrent['href']
torrent_size = self.parseSize(result.find_all('td')[5].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_seeders = tryInt(result.find('td', attrs = {'class': 'ac t_seeders'}).string)
torrent_leechers = tryInt(result.find('td', attrs = {'class': 'ac t_leechers'}).string)
results.append({
'id': torrent_id,
@@ -26,7 +26,7 @@ class Base(TorrentMagnetProvider):
(['dvd'], ['dvdr']),
]
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
cat_backup_id = None
proxy_list = [
@@ -18,12 +18,12 @@ log = CPLog(__name__)
class Base(TorrentProvider):
urls = {
'domain': 'https://tls.passthepopcorn.me',
'detail': 'https://tls.passthepopcorn.me/torrents.php?torrentid=%s',
'torrent': 'https://tls.passthepopcorn.me/torrents.php',
'login': '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'
'domain': 'https://tls.passthepopcorn.me',
'detail': 'https://tls.passthepopcorn.me/torrents.php?torrentid=%s',
'torrent': 'https://tls.passthepopcorn.me/torrents.php',
'login': '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'
}
http_time_between_calls = 2
@@ -136,23 +136,23 @@ class Base(TorrentProvider):
def htmlToUnicode(self, text):
def fixup(m):
text = m.group(0)
if text[:2] == "&#":
txt = m.group(0)
if txt[:2] == "&#":
# character reference
try:
if text[:3] == "&#x":
return unichr(int(text[3:-1], 16))
if txt[:3] == "&#x":
return unichr(int(txt[3:-1], 16))
else:
return unichr(int(text[2:-1]))
return unichr(int(txt[2:-1]))
except ValueError:
pass
else:
# named entity
try:
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
txt = unichr(htmlentitydefs.name2codepoint[txt[1:-1]])
except KeyError:
pass
return text # leave as is
return txt # leave as is
return re.sub("&#?\w+;", fixup, six.u('%s') % text)
def unicodeToASCII(self, text):
@@ -164,11 +164,11 @@ class Base(TorrentProvider):
def getLoginParams(self):
return {
'username': self.conf('username'),
'password': self.conf('password'),
'passkey': self.conf('passkey'),
'keeplogged': '1',
'login': 'Login'
'username': self.conf('username'),
'password': self.conf('password'),
'passkey': self.conf('passkey'),
'keeplogged': '1',
'login': 'Login'
}
def loginSuccess(self, output):
@@ -34,7 +34,7 @@ class Base(TorrentMagnetProvider):
query = self.buildUrl(media)
params = tryUrlencode({
'page':'torrents',
'page': 'torrents',
'search': query,
'active': 1,
})
@@ -22,7 +22,7 @@ class Base(TorrentProvider):
'download': 'https://www.sceneaccess.eu/%s',
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
def _search(self, media, quality, results):
@@ -33,16 +33,16 @@ class Base(TorrentProvider):
html = BeautifulSoup(data)
try:
resultsTable = html.find('table', attrs = {'id' : 'torrents-table'})
resultsTable = html.find('table', attrs = {'id': 'torrents-table'})
if resultsTable is None:
return
entries = resultsTable.find_all('tr', attrs = {'class' : 'tt_row'})
entries = resultsTable.find_all('tr', attrs = {'class': 'tt_row'})
for result in entries:
link = result.find('td', attrs = {'class' : 'ttr_name'}).find('a')
url = result.find('td', attrs = {'class' : 'td_dl'}).find('a')
leechers = result.find('td', attrs = {'class' : 'ttr_leechers'}).find('a')
link = result.find('td', attrs = {'class': 'ttr_name'}).find('a')
url = result.find('td', attrs = {'class': 'td_dl'}).find('a')
leechers = result.find('td', attrs = {'class': 'ttr_leechers'}).find('a')
torrent_id = link['href'].replace('details?id=', '')
results.append({
@@ -50,8 +50,8 @@ class Base(TorrentProvider):
'name': link['title'],
'url': self.urls['download'] % url['href'],
'detail_url': self.urls['detail'] % torrent_id,
'size': self.parseSize(result.find('td', attrs = {'class' : 'ttr_size'}).contents[0]),
'seeders': tryInt(result.find('td', attrs = {'class' : 'ttr_seeders'}).find('a').string),
'size': self.parseSize(result.find('td', attrs = {'class': 'ttr_size'}).contents[0]),
'seeders': tryInt(result.find('td', attrs = {'class': 'ttr_seeders'}).find('a').string),
'leechers': tryInt(leechers.string) if leechers else 0,
'get_more_info': self.getMoreInfo,
})
@@ -62,7 +62,7 @@ class Base(TorrentProvider):
def getMoreInfo(self, item):
full_description = self.getCache('sceneaccess.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
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 ''
item['description'] = description
@@ -108,7 +108,7 @@ class Base(TorrentMagnetProvider):
def getMoreInfo(self, item):
full_description = self.getCache('tpb.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
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 ''
item['description'] = description
@@ -31,7 +31,7 @@ class Base(TorrentProvider):
([20], ['dvdr']),
]
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
cat_backup_id = None
def _searchOnTitle(self, title, movie, quality, results):
@@ -43,7 +43,7 @@ class Base(TorrentProvider):
html = BeautifulSoup(data)
try:
result_table = html.find('table', attrs = {'border' : '1'})
result_table = html.find('table', attrs = {'border': '1'})
if not result_table:
return
@@ -52,7 +52,7 @@ class Base(TorrentProvider):
for result in entries[1:]:
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=', '')
torrent_id = full_id[:6]
@@ -16,7 +16,7 @@ class Base(TorrentProvider):
'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):
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
'download': 'http://www.torrentleech.org%s',
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
cat_backup_id = None
def _search(self, media, quality, results):
@@ -34,7 +34,7 @@ class Base(TorrentProvider):
html = BeautifulSoup(data)
try:
result_table = html.find('table', attrs = {'id' : 'torrenttable'})
result_table = html.find('table', attrs = {'id': 'torrenttable'})
if not result_table:
return
@@ -42,9 +42,9 @@ class Base(TorrentProvider):
for result in entries[1:]:
link = result.find('td', attrs = {'class' : 'name'}).find('a')
url = result.find('td', attrs = {'class' : 'quickdownload'}).find('a')
details = 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')
details = result.find('td', attrs = {'class': 'name'}).find('a')
results.append({
'id': link['href'].replace('/torrent/', ''),
@@ -52,8 +52,8 @@ class Base(TorrentProvider):
'url': self.urls['download'] % url['href'],
'detail_url': self.urls['download'] % details['href'],
'size': self.parseSize(result.find_all('td')[4].string),
'seeders': tryInt(result.find('td', attrs = {'class' : 'seeders'}).string),
'leechers': tryInt(result.find('td', attrs = {'class' : 'leechers'}).string),
'seeders': tryInt(result.find('td', attrs = {'class': 'seeders'}).string),
'leechers': tryInt(result.find('td', attrs = {'class': 'leechers'}).string),
})
except:
@@ -21,7 +21,7 @@ class Base(TorrentProvider):
'download': 'https://torrentshack.net/%s',
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # Seconds
def _search(self, media, quality, results):
@@ -32,16 +32,16 @@ class Base(TorrentProvider):
html = BeautifulSoup(data)
try:
result_table = html.find('table', attrs = {'id' : 'torrent_table'})
result_table = html.find('table', attrs = {'id': 'torrent_table'})
if not result_table:
return
entries = result_table.find_all('tr', attrs = {'class' : 'torrent'})
entries = result_table.find_all('tr', attrs = {'class': 'torrent'})
for result in entries:
link = result.find('span', attrs = {'class' : 'torrent_name_link'}).parent
url = result.find('td', attrs = {'class' : 'torrent_td'}).find('a')
link = result.find('span', attrs = {'class': 'torrent_name_link'}).parent
url = result.find('td', attrs = {'class': 'torrent_td'}).find('a')
results.append({
'id': link['href'].replace('torrents.php?torrentid=', ''),
@@ -16,7 +16,7 @@ class Base(TorrentProvider):
'detail': '%s/api/movie.json?id=%s'
}
http_time_between_calls = 1 #seconds
http_time_between_calls = 1 # seconds
proxy_list = [
'http://yify.unlocktorrent.com',
@@ -6,12 +6,11 @@
top: 0;
text-align: right;
height: 100%;
border-bottom: 4px solid transparent;
transition: all .4s cubic-bezier(0.9,0,0.1,1);
position: absolute;
z-index: 20;
border: 1px solid transparent;
border-width: 0 0 4px;
border: 0 solid transparent;
border-bottom-width: 4px;
}
.search_form:hover {
border-color: #047792;
@@ -22,19 +21,19 @@
right: 44px;
}
}
.search_form.focused,
.search_form.shown {
border-color: #04bce6;
}
.search_form .input {
height: 100%;
overflow: hidden;
width: 45px;
transition: all .4s cubic-bezier(0.9,0,0.1,1);
}
.search_form.focused .input,
.search_form.shown .input {
width: 380px;
@@ -49,7 +48,6 @@
color: #FFF;
font-size: 25px;
height: 100%;
padding: 10px;
width: 100%;
opacity: 0;
padding: 0 40px 0 10px;
@@ -59,23 +57,23 @@
.search_form.shown .input input {
opacity: 1;
}
.search_form input::-ms-clear {
width : 0;
height: 0;
}
@media all and (max-width: 480px) {
.search_form .input input {
font-size: 15px;
}
.search_form.focused .input,
.search_form.shown .input {
width: 277px;
}
}
.search_form .input a {
position: absolute;
top: 0;
@@ -89,7 +87,7 @@
font-size: 15px;
color: #FFF;
}
.search_form .input a:after {
content: "\e03e";
}
@@ -97,7 +95,7 @@
.search_form.shown.filled .input a:after {
content: "\e04e";
}
@media all and (max-width: 480px) {
.search_form .input a {
line-height: 44px;
@@ -167,13 +165,13 @@
.media_result .options select[name=title] { width: 170px; }
.media_result .options select[name=profile] { width: 90px; }
.media_result .options select[name=category] { width: 80px; }
@media all and (max-width: 480px) {
.media_result .options select[name=title] { width: 90px; }
.media_result .options select[name=profile] { width: 50px; }
.media_result .options select[name=category] { width: 50px; }
}
.media_result .options .button {
@@ -227,14 +225,14 @@
right: 7px;
vertical-align: middle;
}
.media_result .info h2 {
margin: 0;
font-weight: normal;
font-size: 20px;
padding: 0;
}
.search_form .info h2 {
position: absolute;
width: 100%;
@@ -247,12 +245,12 @@
overflow: hidden;
white-space: nowrap;
}
.search_form .info h2 .title {
position: absolute;
width: 88%;
}
.media_result .info h2 .year {
padding: 0 5px;
text-align: center;
@@ -260,14 +258,14 @@
width: 12%;
right: 0;
}
@media all and (max-width: 480px) {
.search_form .info h2 .year {
font-size: 12px;
margin-top: 7px;
}
}
.search_form .mask,
@@ -277,4 +275,4 @@
width: 100%;
left: 0;
top: 0;
}
}
@@ -16,7 +16,7 @@ Block.Search = new Class({
'keyup': self.keyup.bind(self),
'focus': function(){
if(focus_timer) clearTimeout(focus_timer);
self.el.addClass('focused')
self.el.addClass('focused');
if(this.get('value'))
self.hideResults(false)
},
@@ -57,17 +57,17 @@ Block.Search = new Class({
(e).preventDefault();
if(self.last_q === ''){
self.input.blur()
self.input.blur();
self.last_q = null;
}
else {
self.last_q = '';
self.input.set('value', '');
self.input.focus()
self.input.focus();
self.media = {}
self.results.empty()
self.media = {};
self.results.empty();
self.el.removeClass('filled')
}
@@ -92,16 +92,16 @@ Block.Search = new Class({
self.hidden = bool;
},
keyup: function(e){
keyup: function(){
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.api_request && self.api_request.isRunning())
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)
}
@@ -111,7 +111,7 @@ Block.Search = new Class({
var self = this;
if(!self.q()){
self.hideResults(true)
self.hideResults(true);
return
}
@@ -139,7 +139,7 @@ Block.Search = new Class({
})
}
else
self.fill(q, cache)
self.fill(q, cache);
self.last_q = q;
@@ -148,31 +148,31 @@ Block.Search = new Class({
fill: function(q, json){
var self = this;
self.cache[q] = json
self.cache[q] = json;
self.media = {}
self.results.empty()
Object.each(json, function(media, type){
self.media = {};
self.results.empty();
Object.each(json, function(media){
if(typeOf(media) == 'array'){
Object.each(media, function(m){
var m = new Block.Search[m.type.capitalize() + 'Item'](m);
$(m).inject(self.results)
self.media[m.imdb || 'r-'+Math.floor(Math.random()*10000)] = m
$(m).inject(self.results);
self.media[m.imdb || 'r-'+Math.floor(Math.random()*10000)] = m;
if(q == m.imdb)
m.showOptions()
});
}
})
});
// Calculate result heights
var w = window.getSize(),
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')
},
@@ -185,4 +185,4 @@ Block.Search = new Class({
return this.input.get('value').trim();
}
});
});
@@ -14,6 +14,7 @@ log = CPLog(__name__)
class Searcher(SearcherBase):
# noinspection PyMissingConstructor
def __init__(self):
addEvent('searcher.protocols', self.getSearchProtocols)
addEvent('searcher.contains_other_quality', self.containsOtherQuality)
@@ -195,7 +196,7 @@ class Searcher(SearcherBase):
req = splitString(req_set, '&')
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)
return False
@@ -26,7 +26,7 @@ var MovieList = new Class({
self.filter = self.options.filter || {
'starts_with': null,
'search': null
}
};
self.el = new Element('div.movies').adopt(
self.title = self.options.title ? new Element('h2', {
@@ -52,7 +52,7 @@ var MovieList = new Class({
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))
},
@@ -96,7 +96,7 @@ var MovieList = new Class({
if(self.options.load_more)
self.scrollspy = new ScrollSpy({
min: function(){
var c = self.load_more.getCoordinates()
var c = self.load_more.getCoordinates();
return c.top - window.document.getSize().y - 300
},
onEnter: self.loadMore.bind(self)
@@ -179,7 +179,7 @@ var MovieList = new Class({
m.fireEvent('injected');
self.movies.include(m)
self.movies.include(m);
self.movies_added[movie._id] = true;
},
@@ -187,7 +187,7 @@ var MovieList = new Class({
var self = this;
var chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ';
self.el.addClass('with_navigation')
self.el.addClass('with_navigation');
self.navigation = new Element('div.alph_nav').adopt(
self.mass_edit_form = new Element('div.mass_edit_form').adopt(
@@ -242,7 +242,7 @@ var MovieList = new Class({
this.addClass(a);
el.inject(el.getParent(), 'top');
el.getSiblings().hide()
el.getSiblings().hide();
setTimeout(function(){
el.getSiblings().setStyle('display', null);
}, 100)
@@ -286,7 +286,7 @@ var MovieList = new Class({
'status': self.options.status
}, self.filter),
'onSuccess': function(json){
available_chars = json.chars
available_chars = json.chars;
available_chars.each(function(c){
self.letters[c.capitalize()].addClass('available')
@@ -300,7 +300,7 @@ var MovieList = new Class({
self.navigation_alpha = new Element('ul.numbers', {
'events': {
'click:relay(li.available)': function(e, el){
self.activateLetter(el.get('data-letter'))
self.activateLetter(el.get('data-letter'));
self.getMovies(true)
}
}
@@ -318,7 +318,7 @@ var MovieList = new Class({
// All
self.letters['all'] = new Element('li.letter_all.available.active', {
'text': 'ALL',
'text': 'ALL'
}).inject(self.navigation_alpha);
// Chars
@@ -334,7 +334,7 @@ var MovieList = new Class({
if (self.options.menu.length > 0)
self.options.menu.each(function(menu_item){
self.navigation_menu.addLink(menu_item);
})
});
else
self.navigation_menu.hide();
@@ -347,15 +347,15 @@ var MovieList = new Class({
movies = self.movies.length;
self.movies.each(function(movie){
selected += movie.isSelected() ? 1 : 0
})
});
var indeterminate = selected > 0 && selected < movies,
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.element[indeterminate ? 'addClass' : 'removeClass']('indeterminate')
self.mass_edit_select_class[checked ? 'check' : 'uncheck']();
self.mass_edit_select_class.element[indeterminate ? 'addClass' : 'removeClass']('indeterminate');
self.mass_edit_selected.set('text', selected);
},
@@ -371,7 +371,7 @@ var MovieList = new Class({
'events': {
'click': function(e){
(e).preventDefault();
this.set('text', 'Deleting..')
this.set('text', 'Deleting..');
Api.request('media.delete', {
'data': {
'id': ids.join(','),
@@ -383,7 +383,7 @@ var MovieList = new Class({
var erase_movies = [];
self.movies.each(function(movie){
if (movie.isSelected()){
$(movie).destroy()
$(movie).destroy();
erase_movies.include(movie);
}
});
@@ -410,7 +410,7 @@ var MovieList = new Class({
changeQualitySelected: function(){
var self = this;
var ids = self.getSelectedMovies()
var ids = self.getSelectedMovies();
Api.request('movie.edit', {
'data': {
@@ -423,11 +423,11 @@ var MovieList = new Class({
refreshSelected: function(){
var self = this;
var ids = self.getSelectedMovies()
var ids = self.getSelectedMovies();
Api.request('media.refresh', {
'data': {
'id': ids.join(','),
'id': ids.join(',')
}
});
},
@@ -435,7 +435,7 @@ var MovieList = new Class({
getSelectedMovies: function(){
var self = this;
var ids = []
var ids = [];
self.movies.each(function(movie){
if (movie.isSelected())
ids.include(movie.get('_id'))
@@ -459,11 +459,11 @@ var MovieList = new Class({
reset: function(){
var self = this;
self.movies = []
self.movies = [];
if(self.mass_edit_select)
self.calculateSelected()
self.calculateSelected();
if(self.navigation_alpha)
self.navigation_alpha.getElements('.active').removeClass('active')
self.navigation_alpha.getElements('.active').removeClass('active');
self.offset = 0;
if(self.scrollspy){
@@ -475,7 +475,7 @@ var MovieList = new Class({
activateLetter: function(letter){
var self = this;
self.reset()
self.reset();
self.letters[letter || 'all'].addClass('active');
self.filter.starts_with = letter;
@@ -487,7 +487,7 @@ var MovieList = new Class({
self.el
.removeClass(self.current_view+'_list')
.addClass(new_view+'_list')
.addClass(new_view+'_list');
self.current_view = new_view;
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);
self.search_timer = (function(){
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.filter.search = search_value;
@@ -563,7 +563,7 @@ var MovieList = new Class({
if(self.loader_first){
var lf = self.loader_first;
self.loader_first.addClass('hide')
self.loader_first.addClass('hide');
self.loader_first = null;
setTimeout(function(){
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);
if(self.title)
self.title[is_empty ? 'hide' : 'show']()
self.title[is_empty ? 'hide' : 'show']();
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){
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'
}
}).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(){
@@ -122,7 +106,7 @@ MA.Release = new Class({
});
if(!self.movie.data.releases || self.movie.data.releases.length == 0)
self.el.hide()
self.el.hide();
else
self.showHelper();
@@ -164,7 +148,7 @@ MA.Release = new Class({
new Element('span.age', {'text': 'Age'}),
new Element('span.score', {'text': 'Score'}),
new Element('span.provider', {'text': 'Provider'})
).inject(self.release_container)
).inject(self.release_container);
if(self.movie.data.releases)
self.movie.data.releases.each(function(release){
@@ -186,7 +170,7 @@ MA.Release = new Class({
}
// Create release
var item = new Element('div', {
release['el'] = new Element('div', {
'class': 'item '+release.status,
'id': 'release_'+release._id
}).adopt(
@@ -219,7 +203,6 @@ MA.Release = new Class({
}
})
).inject(self.release_container);
release['el'] = item;
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'))
@@ -242,13 +225,13 @@ MA.Release = new Class({
status_el.set('text', new_status);
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)) {
q.removeClass(release.status).addClass(new_status);
q.set('title', q.get('title').replace(release.status, new_status));
}
}
};
App.on('release.update_status', update_handle);
@@ -391,12 +374,11 @@ MA.Release = new Class({
},
ignore: function(release){
var self = this;
Api.request('release.ignore', {
'data': {
'id': release._id
},
}
})
},
@@ -456,7 +438,7 @@ MA.Trailer = new Class({
watch: function(offset){
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({
'title': encodeURI(self.getTitle()),
'year': self.get('year'),
@@ -515,7 +497,7 @@ MA.Trailer = new Class({
}
}
}
};
self.player.addEventListener('onStateChange', change_quality);
}
@@ -532,7 +514,7 @@ MA.Trailer = new Class({
$(self.movie).setStyle('height', null);
setTimeout(function(){
self.container.destroy()
self.container.destroy();
self.close_button.destroy();
}, 1800)
}
@@ -661,7 +643,7 @@ MA.Edit = new Class({
self.movie.slide('out');
}
})
});
MA.Refresh = new Class({
@@ -847,7 +829,7 @@ MA.Files = new Class({
new Element('div.item.head').adopt(
new Element('span.name', {'text': 'File'}),
new Element('span.type', {'text': 'Type'})
).inject(self.files_container)
).inject(self.files_container);
if(self.movie.data.releases)
Array.each(self.movie.data.releases, function(release){
@@ -398,7 +398,6 @@
.movies .data .quality span {
padding: 2px 3px;
font-weight: bold;
opacity: 0.5;
font-size: 10px;
height: 16px;
@@ -451,7 +450,6 @@
right: 20px;
line-height: 0;
top: 0;
display: block;
width: auto;
opacity: 0;
display: none;
@@ -833,7 +831,6 @@
}
.movies .alph_nav .search input {
padding: 6px 5px;
width: 100%;
height: 44px;
display: inline-block;
@@ -841,7 +838,6 @@
background: none;
color: #444;
font-size: 14px;
padding: 10px;
padding: 0 10px 0 30px;
border-bottom: 1px solid rgba(0,0,0,.08);
}
@@ -1043,7 +1039,6 @@
}
.movies .progress > div .percentage {
font-weight: bold;
display: inline-block;
text-transform: uppercase;
font-weight: normal;
@@ -23,7 +23,7 @@ var Movie = new Class({
addEvents: function(){
var self = this;
self.global_events = {}
self.global_events = {};
// Do refresh with new data
self.global_events['movie.update'] = function(notification){
@@ -32,7 +32,7 @@ var Movie = new Class({
self.busy(false);
self.removeView();
self.update.delay(2000, self, notification);
}
};
App.on('movie.update', self.global_events['movie.update']);
// Add spinner on load / search
@@ -40,20 +40,20 @@ var Movie = new Class({
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)))
self.busy(true);
}
};
App.on(listener, self.global_events[listener]);
})
});
// Remove spinner
self.global_events['movie.searcher.ended'] = function(notification){
if(notification.data && self.data._id == notification.data._id)
self.busy(false)
}
};
App.on('movie.searcher.ended', self.global_events['movie.searcher.ended']);
// Reload when releases have updated
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(!self.data.releases)
@@ -62,7 +62,7 @@ var Movie = new Class({
self.data.releases.push({'quality': data.quality, 'status': data.status});
self.updateReleases();
}
}
};
App.on('release.update_status', self.global_events['release.update_status']);
@@ -73,7 +73,7 @@ var Movie = new Class({
self.el.destroy();
delete self.list.movies_added[self.get('id')];
self.list.movies.erase(self)
self.list.movies.erase(self);
self.list.checkIfEmpty();
@@ -117,18 +117,6 @@ var Movie = new Class({
}).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){
var self = this;
@@ -209,7 +197,7 @@ var Movie = new Class({
self.updateReleases();
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)
self.actions.adopt(action)
});
@@ -226,7 +214,7 @@ var Movie = new Class({
status = release.status;
if(!q && (status == 'snatched' || status == 'seeding' || status == 'done'))
var q = self.addQuality(release.quality, release.is_3d || false)
q = self.addQuality(release.quality, release.is_3d || false);
if (q && !q.hasClass(status)){
q.addClass(status);
@@ -252,9 +240,9 @@ var Movie = new Class({
var self = this;
if(self.data.title)
return self.getUnprefixedTitle(self.data.title)
return self.getUnprefixedTitle(self.data.title);
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'
},
@@ -275,12 +263,12 @@ var Movie = new Class({
self.el.addEvent('outerClick', function(){
self.removeView();
self.slide('out')
})
});
el.show();
self.data_container.addClass('hide_right');
}
else {
self.el.removeEvents('outerClick')
self.el.removeEvents('outerClick');
setTimeout(function(){
if(self.el)
@@ -297,7 +285,7 @@ var Movie = new Class({
if(self.el)
self.el
.removeClass(self.view+'_view')
.addClass(new_view+'_view')
.addClass(new_view+'_view');
self.view = new_view;
},
@@ -41,7 +41,7 @@ Block.Search.MovieItem = new Class({
)
)
)
)
);
if(info.titles)
info.titles.each(function(title){
@@ -132,19 +132,19 @@ Block.Search.MovieItem = new Class({
if(!self.options_el.hasClass('set')){
if(self.info.in_library){
if(info.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)
});
}
self.options_el.grab(
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(
self.info.in_wanted && self.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')
info.in_wanted && info.in_wanted.profile_id ? new Element('span.in_wanted', {
'text': 'Already in wanted list: ' + Quality.getProfile(info.in_wanted.profile_id).get('label')
}) : (in_library ? new Element('span.in_library', {
'text': 'Already in library: ' + in_library.join(', ')
}) : null),
@@ -172,7 +172,7 @@ Block.Search.MovieItem = new Class({
new Element('option', {
'text': alt.title
}).inject(self.title_select)
})
});
// Fill categories
@@ -215,9 +215,9 @@ Block.Search.MovieItem = new Class({
loadingMask: function(){
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')
},
@@ -62,7 +62,7 @@ class Bluray(Automation, RSS):
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
if not name.find('/') == -1: # make sure it is not a double movie release
continue
if tryInt(year) < self.getMinimal('year'):
@@ -46,7 +46,10 @@ class Goodfilms(Automation):
break
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():
break
@@ -50,7 +50,10 @@ class Letterboxd(Automation):
for movie in soup.find_all('a', attrs = {'class': 'frame'}):
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
@@ -74,6 +74,7 @@ class TheMovieDb(MovieProvider):
if not result:
try:
log.debug('Getting info: %s', cache_key)
# noinspection PyArgumentList
movie = tmdb3.Movie(identifier)
try: exists = movie.title is not None
except: exists = False
@@ -14,6 +14,6 @@ class BiTHDTV(MovieProvider, Base):
def buildUrl(self, media):
query = tryUrlencode({
'search': fireEvent('library.query', media, single = True),
'cat': 7 # Movie cat
'cat': 7 # Movie cat
})
return query
@@ -10,29 +10,29 @@ autoload = 'PassThePopcorn'
class PassThePopcorn(MovieProvider, Base):
quality_search_params = {
'bd50': {'media': 'Blu-ray', 'format': 'BD50'},
'1080p': {'resolution': '1080p'},
'720p': {'resolution': '720p'},
'brrip': {'media': 'Blu-ray'},
'dvdr': {'resolution': 'anysd'},
'dvdrip': {'media': 'DVD'},
'scr': {'media': 'DVD-Screener'},
'r5': {'media': 'R5'},
'tc': {'media': 'TC'},
'ts': {'media': 'TS'},
'cam': {'media': 'CAM'}
'bd50': {'media': 'Blu-ray', 'format': 'BD50'},
'1080p': {'resolution': '1080p'},
'720p': {'resolution': '720p'},
'brrip': {'media': 'Blu-ray'},
'dvdr': {'resolution': 'anysd'},
'dvdrip': {'media': 'DVD'},
'scr': {'media': 'DVD-Screener'},
'r5': {'media': 'R5'},
'tc': {'media': 'TC'},
'ts': {'media': 'TS'},
'cam': {'media': 'CAM'}
}
post_search_filters = {
'bd50': {'Codec': ['BD50']},
'1080p': {'Resolution': ['1080p']},
'720p': {'Resolution': ['720p']},
'brrip': {'Source': ['Blu-ray'], 'Quality': ['High Definition'], 'Container': ['!ISO']},
'dvdr': {'Codec': ['DVD5', 'DVD9']},
'dvdrip': {'Source': ['DVD'], 'Codec': ['!DVD5', '!DVD9']},
'scr': {'Source': ['DVD-Screener']},
'r5': {'Source': ['R5']},
'tc': {'Source': ['TC']},
'ts': {'Source': ['TS']},
'cam': {'Source': ['CAM']}
'bd50': {'Codec': ['BD50']},
'1080p': {'Resolution': ['1080p']},
'720p': {'Resolution': ['720p']},
'brrip': {'Source': ['Blu-ray'], 'Quality': ['High Definition'], 'Container': ['!ISO']},
'dvdr': {'Codec': ['DVD5', 'DVD9']},
'dvdrip': {'Source': ['DVD'], 'Codec': ['!DVD5', '!DVD9']},
'scr': {'Source': ['DVD-Screener']},
'r5': {'Source': ['R5']},
'tc': {'Source': ['TC']},
'ts': {'Source': ['TS']},
'cam': {'Source': ['CAM']}
}
@@ -12,11 +12,11 @@ autoload = 'ThePirateBay'
class ThePirateBay(MovieProvider, Base):
cat_ids = [
([209], ['3d']),
([207], ['720p', '1080p']),
([201], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
([201, 207], ['brrip']),
([202], ['dvdr'])
([209], ['3d']),
([207], ['720p', '1080p']),
([201], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
([201, 207], ['brrip']),
([202], ['dvdr'])
]
def buildUrl(self, media, page, cats):
@@ -16,5 +16,6 @@ class TorrentDay(MovieProvider, Base):
([3], ['dvdr']),
([5], ['bd50']),
]
def buildUrl(self, media):
return fireEvent('library.query', media, single = True)
@@ -52,7 +52,7 @@ class HDTrailers(TrailerProvider):
return result_data
def findViaAlternative(self, group):
results = {'480p':[], '720p':[], '1080p':[]}
results = {'480p': [], '720p': [], '1080p': []}
movie_name = getTitle(group)
-1
View File
@@ -249,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']))
return False
# Provider specific functions
get_more = nzb.get('get_more_info')
if get_more:
@@ -91,7 +91,6 @@
padding: 0 3px 10px 0;
}
.suggestions .media_result .data:before {
bottom: 0;
content: '';
display: block;
height: 10px;
@@ -107,7 +106,7 @@
z-index: 3;
pointer-events: none;
}
.suggestions .media_result .data .info .plot.full {
top: 0;
overflow: auto;
@@ -123,14 +122,14 @@
.suggestions .media_result .options select[name=title] { width: 100%; }
.suggestions .media_result .options select[name=profile] { width: 100%; }
.suggestions .media_result .options select[name=category] { width: 100%; }
.suggestions .media_result .button {
.suggestions .media_result .button {
position: absolute;
margin: 2px 0 0 0;
right: 15px;
bottom: 15px;
}
.suggestions .media_result .thumbnail {
width: 100px;
@@ -116,7 +116,7 @@ var SuggestList = new Class({
}
}
}) : null
)
);
$(m).inject(self.el);
@@ -150,4 +150,4 @@ var SuggestList = new Class({
return this.el;
}
})
});
+1 -1
View File
@@ -131,7 +131,7 @@ class CoreNotifier(Notification):
for message in messages:
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'
fireEvent(message_type, message = message.get('message'), data = message)
@@ -17,14 +17,14 @@ var NotificationBase = new Class({
App.addEvent('load', self.addTestButtons.bind(self));
// Notification bar
self.notifications = []
self.notifications = [];
App.addEvent('load', function(){
App.block.notification = new Block.Menu(self, {
'button_class': 'icon2.eye-open',
'class': 'notification_menu',
'onOpen': self.markAsRead.bind(self)
})
});
$(App.block.notification).inject(App.getBlock('search'), 'after');
self.badge = new Element('div.badge').inject(App.block.notification, 'top').hide();
@@ -40,7 +40,7 @@ var NotificationBase = new Class({
var self = this;
var added = new Date();
added.setTime(result.added*1000)
added.setTime(result.added*1000);
result.el = App.getBlock('notification').addLink(
new Element('span.'+(result.read ? 'read' : '' )).adopt(
@@ -51,7 +51,7 @@ var NotificationBase = new Class({
self.notifications.include(result);
if((result.data.important !== undefined || result.data.sticky !== undefined) && !result.read){
var sticky = true
var sticky = true;
App.trigger('message', [result.message, sticky, result])
}
else if(!result.read){
@@ -62,7 +62,7 @@ var NotificationBase = new Class({
setBadge: function(value){
var self = this;
self.badge.set('text', value)
self.badge.set('text', value);
self.badge[value ? 'show' : 'hide']()
},
@@ -73,9 +73,9 @@ var NotificationBase = new Class({
if(!force_ids) {
var rn = self.notifications.filter(function(n){
return !n.read && n.data.important === undefined
})
});
var ids = []
var ids = [];
rn.each(function(n){
ids.include(n._id)
})
@@ -106,7 +106,7 @@ var NotificationBase = new Class({
'onSuccess': function(json){
self.processData(json, true)
}
}).send()
}).send();
setInterval(function(){
@@ -141,7 +141,7 @@ var NotificationBase = new Class({
stopPoll: function(){
if(this.request)
this.request.cancel()
this.request.cancel();
this.stopped = true;
},
@@ -154,7 +154,7 @@ var NotificationBase = new Class({
App.trigger(result._t || result.type, [result]);
if(result.message && result.read === undefined && !init)
self.showMessage(result.message);
})
});
if(json.result.length > 0)
self.last_id = json.result.getLast().message_id
@@ -180,11 +180,11 @@ var NotificationBase = new Class({
}, 10);
var hide_message = function(){
new_message.addClass('hide')
new_message.addClass('hide');
setTimeout(function(){
new_message.destroy();
}, 1000);
}
};
if(sticky)
new_message.grab(
@@ -206,7 +206,7 @@ var NotificationBase = new Class({
addTestButtons: function(){
var self = this;
var setting_page = App.getPage('Settings')
var setting_page = App.getPage('Settings');
setting_page.addEvent('create', function(){
Object.each(setting_page.tabs.notifications.groups, self.addTestButton.bind(self))
})
+2 -1
View File
@@ -97,7 +97,8 @@ config = [{
'name': 'smtp_server',
'label': 'SMTP server',
},
{ 'name': 'smtp_port',
{
'name': 'smtp_port',
'label': 'SMTP server port',
'default': '25',
'type': 'int',
+2
View File
@@ -19,6 +19,8 @@ class Growl(Notification):
def __init__(self):
super(Growl, self).__init__()
self.growl = None
if self.isEnabled():
addEvent('app.load', self.register)
+1
View File
@@ -20,6 +20,7 @@ autoload = 'NMJ'
class NMJ(Notification):
# noinspection PyMissingConstructor
def __init__(self):
addEvent('renamer.after', self.addToLibrary)
addApiView(self.testNotifyName(), self.test)
+1 -1
View File
@@ -30,7 +30,7 @@ class Pushalot(Notification):
}
headers = {
'Content-type': 'application/x-www-form-urlencoded'
'Content-type': 'application/x-www-form-urlencoded'
}
try:
+3 -4
View File
@@ -33,10 +33,9 @@ class Pushover(Notification):
'url_title': toUnicode('%s on IMDb' % getTitle(data)),
})
http_handler.request('POST',
"/1/messages.json",
headers = {'Content-type': 'application/x-www-form-urlencoded'},
body = tryUrlencode(api_data)
http_handler.request('POST', '/1/messages.json',
headers = {'Content-type': 'application/x-www-form-urlencoded'},
body = tryUrlencode(api_data)
)
response = http_handler.getresponse()
@@ -59,7 +59,7 @@ var TwitterNotification = new Class({
).inject(fieldset.getElement('.test_button'), 'before');
})
},
}
});
+1 -1
View File
@@ -89,7 +89,7 @@ class XBMC(Notification):
self.use_json_notifications[host] = False
# 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:
if r.get('result') and r['result'] == 'OK':
log.debug('Message delivered successfully!')
+4 -3
View File
@@ -43,8 +43,8 @@ class Plugin(object):
http_failed_disabled = {}
http_opener = requests.Session()
def __new__(typ, *args, **kwargs):
new_plugin = super(Plugin, typ).__new__(typ)
def __new__(cls, *args, **kwargs):
new_plugin = super(Plugin, cls).__new__(cls)
new_plugin.registerPlugin()
return new_plugin
@@ -329,7 +329,7 @@ class Plugin(object):
elif 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)
def createFileName(self, data, filedata, media):
@@ -349,6 +349,7 @@ class Plugin(object):
now = time.time()
file_too_new = False
file_time = []
for cur_file in files:
# File got removed while checking
+2 -1
View File
@@ -17,7 +17,8 @@ if os.name == 'nt':
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/")
else:
import win32file #@UnresolvedImport
# noinspection PyUnresolvedReferences
import win32file
autoload = 'FileBrowser'
@@ -9,7 +9,7 @@ var CategoryListBase = new Class({
setup: function(categories){
var self = this;
self.categories = []
self.categories = [];
Array.each(categories, self.createCategory.bind(self));
},
@@ -17,7 +17,7 @@ var CategoryListBase = new Class({
addSettings: function(){
var self = this;
self.settings = App.getPage('Settings')
self.settings = App.getPage('Settings');
self.settings.addEvent('create', function(){
var tab = self.settings.createSubTab('category', {
'label': 'Categories',
@@ -31,7 +31,7 @@ var CategoryListBase = new Class({
self.createList();
self.createOrdering();
})
});
// Add categories in renamer
self.settings.addEvent('create', function(){
@@ -97,9 +97,9 @@ var CategoryListBase = new Class({
createCategory: function(data){
var self = this;
var data = data || {'id': randomString()}
var category = new Category(data)
self.categories.include(category)
var data = data || {'id': randomString()};
var category = new Category(data);
self.categories.include(category);
return category;
},
@@ -108,7 +108,7 @@ var CategoryListBase = new Class({
var self = this;
var category_list;
var group = self.settings.createGroup({
self.settings.createGroup({
'label': '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.'
})
)
).inject(self.content)
).inject(self.content);
Array.each(self.categories, function(category){
new Element('li', {'data-id': category.data._id}).adopt(
@@ -145,7 +145,7 @@ var CategoryListBase = new Class({
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'));
});
@@ -157,7 +157,7 @@ var CategoryListBase = new Class({
}
})
});
window.CategoryList = new CategoryListBase();
@@ -235,8 +235,6 @@ var Category = new Class({
if(self.save_timer) clearTimeout(self.save_timer);
self.save_timer = (function(){
var data = self.getData();
Api.request('category.save', {
'data': self.getData(),
'useSpinner': true,
@@ -257,7 +255,7 @@ var Category = new Class({
getData: function(){
var self = this;
var data = {
return {
'id' : self.data._id,
'label' : self.el.getElement('.category_label 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'),
'destination': self.data.destination
}
return data
},
del: function(){
+2 -2
View File
@@ -77,8 +77,8 @@ class Dashboard(Plugin):
if coming_soon:
# 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
(late and ((media['info']['year'] < now_year-1) or ((eta.get('dvd', 0) > 0 or eta.get('theater')) and eta.get('dvd') < (now - 2419200))))):
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)))):
medias.append(media)
if len(medias) >= limit:
+1 -2
View File
@@ -1,5 +1,4 @@
import os.path
import time
import traceback
from couchpotato import get_db
@@ -64,7 +63,7 @@ class FileManager(Plugin):
def download(self, url = '', dest = None, overwrite = False, urlopen_kwargs = None):
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)))
if not overwrite and os.path.isfile(dest):
+3 -3
View File
@@ -67,14 +67,14 @@ class Logging(Plugin):
if x is nr:
current_path = path
log = ''
log_content = ''
if current_path:
f = open(current_path, 'r')
log = f.read()
log_content = f.read()
return {
'success': True,
'log': toUnicode(log),
'log': toUnicode(log_content),
'total': total,
}
+1 -1
View File
@@ -50,7 +50,7 @@
overflow: hidden;
line-height: 150%;
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 {
+3 -4
View File
@@ -42,7 +42,7 @@ Page.Log = new Class({
}
}
}).inject(nav);
};
}
new Element('li', {
'text': 'clear',
@@ -63,7 +63,6 @@ Page.Log = new Class({
},
addColors: function(text){
var self = this;
text = text
.replace(/&/g, '&amp;')
@@ -74,9 +73,9 @@ Page.Log = new Class({
.replace(/\u001b\[36m/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/gi, '</span><span>')
.replace(/\u001b\[0m/gi, '</span><span>');
return '<div class="time">' + text + '</div>';
}
})
});
+3 -5
View File
@@ -160,7 +160,7 @@ class Manage(Plugin):
except:
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 = {}
@@ -171,14 +171,12 @@ class Manage(Plugin):
for delete in delete_me:
del self.in_progress[delete]
if len(self.in_progress) == 0:
break
time.sleep(1)
fireEvent('notify.frontend', type = 'manage.updating', data = False)
self.in_progress = False
# noinspection PyDefaultArgument
def createAddToLibrary(self, folder, added_identifiers = []):
def addToLibrary(group, total_found, to_go):
@@ -219,7 +217,7 @@ class Manage(Plugin):
pr = self.in_progress[folder]
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'])
@@ -119,7 +119,7 @@ var Profile = new Class({
'label' : self.el.getElement('.quality_label input').get('value'),
'wait_for' : self.el.getElement('.wait_for input').get('value'),
'types': []
}
};
Array.each(self.type_container.getElements('.type'), function(type){
if(!type.hasClass('deleted') && type.getElement('select').get('value') != -1)
@@ -129,7 +129,7 @@ var Profile = new Class({
'3d': +type.getElement('input.3d[type=checkbox]').checked,
'wait_for': 0
});
})
});
return data
},
@@ -261,10 +261,10 @@ Profile.Type = new Class({
self.finish = new Element('input.inlay.finish[type=checkbox]', {
'checked': data.finish !== undefined ? data.finish : 1,
'events': {
'change': function(e){
'change': function(){
if(self.el == self.el.getParent().getElement(':first-child')){
self.finish_class.check();
alert('Top quality always finishes the search')
alert('Top quality always finishes the search');
return;
}
@@ -280,7 +280,7 @@ Profile.Type = new Class({
self['3d'] = new Element('input.inlay.3d[type=checkbox]', {
'checked': data['3d'] !== undefined ? data['3d'] : 0,
'events': {
'change': function(e){
'change': function(){
self.fireEvent('change');
}
}
@@ -363,4 +363,4 @@ Profile.Type = new Class({
return this.el;
}
})
});
+3 -2
View File
@@ -63,6 +63,7 @@ class QualityPlugin(Plugin):
addEvent('app.test', self.doTest)
self.order = []
self.addOrder()
def addOrder(self):
@@ -247,12 +248,12 @@ class QualityPlugin(Plugin):
qualities = [qualities] if isinstance(qualities, (str, unicode)) else qualities
for alt in qualities:
if (isinstance(alt, tuple)):
if isinstance(alt, tuple):
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))
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))
score += points.get(tag_type) / 2
@@ -8,7 +8,7 @@ var QualityBase = new Class({
self.qualities = data.qualities;
self.profiles = []
self.profiles = [];
Array.each(data.profiles, self.createProfilesClass.bind(self));
App.addEvent('load', self.addSettings.bind(self))
@@ -37,7 +37,7 @@ var QualityBase = new Class({
addSettings: function(){
var self = this;
self.settings = App.getPage('Settings')
self.settings = App.getPage('Settings');
self.settings.addEvent('create', function(){
var tab = self.settings.createSubTab('profile', {
'label': 'Quality',
@@ -91,9 +91,9 @@ var QualityBase = new Class({
createProfilesClass: function(data){
var self = this;
var data = data || {'id': randomString()}
var profile = new Profile(data)
self.profiles.include(profile)
var data = data || {'id': randomString()};
var profile = new Profile(data);
self.profiles.include(profile);
return profile;
},
@@ -102,7 +102,7 @@ var QualityBase = new Class({
var self = this;
var profile_list;
var group = self.settings.createGroup({
self.settings.createGroup({
'label': 'Profile Defaults',
'description': '(Needs refresh \'' +(App.isMac() ? 'CMD+R' : 'F5')+ '\' after editing)'
}).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.'
})
)
).inject(self.content)
).inject(self.content);
Array.each(self.profiles, function(profile){
var check;
@@ -175,14 +175,14 @@ var QualityBase = new Class({
'description': 'Edit the minimal and maximum sizes (in MB) for each quality.',
'advanced': true,
'name': 'sizes'
}).inject(self.content)
}).inject(self.content);
new Element('div.item.head.ctrlHolder').adopt(
new Element('span.label', {'text': 'Quality'}),
new Element('span.min', {'text': 'Min'}),
new Element('span.max', {'text': 'Max'})
).inject(group)
).inject(group);
Array.each(self.qualities, function(quality){
new Element('div.ctrlHolder.item').adopt(
+6 -6
View File
@@ -148,7 +148,7 @@ class Renamer(Plugin):
log.debug('The provided media folder %s does not exist. Trying to find it in the \'from\' folder.', media_folder)
# Update to the from folder
if len(release_download.get('files'), []) == 1:
if len(release_download.get('files', [])) == 1:
new_media_folder = from_folder
else:
new_media_folder = os.path.join(from_folder, os.path.basename(media_folder))
@@ -504,7 +504,7 @@ class Renamer(Plugin):
fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True)
# Remove leftover files
if not remove_leftovers: # Don't remove anything
if not remove_leftovers: # Don't remove anything
break
log.debug('Removing leftover files')
@@ -529,8 +529,8 @@ class Renamer(Plugin):
parent_dir = os.path.dirname(src)
if delete_folders.count(parent_dir) == 0 and os.path.isdir(parent_dir) and \
not isSubFolder(destination, parent_dir) and not isSubFolder(media_folder, parent_dir) and \
not isSubFolder(parent_dir, base_folder):
not isSubFolder(destination, parent_dir) and not isSubFolder(media_folder, parent_dir) and \
not isSubFolder(parent_dir, base_folder):
delete_folders.append(parent_dir)
@@ -659,7 +659,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
for filename in tag_files:
# Dont tag .ignore files
# Don't tag .ignore files
if os.path.splitext(filename)[1] == '.ignore':
continue
@@ -1017,7 +1017,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
if release_download['pause'] and self.conf('file_action') == 'link':
fireEvent('download.pause', release_download = release_download, pause = False, single = True)
if release_download['process_complete']:
#First make sure the files were succesfully processed
# First make sure the files were successfully processed
if not self.hastagRelease(release_download = release_download, tag = 'failed_rename'):
# Remove the seeding tag if it exists
self.untagRelease(release_download = release_download, tag = 'renamed_already')
+4 -3
View File
@@ -28,7 +28,7 @@ class Scanner(Plugin):
ignored_in_path = [os.path.sep + 'extracted' + os.path.sep, 'extracting', '_unpack', '_failed_', '_unknown_', '_exists_', '_failed_remove_',
'_failed_rename_', '.appledouble', '.appledb', '.appledesktop', os.path.sep + '._', '.ds_store', 'cp.cpnfo',
'thumbs.db', 'ehthumbs.db', 'desktop.ini'] #unpacking, smb-crap, hidden files
'thumbs.db', 'ehthumbs.db', 'desktop.ini'] # unpacking, smb-crap, hidden files
ignore_names = ['extract', 'extracting', 'extracted', 'movie', 'movies', 'film', 'films', 'download', 'downloads', 'video_ts', 'audio_ts', 'bdmv', 'certificate']
extensions = {
'movie': ['mkv', 'wmv', 'avi', 'mpg', 'mpeg', 'mp4', 'm2ts', 'iso', 'img', 'mdf', 'ts', 'm4v'],
@@ -589,7 +589,7 @@ class Scanner(Plugin):
if len(movie) > 0:
imdb_id = movie[0].get('imdb')
log.debug('Found movie via search: %s', cur_file)
log.debug('Found movie via search: %s', identifier)
if imdb_id: break
else:
log.debug('Identifier to short to use for search: %s', identifier)
@@ -835,6 +835,7 @@ class Scanner(Plugin):
cleaned = ' '.join(re.split('\W+', simplifyString(release_name)))
cleaned = re.sub(self.clean, ' ', cleaned)
year = None
for year_str in [file_name, release_name, cleaned]:
if not year_str: continue
year = self.findYear(year_str)
@@ -843,7 +844,7 @@ class Scanner(Plugin):
cp_guess = {}
if year: # Split name on year
if year: # Split name on year
try:
movie_name = cleaned.rsplit(year, 1).pop(0).strip()
if movie_name:
@@ -32,7 +32,7 @@ var isCorrectUrl = function() {
}
var addUserscript = function() {
// Add window param
document.body.setAttribute('cp_auto_open', true)
document.body.setAttribute('cp_auto_open', 'true')
// Load userscript
var e = document.createElement('script');
+2 -2
View File
@@ -35,7 +35,7 @@ class Userscript(Plugin):
'host': host,
}
return self.renderTemplate(__file__, 'bookmark.js', **params)
return self.renderTemplate(__file__, 'bookmark.js_tmpl', **params)
def getIncludes(self, **kwargs):
@@ -60,7 +60,7 @@ class Userscript(Plugin):
'host': '%s://%s' % (self.request.protocol, self.request.headers.get('X-Forwarded-Host') or self.request.headers.get('host')),
}
script = klass.renderTemplate(__file__, 'template.js', **params)
script = klass.renderTemplate(__file__, 'template.js_tmpl', **params)
klass.createFile(os.path.join(Env.get('cache_dir'), 'couchpotato.user.js'), script)
self.redirect(Env.get('api_base') + 'file.cache/couchpotato.user.js')
@@ -12,7 +12,7 @@ Page.Userscript = new Class({
}
},
indexAction: function(param){
indexAction: function(){
var self = this;
self.el.adopt(
@@ -60,7 +60,7 @@ var UserscriptSettingTab = new Class({
addSettings: function(){
var self = this;
self.settings = App.getPage('Settings')
self.settings = App.getPage('Settings');
self.settings.addEvent('create', function(){
var host_url = window.location.protocol + '//' + window.location.host;
@@ -74,7 +74,7 @@ var UserscriptSettingTab = new Class({
'text': 'Install userscript',
'href': Api.createUrl('userscript.get')+randomString()+'/couchpotato.user.js',
'target': '_blank'
}),
}),
new Element('span.or[text=or]'),
new Element('span.bookmarklet').adopt(
new Element('a.button.green', {
@@ -86,7 +86,7 @@ var UserscriptSettingTab = new Class({
'target': '',
'events': {
'click': function(e){
(e).stop()
(e).stop();
alert('Drag it to your bookmark ;)')
}
}
@@ -5,10 +5,9 @@
.page.wizard h1 {
padding: 10px 0;
margin: 0 5px;
display: block;
font-size: 30px;
margin-top: 80px;
margin: 80px 5px 0;
}
.page.wizard .description {
@@ -52,7 +51,7 @@
font-weight: normal;
border-bottom: 4px solid transparent;
}
.page.wizard .tabs li:hover a { border-color: #047792; }
.page.wizard .tabs li.done a { border-color: #04bce6; }
@@ -111,10 +111,10 @@ Page.Wizard = new Class({
var form = self.el.getElement('.uniForm');
var tabs = self.el.getElement('.tabs');
self.groups.each(function(group, nr){
self.groups.each(function(group){
if(self.headers[group]){
group_container = new Element('.wgroup_'+group, {
var group_container = new Element('.wgroup_'+group, {
'styles': {
'opacity': 0.2
},
@@ -129,7 +129,7 @@ Page.Wizard = new Class({
})
}
var content = self.headers[group].content
var content = self.headers[group].content;
group_container.adopt(
new Element('h1', {
'text': self.headers[group].title
@@ -144,7 +144,7 @@ Page.Wizard = new Class({
var tab_navigation = tabs.getElement('.t_'+group);
if(!tab_navigation && self.headers[group] && self.headers[group].include){
tab_navigation = []
tab_navigation = [];
self.headers[group].include.each(function(inc){
tab_navigation.include(tabs.getElement('.t_'+inc));
})
@@ -157,7 +157,7 @@ Page.Wizard = new Class({
self.headers[group].include.each(function(inc){
self.el.getElement('.tab_'+inc).inject(group_container);
})
});
new Element('li.t_'+group).adopt(
new Element('a', {
@@ -215,9 +215,9 @@ Page.Wizard = new Class({
self.groups.each(function(groups2, nr2){
var t2 = self.el.getElement('.t_'+groups2);
t2[nr2 > nr ? 'removeClass' : 'addClass' ]('done');
})
});
g.tween('opacity', 1);
}
};
if(nr == 0)
func();
@@ -241,4 +241,4 @@ Page.Wizard = new Class({
}
});
});
+5 -1
View File
@@ -56,6 +56,10 @@ class Settings(object):
addEvent('database.setup', self.databaseSetup)
self.file = None
self.p = None
self.log = None
def setFile(self, config_file):
self.file = config_file
@@ -195,7 +199,6 @@ class Settings(object):
def getOptions(self):
return self.options
def view(self, **kwargs):
return {
'options': self.getOptions(),
@@ -254,6 +257,7 @@ class Settings(object):
'value': toUnicode(value),
})
class PropertyIndex(HashIndex):
_version = 1
+9 -7
View File
@@ -100,14 +100,14 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En
if not os.path.isdir(backup_path): os.makedirs(backup_path)
for root, dirs, files in scandir.walk(backup_path):
for file in files:
ints = re.findall('\d+', file)
for backup_file in files:
ints = re.findall('\d+', backup_file)
# Delete non zip files
if len(ints) != 1:
os.remove(os.path.join(backup_path, file))
os.remove(os.path.join(backup_path, backup_file))
else:
existing_backups.append((int(ints[0]), file))
existing_backups.append((int(ints[0]), backup_file))
# Remove all but the last 5
for eb in existing_backups[:-backup_count]:
@@ -117,8 +117,8 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En
new_backup = toUnicode(os.path.join(backup_path, '%s.tar.gz' % int(time.time())))
zipf = tarfile.open(new_backup, 'w:gz')
for root, dirs, files in scandir.walk(db_path):
for file in files:
zipf.add(os.path.join(root, file), arcname = 'database/%s' % os.path.join(root[len(db_path)+1:], file))
for zfilename in files:
zipf.add(os.path.join(root, zfilename), arcname = 'database/%s' % os.path.join(root[len(db_path) + 1:], zfilename))
zipf.close()
# Open last
@@ -178,6 +178,7 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En
logger.addHandler(hdlr2)
# Start logging & enable colors
# noinspection PyUnresolvedReferences
import color_logs
from couchpotato.core.logger import CPLog
log = CPLog(__name__)
@@ -212,7 +213,8 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En
}
# Load the app
application = Application([],
application = Application(
[],
log_function = lambda x: None,
debug = config['use_reloader'],
gzip = True,
+1 -1
View File
@@ -369,7 +369,7 @@
// Create parallel callback
var callbacks = [];
self.global_events[name].each(function(handle, nr){
self.global_events[name].each(function(handle){
callbacks.push(function(callback){
var results = handle.apply(handle, args || []);
@@ -68,7 +68,7 @@ var DownloadersBase = new Class({
testButtonName: function(fieldset){
var name = String(fieldset.getElement('h2').innerHTML).substring(0,String(fieldset.getElement('h2').innerHTML).indexOf("<span"));
return 'Test '+name;
},
}
});
+1 -1
View File
@@ -67,7 +67,7 @@ Page.Home = new Class({
// Force update after search
self.available_list.update();
App.off('movie.searcher.ended', after_search);
}
};
App.on('movie.searcher.ended', after_search);
}
+4 -4
View File
@@ -105,7 +105,7 @@ Page.Manage = new Class({
}
else {
// Capture progress so we can use it in our *each* closure
var progress = json.progress
var progress = json.progress;
// Don't add loader when page is loading still
if(!self.list.navigation)
@@ -116,15 +116,15 @@ Page.Manage = new Class({
self.progress_container.empty();
var sorted_table = self.parseProgress(json.progress)
var sorted_table = self.parseProgress(json.progress);
sorted_table.each(function(folder){
var folder_progress = progress[folder]
var folder_progress = progress[folder];
new Element('div').adopt(
new Element('span.folder', {'text': folder +
(folder_progress.eta > 0 ? ', ' + new Date ().increment('second', folder_progress.eta).timeDiffInWords().replace('from now', 'to go') : '')
}),
new Element('span.percentage', {'text': folder_progress.total ? (((folder_progress.total-folder_progress.to_go)/folder_progress.total)*100).round() + '%' : '0%'})
new Element('span.percentage', {'text': folder_progress.total ? Math.round(((folder_progress.total-folder_progress.to_go)/folder_progress.total)*100) + '%' : '0%'})
).inject(self.progress_container)
});
+4 -3
View File
@@ -370,7 +370,7 @@ var OptionBase = new Class({
createTooltip(self.options.description[1]).inject(hint, 'top');
}
else {
var hint = new Element('p.formHint', {
new Element('p.formHint', {
'html': self.options.description || ''
}).inject(self.el)
}
@@ -1312,8 +1312,9 @@ Option.Combined = new Class({
var head = new Element('div.head').inject(self.combined_list);
Object.each(self.inputs, function(input, name){
var _in = input.getNext();
self.labels[name] = input.getPrevious().get('text');
self.descriptions[name] = (_in = input.getNext()) ? _in.get('text') : '';
self.descriptions[name] = _in ? _in.get('text') : '';
new Element('abbr', {
'class': name,
@@ -1465,4 +1466,4 @@ var createTooltip = function(description){
);
return tip;
}
};
+5 -5
View File
@@ -73,7 +73,7 @@ Page.Wanted = new Class({
}
else {
var progress = json.movie;
self.manual_search.set('text', 'Searching.. (' + (((progress.total-progress.to_go)/progress.total)*100).round() + '%)');
self.manual_search.set('text', 'Searching.. (' + Math.round(((progress.total-progress.to_go)/progress.total)*100) + '%)');
}
}
});
@@ -87,7 +87,7 @@ Page.Wanted = new Class({
var self = this;
var options = {
'name': 'Scan_folder'
}
};
if(!self.folder_browser){
self.folder_browser = new Option['Directory']("Scan", "folder", "", options);
@@ -96,9 +96,9 @@ Page.Wanted = new Class({
var folder = self.folder_browser.getValue();
Api.request('renamer.scan', {
'data': {
'base_folder': folder,
},
});
'base_folder': folder
}
});
};
self.folder_browser.inject(self.el, 'top');
+57 -57
View File
@@ -111,7 +111,7 @@ body > .spinner, .mask{
width: 100%;
padding: 200px;
}
@media all and (max-width: 480px) {
body > .mask {
padding: 20px;
@@ -185,9 +185,9 @@ body > .spinner, .mask{
.icon2.completed:before { content: "\e070"; }
.icon2.info:before { content: "\e089"; }
.icon2.attention:before { content: "\e009"; }
.icon2.readd:before {
display: inline-block;
content: "\e04b";
.icon2.readd:before {
display: inline-block;
content: "\e04b";
transform: scale(-1, 1);
}
.icon2.imdb:before {
@@ -200,8 +200,8 @@ body > .spinner, .mask{
position: relative;
top: -3px;
}
.icon2.menu:before {
content: "\e076\00a0 \e076\00a0 \e076\00a0";
.icon2.menu:before {
content: "\e076\00a0 \e076\00a0 \e076\00a0";
line-height: 6px;
transform: scaleX(2);
width: 20px;
@@ -213,7 +213,7 @@ body > .spinner, .mask{
margin-left: 5px;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {
.icon2.menu:before {
.icon2.menu:before {
margin-top: -7px;
}
}
@@ -229,7 +229,7 @@ body > .spinner, .mask{
box-shadow: 0 0 10px rgba(0,0,0,.1);
transition: all .4s ease-in-out;
}
@media all and (max-width: 480px) {
.header {
height: 44px;
@@ -253,7 +253,7 @@ body > .spinner, .mask{
left: 0;
bottom: 0;
}
.header .foldout {
width: 44px;
height: 100%;
@@ -264,7 +264,7 @@ body > .spinner, .mask{
line-height: 42px;
color: #FFF;
}
.header .logo {
display: inline-block;
font-size: 3em;
@@ -274,36 +274,36 @@ body > .spinner, .mask{
color: #FFF;
font-weight: normal;
vertical-align: top;
font-family: Lobster;
font-family: Lobster, sans-serif;
}
@media all and (max-width: 480px) {
.header .foldout {
display: inline-block;
}
.header .logo {
padding-top: 7px;
border: 0;
font-size: 1.7em;
}
}
@media all and (min-width: 481px) and (max-width: 640px) {
.header .logo {
display: none;
}
}
.header .navigation ul {
display: inline-block;
margin: 0;
padding: 0;
height: 100%;
}
.header .navigation li {
color: #fff;
display: inline-block;
@@ -317,7 +317,7 @@ body > .spinner, .mask{
.header .navigation li:first-child {
border: none;
}
.header .navigation li a {
display: block;
padding: 15px;
@@ -327,13 +327,13 @@ body > .spinner, .mask{
border-width: 0 0 4px 0;
font-weight: normal;
}
.header .navigation li:hover a { border-color: #047792; }
.header .navigation li.active a { border-color: #04bce6; }
.header .navigation li.disabled { color: #e5e5e5; }
.header .navigation li a { color: #fff; }
.header .navigation .backtotop {
opacity: 0;
display: block;
@@ -349,24 +349,24 @@ body > .spinner, .mask{
font-weight: normal;
}
.header:hover .navigation .backtotop { color: #fff; }
@media all and (max-width: 480px) {
body {
position: absolute;
width: 100%;
transition: all .5s cubic-bezier(0.9,0,0.1,1);
left: 0;
}
.menu_shown body {
left: 240px;
}
.header .navigation {
height: 100%;
}
.menu_shown .header .navigation .overlay {
position: fixed;
right: 0;
@@ -374,7 +374,7 @@ body > .spinner, .mask{
bottom: 0;
left: 240px;
}
.header .navigation ul {
width: 240px;
position: fixed;
@@ -382,11 +382,11 @@ body > .spinner, .mask{
background: rgba(0,0,0,.5);
transition: all .5s cubic-bezier(0.9,0,0.1,1);
}
.menu_shown .header .navigation ul {
left: 0;
}
.header .navigation ul li {
display: block;
text-align: left;
@@ -397,7 +397,7 @@ body > .spinner, .mask{
border-width: 0 4px 0 0;
padding: 5px 20px;
}
.header .navigation ul li.separator {
background-color: rgba(255,255,255, .07);
height: 5px;
@@ -410,31 +410,31 @@ body > .spinner, .mask{
height: 100%;
border-left: 1px solid rgba(255,255,255,.07);
}
@media all and (max-width: 480px) {
.header .more_menu {
display: none;
}
}
.header .more_menu .button {
height: 100%;
line-height: 66px;
text-align: center;
padding: 0;
}
.header .more_menu .wrapper {
width: 200px;
margin-left: -106px;
margin-top: 22px;
}
@media all and (max-width: 480px) {
.header .more_menu .button {
line-height: 44px;
}
.header .more_menu .wrapper {
margin-top: 0;
}
@@ -454,12 +454,12 @@ body > .spinner, .mask{
top: 0;
right: 0;
}
.header .notification_menu {
right: 60px;
display: block;
}
@media all and (max-width: 480px) {
.header .notification_menu {
right: 0;
@@ -685,15 +685,15 @@ body > .spinner, .mask{
border-bottom: 4px solid transparent;
border-radius: 0;
}
.more_menu .button:hover {
border-color: #047792;
}
.more_menu.show .button {
border-color: #04bce6;
}
.more_menu .wrapper {
display: none;
top: 0;
@@ -706,23 +706,23 @@ body > .spinner, .mask{
color: #444;
background: #fff;
}
.more_menu.show .wrapper {
display: block;
top: 44px;
}
.more_menu ul {
padding: 0;
margin: 0;
list-style: none;
}
.more_menu .wrapper li {
width: 100%;
height: auto;
}
.more_menu .wrapper li a {
display: block;
border-bottom: 1px solid rgba(255,255,255,0.2);
@@ -735,21 +735,21 @@ body > .spinner, .mask{
}
.more_menu .wrapper li:first-child a { padding-top: 5px; }
.more_menu .wrapper li:last-child a { padding-bottom: 5px; }
.more_menu .wrapper li .separator {
border-bottom: 1px solid rgba(0,0,0,.1);
display: block;
height: 1px;
margin: 5px 0;
}
.more_menu .wrapper li:last-child a {
border: none;
}
.more_menu .wrapper li a:hover {
background: rgba(0,0,0,0.05);
}
.messages {
position: fixed;
right: 0;
@@ -823,7 +823,7 @@ body > .spinner, .mask{
margin: -200px 0 0 -200px;
}
@media all and (max-width: 480px) {
.login form {
padding: 0;
height: 300px;
@@ -833,9 +833,9 @@ body > .spinner, .mask{
top: 10px;
margin: 0;
}
}
.page.login .ctrlHolder {
padding: 0;
margin: 0 0 20px;
@@ -843,31 +843,31 @@ body > .spinner, .mask{
.page.login .ctrlHolder:hover {
background: none;
}
.page.login input[type=text],
.page.login input[type=password] {
width: 100% !important;
font-size: 25px;
padding: 14px !important;
}
.page.login .remember_me {
font-size: 15px;
float: left;
width: 150px;
padding: 20px 0;
}
.page.login .remember_me .check {
margin: 5px 5px 0 0;
}
.page.login .button {
font-size: 25px;
padding: 20px;
float: right;
}
/* Fonts */
@font-face {
font-family: 'Elusive-Icons';
@@ -936,4 +936,4 @@ body > .spinner, .mask{
url('../fonts/Lobster-webfont.svg#lobster_1.4regular') format('svg');
font-weight: normal;
font-style: normal;
}
}
+1 -1
View File
@@ -741,7 +741,7 @@
.tooltip {
position: absolute;
right: 0px;
right: 0;
width: 30px;
height: 30px;
}
+1 -1
View File
@@ -26,7 +26,7 @@
)
);
documents.each(function(doc, nr){
documents.each(function(doc){
new Element('tr.document').adopt(
new Element('td.id', {'text': doc['_id']}),
new Element('td._rev', {'text': doc['_rev']}),