Merge branch 'refs/heads/develop'
This commit is contained in:
@@ -44,12 +44,13 @@ class NonBlockHandler(RequestHandler):
|
||||
|
||||
def onNewMessage(self, response):
|
||||
if self.request.connection.stream.closed():
|
||||
self.on_connection_close()
|
||||
return
|
||||
|
||||
try:
|
||||
self.finish(response)
|
||||
except:
|
||||
log.error('Failed doing nonblock request: %s', (traceback.format_exc()))
|
||||
log.debug('Failed doing nonblock request, probably already closed: %s', (traceback.format_exc()))
|
||||
try: self.finish({'success': False, 'error': 'Failed returning results'})
|
||||
except: pass
|
||||
|
||||
|
||||
@@ -38,8 +38,14 @@ def toUnicode(original, *args):
|
||||
return toUnicode(ascii_text)
|
||||
|
||||
def ss(original, *args):
|
||||
from couchpotato.environment import Env
|
||||
return toUnicode(original, *args).encode(Env.get('encoding'))
|
||||
|
||||
u_original = toUnicode(original, *args)
|
||||
try:
|
||||
from couchpotato.environment import Env
|
||||
return u_original.encode(Env.get('encoding'))
|
||||
except Exception, e:
|
||||
log.debug('Failed ss encoding char, force UTF8: %s', e)
|
||||
return u_original.encode('UTF-8')
|
||||
|
||||
def ek(original, *args):
|
||||
if isinstance(original, (str, unicode)):
|
||||
|
||||
@@ -18,11 +18,13 @@ var MovieAction = new Class({
|
||||
create: function(){},
|
||||
|
||||
disable: function(){
|
||||
this.el.addClass('disable')
|
||||
if(this.el)
|
||||
this.el.addClass('disable')
|
||||
},
|
||||
|
||||
enable: function(){
|
||||
this.el.removeClass('disable')
|
||||
if(this.el)
|
||||
this.el.removeClass('disable')
|
||||
},
|
||||
|
||||
getTitle: function(){
|
||||
@@ -252,10 +254,10 @@ MA.Release = new Class({
|
||||
});
|
||||
|
||||
if(self.last_release)
|
||||
self.release_container.getElement('#release_'+self.last_release.id).addClass('last_release');
|
||||
self.release_container.getElements('#release_'+self.last_release.id).addClass('last_release');
|
||||
|
||||
if(self.next_release)
|
||||
self.release_container.getElement('#release_'+self.next_release.id).addClass('next_release');
|
||||
self.release_container.getElements('#release_'+self.next_release.id).addClass('next_release');
|
||||
|
||||
if(self.next_release || (self.last_release && ['ignored', 'failed'].indexOf(self.last_release.status.identifier) === false)){
|
||||
|
||||
@@ -365,21 +367,25 @@ MA.Release = new Class({
|
||||
var release_el = self.release_container.getElement('#release_'+release.id),
|
||||
icon = release_el.getElement('.download.icon2');
|
||||
|
||||
icon.addClass('icon spinner').removeClass('download');
|
||||
if(icon)
|
||||
icon.addClass('icon spinner').removeClass('download');
|
||||
|
||||
Api.request('release.download', {
|
||||
'data': {
|
||||
'id': release.id
|
||||
},
|
||||
'onComplete': function(json){
|
||||
icon.removeClass('icon spinner');
|
||||
if(icon)
|
||||
icon.removeClass('icon spinner');
|
||||
|
||||
if(json.success){
|
||||
icon.addClass('completed');
|
||||
if(icon)
|
||||
icon.addClass('completed');
|
||||
release_el.getElement('.release_status').set('text', 'snatched');
|
||||
}
|
||||
else
|
||||
icon.addClass('attention').set('title', 'Something went wrong when downloading, please check logs.');
|
||||
if(icon)
|
||||
icon.addClass('attention').set('title', 'Something went wrong when downloading, please check logs.');
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -393,11 +399,11 @@ MA.Release = new Class({
|
||||
},
|
||||
'onComplete': function(){
|
||||
var el = release.el;
|
||||
if(el.hasClass('failed') || el.hasClass('ignored')){
|
||||
if(el && (el.hasClass('failed') || el.hasClass('ignored'))){
|
||||
el.removeClass('failed').removeClass('ignored');
|
||||
el.getElement('.release_status').set('text', 'available');
|
||||
}
|
||||
else {
|
||||
else if(el) {
|
||||
el.addClass('ignored');
|
||||
el.getElement('.release_status').set('text', 'ignored');
|
||||
}
|
||||
|
||||
@@ -181,18 +181,18 @@ var Movie = new Class({
|
||||
// Add releases
|
||||
if(self.data.releases)
|
||||
self.data.releases.each(function(release){
|
||||
|
||||
|
||||
var q = self.quality.getElement('.q_id'+ release.quality_id),
|
||||
status = Status.get(release.status_id);
|
||||
|
||||
|
||||
if(!q && (status.identifier == 'snatched' || status.identifier == 'done'))
|
||||
var q = self.addQuality(release.quality_id)
|
||||
|
||||
|
||||
if (status && q && !q.hasClass(status.identifier)){
|
||||
q.addClass(status.identifier);
|
||||
q.set('title', (q.get('title') ? q.get('title') : '') + ' status: '+ status.label)
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
Object.each(self.options.actions, function(action, key){
|
||||
@@ -256,7 +256,8 @@ var Movie = new Class({
|
||||
self.el.removeEvents('outerClick')
|
||||
|
||||
setTimeout(function(){
|
||||
self.el.getElements('> :not(.data):not(.poster):not(.movie_container)').hide();
|
||||
if(self.el)
|
||||
self.el.getElements('> :not(.data):not(.poster):not(.movie_container)').hide();
|
||||
}, 600);
|
||||
|
||||
self.data_container.removeClass('hide_right');
|
||||
@@ -266,9 +267,10 @@ var Movie = new Class({
|
||||
changeView: function(new_view){
|
||||
var self = this;
|
||||
|
||||
self.el
|
||||
.removeClass(self.view+'_view')
|
||||
.addClass(new_view+'_view')
|
||||
if(self.el)
|
||||
self.el
|
||||
.removeClass(self.view+'_view')
|
||||
.addClass(new_view+'_view')
|
||||
|
||||
self.view = new_view;
|
||||
},
|
||||
|
||||
@@ -198,13 +198,16 @@ class CoreNotifier(Notification):
|
||||
def removeListener(self, callback):
|
||||
|
||||
self.m_lock.acquire()
|
||||
new_listeners = []
|
||||
for list_tuple in self.listeners:
|
||||
try:
|
||||
listener, last_id = list_tuple
|
||||
if listener == callback:
|
||||
self.listeners.remove(list_tuple)
|
||||
if listener != callback:
|
||||
new_listeners.append(list_tuple)
|
||||
except:
|
||||
log.debug('Failed removing listener: %s', traceback.format_exc())
|
||||
|
||||
self.listeners = new_listeners
|
||||
self.m_lock.release()
|
||||
|
||||
def cleanMessages(self):
|
||||
|
||||
@@ -4,9 +4,10 @@ from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.variable import splitString, tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Movie, Library, LibraryTitle
|
||||
from couchpotato.core.settings.model import Movie, Library, LibraryTitle, \
|
||||
Release
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
from sqlalchemy.sql.expression import asc
|
||||
from sqlalchemy.sql.expression import asc, or_
|
||||
import random as rndm
|
||||
import time
|
||||
|
||||
@@ -48,12 +49,14 @@ class Dashboard(Plugin):
|
||||
limit = tryInt(splt[0])
|
||||
|
||||
# Get all active movies
|
||||
active_status = fireEvent('status.get', ['active'], single = True)
|
||||
active_status, ignored_status = fireEvent('status.get', ['active', 'ignored'], single = True)
|
||||
q = db.query(Movie) \
|
||||
.join(Library) \
|
||||
.outerjoin(Movie.releases) \
|
||||
.filter(Movie.status_id == active_status.get('id')) \
|
||||
.with_entities(Movie.id, Movie.profile_id, Library.info, Library.year) \
|
||||
.group_by(Movie.id)
|
||||
.group_by(Movie.id) \
|
||||
.filter(or_(Release.id == None, Release.status_id == ignored_status.get('id')))
|
||||
|
||||
if not random:
|
||||
q = q.join(LibraryTitle) \
|
||||
|
||||
@@ -102,6 +102,6 @@ class Suggestion(Plugin):
|
||||
if suggestions:
|
||||
new_suggestions.extend(suggestions)
|
||||
|
||||
self.setCache('suggestion_cached', new_suggestions, timeout = 6048000)
|
||||
self.setCache('suggestion_cached', new_suggestions, timeout = 3024000)
|
||||
|
||||
return new_suggestions
|
||||
|
||||
@@ -58,54 +58,59 @@ var SuggestList = new Class({
|
||||
|
||||
var self = this;
|
||||
|
||||
if(!json) return;
|
||||
if(!json || json.count == 0){
|
||||
self.el.hide();
|
||||
}
|
||||
else {
|
||||
|
||||
Object.each(json.suggestions, function(movie){
|
||||
Object.each(json.suggestions, function(movie){
|
||||
|
||||
var m = new Block.Search.Item(movie, {
|
||||
'onAdded': function(){
|
||||
self.afterAdded(m, movie)
|
||||
}
|
||||
});
|
||||
m.data_container.grab(
|
||||
new Element('div.actions').adopt(
|
||||
new Element('a.add.icon2', {
|
||||
'title': 'Add movie with your default quality',
|
||||
'data-add': movie.imdb,
|
||||
'events': {
|
||||
'click': m.showOptions.bind(m)
|
||||
}
|
||||
}),
|
||||
$(new MA.IMDB(m)),
|
||||
$(new MA.Trailer(m, {
|
||||
'height': 150
|
||||
})),
|
||||
new Element('a.delete.icon2', {
|
||||
'title': 'Don\'t suggest this movie again',
|
||||
'data-ignore': movie.imdb
|
||||
}),
|
||||
new Element('a.eye-open.icon2', {
|
||||
'title': 'Seen it, like it, don\'t add',
|
||||
'data-seen': movie.imdb
|
||||
})
|
||||
var m = new Block.Search.Item(movie, {
|
||||
'onAdded': function(){
|
||||
self.afterAdded(m, movie)
|
||||
}
|
||||
});
|
||||
m.data_container.grab(
|
||||
new Element('div.actions').adopt(
|
||||
new Element('a.add.icon2', {
|
||||
'title': 'Add movie with your default quality',
|
||||
'data-add': movie.imdb,
|
||||
'events': {
|
||||
'click': m.showOptions.bind(m)
|
||||
}
|
||||
}),
|
||||
$(new MA.IMDB(m)),
|
||||
$(new MA.Trailer(m, {
|
||||
'height': 150
|
||||
})),
|
||||
new Element('a.delete.icon2', {
|
||||
'title': 'Don\'t suggest this movie again',
|
||||
'data-ignore': movie.imdb
|
||||
}),
|
||||
new Element('a.eye-open.icon2', {
|
||||
'title': 'Seen it, like it, don\'t add',
|
||||
'data-seen': movie.imdb
|
||||
})
|
||||
)
|
||||
);
|
||||
m.data_container.removeEvents('click');
|
||||
|
||||
// Add rating
|
||||
m.info_container.adopt(
|
||||
m.rating = m.info.rating && m.info.rating.imdb.length == 2 && parseFloat(m.info.rating.imdb[0]) > 0 ? new Element('span.rating', {
|
||||
'text': parseFloat(m.info.rating.imdb[0]),
|
||||
'title': parseInt(m.info.rating.imdb[1]) + ' votes'
|
||||
}) : null,
|
||||
m.genre = m.info.genres && m.info.genres.length > 0 ? new Element('span.genres', {
|
||||
'text': m.info.genres.slice(0, 3).join(', ')
|
||||
}) : null
|
||||
)
|
||||
);
|
||||
m.data_container.removeEvents('click');
|
||||
|
||||
// Add rating
|
||||
m.info_container.adopt(
|
||||
m.rating = m.info.rating && m.info.rating.imdb.length == 2 && parseFloat(m.info.rating.imdb[0]) > 0 ? new Element('span.rating', {
|
||||
'text': parseFloat(m.info.rating.imdb[0]),
|
||||
'title': parseInt(m.info.rating.imdb[1]) + ' votes'
|
||||
}) : null,
|
||||
m.genre = m.info.genres && m.info.genres.length > 0 ? new Element('span.genres', {
|
||||
'text': m.info.genres.slice(0, 3).join(', ')
|
||||
}) : null
|
||||
)
|
||||
$(m).inject(self.el);
|
||||
|
||||
$(m).inject(self.el);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
self.fireEvent('loaded');
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ var UserscriptSettingTab = new Class({
|
||||
})
|
||||
)
|
||||
).setStyles({
|
||||
'background-image': "url('"+Api.createUrl('static/userscript/userscript.png')+"')"
|
||||
'background-image': "url('"+App.createUrl('static/plugin/userscript/userscript.png')+"')"
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -24,9 +24,10 @@ Page.Wizard = new Class({
|
||||
'title': 'What download apps are you using?',
|
||||
'description': 'CP needs an external download app to work with. Choose one below. For more downloaders check settings after you have filled in the wizard. If your download app isn\'t in the list, use the default Blackhole.'
|
||||
},
|
||||
'providers': {
|
||||
'searcher': {
|
||||
'label': 'Providers',
|
||||
'title': 'Are you registered at any of these sites?',
|
||||
'description': 'CP uses these sites to search for movies. A few free are enabled by default, but it\'s always better to have a few more. Check settings for the full list of available providers.'
|
||||
'description': 'CP uses these sites to search for movies. A few free are enabled by default, but it\'s always better to have more.'
|
||||
},
|
||||
'renamer': {
|
||||
'title': 'Move & rename the movies after downloading?',
|
||||
@@ -38,7 +39,7 @@ Page.Wizard = new Class({
|
||||
'<br />Once installed, just click the bookmarklet on a movie page and watch the magic happen ;)',
|
||||
'content': function(){
|
||||
return App.createUserscriptButtons().setStyles({
|
||||
'background-image': "url('"+Api.createUrl('static/userscript/userscript.png')+"')"
|
||||
'background-image': "url('"+App.createUrl('static/plugin/userscript/userscript.png')+"')"
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -76,7 +77,7 @@ Page.Wizard = new Class({
|
||||
)
|
||||
}
|
||||
},
|
||||
groups: ['welcome', 'general', 'downloaders', 'searcher', 'providers', 'renamer', 'automation', 'finish'],
|
||||
groups: ['welcome', 'general', 'downloaders', 'searcher', 'renamer', 'automation', 'finish'],
|
||||
|
||||
open: function(action, params){
|
||||
var self = this;
|
||||
@@ -195,8 +196,7 @@ Page.Wizard = new Class({
|
||||
self.el.getElement('.advanced_toggle').destroy();
|
||||
|
||||
// Hide retention
|
||||
self.el.getElement('.tab_searcher').hide();
|
||||
self.el.getElement('.t_searcher').hide();
|
||||
self.el.getElement('.section_nzb').hide();
|
||||
|
||||
// Add pointer
|
||||
new Element('.tab_wrapper').wraps(tabs);
|
||||
|
||||
@@ -56,6 +56,10 @@ class BinSearch(NZBProvider):
|
||||
info = row.find('span', attrs = {'class':'d'})
|
||||
size_match = re.search('size:.(?P<size>[0-9\.]+.[GMB]+)', info.text)
|
||||
|
||||
age = 0
|
||||
try: age = re.search('(?P<size>\d+d)', row.find_all('td')[-1:][0].text).group('size')[:-1]
|
||||
except: pass
|
||||
|
||||
def extra_check(item):
|
||||
parts = re.search('available:.(?P<parts>\d+)./.(?P<total>\d+)', info.text)
|
||||
total = tryInt(parts.group('total'))
|
||||
@@ -74,7 +78,7 @@ class BinSearch(NZBProvider):
|
||||
results.append({
|
||||
'id': nzb_id,
|
||||
'name': title.text,
|
||||
'age': tryInt(re.search('(?P<size>\d+d)', row.find_all('td')[-1:][0].text).group('size')[:-1]),
|
||||
'age': tryInt(age),
|
||||
'size': self.parseSize(size_match.group('size')),
|
||||
'url': self.urls['download'] % nzb_id,
|
||||
'detail_url': self.urls['detail'] % info.find('a')['href'],
|
||||
|
||||
Reference in New Issue
Block a user