Merge branch 'refs/heads/develop'
This commit is contained in:
commit
52214e4938
22 files changed
+272
-79
No files matched your search
+6
-1
@@ -19,7 +19,12 @@ base_path = dirname(os.path.abspath(__file__))
|
|||||||
sys.path.insert(0, os.path.join(base_path, 'libs'))
|
sys.path.insert(0, os.path.join(base_path, 'libs'))
|
||||||
|
|
||||||
from couchpotato.environment import Env
|
from couchpotato.environment import Env
|
||||||
from couchpotato.core.helpers.variable import getDataDir
|
from couchpotato.core.helpers.variable import getDataDir, removePyc
|
||||||
|
|
||||||
|
|
||||||
|
# Remove pyc files before dynamic load (sees .pyc files regular .py modules)
|
||||||
|
removePyc(base_path)
|
||||||
|
|
||||||
|
|
||||||
class Loader(object):
|
class Loader(object):
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from threading import RLock
|
|||||||
from couchpotato.api import addApiView
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
||||||
from couchpotato.core.helpers.encoding import sp
|
from couchpotato.core.helpers.encoding import sp
|
||||||
|
from couchpotato.core.helpers.variable import removePyc
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
from couchpotato.environment import Env
|
from couchpotato.environment import Env
|
||||||
@@ -143,7 +144,7 @@ class Updater(Plugin):
|
|||||||
|
|
||||||
def doShutdown(self):
|
def doShutdown(self):
|
||||||
if not Env.get('dev'):
|
if not Env.get('dev'):
|
||||||
self.updater.deletePyc(show_logs = False)
|
removePyc(Env.get('app_dir'), show_logs = False)
|
||||||
|
|
||||||
return super(Updater, self).doShutdown()
|
return super(Updater, self).doShutdown()
|
||||||
|
|
||||||
@@ -181,30 +182,6 @@ class BaseUpdater(Plugin):
|
|||||||
def check(self):
|
def check(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def deletePyc(self, only_excess = True, show_logs = True):
|
|
||||||
|
|
||||||
for root, dirs, files in os.walk(Env.get('app_dir')):
|
|
||||||
|
|
||||||
pyc_files = filter(lambda filename: filename.endswith('.pyc'), files)
|
|
||||||
py_files = set(filter(lambda filename: filename.endswith('.py'), files))
|
|
||||||
excess_pyc_files = filter(lambda pyc_filename: pyc_filename[:-1] not in py_files, pyc_files) if only_excess else pyc_files
|
|
||||||
|
|
||||||
for excess_pyc_file in excess_pyc_files:
|
|
||||||
full_path = os.path.join(root, excess_pyc_file)
|
|
||||||
if show_logs: log.debug('Removing old PYC file: %s', full_path)
|
|
||||||
try:
|
|
||||||
os.remove(full_path)
|
|
||||||
except:
|
|
||||||
log.error('Couldn\'t remove %s: %s', (full_path, traceback.format_exc()))
|
|
||||||
|
|
||||||
for dir_name in dirs:
|
|
||||||
full_path = os.path.join(root, dir_name)
|
|
||||||
if len(os.listdir(full_path)) == 0:
|
|
||||||
try:
|
|
||||||
os.rmdir(full_path)
|
|
||||||
except:
|
|
||||||
log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc()))
|
|
||||||
|
|
||||||
|
|
||||||
class GitUpdater(BaseUpdater):
|
class GitUpdater(BaseUpdater):
|
||||||
|
|
||||||
@@ -328,7 +305,7 @@ class SourceUpdater(BaseUpdater):
|
|||||||
data_dir = Env.get('data_dir')
|
data_dir = Env.get('data_dir')
|
||||||
|
|
||||||
# Get list of files we want to overwrite
|
# Get list of files we want to overwrite
|
||||||
self.deletePyc()
|
removePyc(app_dir)
|
||||||
existing_files = []
|
existing_files = []
|
||||||
for root, subfiles, filenames in os.walk(app_dir):
|
for root, subfiles, filenames in os.walk(app_dir):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ class Database(object):
|
|||||||
addApiView('database.document.update', self.updateDocument)
|
addApiView('database.document.update', self.updateDocument)
|
||||||
addApiView('database.document.delete', self.deleteDocument)
|
addApiView('database.document.delete', self.deleteDocument)
|
||||||
|
|
||||||
|
addEvent('database.setup.after', self.startup_compact)
|
||||||
addEvent('database.setup_index', self.setupIndex)
|
addEvent('database.setup_index', self.setupIndex)
|
||||||
|
|
||||||
addEvent('app.migrate', self.migrate)
|
addEvent('app.migrate', self.migrate)
|
||||||
addEvent('app.after_shutdown', self.close)
|
addEvent('app.after_shutdown', self.close)
|
||||||
|
|
||||||
@@ -140,8 +142,14 @@ class Database(object):
|
|||||||
|
|
||||||
success = True
|
success = True
|
||||||
try:
|
try:
|
||||||
|
start = time.time()
|
||||||
db = self.getDB()
|
db = self.getDB()
|
||||||
|
size = float(db.get_db_details().get('size', 0))
|
||||||
|
log.debug('Compacting database, current size: %sMB', round(size/1048576, 2))
|
||||||
|
|
||||||
db.compact()
|
db.compact()
|
||||||
|
new_size = float(db.get_db_details().get('size', 0))
|
||||||
|
log.debug('Done compacting database in %ss, new size: %sMB, saved: %sMB', (round(time.time()-start, 2), round(new_size/1048576, 2), round((size-new_size)/1048576, 2)))
|
||||||
except:
|
except:
|
||||||
log.error('Failed compact: %s', traceback.format_exc())
|
log.error('Failed compact: %s', traceback.format_exc())
|
||||||
success = False
|
success = False
|
||||||
@@ -150,6 +158,18 @@ class Database(object):
|
|||||||
'success': success
|
'success': success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Compact on start
|
||||||
|
def startup_compact(self):
|
||||||
|
from couchpotato import Env
|
||||||
|
|
||||||
|
db = self.getDB()
|
||||||
|
size = db.get_db_details().get('size')
|
||||||
|
prop_name = 'last_db_compact'
|
||||||
|
last_check = int(Env.prop(prop_name, default = 0))
|
||||||
|
if size > 26214400 and last_check < time.time()-604800: # 25MB / 7 days
|
||||||
|
self.compact()
|
||||||
|
Env.prop(prop_name, value = int(time.time()))
|
||||||
|
|
||||||
def migrate(self):
|
def migrate(self):
|
||||||
|
|
||||||
from couchpotato import Env
|
from couchpotato import Env
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ import random
|
|||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss
|
from couchpotato.core.helpers.encoding import simplifyString, toSafeString, ss, sp
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
import six
|
import six
|
||||||
from six.moves import map, zip, filter
|
from six.moves import map, zip, filter
|
||||||
@@ -313,3 +314,30 @@ under_pat = re.compile(r'_([a-z])')
|
|||||||
|
|
||||||
def underscoreToCamel(name):
|
def underscoreToCamel(name):
|
||||||
return under_pat.sub(lambda x: x.group(1).upper(), name)
|
return under_pat.sub(lambda x: x.group(1).upper(), name)
|
||||||
|
|
||||||
|
|
||||||
|
def removePyc(folder, only_excess = True, show_logs = True):
|
||||||
|
|
||||||
|
folder = sp(folder)
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(folder):
|
||||||
|
|
||||||
|
pyc_files = filter(lambda filename: filename.endswith('.pyc'), files)
|
||||||
|
py_files = set(filter(lambda filename: filename.endswith('.py'), files))
|
||||||
|
excess_pyc_files = filter(lambda pyc_filename: pyc_filename[:-1] not in py_files, pyc_files) if only_excess else pyc_files
|
||||||
|
|
||||||
|
for excess_pyc_file in excess_pyc_files:
|
||||||
|
full_path = os.path.join(root, excess_pyc_file)
|
||||||
|
if show_logs: log.debug('Removing old PYC file: %s', full_path)
|
||||||
|
try:
|
||||||
|
os.remove(full_path)
|
||||||
|
except:
|
||||||
|
log.error('Couldn\'t remove %s: %s', (full_path, traceback.format_exc()))
|
||||||
|
|
||||||
|
for dir_name in dirs:
|
||||||
|
full_path = os.path.join(root, dir_name)
|
||||||
|
if len(os.listdir(full_path)) == 0:
|
||||||
|
try:
|
||||||
|
os.rmdir(full_path)
|
||||||
|
except:
|
||||||
|
log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc()))
|
||||||
@@ -176,3 +176,24 @@ class MediaChildrenIndex(TreeBasedIndex):
|
|||||||
if data.get('_t') == 'media' and data.get('parent_id'):
|
if data.get('_t') == 'media' and data.get('parent_id'):
|
||||||
return data.get('parent_id'), None
|
return data.get('parent_id'), None
|
||||||
|
|
||||||
|
|
||||||
|
class MediaTagIndex(MultiTreeBasedIndex):
|
||||||
|
_version = 2
|
||||||
|
|
||||||
|
custom_header = """from CodernityDB.tree_index import MultiTreeBasedIndex"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['key_format'] = '32s'
|
||||||
|
super(MediaTagIndex, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def make_key_value(self, data):
|
||||||
|
if data.get('_t') == 'media' and data.get('tags') and len(data.get('tags', [])) > 0:
|
||||||
|
|
||||||
|
tags = set()
|
||||||
|
for tag in data.get('tags', []):
|
||||||
|
tags.add(self.make_key(tag))
|
||||||
|
|
||||||
|
return list(tags), None
|
||||||
|
|
||||||
|
def make_key(self, key):
|
||||||
|
return md5(key).hexdigest()
|
||||||
@@ -9,7 +9,7 @@ from couchpotato.core.helpers.encoding import toUnicode
|
|||||||
from couchpotato.core.helpers.variable import splitString, getImdb, getTitle
|
from couchpotato.core.helpers.variable import splitString, getImdb, getTitle
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.media import MediaBase
|
from couchpotato.core.media import MediaBase
|
||||||
from .index import MediaIndex, MediaStatusIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex, MediaChildrenIndex
|
from .index import MediaIndex, MediaStatusIndex, MediaTypeIndex, TitleSearchIndex, TitleIndex, StartsWithIndex, MediaChildrenIndex, MediaTagIndex
|
||||||
|
|
||||||
|
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
@@ -21,6 +21,7 @@ class MediaPlugin(MediaBase):
|
|||||||
'media': MediaIndex,
|
'media': MediaIndex,
|
||||||
'media_search_title': TitleSearchIndex,
|
'media_search_title': TitleSearchIndex,
|
||||||
'media_status': MediaStatusIndex,
|
'media_status': MediaStatusIndex,
|
||||||
|
'media_tag': MediaTagIndex,
|
||||||
'media_by_type': MediaTypeIndex,
|
'media_by_type': MediaTypeIndex,
|
||||||
'media_title': TitleIndex,
|
'media_title': TitleIndex,
|
||||||
'media_startswith': StartsWithIndex,
|
'media_startswith': StartsWithIndex,
|
||||||
@@ -81,6 +82,8 @@ class MediaPlugin(MediaBase):
|
|||||||
addEvent('media.list', self.list)
|
addEvent('media.list', self.list)
|
||||||
addEvent('media.delete', self.delete)
|
addEvent('media.delete', self.delete)
|
||||||
addEvent('media.restatus', self.restatus)
|
addEvent('media.restatus', self.restatus)
|
||||||
|
addEvent('media.tag', self.tag)
|
||||||
|
addEvent('media.untag', self.unTag)
|
||||||
|
|
||||||
def refresh(self, id = '', **kwargs):
|
def refresh(self, id = '', **kwargs):
|
||||||
handlers = []
|
handlers = []
|
||||||
@@ -177,7 +180,7 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
log.debug('No media found with identifiers: %s', identifiers)
|
log.debug('No media found with identifiers: %s', identifiers)
|
||||||
|
|
||||||
def list(self, types = None, status = None, release_status = None, status_or = False, limit_offset = None, starts_with = None, search = None):
|
def list(self, types = None, status = None, release_status = None, status_or = False, limit_offset = None, with_tags = None, starts_with = None, search = None):
|
||||||
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
@@ -188,6 +191,8 @@ class MediaPlugin(MediaBase):
|
|||||||
release_status = [release_status]
|
release_status = [release_status]
|
||||||
if types and not isinstance(types, (list, tuple)):
|
if types and not isinstance(types, (list, tuple)):
|
||||||
types = [types]
|
types = [types]
|
||||||
|
if with_tags and not isinstance(with_tags, (list, tuple)):
|
||||||
|
with_tags = [with_tags]
|
||||||
|
|
||||||
# query media ids
|
# query media ids
|
||||||
if types:
|
if types:
|
||||||
@@ -214,11 +219,17 @@ class MediaPlugin(MediaBase):
|
|||||||
|
|
||||||
# Add search filters
|
# Add search filters
|
||||||
if starts_with:
|
if starts_with:
|
||||||
filter_by['starts_with'] = set()
|
|
||||||
starts_with = toUnicode(starts_with.lower())[0]
|
starts_with = toUnicode(starts_with.lower())[0]
|
||||||
starts_with = starts_with if starts_with in ascii_lowercase else '#'
|
starts_with = starts_with if starts_with in ascii_lowercase else '#'
|
||||||
filter_by['starts_with'] = [x['_id'] for x in db.get_many('media_startswith', starts_with)]
|
filter_by['starts_with'] = [x['_id'] for x in db.get_many('media_startswith', starts_with)]
|
||||||
|
|
||||||
|
# Add tag filter
|
||||||
|
if with_tags:
|
||||||
|
filter_by['with_tags'] = set()
|
||||||
|
for tag in with_tags:
|
||||||
|
for x in db.get_many('media_tag', tag):
|
||||||
|
filter_by['with_tags'].add(x['_id'])
|
||||||
|
|
||||||
# Filter with search query
|
# Filter with search query
|
||||||
if search:
|
if search:
|
||||||
filter_by['search'] = [x['_id'] for x in db.get_many('media_search_title', search)]
|
filter_by['search'] = [x['_id'] for x in db.get_many('media_search_title', search)]
|
||||||
@@ -271,7 +282,8 @@ class MediaPlugin(MediaBase):
|
|||||||
release_status = splitString(kwargs.get('release_status')),
|
release_status = splitString(kwargs.get('release_status')),
|
||||||
status_or = kwargs.get('status_or') is not None,
|
status_or = kwargs.get('status_or') is not None,
|
||||||
limit_offset = kwargs.get('limit_offset'),
|
limit_offset = kwargs.get('limit_offset'),
|
||||||
starts_with = kwargs.get('starts_with'),
|
with_tags = kwargs.get('with_tags'),
|
||||||
|
starts_with = splitString(kwargs.get('starts_with')),
|
||||||
search = kwargs.get('search')
|
search = kwargs.get('search')
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -459,3 +471,41 @@ class MediaPlugin(MediaBase):
|
|||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
log.error('Failed restatus: %s', traceback.format_exc())
|
log.error('Failed restatus: %s', traceback.format_exc())
|
||||||
|
|
||||||
|
def tag(self, media_id, tag):
|
||||||
|
|
||||||
|
try:
|
||||||
|
db = get_db()
|
||||||
|
m = db.get('id', media_id)
|
||||||
|
|
||||||
|
tags = m.get('tags') or []
|
||||||
|
if tag not in tags:
|
||||||
|
tags.append(tag)
|
||||||
|
m['tags'] = tags
|
||||||
|
db.update(m)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
log.error('Failed tagging: %s', traceback.format_exc())
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def unTag(self, media_id, tag):
|
||||||
|
|
||||||
|
try:
|
||||||
|
db = get_db()
|
||||||
|
m = db.get('id', media_id)
|
||||||
|
|
||||||
|
tags = m.get('tags') or []
|
||||||
|
if tag in tags:
|
||||||
|
new_tags = list(set(tags))
|
||||||
|
new_tags.remove(tag)
|
||||||
|
|
||||||
|
m['tags'] = new_tags
|
||||||
|
db.update(m)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
log.error('Failed untagging: %s', traceback.format_exc())
|
||||||
|
|
||||||
|
return False
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup, SoupStrainer
|
||||||
from couchpotato.core.helpers.variable import tryInt
|
from couchpotato.core.helpers.variable import tryInt
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||||
@@ -20,6 +20,7 @@ class Base(TorrentProvider):
|
|||||||
}
|
}
|
||||||
|
|
||||||
http_time_between_calls = 1 # Seconds
|
http_time_between_calls = 1 # Seconds
|
||||||
|
only_tables_tags = SoupStrainer('table')
|
||||||
|
|
||||||
def _searchOnTitle(self, title, movie, quality, results):
|
def _searchOnTitle(self, title, movie, quality, results):
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ class Base(TorrentProvider):
|
|||||||
data = self.getHTMLData(url)
|
data = self.getHTMLData(url)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
html = BeautifulSoup(data)
|
html = BeautifulSoup(data, 'html.parser', parse_only = self.only_tables_tags)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result_table = html.find('table', attrs = {'class': 'koptekst'})
|
result_table = html.find('table', attrs = {'class': 'koptekst'})
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class MovieBase(MovieTypeBase):
|
|||||||
|
|
||||||
# Default profile and category
|
# Default profile and category
|
||||||
default_profile = {}
|
default_profile = {}
|
||||||
if not params.get('profile_id'):
|
if not params.get('profile_id') and status != 'done':
|
||||||
default_profile = fireEvent('profile.default', single = True)
|
default_profile = fireEvent('profile.default', single = True)
|
||||||
cat_id = params.get('category_id')
|
cat_id = params.get('category_id')
|
||||||
|
|
||||||
@@ -149,6 +149,7 @@ class MovieBase(MovieTypeBase):
|
|||||||
m['profile_id'] = params.get('profile_id', default_profile.get('id'))
|
m['profile_id'] = params.get('profile_id', default_profile.get('id'))
|
||||||
m['category_id'] = cat_id if cat_id is not None and len(cat_id) > 0 else (m.get('category_id') or None)
|
m['category_id'] = cat_id if cat_id is not None and len(cat_id) > 0 else (m.get('category_id') or None)
|
||||||
m['last_edit'] = int(time.time())
|
m['last_edit'] = int(time.time())
|
||||||
|
m['tags'] = []
|
||||||
|
|
||||||
do_search = True
|
do_search = True
|
||||||
db.update(m)
|
db.update(m)
|
||||||
|
|||||||
@@ -365,6 +365,32 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.movies .data .eta {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.movies.details_list .data .eta {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
display: block;
|
||||||
|
min-height: 20px;
|
||||||
|
text-align: right;
|
||||||
|
font-style: italic;
|
||||||
|
opacity: .8;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.movies.details_list .movie:hover .data .eta {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.movies.thumbs_list .data .eta {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.movies .data .quality {
|
.movies .data .quality {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
|
|||||||
@@ -136,6 +136,21 @@ var Movie = new Class({
|
|||||||
|
|
||||||
self.el.addClass('status_'+self.get('status'));
|
self.el.addClass('status_'+self.get('status'));
|
||||||
|
|
||||||
|
var eta = null,
|
||||||
|
eta_date = null,
|
||||||
|
now = Math.round(+new Date()/1000);
|
||||||
|
|
||||||
|
if(self.data.info.release_date)
|
||||||
|
[self.data.info.release_date.dvd, self.data.info.release_date.theater].each(function(timestamp){
|
||||||
|
if (timestamp > 0 && (eta == null || Math.abs(timestamp - now) < Math.abs(eta - now)))
|
||||||
|
eta = timestamp;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(eta){
|
||||||
|
eta_date = new Date(eta * 1000);
|
||||||
|
eta_date = eta_date.toLocaleString('en-us', { month: "long" }) + ' ' + eta_date.getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
self.el.adopt(
|
self.el.adopt(
|
||||||
self.select_checkbox = new Element('input[type=checkbox].inlay', {
|
self.select_checkbox = new Element('input[type=checkbox].inlay', {
|
||||||
'events': {
|
'events': {
|
||||||
@@ -161,6 +176,10 @@ var Movie = new Class({
|
|||||||
self.description = new Element('div.description.tiny_scroll', {
|
self.description = new Element('div.description.tiny_scroll', {
|
||||||
'text': self.data.info.plot
|
'text': self.data.info.plot
|
||||||
}),
|
}),
|
||||||
|
self.eta = eta_date && (now+8035200 > eta) ? new Element('div.eta', {
|
||||||
|
'text': eta_date,
|
||||||
|
'title': 'ETA'
|
||||||
|
}) : null,
|
||||||
self.quality = new Element('div.quality', {
|
self.quality = new Element('div.quality', {
|
||||||
'events': {
|
'events': {
|
||||||
'click': function(e){
|
'click': function(e){
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ config = [{
|
|||||||
'name': 'automation_charts_rentals',
|
'name': 'automation_charts_rentals',
|
||||||
'type': 'bool',
|
'type': 'bool',
|
||||||
'label': 'DVD Rentals',
|
'label': 'DVD Rentals',
|
||||||
'description': 'Top DVD <a href="http://www.imdb.com/boxoffice/rentals/">rentals</a> chart',
|
'description': 'Top DVD <a href="http://www.imdb.com/boxoffice/rentals">rentals</a> chart',
|
||||||
'default': True,
|
'default': True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -312,7 +312,7 @@ config = [{
|
|||||||
'name': 'chart_display_rentals',
|
'name': 'chart_display_rentals',
|
||||||
'type': 'bool',
|
'type': 'bool',
|
||||||
'label': 'DVD Rentals',
|
'label': 'DVD Rentals',
|
||||||
'description': 'Top DVD <a href="http://www.imdb.com/boxoffice/rentals/">rentals</a> chart',
|
'description': 'Top DVD <a href="http://www.imdb.com/boxoffice/rentals">rentals</a> chart',
|
||||||
'default': True,
|
'default': True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -153,8 +153,10 @@ class TheMovieDb(MovieProvider):
|
|||||||
movie_data = dict((k, v) for k, v in movie_data.items() if v)
|
movie_data = dict((k, v) for k, v in movie_data.items() if v)
|
||||||
|
|
||||||
# Add alternative names
|
# Add alternative names
|
||||||
|
if movie_data['original_title'] and movie_data['original_title'] not in movie_data['titles']:
|
||||||
|
movie_data['titles'].insert(0, movie_data['original_title'])
|
||||||
|
|
||||||
if extended:
|
if extended:
|
||||||
movie_data['titles'].append(movie.originaltitle)
|
|
||||||
for alt in movie.alternate_titles:
|
for alt in movie.alternate_titles:
|
||||||
alt_name = alt.title
|
alt_name = alt.title
|
||||||
if alt_name and alt_name not in movie_data['titles'] and alt_name.lower() != 'none' and alt_name is not None:
|
if alt_name and alt_name not in movie_data['titles'] and alt_name.lower() != 'none' and alt_name is not None:
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
outside_eta_results = 0
|
outside_eta_results = 0
|
||||||
alway_search = self.conf('always_search')
|
alway_search = self.conf('always_search')
|
||||||
ignore_eta = manual
|
ignore_eta = manual
|
||||||
|
total_result_count = 0
|
||||||
|
|
||||||
default_title = getTitle(movie)
|
default_title = getTitle(movie)
|
||||||
if not default_title:
|
if not default_title:
|
||||||
@@ -199,6 +200,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
|
|
||||||
results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or []
|
results = fireEvent('searcher.search', search_protocols, movie, quality, single = True) or []
|
||||||
results_count = len(results)
|
results_count = len(results)
|
||||||
|
total_result_count += results_count
|
||||||
if results_count == 0:
|
if results_count == 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']))
|
||||||
|
|
||||||
@@ -235,6 +237,9 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
|
|||||||
if self.shuttingDown() or ret:
|
if self.shuttingDown() or ret:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if total_result_count > 0:
|
||||||
|
fireEvent('media.tag', movie['_id'], 'recent', single = True)
|
||||||
|
|
||||||
if len(too_early_to_search) > 0:
|
if len(too_early_to_search) > 0:
|
||||||
log.info2('Too early to search for %s, %s', (too_early_to_search, default_title))
|
log.info2('Too early to search for %s, %s', (too_early_to_search, default_title))
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class Manage(Plugin):
|
|||||||
# Get movies with done status
|
# Get movies with done status
|
||||||
total_movies, done_movies = fireEvent('media.list', types = 'movie', status = 'done', release_status = 'done', status_or = True, single = True)
|
total_movies, done_movies = fireEvent('media.list', types = 'movie', status = 'done', release_status = 'done', status_or = True, single = True)
|
||||||
|
|
||||||
|
deleted_releases = []
|
||||||
for done_movie in done_movies:
|
for done_movie in done_movies:
|
||||||
if getIdentifier(done_movie) not in added_identifiers:
|
if getIdentifier(done_movie) not in added_identifiers:
|
||||||
fireEvent('media.delete', media_id = done_movie['_id'], delete_from = 'all')
|
fireEvent('media.delete', media_id = done_movie['_id'], delete_from = 'all')
|
||||||
@@ -165,12 +166,11 @@ class Manage(Plugin):
|
|||||||
already_used = used_files.get(release_file)
|
already_used = used_files.get(release_file)
|
||||||
|
|
||||||
if already_used:
|
if already_used:
|
||||||
# delete current one
|
if release_id not in deleted_releases:
|
||||||
if already_used.get('last_edit', 0) < release.get('last_edit', 0):
|
release_id = release['_id'] if already_used.get('last_edit', 0) < release.get('last_edit', 0) else already_used['_id']
|
||||||
fireEvent('release.delete', release['_id'], single = True)
|
fireEvent('release.delete', release_id, single = True)
|
||||||
# delete previous one
|
|
||||||
else:
|
deleted_releases.append(release_id)
|
||||||
fireEvent('release.delete', already_used['_id'], single = True)
|
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
used_files[release_file] = release
|
used_files[release_file] = release
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import traceback
|
import traceback
|
||||||
import re
|
import re
|
||||||
from CodernityDB.database import RecordNotFound
|
|
||||||
|
|
||||||
|
from CodernityDB.database import RecordNotFound
|
||||||
from couchpotato import get_db
|
from couchpotato import get_db
|
||||||
from couchpotato.api import addApiView
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.event import addEvent
|
from couchpotato.core.event import addEvent, fireEvent
|
||||||
from couchpotato.core.helpers.encoding import toUnicode, ss
|
from couchpotato.core.helpers.encoding import toUnicode, ss
|
||||||
from couchpotato.core.helpers.variable import mergeDicts, getExt, tryInt
|
from couchpotato.core.helpers.variable import mergeDicts, getExt, tryInt, splitString
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
from couchpotato.core.plugins.base import Plugin
|
from couchpotato.core.plugins.base import Plugin
|
||||||
from couchpotato.core.plugins.quality.index import QualityIndex
|
from couchpotato.core.plugins.quality.index import QualityIndex
|
||||||
@@ -22,12 +22,12 @@ class QualityPlugin(Plugin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
qualities = [
|
qualities = [
|
||||||
{'identifier': 'bd50', 'hd': True, 'allow_3d': True, 'size': (20000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25'], 'allow': ['1080p'], 'ext':['iso', 'img'], 'tags': ['bdmv', 'certificate', ('complete', 'bluray'), 'avc', 'mvc']},
|
{'identifier': 'bd50', 'hd': True, 'allow_3d': True, 'size': (20000, 60000), 'label': 'BR-Disk', 'alternative': ['bd25', ('br', 'disk')], 'allow': ['1080p'], 'ext':['iso', 'img'], 'tags': ['bdmv', 'certificate', ('complete', 'bluray'), 'avc', 'mvc']},
|
||||||
{'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': '1080p', 'hd': True, 'allow_3d': True, 'size': (4000, 20000), 'label': '1080p', 'width': 1920, 'height': 1080, 'alternative': [], 'allow': [], 'ext':['mkv', 'm2ts', 'ts'], 'tags': ['m2ts', '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': '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, 'allow_3d': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip'], 'allow': ['720p', '1080p'], 'ext':[], 'tags': ['hdtv', 'hdrip', 'webdl', ('web', 'dl')]},
|
{'identifier': 'brrip', 'hd': True, 'allow_3d': True, 'size': (700, 7000), 'label': 'BR-Rip', 'alternative': ['bdrip', ('br', 'rip')], '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'), 'dvd9']},
|
{'identifier': 'dvdr', 'size': (3000, 10000), 'label': 'DVD-R', 'alternative': ['br2dvd', ('dvd', 'r')], 'allow': [], 'ext':['iso', 'img', 'vob'], 'tags': ['pal', 'ntsc', 'video_ts', 'audio_ts', ('dvd', 'r'), 'dvd9']},
|
||||||
{'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': [('dvd', 'rip')], 'allow': [], 'ext':[], 'tags': [('dvd', 'rip'), ('dvd', 'xvid'), ('dvd', 'divx')]},
|
||||||
{'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip', 'dvdscreener', 'hdscr'], 'allow': ['dvdr', 'dvdrip', '720p', '1080p'], 'ext':[], 'tags': ['webrip', ('web', 'rip')]},
|
{'identifier': 'scr', 'size': (600, 1600), 'label': 'Screener', 'alternative': ['screener', 'dvdscr', 'ppvrip', 'dvdscreener', 'hdscr'], 'allow': ['dvdr', 'dvdrip', '720p', '1080p'], 'ext':[], 'tags': ['webrip', ('web', 'rip')]},
|
||||||
{'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': ['r6'], 'allow': ['dvdr'], 'ext':[]},
|
{'identifier': 'r5', 'size': (600, 1000), 'label': 'R5', 'alternative': ['r6'], 'allow': ['dvdr'], 'ext':[]},
|
||||||
{'identifier': 'tc', 'size': (600, 1000), 'label': 'TeleCine', 'alternative': ['telecine'], 'allow': [], 'ext':[]},
|
{'identifier': 'tc', 'size': (600, 1000), 'label': 'TeleCine', 'alternative': ['telecine'], 'allow': [], 'ext':[]},
|
||||||
@@ -95,15 +95,14 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
qualities = db.all('quality', with_doc = True)
|
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for quality in qualities:
|
for quality in self.qualities:
|
||||||
quality = quality['doc']
|
quality_doc = db.get('quality', quality.get('identifier'), with_doc = True)['doc']
|
||||||
q = mergeDicts(self.getQuality(quality.get('identifier')), quality)
|
q = mergeDicts(quality, quality_doc)
|
||||||
temp.append(q)
|
temp.append(q)
|
||||||
|
|
||||||
self.cached_qualities = temp
|
if len(temp) == len(self.qualities):
|
||||||
|
self.cached_qualities = temp
|
||||||
|
|
||||||
return temp
|
return temp
|
||||||
|
|
||||||
@@ -209,10 +208,15 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
for cur_file in files:
|
for cur_file in files:
|
||||||
words = re.split('\W+', cur_file.lower())
|
words = re.split('\W+', cur_file.lower())
|
||||||
|
name_year = fireEvent('scanner.name_year', cur_file, file_name = cur_file, single = True)
|
||||||
|
threed_words = words
|
||||||
|
if name_year and name_year.get('name'):
|
||||||
|
split_name = splitString(name_year.get('name'), ' ')
|
||||||
|
threed_words = [x for x in words if x not in split_name]
|
||||||
|
|
||||||
for quality in qualities:
|
for quality in qualities:
|
||||||
contains_score = self.containsTagScore(quality, words, cur_file)
|
contains_score = self.containsTagScore(quality, words, cur_file)
|
||||||
threedscore = self.contains3D(quality, words, cur_file) if quality.get('allow_3d') else (0, None)
|
threedscore = self.contains3D(quality, threed_words, cur_file) if quality.get('allow_3d') else (0, None)
|
||||||
|
|
||||||
self.calcScore(score, quality, contains_score, threedscore)
|
self.calcScore(score, quality, contains_score, threedscore)
|
||||||
|
|
||||||
@@ -257,6 +261,9 @@ class QualityPlugin(Plugin):
|
|||||||
cur_file = ss(cur_file)
|
cur_file = ss(cur_file)
|
||||||
score = 0
|
score = 0
|
||||||
|
|
||||||
|
extension = words[-1]
|
||||||
|
words = words[:-1]
|
||||||
|
|
||||||
points = {
|
points = {
|
||||||
'identifier': 10,
|
'identifier': 10,
|
||||||
'label': 10,
|
'label': 10,
|
||||||
@@ -276,7 +283,7 @@ class QualityPlugin(Plugin):
|
|||||||
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 words:
|
||||||
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
|
||||||
|
|
||||||
@@ -286,8 +293,8 @@ class QualityPlugin(Plugin):
|
|||||||
|
|
||||||
# Check extention
|
# Check extention
|
||||||
for ext in quality.get('ext', []):
|
for ext in quality.get('ext', []):
|
||||||
if ext == words[-1]:
|
if ext == extension:
|
||||||
log.debug('Found %s extension in %s', (ext, cur_file))
|
log.debug('Found %s with .%s extension in %s', (quality['identifier'], ext, cur_file))
|
||||||
score += points['ext']
|
score += points['ext']
|
||||||
|
|
||||||
return score
|
return score
|
||||||
@@ -433,7 +440,12 @@ class QualityPlugin(Plugin):
|
|||||||
'Movie Monuments 2013 BrRip 720p': {'size': 1300, 'quality': 'brrip'},
|
'Movie Monuments 2013 BrRip 720p': {'size': 1300, 'quality': 'brrip'},
|
||||||
'The.Movie.2014.3D.1080p.BluRay.AVC.DTS-HD.MA.5.1-GroupName': {'size': 30000, 'quality': 'bd50', 'is_3d': True},
|
'The.Movie.2014.3D.1080p.BluRay.AVC.DTS-HD.MA.5.1-GroupName': {'size': 30000, 'quality': 'bd50', 'is_3d': True},
|
||||||
'/home/namehou/Movie Monuments (2013)/Movie Monuments.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': False},
|
'/home/namehou/Movie Monuments (2013)/Movie Monuments.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': False},
|
||||||
'/home/namehou/Movie Monuments (2013)/Movie Monuments Full-OU.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': True}
|
'/home/namehou/Movie Monuments (2013)/Movie Monuments Full-OU.mkv': {'size': 4500, 'quality': '1080p', 'is_3d': True},
|
||||||
|
'/volume1/Public/3D/Moviename/Moviename (2009).3D.SBS.ts': {'size': 7500, 'quality': '1080p', 'is_3d': True},
|
||||||
|
'/volume1/Public/Moviename/Moviename (2009).ts': {'size': 5500, 'quality': '1080p'},
|
||||||
|
'/movies/BluRay HDDVD H.264 MKV 720p EngSub/QuiQui le fou (criterion collection #123, 1915)/QuiQui le fou (1915) 720p x264 BluRay.mkv': {'size': 5500, 'quality': '720p'},
|
||||||
|
'C:\\movies\QuiQui le fou (collection #123, 1915)\QuiQui le fou (1915) 720p x264 BluRay.mkv': {'size': 5500, 'quality': '720p'},
|
||||||
|
'C:\\movies\QuiQui le fou (collection #123, 1915)\QuiQui le fou (1915) half-sbs 720p x264 BluRay.mkv': {'size': 5500, 'quality': '720p', 'is_3d': True},
|
||||||
}
|
}
|
||||||
|
|
||||||
correct = 0
|
correct = 0
|
||||||
@@ -441,7 +453,10 @@ class QualityPlugin(Plugin):
|
|||||||
test_quality = self.guess(files = [name], extra = tests[name].get('extra', None), size = tests[name].get('size', None)) or {}
|
test_quality = self.guess(files = [name], extra = tests[name].get('extra', None), size = tests[name].get('size', None)) or {}
|
||||||
success = test_quality.get('identifier') == tests[name]['quality'] and test_quality.get('is_3d') == tests[name].get('is_3d', False)
|
success = test_quality.get('identifier') == tests[name]['quality'] and test_quality.get('is_3d') == tests[name].get('is_3d', False)
|
||||||
if not success:
|
if not success:
|
||||||
log.error('%s failed check, thinks it\'s %s', (name, test_quality.get('identifier')))
|
log.error('%s failed check, thinks it\'s "%s" expecting "%s"', (name,
|
||||||
|
test_quality.get('identifier') + (' 3D' if test_quality.get('is_3d') else ''),
|
||||||
|
tests[name]['quality'] + (' 3D' if tests[name].get('is_3d') else '')
|
||||||
|
))
|
||||||
|
|
||||||
correct += success
|
correct += success
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ var QualityBase = new Class({
|
|||||||
|
|
||||||
self.qualities = data.qualities;
|
self.qualities = data.qualities;
|
||||||
|
|
||||||
|
self.profiles_list = null;
|
||||||
self.profiles = [];
|
self.profiles = [];
|
||||||
Array.each(data.profiles, self.createProfilesClass.bind(self));
|
Array.each(data.profiles, self.createProfilesClass.bind(self));
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ var QualityBase = new Class({
|
|||||||
}).pick();
|
}).pick();
|
||||||
}
|
}
|
||||||
catch(e){}
|
catch(e){}
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -106,14 +107,13 @@ var QualityBase = new Class({
|
|||||||
createProfileOrdering: function(){
|
createProfileOrdering: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var profile_list;
|
|
||||||
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(
|
||||||
new Element('.ctrlHolder#profile_ordering').adopt(
|
new Element('.ctrlHolder#profile_ordering').adopt(
|
||||||
new Element('label[text=Order]'),
|
new Element('label[text=Order]'),
|
||||||
profile_list = new Element('ul'),
|
self.profiles_list = new Element('ul'),
|
||||||
new Element('p.formHint', {
|
new Element('p.formHint', {
|
||||||
'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.'
|
||||||
})
|
})
|
||||||
@@ -133,7 +133,7 @@ var QualityBase = new Class({
|
|||||||
'text': profile.data.label
|
'text': profile.data.label
|
||||||
}),
|
}),
|
||||||
new Element('span.handle')
|
new Element('span.handle')
|
||||||
).inject(profile_list);
|
).inject(self.profiles_list);
|
||||||
|
|
||||||
new Form.Check(check);
|
new Form.Check(check);
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ var QualityBase = new Class({
|
|||||||
|
|
||||||
// Sortable
|
// Sortable
|
||||||
var sorted_changed = false;
|
var sorted_changed = false;
|
||||||
self.profile_sortable = new Sortables(profile_list, {
|
self.profile_sortable = new Sortables(self.profiles_list, {
|
||||||
'revert': true,
|
'revert': true,
|
||||||
'handle': '.handle',
|
'handle': '.handle',
|
||||||
'opacity': 0.5,
|
'opacity': 0.5,
|
||||||
@@ -163,7 +163,7 @@ var QualityBase = new Class({
|
|||||||
ids = [],
|
ids = [],
|
||||||
hidden = [];
|
hidden = [];
|
||||||
|
|
||||||
self.profile_sortable.list.getElements('li').each(function(el, nr){
|
self.profiles_list.getElements('li').each(function(el, nr){
|
||||||
ids.include(el.get('data-id'));
|
ids.include(el.get('data-id'));
|
||||||
hidden[nr] = +!el.getElement('input[type=checkbox]').get('checked');
|
hidden[nr] = +!el.getElement('input[type=checkbox]').get('checked');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ class Release(Plugin):
|
|||||||
elif rel['status'] in ['snatched', 'downloaded']:
|
elif rel['status'] in ['snatched', 'downloaded']:
|
||||||
self.updateStatus(rel['_id'], status = 'ignore')
|
self.updateStatus(rel['_id'], status = 'ignore')
|
||||||
|
|
||||||
|
fireEvent('media.untag', media.get('_id'), 'recent', single = True)
|
||||||
|
|
||||||
def add(self, group, update_info = True, update_id = None):
|
def add(self, group, update_info = True, update_id = None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -149,7 +151,7 @@ class Release(Plugin):
|
|||||||
r = db.get('release_identifier', release_identifier, with_doc = True)['doc']
|
r = db.get('release_identifier', release_identifier, with_doc = True)['doc']
|
||||||
r['media_id'] = media['_id']
|
r['media_id'] = media['_id']
|
||||||
except:
|
except:
|
||||||
log.error('Failed updating release by identifier: %s', traceback.format_exc())
|
log.debug('Failed updating release by identifier "%s". Inserting new.', release_identifier)
|
||||||
r = db.insert(release)
|
r = db.insert(release)
|
||||||
|
|
||||||
# Update with ref and _id
|
# Update with ref and _id
|
||||||
@@ -184,7 +186,7 @@ class Release(Plugin):
|
|||||||
db.delete(rel)
|
db.delete(rel)
|
||||||
return True
|
return True
|
||||||
except RecordDeleted:
|
except RecordDeleted:
|
||||||
log.error('Already deleted: %s', release_id)
|
log.debug('Already deleted: %s', release_id)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
log.error('Failed: %s', traceback.format_exc())
|
log.error('Failed: %s', traceback.format_exc())
|
||||||
@@ -346,6 +348,8 @@ class Release(Plugin):
|
|||||||
mdia['last_edit'] = int(time.time())
|
mdia['last_edit'] = int(time.time())
|
||||||
db.update(mdia)
|
db.update(mdia)
|
||||||
|
|
||||||
|
fireEvent('media.tag', media['_id'], 'recent', single = True)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Assume release downloaded
|
# Assume release downloaded
|
||||||
|
|||||||
@@ -457,9 +457,15 @@ class Renamer(Plugin):
|
|||||||
mdia['last_edit'] = int(time.time())
|
mdia['last_edit'] = int(time.time())
|
||||||
db.update(mdia)
|
db.update(mdia)
|
||||||
|
|
||||||
|
# List movie on dashboard
|
||||||
|
fireEvent('media.tag', media['_id'], 'recent', single = True)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
log.error('Failed marking movie finished: %s', (traceback.format_exc()))
|
log.error('Failed marking movie finished: %s', (traceback.format_exc()))
|
||||||
|
|
||||||
|
# Mark media for dashboard
|
||||||
|
mark_as_recent = False
|
||||||
|
|
||||||
# Go over current movie releases
|
# Go over current movie releases
|
||||||
for release in fireEvent('release.for_media', media['_id'], single = True):
|
for release in fireEvent('release.for_media', media['_id'], single = True):
|
||||||
|
|
||||||
@@ -506,14 +512,21 @@ class Renamer(Plugin):
|
|||||||
# Set the release to downloaded
|
# Set the release to downloaded
|
||||||
fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True)
|
fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True)
|
||||||
group['release_download'] = release_download
|
group['release_download'] = release_download
|
||||||
|
mark_as_recent = True
|
||||||
elif release_download['status'] == 'seeding':
|
elif release_download['status'] == 'seeding':
|
||||||
# Set the release to seeding
|
# Set the release to seeding
|
||||||
fireEvent('release.update_status', release['_id'], status = 'seeding', single = True)
|
fireEvent('release.update_status', release['_id'], status = 'seeding', single = True)
|
||||||
|
mark_as_recent = True
|
||||||
|
|
||||||
elif release.get('identifier') == group['meta_data']['quality']['identifier']:
|
elif release.get('identifier') == group['meta_data']['quality']['identifier']:
|
||||||
# Set the release to downloaded
|
# Set the release to downloaded
|
||||||
fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True)
|
fireEvent('release.update_status', release['_id'], status = 'downloaded', single = True)
|
||||||
group['release_download'] = release_download
|
group['release_download'] = release_download
|
||||||
|
mark_as_recent = True
|
||||||
|
|
||||||
|
# Mark media for dashboard
|
||||||
|
if mark_as_recent:
|
||||||
|
fireEvent('media.tag', group['media'].get('_id'), 'recent', single = True)
|
||||||
|
|
||||||
# Remove leftover files
|
# Remove leftover files
|
||||||
if not remove_leftovers: # Don't remove anything
|
if not remove_leftovers: # Don't remove anything
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class Scanner(Plugin):
|
|||||||
'HDTV': ['hdtv']
|
'HDTV': ['hdtv']
|
||||||
}
|
}
|
||||||
|
|
||||||
clean = '([ _\,\.\(\)\[\]\-]|^)(3d|hsbs|sbs|ou|extended.cut|directors.cut|french|fr|swedisch|sw|danish|dutch|nl|swesub|subs|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip' \
|
clean = '([ _\,\.\(\)\[\]\-]|^)(3d|hsbs|sbs|half.sbs|full.sbs|ou|half.ou|full.ou|extended.cut|directors.cut|french|fr|swedisch|sw|danish|dutch|nl|swesub|subs|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip' \
|
||||||
'|hdtvrip|webdl|web.dl|webrip|web.rip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|video_ts|audio_ts|480p|480i|576p|576i|720p|720i|1080p|1080i|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|hc|\[.*\])(?=[ _\,\.\(\)\[\]\-]|$)'
|
'|hdtvrip|webdl|web.dl|webrip|web.rip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|r3|r5|bd5|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|video_ts|audio_ts|480p|480i|576p|576i|720p|720i|1080p|1080i|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|hc|\[.*\])(?=[ _\,\.\(\)\[\]\-]|$)'
|
||||||
multipart_regex = [
|
multipart_regex = [
|
||||||
'[ _\.-]+cd[ _\.-]*([0-9a-d]+)', #*cd1
|
'[ _\.-]+cd[ _\.-]*([0-9a-d]+)', #*cd1
|
||||||
@@ -903,6 +903,7 @@ class Scanner(Plugin):
|
|||||||
log.debug('Could not detect via guessit "%s": %s', (file_name, traceback.format_exc()))
|
log.debug('Could not detect via guessit "%s": %s', (file_name, traceback.format_exc()))
|
||||||
|
|
||||||
# Backup to simple
|
# Backup to simple
|
||||||
|
release_name = os.path.basename(release_name.replace('\\', '/'))
|
||||||
cleaned = ' '.join(re.split('\W+', simplifyString(release_name)))
|
cleaned = ' '.join(re.split('\W+', simplifyString(release_name)))
|
||||||
cleaned = re.sub(self.clean, ' ', cleaned)
|
cleaned = re.sub(self.clean, ' ', cleaned)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import os
|
|||||||
|
|
||||||
from couchpotato.core.database import Database
|
from couchpotato.core.database import Database
|
||||||
from couchpotato.core.event import fireEvent, addEvent
|
from couchpotato.core.event import fireEvent, addEvent
|
||||||
|
from couchpotato.core.helpers.encoding import toUnicode
|
||||||
from couchpotato.core.loader import Loader
|
from couchpotato.core.loader import Loader
|
||||||
from couchpotato.core.settings import Settings
|
from couchpotato.core.settings import Settings
|
||||||
|
|
||||||
@@ -38,8 +39,11 @@ class Env(object):
|
|||||||
return Env._debug
|
return Env._debug
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(attr):
|
def get(attr, unicode = False):
|
||||||
return getattr(Env, '_' + attr)
|
if unicode:
|
||||||
|
return toUnicode(getattr(Env, '_' + attr))
|
||||||
|
else:
|
||||||
|
return getattr(Env, '_' + attr)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def all():
|
def all():
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ Page.Home = new Class({
|
|||||||
})
|
})
|
||||||
),
|
),
|
||||||
'filter': {
|
'filter': {
|
||||||
'release_status': 'snatched,seeding,missing,available,downloaded'
|
'release_status': 'snatched,missing,available,downloaded,done,seeding',
|
||||||
|
'with_tags': 'recent'
|
||||||
},
|
},
|
||||||
'limit': null,
|
'limit': null,
|
||||||
'onLoaded': function(){
|
'onLoaded': function(){
|
||||||
|
|||||||
@@ -73,10 +73,10 @@
|
|||||||
|
|
||||||
App.setup({
|
App.setup({
|
||||||
'base_url': {{ json_encode(Env.get('web_base')) }},
|
'base_url': {{ json_encode(Env.get('web_base')) }},
|
||||||
'args': {{ json_encode(Env.get('args')) }},
|
'args': {{ json_encode(Env.get('args', unicode = True)) }},
|
||||||
'options': {{ json_encode(('%s' % Env.get('options'))) }},
|
'options': {{ json_encode(('%s' % Env.get('options'))) }},
|
||||||
'app_dir': {{ json_encode(Env.get('app_dir')) }},
|
'app_dir': {{ json_encode(Env.get('app_dir', unicode = True)) }},
|
||||||
'data_dir': {{ json_encode(Env.get('data_dir')) }},
|
'data_dir': {{ json_encode(Env.get('data_dir', unicode = True)) }},
|
||||||
'pid': {{ json_encode(Env.getPid()) }},
|
'pid': {{ json_encode(Env.getPid()) }},
|
||||||
'userscript_version': {{ json_encode(fireEvent('userscript.get_version', single = True)) }}
|
'userscript_version': {{ json_encode(fireEvent('userscript.get_version', single = True)) }}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user