Manage page base
This commit is contained in:
@@ -67,7 +67,7 @@ def getImdb(txt):
|
||||
output.close()
|
||||
|
||||
try:
|
||||
id = re.findall('imdb\.com\/title\/(tt\d{7})', txt)[0]
|
||||
id = re.findall('(tt\d{7})', txt)[0]
|
||||
return id
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
@@ -164,7 +164,7 @@ class Plugin(object):
|
||||
def getCache(self, cache_key, url = None):
|
||||
cache = Env.get('cache').get(cache_key)
|
||||
if cache:
|
||||
log.debug('Getting cache %s' % cache_key)
|
||||
if not Env.setting('development'): log.debug('Getting cache %s' % cache_key)
|
||||
return cache
|
||||
|
||||
if url:
|
||||
|
||||
@@ -27,8 +27,8 @@ class FileManager(Plugin):
|
||||
|
||||
def showImage(self, filename = ''):
|
||||
|
||||
filename = filename.replace(cache_dir[1:] + '/', '')
|
||||
cache_dir = Env.get('cache_dir')
|
||||
filename = filename.replace(cache_dir[1:] + '/', '')
|
||||
|
||||
return send_from_directory(cache_dir, filename)
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
from .main import Manage
|
||||
|
||||
def start():
|
||||
return Manage()
|
||||
|
||||
config = [{
|
||||
'name': 'manage',
|
||||
'groups': [
|
||||
{
|
||||
'tab': 'renamer',
|
||||
'label': 'movie library manager',
|
||||
'description': 'Add multiple movie folders.',
|
||||
'wizard': True,
|
||||
'options': [
|
||||
{
|
||||
'name': 'enabled',
|
||||
'default': False,
|
||||
'type': 'enabler',
|
||||
},
|
||||
{
|
||||
'name': 'library',
|
||||
'type': 'directories',
|
||||
'description': 'Folder where the movies should be moved to.',
|
||||
},
|
||||
{
|
||||
'label': 'Cleanup After',
|
||||
'name': 'cleanup',
|
||||
'type': 'bool',
|
||||
'description': 'Remove movie from db if it can\'t be found after re-scan.',
|
||||
'default': True,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}]
|
||||
@@ -0,0 +1,65 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent, addEvent, fireEventAsync
|
||||
from couchpotato.core.helpers.request import jsonified, getParams
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import File
|
||||
from couchpotato.environment import Env
|
||||
import time
|
||||
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
class Manage(Plugin):
|
||||
|
||||
last_update = 0
|
||||
|
||||
def __init__(self):
|
||||
|
||||
fireEvent('scheduler.interval', identifier = 'manage.update_library', handle = self.updateLibrary, hours = 2)
|
||||
|
||||
addEvent('manage.update', self.updateLibrary)
|
||||
addApiView('manage.update', self.updateLibraryView)
|
||||
|
||||
if not Env.setting('development'):
|
||||
addEvent('app.load', self.updateLibrary)
|
||||
|
||||
def updateLibraryView(self):
|
||||
|
||||
params = getParams()
|
||||
|
||||
fireEventAsync('manage.update', full = params.get('full', True))
|
||||
|
||||
return jsonified({
|
||||
'success': True
|
||||
})
|
||||
|
||||
|
||||
def updateLibrary(self, full = False):
|
||||
|
||||
if self.isDisabled() or (self.last_update > time.time() - 20):
|
||||
return
|
||||
|
||||
directories = self.directories()
|
||||
|
||||
log.info('Updating manage library: %s' % directories)
|
||||
|
||||
for directory in directories:
|
||||
fireEvent('scanner.folder', folder = directory)
|
||||
|
||||
# If cleanup option is enabled, remove offline files from database
|
||||
if self.conf('cleanup'):
|
||||
db = get_session()
|
||||
files_in_path = db.query(File).filter(File.path.like(directory + '%%')).filter_by(available = 0).all()
|
||||
[db.delete(x) for x in files_in_path]
|
||||
db.commit()
|
||||
db.remove()
|
||||
|
||||
self.last_update = time.time()
|
||||
|
||||
def directories(self):
|
||||
try:
|
||||
return self.conf('library', default = '').split('::')
|
||||
except:
|
||||
return []
|
||||
@@ -2,12 +2,15 @@ from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent, fireEventAsync, addEvent
|
||||
from couchpotato.core.helpers.request import getParams, jsonified
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Movie
|
||||
from couchpotato.environment import Env
|
||||
from sqlalchemy.sql.expression import or_
|
||||
from urllib import urlencode
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class MoviePlugin(Plugin):
|
||||
|
||||
@@ -30,6 +33,7 @@ class MoviePlugin(Plugin):
|
||||
|
||||
addEvent('movie.get', self.get)
|
||||
addEvent('movie.list', self.list)
|
||||
addEvent('movie.restatus', self.restatus)
|
||||
|
||||
def get(self, movie_id):
|
||||
|
||||
@@ -146,7 +150,7 @@ class MoviePlugin(Plugin):
|
||||
def edit(self):
|
||||
|
||||
params = getParams()
|
||||
db = get_session();
|
||||
db = get_session()
|
||||
|
||||
m = db.query(Movie).filter_by(id = params.get('id')).first()
|
||||
m.profile_id = params.get('profile_id')
|
||||
@@ -157,6 +161,11 @@ class MoviePlugin(Plugin):
|
||||
|
||||
db.commit()
|
||||
|
||||
fireEvent('movie.restatus', m.id)
|
||||
|
||||
movie_dict = m.to_dict(self.default_dict)
|
||||
fireEventAsync('searcher.single', movie_dict)
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
})
|
||||
@@ -175,3 +184,28 @@ class MoviePlugin(Plugin):
|
||||
return jsonified({
|
||||
'success': True,
|
||||
})
|
||||
|
||||
def restatus(self, movie_id):
|
||||
|
||||
active_status = fireEvent('status.get', 'active', single = True)
|
||||
done_status = fireEvent('status.get', 'done', single = True)
|
||||
|
||||
db = get_session()
|
||||
|
||||
m = db.query(Movie).filter_by(id = movie_id).first()
|
||||
|
||||
if not m.profile:
|
||||
return
|
||||
|
||||
log.debug('Changing status for %s' % (m.library.titles[0].title))
|
||||
|
||||
move_to_wanted = True
|
||||
|
||||
for t in m.profile.types:
|
||||
for release in m.releases:
|
||||
if t.quality.identifier is release.quality.identifier and (release.status_id is done_status.get('id') and t.finish):
|
||||
move_to_wanted = False
|
||||
|
||||
m.status_id = active_status.get('id') if move_to_wanted else done_status.get('id')
|
||||
|
||||
db.commit()
|
||||
|
||||
@@ -9,7 +9,7 @@ var Movie = new Class({
|
||||
|
||||
self.data = data;
|
||||
|
||||
self.profile = Quality.getProfile(data.profile_id);
|
||||
self.profile = Quality.getProfile(data.profile_id) || {};
|
||||
self.parent(self, options);
|
||||
self.addEvent('injected', self.afterInject.bind(self))
|
||||
},
|
||||
@@ -39,26 +39,31 @@ var Movie = new Class({
|
||||
self.description = new Element('div.description', {
|
||||
'text': self.data.library.plot
|
||||
}),
|
||||
self.quality = new Element('div.quality', {
|
||||
'text': self.profile.get('label')+ ':'
|
||||
})
|
||||
self.quality = new Element('div.quality')
|
||||
),
|
||||
self.actions = new Element('div.actions')
|
||||
)
|
||||
);
|
||||
|
||||
self.profile.get('types').each(function(type){
|
||||
// Add profile
|
||||
if(self.profile.data)
|
||||
self.profile.getTypes().each(function(type){
|
||||
|
||||
var q = self.addQuality(type.quality_id || type.get('quality_id'));
|
||||
if(type.finish || type.get('finish'))
|
||||
q.addClass('finish');
|
||||
|
||||
// Check if quality is snatched
|
||||
var is_snatched = self.data.releases.filter(function(release){
|
||||
return release.quality_id == type.quality_id && release.status.identifier == 'snatched'
|
||||
}).pick();
|
||||
});
|
||||
|
||||
// Add done releases
|
||||
Array.each(self.data.releases, function(release){
|
||||
|
||||
var q = self.quality.getElement('.q_'+ release.quality.identifier);
|
||||
if(!q)
|
||||
var q = self.addQuality(release.quality_id)
|
||||
|
||||
q.addClass(release.status.identifier);
|
||||
|
||||
var q = Quality.getQuality(type.quality_id);
|
||||
new Element('span', {
|
||||
'text': q.label,
|
||||
'class': is_snatched ? 'snatched' : ''
|
||||
}).inject(self.quality);
|
||||
});
|
||||
|
||||
Object.each(self.options.actions, function(action, key){
|
||||
@@ -72,6 +77,17 @@ var Movie = new Class({
|
||||
|
||||
},
|
||||
|
||||
addQuality: function(quality_id){
|
||||
var self = this;
|
||||
|
||||
var q = Quality.getQuality(quality_id);
|
||||
return new Element('span', {
|
||||
'text': q.label,
|
||||
'class': 'q_'+q.identifier
|
||||
}).inject(self.quality);
|
||||
|
||||
},
|
||||
|
||||
afterInject: function(){
|
||||
var self = this;
|
||||
|
||||
@@ -225,7 +241,7 @@ var ReleaseAction = new Class({
|
||||
$(self.movie.thumbnail).clone(),
|
||||
self.release_container = new Element('div.releases')
|
||||
).inject(self.movie, 'top');
|
||||
|
||||
|
||||
// Header
|
||||
new Element('div.item.head').adopt(
|
||||
new Element('span.name', {'text': 'Release name'}),
|
||||
@@ -278,17 +294,17 @@ var ReleaseAction = new Class({
|
||||
return type == info.identifier
|
||||
}).pick() || {}).value
|
||||
},
|
||||
|
||||
|
||||
download: function(release){
|
||||
var self = this;
|
||||
|
||||
|
||||
Api.request('release.download', {
|
||||
'data': {
|
||||
'id': release.id
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
del: function(release){
|
||||
var self = this;
|
||||
|
||||
@@ -297,7 +313,7 @@ var ReleaseAction = new Class({
|
||||
'id': release.id
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@@ -58,7 +58,7 @@ var Profile = new Class({
|
||||
|
||||
if(data.types)
|
||||
Object.each(data.types, self.addType.bind(self))
|
||||
|
||||
|
||||
self.addType();
|
||||
},
|
||||
|
||||
@@ -133,6 +133,15 @@ var Profile = new Class({
|
||||
|
||||
},
|
||||
|
||||
getTypes: function(){
|
||||
var self = this;
|
||||
|
||||
return self.types.filter(function(type){
|
||||
return type.get('quality_id')
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
del: function(){
|
||||
var self = this;
|
||||
|
||||
@@ -281,6 +290,10 @@ Profile.Type = new Class({
|
||||
}
|
||||
},
|
||||
|
||||
get: function(key){
|
||||
return this.data[key];
|
||||
},
|
||||
|
||||
del: function(){
|
||||
var self = this;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.request import jsonified, getParams
|
||||
from couchpotato.core.helpers.variable import mergeDicts, md5
|
||||
from couchpotato.core.helpers.variable import mergeDicts, md5, getExt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Quality, Profile, ProfileType
|
||||
@@ -136,7 +136,7 @@ class QualityPlugin(Plugin):
|
||||
def guess(self, files, extra = {}, loose = False):
|
||||
|
||||
# Create hash for cache
|
||||
hash = md5(str(files))
|
||||
hash = md5(str([f.replace('.' + getExt(f), '') for f in files]))
|
||||
cached = self.getCache(hash)
|
||||
if cached: return cached
|
||||
|
||||
@@ -148,15 +148,15 @@ class QualityPlugin(Plugin):
|
||||
|
||||
# Check tags
|
||||
if quality['identifier'] in words:
|
||||
log.debug('Found via identifier "%s" in %s' % (quality['identifier'], file))
|
||||
log.debug('Found via identifier "%s" in %s' % (quality['identifier'], cur_file))
|
||||
return self.setCache(hash, quality)
|
||||
|
||||
if list(set(quality.get('alternative', [])) & set(words)):
|
||||
log.debug('Found %s via alt %s in %s' % (quality['identifier'], quality.get('alternative'), file))
|
||||
log.debug('Found %s via alt %s in %s' % (quality['identifier'], quality.get('alternative'), cur_file))
|
||||
return self.setCache(hash, quality)
|
||||
|
||||
if list(set(quality.get('tags', [])) & set(words)):
|
||||
log.debug('Found %s via tag %s in %s' % (quality['identifier'], quality.get('tags'), file))
|
||||
log.debug('Found %s via tag %s in %s' % (quality['identifier'], quality.get('tags'), cur_file))
|
||||
return self.setCache(hash, quality)
|
||||
|
||||
# Check on unreliable stuff
|
||||
|
||||
@@ -65,6 +65,8 @@ class Release(Plugin):
|
||||
except Exception, e:
|
||||
log.debug('Failed to attach "%s" to release: %s' % (cur_file, e))
|
||||
|
||||
fireEvent('movie.restatus', movie.id)
|
||||
|
||||
db.remove()
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ config = [{
|
||||
{
|
||||
'tab': 'renamer',
|
||||
'name': 'renamer',
|
||||
'label': 'Enable renaming',
|
||||
'label': 'Rename downloaded movies',
|
||||
'wizard': True,
|
||||
'options': [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent, fireEventAsync
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.request import jsonified
|
||||
from couchpotato.core.helpers.variable import getExt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
@@ -19,11 +21,21 @@ class Renamer(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
addApiView('renamer.scan', self.scanView)
|
||||
|
||||
addEvent('renamer.scan', self.scan)
|
||||
addEvent('app.load', self.scan)
|
||||
|
||||
fireEvent('schedule.interval', 'renamer.scan', self.scan, minutes = self.conf('run_every'))
|
||||
|
||||
def scanView(self):
|
||||
|
||||
fireEvent('renamer.scan')
|
||||
|
||||
return jsonified({
|
||||
'success': True
|
||||
})
|
||||
|
||||
def scan(self):
|
||||
|
||||
if self.isDisabled():
|
||||
@@ -39,7 +51,6 @@ class Renamer(Plugin):
|
||||
return
|
||||
|
||||
groups = fireEvent('scanner.scan', folder = self.conf('from'), single = True)
|
||||
if groups is None: return
|
||||
|
||||
self.renaming_started = True
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ class Scanner(Plugin):
|
||||
}
|
||||
file_types = {
|
||||
'subtitle': ('subtitle', 'subtitle'),
|
||||
'subtitle_extra': ('subtitle', 'subtitle_extra'),
|
||||
'trailer': ('video', 'trailer'),
|
||||
'nfo': ('nfo', 'nfo'),
|
||||
'movie': ('video', 'movie'),
|
||||
@@ -53,7 +54,7 @@ class Scanner(Plugin):
|
||||
'hdtv': ['hdtv']
|
||||
}
|
||||
|
||||
clean = '[ _\,\.\(\)\[\]\-](french|swedisch|danish|dutch|swesub|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|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|cd[1-9]|\[.*\])([ _\,\.\(\)\[\]\-]|$)'
|
||||
clean = '[ _\,\.\(\)\[\]\-](french|swedisch|danish|dutch|swesub|spanish|german|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdr|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|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|cd[1-9]|\[.*\])([ _\,\.\(\)\[\]\-]|$)'
|
||||
multipart_regex = [
|
||||
'[ _\.-]+cd[ _\.-]*([0-9a-d]+)', #*cd1
|
||||
'[ _\.-]+dvd[ _\.-]*([0-9a-d]+)', #*dvd1
|
||||
@@ -68,6 +69,8 @@ class Scanner(Plugin):
|
||||
'()([ab])(\.....?)$' #*a.mkv
|
||||
]
|
||||
|
||||
cp_imdb = '(cp\((?P<id>tt[0-9{7}]+)\))'
|
||||
|
||||
def __init__(self):
|
||||
|
||||
addEvent('scanner.create_file_identifier', self.createStringIdentifier)
|
||||
@@ -122,12 +125,6 @@ class Scanner(Plugin):
|
||||
for identifier in update_after:
|
||||
fireEvent('library.update', identifier = identifier)
|
||||
|
||||
# If cleanup option is enabled, remove offline files from database
|
||||
if self.conf('cleanup_offline'):
|
||||
files_in_path = db.query(File).filter(File.path.like(folder + '%%')).filter_by(available = 0)
|
||||
[db.delete(x) for x in files_in_path]
|
||||
db.commit()
|
||||
|
||||
db.remove()
|
||||
|
||||
|
||||
@@ -157,12 +154,17 @@ class Scanner(Plugin):
|
||||
is_dvd_file = self.isDVDFile(file_path)
|
||||
if os.path.getsize(file_path) > self.minimal_filesize['media'] or is_dvd_file: # Minimal 300MB files or is DVD file
|
||||
|
||||
# Normal identifier
|
||||
identifier = self.createStringIdentifier(file_path, folder, exclude_filename = is_dvd_file)
|
||||
|
||||
# Identifier with quality
|
||||
quality = fireEvent('quality.guess', [file_path], single = True)
|
||||
identifier_with_quality = '%s %s' % (identifier, quality.get('identifier', ''))
|
||||
|
||||
if not movie_files.get(identifier):
|
||||
movie_files[identifier] = {
|
||||
'unsorted_files': [],
|
||||
'identifiers': [],
|
||||
'identifiers': [identifier_with_quality, identifier],
|
||||
'is_dvd': is_dvd_file,
|
||||
}
|
||||
|
||||
@@ -174,24 +176,16 @@ class Scanner(Plugin):
|
||||
# files will be grouped first.
|
||||
leftovers = set(sorted(leftovers, reverse = True))
|
||||
|
||||
id_handles = [
|
||||
None, # Attach files to group by identifier
|
||||
lambda x: os.path.split(x)[-1], # Attach files via filename of master_file name only
|
||||
os.path.dirname, # Attach files via master_file dirname
|
||||
]
|
||||
# Create identifiers
|
||||
for identifier, group in movie_files.iteritems():
|
||||
if identifier not in group['identifiers'] and len(identifier) > 0: group['identifiers'].append(identifier)
|
||||
|
||||
# Create identifier based on handle
|
||||
for handler in id_handles:
|
||||
for identifier, group in movie_files.iteritems():
|
||||
identifier = handler(identifier) if handler else identifier
|
||||
if identifier not in group['identifiers'] and len(identifier) > 0: group['identifiers'].append(identifier)
|
||||
# Group the files based on the identifier
|
||||
found_files = self.getGroupFiles(identifier, folder, leftovers)
|
||||
group['unsorted_files'].extend(found_files)
|
||||
|
||||
# Group the files based on the identifier
|
||||
found_files = self.getGroupFiles(identifier, folder, leftovers)
|
||||
group['unsorted_files'].extend(found_files)
|
||||
|
||||
# Remove the found files from the leftover stack
|
||||
leftovers = leftovers - found_files
|
||||
# Remove the found files from the leftover stack
|
||||
leftovers = leftovers - found_files
|
||||
|
||||
|
||||
# Determine file types
|
||||
@@ -213,7 +207,7 @@ class Scanner(Plugin):
|
||||
continue
|
||||
|
||||
# Group extra (and easy) files first
|
||||
images = self.getImages(group['unsorted_files'])
|
||||
# images = self.getImages(group['unsorted_files'])
|
||||
group['files'] = {
|
||||
'subtitle': self.getSubtitles(group['unsorted_files']),
|
||||
'subtitle_extra': self.getSubtitlesExtras(group['unsorted_files']),
|
||||
@@ -318,14 +312,18 @@ class Scanner(Plugin):
|
||||
# Check for CP(imdb_id) string in the file paths
|
||||
for cur_file in files['movie']:
|
||||
imdb_id = self.getCPImdb(cur_file)
|
||||
if imdb_id: break
|
||||
if imdb_id:
|
||||
log.debug('Found movie via CP tag: %s' % cur_file)
|
||||
break
|
||||
|
||||
# Check and see if nfo contains the imdb-id
|
||||
if not imdb_id:
|
||||
try:
|
||||
for nfo_file in files['nfo']:
|
||||
imdb_id = getImdb(nfo_file)
|
||||
if imdb_id: break
|
||||
if imdb_id:
|
||||
log.debug('Found movie via nfo file: %s' % nfo_file)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -336,6 +334,7 @@ class Scanner(Plugin):
|
||||
f = db.query(File).filter_by(path = toUnicode(cur_file)).first()
|
||||
try:
|
||||
imdb_id = f.library[0].identifier
|
||||
log.debug('Found movie via database: %s' % cur_file)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
@@ -348,25 +347,25 @@ class Scanner(Plugin):
|
||||
|
||||
if len(movie) > 0:
|
||||
imdb_id = movie[0]['imdb']
|
||||
if imdb_id: break
|
||||
if imdb_id:
|
||||
log.debug('Found movie via OpenSubtitleHash: %s' % cur_file)
|
||||
break
|
||||
|
||||
# Search based on identifiers
|
||||
if not imdb_id:
|
||||
for identifier in group['identifiers']:
|
||||
|
||||
if len(identifier) > 2:
|
||||
|
||||
movie = fireEvent('movie.search', q = identifier, merge = True, limit = 1)
|
||||
movie = fireEvent('movie.search', q = '%(name)s %(year)s' % self.getReleaseNameYear(identifier), merge = True, limit = 1)
|
||||
|
||||
if len(movie) > 0:
|
||||
imdb_id = movie[0]['imdb']
|
||||
log.debug('Found movie via cp identifier: %s' % cur_file)
|
||||
if imdb_id: break
|
||||
else:
|
||||
log.debug('Identifier to short to use for search: %s' % identifier)
|
||||
|
||||
if imdb_id:
|
||||
#movie = fireEvent('movie.info', identifier = imdb_id, merge = True)
|
||||
#if movie and movie.get('imdb'):
|
||||
return fireEvent('library.add', attrs = {
|
||||
'identifier': imdb_id
|
||||
}, update_after = False, single = True)
|
||||
@@ -377,7 +376,7 @@ class Scanner(Plugin):
|
||||
def getCPImdb(self, string):
|
||||
|
||||
try:
|
||||
m = re.search('(cp\((?P<id>tt[0-9{7}]+)\))', string.lower())
|
||||
m = re.search(self.cp_imdb, string.lower())
|
||||
id = m.group('id')
|
||||
if id: return id
|
||||
except AttributeError:
|
||||
@@ -385,6 +384,16 @@ class Scanner(Plugin):
|
||||
|
||||
return False
|
||||
|
||||
def removeCPImdb(self, name):
|
||||
for regex in self.multipart_regex:
|
||||
try:
|
||||
found = re.sub(regex, '', name)
|
||||
if found != name:
|
||||
name = found
|
||||
except:
|
||||
pass
|
||||
return name
|
||||
|
||||
def getMediaFiles(self, files):
|
||||
|
||||
def test(s):
|
||||
@@ -486,6 +495,9 @@ class Scanner(Plugin):
|
||||
# multipart
|
||||
identifier = self.removeMultipart(identifier)
|
||||
|
||||
# remove cptag
|
||||
identifier = self.removeCPImdb(identifier)
|
||||
|
||||
# groups, release tags, scenename cleaner, regex isn't correct
|
||||
identifier = re.sub(self.clean, '::', simplifyString(identifier))
|
||||
|
||||
@@ -496,10 +508,6 @@ class Scanner(Plugin):
|
||||
else:
|
||||
identifier = identifier.split('::')[0]
|
||||
|
||||
# Quality
|
||||
quality = fireEvent('quality.guess', [file_path], single = True)
|
||||
identifier += ' %s' % quality.get('identifier', '')
|
||||
|
||||
# Remove duplicates
|
||||
out = []
|
||||
for word in identifier.split():
|
||||
@@ -530,7 +538,7 @@ class Scanner(Plugin):
|
||||
return 1
|
||||
except:
|
||||
pass
|
||||
return name
|
||||
return 1
|
||||
|
||||
def getCodec(self, filename, codecs):
|
||||
codecs = map(re.escape, codecs)
|
||||
|
||||
@@ -24,7 +24,7 @@ class Searcher(Plugin):
|
||||
# Schedule cronjob
|
||||
fireEvent('schedule.cron', 'searcher.all', self.all, day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))
|
||||
|
||||
if Env.doDebug():
|
||||
if not Env.setting('development'):
|
||||
addEvent('app.load', self.all)
|
||||
|
||||
def all(self):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.request import jsonified
|
||||
from couchpotato.core.logger import CPLog
|
||||
|
||||
@@ -7,10 +7,10 @@ log = CPLog(__name__)
|
||||
class ThePirateBay(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'download': 'http://torrents.thepiratebay.org/%s/%s.torrent',
|
||||
'nfo': 'http://thepiratebay.org/torrent/%s',
|
||||
'detail': 'http://thepiratebay.org/torrent/%s',
|
||||
'search': 'http://thepiratebay.org/search/%s/0/7/%d',
|
||||
'download': 'http://torrents.depiraatbaai.be/%s/%s.torrent',
|
||||
'nfo': 'https://depiraatbaai.be/torrent/%s',
|
||||
'detail': 'https://depiraatbaai.be/torrent/%s',
|
||||
'search': 'https://depiraatbaai.be/search/%s/0/7/%d',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 840 B |
@@ -8,19 +8,26 @@ Page.Manage = new Class({
|
||||
indexAction: function(param){
|
||||
var self = this;
|
||||
|
||||
self.refresh_button = new Element('a.icon.refresh', {
|
||||
'text': 'Refresh',
|
||||
'events':{
|
||||
'click': self.refresh.bind(self)
|
||||
}
|
||||
}).inject(self.el);
|
||||
|
||||
self.list = new MovieList({
|
||||
'status': 'done',
|
||||
'actions': Manage.Action
|
||||
'actions': MovieActions
|
||||
});
|
||||
$(self.list).inject(self.el);
|
||||
|
||||
|
||||
},
|
||||
|
||||
refresh: function(){
|
||||
var self = this;
|
||||
|
||||
Api.request('manage.update')
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var Manage = {
|
||||
'Action': {
|
||||
'IMBD': IMDBAction
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -473,7 +473,7 @@ Option.Directory = new Class({
|
||||
Extends: OptionBase,
|
||||
|
||||
type: 'span',
|
||||
browser: '',
|
||||
browser: null,
|
||||
save_on_change: false,
|
||||
use_cache: false,
|
||||
|
||||
|
||||
@@ -29,27 +29,27 @@ window.addEvent('domready', function(){
|
||||
MovieActions.Wanted = {
|
||||
'IMBD': IMDBAction
|
||||
,'releases': ReleaseAction
|
||||
|
||||
|
||||
,'Edit': new Class({
|
||||
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
|
||||
self.el = new Element('a.edit', {
|
||||
'title': 'Refresh the movie info and do a forced search',
|
||||
'events': {
|
||||
'click': self.editMovie.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
editMovie: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
|
||||
if(!self.options_container){
|
||||
self.options_container = new Element('div.options').adopt(
|
||||
$(self.movie.thumbnail).clone(),
|
||||
@@ -72,30 +72,30 @@ window.addEvent('domready', function(){
|
||||
})
|
||||
)
|
||||
).inject(self.movie, 'top');
|
||||
|
||||
|
||||
Array.each(self.movie.data.library.titles, function(alt){
|
||||
new Element('option', {
|
||||
'text': alt.title
|
||||
}).inject(self.title_select);
|
||||
});
|
||||
|
||||
|
||||
Object.each(Quality.getActiveProfiles(), function(profile){
|
||||
new Element('option', {
|
||||
'value': profile.id ? profile.id : profile.data.id,
|
||||
'text': profile.label ? profile.label : profile.data.label
|
||||
}).inject(self.profile_select);
|
||||
self.profile_select.set('value', self.movie.profile.get('id'));
|
||||
self.profile_select.set('value', (self.movie.profile || {})['id']);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
self.movie.slide('in', self.options_container);
|
||||
},
|
||||
|
||||
|
||||
save: function(e){
|
||||
(e).stop();
|
||||
var self = this;
|
||||
|
||||
|
||||
Api.request('movie.edit', {
|
||||
'data': {
|
||||
'id': self.movie.get('id'),
|
||||
@@ -109,63 +109,63 @@ window.addEvent('domready', function(){
|
||||
self.movie.title.set('text', self.title_select.getSelected()[0].get('text'));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
self.movie.slide('out');
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
,'Refresh': new Class({
|
||||
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
|
||||
self.el = new Element('a.refresh', {
|
||||
'title': 'Refresh the movie info and do a forced search',
|
||||
'events': {
|
||||
'click': self.doSearch.bind(self)
|
||||
'click': self.doRefresh.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
doSearch: function(e){
|
||||
|
||||
doRefresh: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
|
||||
Api.request('movie.refresh', {
|
||||
'data': {
|
||||
'id': self.movie.get('id')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
,'Delete': new Class({
|
||||
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
|
||||
Implements: [Chain],
|
||||
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
|
||||
self.el = new Element('a.delete', {
|
||||
'title': 'Remove the movie from your wanted list',
|
||||
'events': {
|
||||
'click': self.showConfirm.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
showConfirm: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
|
||||
if(!self.delete_container){
|
||||
self.delete_container = new Element('div.delete_container', {
|
||||
'styles': {
|
||||
@@ -193,20 +193,20 @@ window.addEvent('domready', function(){
|
||||
self.movie.slide('in', self.delete_container);
|
||||
|
||||
},
|
||||
|
||||
|
||||
hideConfirm: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
|
||||
self.movie.slide('out');
|
||||
},
|
||||
|
||||
|
||||
del: function(e){
|
||||
(e).stop();
|
||||
var self = this;
|
||||
|
||||
|
||||
var movie = $(self.movie);
|
||||
|
||||
|
||||
self.chain(
|
||||
function(){
|
||||
self.callChain();
|
||||
@@ -227,17 +227,74 @@ window.addEvent('domready', function(){
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
self.callChain();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
MovieActions.Snatched = {
|
||||
'IMBD': IMDBAction
|
||||
,'Delete': MovieActions.Wanted.Delete
|
||||
};
|
||||
|
||||
MovieActions.Done = {
|
||||
'IMBD': IMDBAction
|
||||
,'Edit': MovieActions.Wanted.Edit
|
||||
,'Files': new Class({
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('a.files', {
|
||||
'title': 'Available files',
|
||||
'events': {
|
||||
'click': self.showFiles.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
showFiles: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
if(!self.options_container){
|
||||
self.options_container = new Element('div.options').adopt(
|
||||
$(self.movie.thumbnail).clone(),
|
||||
self.release_container = new Element('div.releases')
|
||||
).inject(self.movie, 'top');
|
||||
|
||||
// Header
|
||||
new Element('div.item.head').adopt(
|
||||
new Element('span.name', {'text': 'File'}),
|
||||
new Element('span.type', {'text': 'Type'}),
|
||||
new Element('span.available', {'text': 'Available'})
|
||||
).inject(self.release_container)
|
||||
|
||||
Array.each(self.movie.data.releases, function(release){
|
||||
|
||||
var rel = new Element('div.release').inject(self.release_container);
|
||||
|
||||
Array.each(release.files, function(file){
|
||||
new Element('div.file').adopt(
|
||||
new Element('span.name', {'text': file.path}),
|
||||
new Element('span.type', {'text': File.Type.get(file.type_id).name}),
|
||||
new Element('span.available', {'text': file.available})
|
||||
).inject(rel)
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
self.movie.slide('in', self.options_container);
|
||||
},
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
})
|
||||
@@ -155,6 +155,7 @@ body > .spinner, .mask{
|
||||
.icon.imdb { background-image: url('../images/icon.imdb.png'); }
|
||||
.icon.refresh { background-image: url('../images/icon.refresh.png'); }
|
||||
.icon.rating { background-image: url('../images/icon.rating.png'); }
|
||||
.icon.files { background-image: url('../images/icon.files.png'); }
|
||||
|
||||
/*** Navigation ***/
|
||||
.header {
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/wanted.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/settings.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/about.js') }}"></script>
|
||||
<!--<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/soon.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/manage.js') }}"></script>-->
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/manage.js') }}"></script>
|
||||
<!--<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/soon.js') }}"></script>-->
|
||||
|
||||
{% for url in fireEvent('clientscript.get_scripts', as_html = True, single = True) %}
|
||||
<script type="text/javascript" src="{{ url_for('web.index') }}{{ url }}"></script>{% endfor %}
|
||||
|
||||
Reference in New Issue
Block a user