diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index 03cf65d..91f5bb6 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -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 diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index 6eff56b..822485e 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -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: diff --git a/couchpotato/core/plugins/file/main.py b/couchpotato/core/plugins/file/main.py index 5b31c41..7556838 100644 --- a/couchpotato/core/plugins/file/main.py +++ b/couchpotato/core/plugins/file/main.py @@ -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) diff --git a/couchpotato/core/plugins/manage/__init__.py b/couchpotato/core/plugins/manage/__init__.py new file mode 100644 index 0000000..496fe62 --- /dev/null +++ b/couchpotato/core/plugins/manage/__init__.py @@ -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, + }, + ], + }, + ], +}] diff --git a/couchpotato/core/plugins/manage/main.py b/couchpotato/core/plugins/manage/main.py new file mode 100644 index 0000000..b406b45 --- /dev/null +++ b/couchpotato/core/plugins/manage/main.py @@ -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 [] diff --git a/couchpotato/core/plugins/movie/main.py b/couchpotato/core/plugins/movie/main.py index 6f6b0c6..1bcf5c0 100644 --- a/couchpotato/core/plugins/movie/main.py +++ b/couchpotato/core/plugins/movie/main.py @@ -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() diff --git a/couchpotato/core/plugins/movie/static/movie.js b/couchpotato/core/plugins/movie/static/movie.js index 4953b18..60b622b 100644 --- a/couchpotato/core/plugins/movie/static/movie.js +++ b/couchpotato/core/plugins/movie/static/movie.js @@ -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'); + + }); + + // Add done releases + Array.each(self.data.releases, function(release){ - // 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(); + 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 } }) - + } }); \ No newline at end of file diff --git a/couchpotato/core/plugins/profile/static/profile.js b/couchpotato/core/plugins/profile/static/profile.js index 8abe0c0..7f35b01 100644 --- a/couchpotato/core/plugins/profile/static/profile.js +++ b/couchpotato/core/plugins/profile/static/profile.js @@ -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; diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index 4cd00b1..6bce513 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -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 diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 01d7b8f..9e92d16 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -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() diff --git a/couchpotato/core/plugins/renamer/__init__.py b/couchpotato/core/plugins/renamer/__init__.py index 74a12d9..4337aa4 100644 --- a/couchpotato/core/plugins/renamer/__init__.py +++ b/couchpotato/core/plugins/renamer/__init__.py @@ -28,7 +28,7 @@ config = [{ { 'tab': 'renamer', 'name': 'renamer', - 'label': 'Enable renaming', + 'label': 'Rename downloaded movies', 'wizard': True, 'options': [ { diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index f09ea34..b0f5a32 100644 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -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 diff --git a/couchpotato/core/plugins/scanner/main.py b/couchpotato/core/plugins/scanner/main.py index 65dd1f9..9973bb1 100644 --- a/couchpotato/core/plugins/scanner/main.py +++ b/couchpotato/core/plugins/scanner/main.py @@ -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\((?Ptt[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\((?Ptt[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) diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py index a638369..b8fe3fa 100644 --- a/couchpotato/core/plugins/searcher/main.py +++ b/couchpotato/core/plugins/searcher/main.py @@ -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): diff --git a/couchpotato/core/plugins/status/main.py b/couchpotato/core/plugins/status/main.py index 940fc5d..bead35f 100644 --- a/couchpotato/core/plugins/status/main.py +++ b/couchpotato/core/plugins/status/main.py @@ -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 diff --git a/couchpotato/core/providers/torrent/thepiratebay/main.py b/couchpotato/core/providers/torrent/thepiratebay/main.py index e7e8e68..d9b06bf 100644 --- a/couchpotato/core/providers/torrent/thepiratebay/main.py +++ b/couchpotato/core/providers/torrent/thepiratebay/main.py @@ -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 = [ diff --git a/couchpotato/static/images/icon.files.png b/couchpotato/static/images/icon.files.png new file mode 100644 index 0000000..2ed1c6a Binary files /dev/null and b/couchpotato/static/images/icon.files.png differ diff --git a/couchpotato/static/scripts/page/manage.js b/couchpotato/static/scripts/page/manage.js index d3db0e0..8693ec0 100644 --- a/couchpotato/static/scripts/page/manage.js +++ b/couchpotato/static/scripts/page/manage.js @@ -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 } -} +}); diff --git a/couchpotato/static/scripts/page/settings.js b/couchpotato/static/scripts/page/settings.js index b906478..0463382 100644 --- a/couchpotato/static/scripts/page/settings.js +++ b/couchpotato/static/scripts/page/settings.js @@ -473,7 +473,7 @@ Option.Directory = new Class({ Extends: OptionBase, type: 'span', - browser: '', + browser: null, save_on_change: false, use_cache: false, diff --git a/couchpotato/static/scripts/page/wanted.js b/couchpotato/static/scripts/page/wanted.js index a158235..cc47c44 100644 --- a/couchpotato/static/scripts/page/wanted.js +++ b/couchpotato/static/scripts/page/wanted.js @@ -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); + }, + + }) + }; + }) \ No newline at end of file diff --git a/couchpotato/static/style/main.css b/couchpotato/static/style/main.css index 28fa3fa..c59873d 100644 --- a/couchpotato/static/style/main.css +++ b/couchpotato/static/style/main.css @@ -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 { diff --git a/couchpotato/templates/_desktop.html b/couchpotato/templates/_desktop.html index 67f0887..314d48b 100644 --- a/couchpotato/templates/_desktop.html +++ b/couchpotato/templates/_desktop.html @@ -31,8 +31,8 @@ - + + {% for url in fireEvent('clientscript.get_scripts', as_html = True, single = True) %} {% endfor %}