diff --git a/couchpotato/api.py b/couchpotato/api.py index 718527c9..58fd3102 100644 --- a/couchpotato/api.py +++ b/couchpotato/api.py @@ -11,16 +11,12 @@ api_nonblock = {} class NonBlockHandler(RequestHandler): - def __init__(self, application, request, **kwargs): - cls = NonBlockHandler - cls.stoppers = [] - super(NonBlockHandler, self).__init__(application, request, **kwargs) + stoppers = [] @asynchronous def get(self, route): - cls = NonBlockHandler start, stop = api_nonblock[route] - cls.stoppers.append(stop) + self.stoppers.append(stop) start(self.onNewMessage, last_id = self.get_argument("last_id", None)) @@ -30,12 +26,11 @@ class NonBlockHandler(RequestHandler): self.finish(response) def on_connection_close(self): - cls = NonBlockHandler - for stop in cls.stoppers: + for stop in self.stoppers: stop(self.onNewMessage) - cls.stoppers = [] + self.stoppers = [] def addApiView(route, func, static = False, docs = None, **kwargs): diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index d0533d5c..78e2b957 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -52,9 +52,7 @@ class NZBGet(Downloader): if xml_response: log.info('NZB sent successfully to NZBGet') - groups = rpc.listgroups() - nzb_id = [item['NZBID'] for item in groups if item['NZBFilename'] == nzb_name][0] - return self.downloadReturnId(nzb_id) + return True else: log.error('NZBGet could not add %s to the queue.', nzb_name) return False diff --git a/couchpotato/core/plugins/movie/static/list.js b/couchpotato/core/plugins/movie/static/list.js index 3d5545e3..a89f89af 100644 --- a/couchpotato/core/plugins/movie/static/list.js +++ b/couchpotato/core/plugins/movie/static/list.js @@ -6,6 +6,7 @@ var MovieList = new Class({ navigation: true, limit: 50, load_more: true, + loader: true, menu: [], add_new: false }, @@ -251,7 +252,7 @@ var MovieList = new Class({ 'data': Object.merge({ 'status': self.options.status }, self.filter), - 'onComplete': function(json){ + 'onSuccess': function(json){ json.chars.split('').each(function(c){ self.letters[c.capitalize()].addClass('available') @@ -475,12 +476,39 @@ var MovieList = new Class({ self.load_more.set('text', 'loading...'); } + if(self.movies.length == 0 && self.options.loader){ + + self.loader_first = new Element('div.loading').adopt( + new Element('div.message', {'text': self.options.title ? 'Loading \'' + self.options.title + '\'' : 'Loading...'}) + ).inject(self.el, 'top'); + + createSpinner(self.loader_first, { + radius: 4, + length: 4, + width: 1 + }); + + self.el.setStyle('min-height', 93); + + } + Api.request(self.options.api_call || 'movie.list', { 'data': Object.merge({ 'status': self.options.status, 'limit_offset': self.options.limit + ',' + self.offset }, self.filter), - 'onComplete': function(json){ + 'onSuccess': function(json){ + + if(self.loader_first){ + var lf = self.loader_first; + self.loader_first.addClass('hide') + self.loader_first = null; + setTimeout(function(){ + lf.destroy(); + }, 20000); + self.el.setStyle('min-height', null); + } + self.store(json.movies); self.addMovies(json.movies, json.total); if(self.scrollspy) { @@ -488,7 +516,7 @@ var MovieList = new Class({ self.scrollspy.start(); } - self.checkIfEmpty() + self.checkIfEmpty(); } }); }, @@ -518,7 +546,7 @@ var MovieList = new Class({ self.description[is_empty ? 'hide' : 'show']() if(is_empty && self.options.on_empty_element){ - self.el.grab(self.options.on_empty_element); + self.options.on_empty_element.inject(self.loader_first || self.title || self.movie_list, 'after'); if(self.navigation) self.navigation.hide(); diff --git a/couchpotato/core/plugins/movie/static/movie.css b/couchpotato/core/plugins/movie/static/movie.css index 3e947ddf..c6fe4e0a 100644 --- a/couchpotato/core/plugins/movie/static/movie.css +++ b/couchpotato/core/plugins/movie/static/movie.css @@ -4,7 +4,33 @@ z-index: 3; } - .movies h2 { + .movies .loading { + display: block; + padding: 20px 0 0 0; + width: 100%; + z-index: 3; + transition: all .4s cubic-bezier(0.9,0,0.1,1); + height: 40px; + opacity: 1; + position: absolute; + text-align: center; + } + .movies .loading.hide { + height: 0; + padding: 20px 0 0 0; + opacity: 0; + margin-top: -20px; + } + + .movies .loading .spinner { + display: inline-block; + } + + .movies .loading .message { + margin: 0 20px; + } + + .movies > h2 { margin-bottom: 20px; } @@ -27,6 +53,7 @@ .home .movies { padding-top: 6px; } + .movies.mass_edit_list { padding-top: 90px; diff --git a/couchpotato/core/plugins/renamer/__init__.py b/couchpotato/core/plugins/renamer/__init__.py index f90828bc..90f5c980 100644 --- a/couchpotato/core/plugins/renamer/__init__.py +++ b/couchpotato/core/plugins/renamer/__init__.py @@ -117,7 +117,7 @@ config = [{ 'label': 'File Action', 'default': 'move', 'type': 'dropdown', - 'values': [('Move', 'move'), ('Copy', 'copy'), ('Hard link', 'hardlink'), ('Sym link', 'symlink')], + 'values': [('Move', 'move'), ('Copy', 'copy'), ('Hard link', 'hardlink'), ('Sym link', 'symlink'), ('Move & Sym link', 'move_symlink')], 'description': 'Define which kind of file operation you want to use. Before you start using hard links or sym links, PLEASE read about their possible drawbacks.', 'advanced': True, }, diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index 26aa9dea..87d9aaf3 100644 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -10,8 +10,8 @@ from couchpotato.core.plugins.base import Plugin from couchpotato.core.settings.model import Library, File, Profile, Release, \ ReleaseInfo from couchpotato.environment import Env +from linktastic.linktastic import link, symlink import errno -import linktastic.linktastic as linktastic import os import re import shutil @@ -89,7 +89,8 @@ class Renamer(Plugin): # Check to see if the "to" folder is inside the "from" folder. if movie_folder and not os.path.isdir(movie_folder) or not os.path.isdir(self.conf('from')) or not os.path.isdir(self.conf('to')): - log.error('"To" and "From" have to exist.') + l = log.debug if movie_folder else log.error + l('Both the "To" and "From" have to exist.') return elif self.conf('from') in self.conf('to'): log.error('The "to" can\'t be inside of the "from" folder. You\'ll get an infinite loop.') @@ -521,11 +522,14 @@ Remove it if you want it to be renamed (again, or at least let it try again) dest = ss(dest) try: if self.conf('file_action') == 'hardlink': - linktastic.link(old, dest) + link(old, dest) elif self.conf('file_action') == 'symlink': - linktastic.symlink(old, dest) + symlink(old, dest) elif self.conf('file_action') == 'copy': shutil.copy(old, dest) + elif self.conf('file_action') == 'move_symlink': + shutil.move(old, dest) + symlink(dest, old) else: shutil.move(old, dest) diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py index 855f3c72..1f0df964 100644 --- a/couchpotato/core/providers/base.py +++ b/couchpotato/core/providers/base.py @@ -104,6 +104,7 @@ class YarrProvider(Provider): try: cookiejar = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar)) + opener.addheaders = [] urllib2.install_opener(opener) log.info2('Logging into %s', self.urls['login']) f = opener.open(self.urls['login'], self.getLoginParams()) diff --git a/couchpotato/static/scripts/page/home.js b/couchpotato/static/scripts/page/home.js index 004f0513..1839e3b0 100644 --- a/couchpotato/static/scripts/page/home.js +++ b/couchpotato/static/scripts/page/home.js @@ -25,7 +25,18 @@ Page.Home = new Class({ 'view': 'list', 'actions': [MA.IMDB, MA.Trailer, MA.Release, MA.Refresh, MA.Delete], 'title': 'Snatched & Available', - 'on_empty_element': new Element('div'), + 'description': 'These movies have been snatched or have finished downloading', + 'on_empty_element': new Element('div').adopt( + new Element('h2', {'text': 'Snatched & Available'}), + new Element('span', { + 'html': 'No snatched movies or anything!? Damn.. Maybe add a movie.', + 'events': { + 'click': function(){ + $(document.body).getElement('.search_form input').focus(); + } + } + }) + ), 'filter': { 'release_status': 'snatched,available' } @@ -39,7 +50,7 @@ Page.Home = new Class({ 'title': 'Available soon', 'description': 'These are being searched for and should be available soon as they will be released on DVD in the next few weeks.', 'on_empty_element': new Element('div').adopt( - new Element('h1', {'text': 'Available soon'}), + new Element('h2', {'text': 'Available soon'}), new Element('span', {'text': 'There are no movies available soon. Add some movies, so you have something to watch later.'}) ), 'filter': { @@ -58,10 +69,10 @@ Page.Home = new Class({ 'limit': 50, 'title': 'Still not available', 'description': 'Try another quality profile or maybe add more providers in Settings.', - 'on_empty_element': new Element('div'), 'filter': { 'late': true }, + 'loader': false, 'load_more': false, 'view': 'list', 'actions': [MA.IMDB, MA.Trailer, MA.Edit, MA.Refresh, MA.Delete], diff --git a/libs/linktastic/README.txt b/libs/linktastic/README.txt deleted file mode 100644 index 7fad24db..00000000 --- a/libs/linktastic/README.txt +++ /dev/null @@ -1,19 +0,0 @@ -Linktastic - -Linktastic is an extension of the os.link and os.symlink functionality provided -by the python language since version 2. Python only supports file linking on -*NIX-based systems, even though it is relatively simple to engineer a solution -to utilize NTFS's built-in linking functionality. Linktastic attempts to unify -linking on the windows platform with linking on *NIX-based systems. - -Usage - -Linktastic is a single python module and can be imported as such. Examples: - -# Hard linking src to dest -import linktastic -linktastic.link(src, dest) - -# Symlinking src to dest -import linktastic -linktastic.symlink(src, dest) diff --git a/libs/linktastic/setup.py b/libs/linktastic/setup.py deleted file mode 100644 index e15cc2b7..00000000 --- a/libs/linktastic/setup.py +++ /dev/null @@ -1,13 +0,0 @@ -from distutils.core import setup - -setup( - name='Linktastic', - version='0.1.0', - author='Jon "Berkona" Monroe', - author_email='solipsis.dev@gmail.com', - py_modules=['linktastic'], - url="http://github.com/berkona/linktastic", - license='MIT License - See http://opensource.org/licenses/MIT for details', - description='Truly platform-independent file linking', - long_description=open('README.txt').read(), -)