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(),
-)