Browse Source

Updater

Event priority
Mootools defaults fixes
pull/51/merge
Ruud 14 years ago
parent
commit
1effeb2134
  1. 2
      CouchPotato.py
  2. 1
      couchpotato/api/__init__.py
  3. 11
      couchpotato/core/_base/_core/main.py
  4. 4
      couchpotato/core/downloaders/base.py
  5. 7
      couchpotato/core/event.py
  6. 4
      couchpotato/core/plugins/profile/main.py
  7. 2
      couchpotato/core/plugins/quality/main.py
  8. 2
      couchpotato/core/plugins/searcher/main.py
  9. 39
      couchpotato/core/plugins/updater/main.py
  10. 89
      couchpotato/core/plugins/updater/static/updater.js
  11. 2
      couchpotato/core/providers/nzb/newznab/__init__.py
  12. 2
      couchpotato/core/providers/nzb/newznab/static/newznab.js
  13. 10
      couchpotato/static/scripts/couchpotato.js
  14. 4
      couchpotato/static/scripts/library/form_replacement/form_check.js
  15. 2
      couchpotato/static/scripts/library/form_replacement/form_dropdown.js
  16. 2
      couchpotato/static/scripts/library/form_replacement/form_radio.js
  17. 970
      couchpotato/static/scripts/library/mootools.js
  18. 2
      couchpotato/static/scripts/page/settings.js
  19. 4
      couchpotato/static/scripts/page/wanted.js
  20. 22
      couchpotato/static/style/main.css
  21. 11
      libs/axl/axel.py

2
CouchPotato.py

@ -33,7 +33,7 @@ def start():
new_environ[key] = value.encode('iso-8859-1') new_environ[key] = value.encode('iso-8859-1')
subprocess.call(args, env = new_environ) subprocess.call(args, env = new_environ)
return os.path.isfile(os.path.join(options.data_dir, 'restart')) return os.path.isfile(os.path.join(base_path, 'restart'))
except Exception, e: except Exception, e:
log.critical(e) log.critical(e)
return 0 return 0

1
couchpotato/api/__init__.py

@ -18,3 +18,4 @@ def index():
return jsonified({'routes': routes}) return jsonified({'routes': routes})
addApiView('', index) addApiView('', index)
addApiView('default', index)

11
couchpotato/core/_base/_core/main.py

@ -1,5 +1,5 @@
from couchpotato.api import addApiView from couchpotato.api import addApiView
from couchpotato.core.event import fireEvent from couchpotato.core.event import fireEvent, addEvent
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env from couchpotato.environment import Env
@ -43,14 +43,13 @@ class Core(Plugin):
time.sleep(1) time.sleep(1)
if restart: if restart:
self.createFile(self.restartFilePath(), 'This is the most suckiest way to register if CP is restarted. Ever...') self.createFile(self.restartFilePath(), 'This is the most suckiest way to register if CP is restarted. Ever...')
func = request.environ.get('werkzeug.server.shutdown') try:
if func is None: request.environ.get('werkzeug.server.shutdown')()
except:
log.error('Failed shutting down the server') log.error('Failed shutting down the server')
func()
def removeRestartFile(self): def removeRestartFile(self):
try: try:
@ -59,4 +58,4 @@ class Core(Plugin):
pass pass
def restartFilePath(self): def restartFilePath(self):
return os.path.join(Env.get('data_dir'), 'restart') return os.path.join(Env.get('app_dir'), 'restart')

4
couchpotato/core/downloaders/base.py

@ -1,6 +1,7 @@
from couchpotato.core.event import addEvent from couchpotato.core.event import addEvent
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
log = CPLog(__name__) log = CPLog(__name__)
@ -16,8 +17,11 @@ class Downloader(Plugin):
pass pass
def cpTag(self, movie): def cpTag(self, movie):
if Env.setting('enabled', 'renamer'):
return '.cp(' + movie['library'].get('identifier') + ')' if movie['library'].get('identifier') else '' return '.cp(' + movie['library'].get('identifier') + ')' if movie['library'].get('identifier') else ''
return ''
def isDisabled(self): def isDisabled(self):
return not self.isEnabled() return not self.isEnabled()

7
couchpotato/core/event.py

@ -8,7 +8,7 @@ log = CPLog(__name__)
events = {} events = {}
def addEvent(name, handler): def addEvent(name, handler, priority = 0):
if events.get(name): if events.get(name):
e = events[name] e = events[name]
@ -27,7 +27,10 @@ def addEvent(name, handler):
return h return h
e += createHandle if name == 'app.initialize':
print 'test', priority
e.handle(createHandle, priority = priority)
def removeEvent(name, handler): def removeEvent(name, handler):
e = events[name] e = events[name]

4
couchpotato/core/plugins/profile/main.py

@ -19,7 +19,7 @@ class ProfilePlugin(Plugin):
addApiView('profile.save_order', self.saveOrder) addApiView('profile.save_order', self.saveOrder)
addApiView('profile.delete', self.delete) addApiView('profile.delete', self.delete)
addEvent('app.initialize', self.fill) addEvent('app.initialize', self.fill, priority = 90)
def all(self): def all(self):
@ -127,7 +127,7 @@ class ProfilePlugin(Plugin):
}] }]
# Create default quality profile # Create default quality profile
order = 99 order = -2
for profile in profiles: for profile in profiles:
log.info('Creating default profile: %s' % profile.get('label')) log.info('Creating default profile: %s' % profile.get('label'))
p = Profile( p = Profile(

2
couchpotato/core/plugins/quality/main.py

@ -32,7 +32,7 @@ class QualityPlugin(Plugin):
addEvent('quality.single', self.single) addEvent('quality.single', self.single)
addEvent('quality.guess', self.guess) addEvent('quality.guess', self.guess)
addEvent('app.initialize', self.fill) addEvent('app.initialize', self.fill, priority = 10)
def all(self): def all(self):

2
couchpotato/core/plugins/searcher/main.py

@ -86,7 +86,7 @@ class Searcher(Plugin):
for info in nzb: for info in nzb:
try: try:
if not isinstance(nzb[info], (str, unicode)): if not isinstance(nzb[info], (str, unicode, int, long)):
continue continue
rls_info = ReleaseInfo( rls_info = ReleaseInfo(

39
couchpotato/core/plugins/updater/main.py

@ -1,4 +1,6 @@
from couchpotato.api import addApiView
from couchpotato.core.event import addEvent, fireEvent from couchpotato.core.event import addEvent, fireEvent
from couchpotato.core.helpers.request import jsonified
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env from couchpotato.environment import Env
@ -10,14 +12,13 @@ log = CPLog(__name__)
class Updater(Plugin): class Updater(Plugin):
git = 'git://github.com/CouchPotato/CouchPotato.git' repo_name = 'RuudBurger/CouchPotatoServer'
running = False running = False
version = None version = None
updateFailed = False update_failed = False
updateAvailable = False update_version = None
updateVersion = None last_check = 0
lastCheck = 0
def __init__(self): def __init__(self):
@ -27,6 +28,18 @@ class Updater(Plugin):
addEvent('app.load', self.check) addEvent('app.load', self.check)
addApiView('updater.info', self.getInfo)
addApiView('updater.update', self.doUpdateView)
def getInfo(self):
return jsonified({
'repo_name': self.repo_name,
'last_check': self.last_check,
'update_version': self.update_version,
'version': self.getVersion(),
})
def getVersion(self): def getVersion(self):
if not self.version: if not self.version:
@ -42,7 +55,7 @@ class Updater(Plugin):
def check(self): def check(self):
if self.updateAvailable or self.isDisabled(): if self.update_version or self.isDisabled():
return return
current_branch = self.repo.getCurrentBranch().name current_branch = self.repo.getCurrentBranch().name
@ -54,13 +67,17 @@ class Updater(Plugin):
remote = branch.getHead() remote = branch.getHead()
if local.getDate() < remote.getDate(): if local.getDate() < remote.getDate():
if self.conf('automatic') and not self.updateFailed: if self.conf('automatic') and not self.update_failed:
self.doUpdate() self.doUpdate()
else: else:
self.updateAvailable = True self.update_version = remote.hash
self.updateVersion = remote.hash
self.last_check = time.time()
self.lastCheck = time.time() def doUpdateView(self):
return jsonified({
'success': self.doUpdate()
})
def doUpdate(self): def doUpdate(self):
try: try:
@ -70,7 +87,7 @@ class Updater(Plugin):
except Exception, e: except Exception, e:
log.error('Failed updating via GIT: %s' % e) log.error('Failed updating via GIT: %s' % e)
self.updateFailed = True self.update_failed = True
return False return False

89
couchpotato/core/plugins/updater/static/updater.js

@ -0,0 +1,89 @@
var UpdaterBase = new Class({
initialize: function(){
var self = this;
App.addEvent('load', self.info.bind(self, 1000))
},
info: function(timeout){
var self = this;
if(self.timer) clearTimeout(self.timer);
self.timer = setTimeout(function(){
Api.request('updater.info', {
'onComplete': function(json){
if(json.update_version){
self.createMessage(json);
}
else {
if(self.message)
self.message.destroy();
}
}
})
}, (timeout || 0))
},
createMessage: function(data){
var self = this;
self.message = new Element('div.message.update').adopt(
new Element('span', {
'text': 'A new version is available'
}),
new Element('a', {
'href': 'https://github.com/'+data.repo_name+'/compare/'+data.version.substr(0, 7)+'...'+data.update_version.substr(0, 7),
'text': 'see what has changed',
'target': '_blank'
}),
new Element('span[text=or]'),
new Element('a', {
'text': 'just update, gogogo!',
'events': {
'click': self.doUpdate.bind(self)
}
})
).inject($(document.body).getElement('.header'))
},
doUpdate: function(){
var self = this;
Api.request('updater.update', {
'onComplete': function(json){
if(json.success){
App.restart();
$(document.body).set('spin', {
'message': 'Updating'
});
$(document.body).spin();
var checks = 0;
var interval = 0;
interval = setInterval(function(){
Api.request('', {
'onSuccess': function(){
if(checks > 2){
clearInterval(interval);
$(document.body).unspin();
self.info();
}
}
});
checks++;
}, 500)
}
}
});
}
});
var Updater = new UpdaterBase();

2
couchpotato/core/providers/nzb/newznab/__init__.py

@ -21,7 +21,7 @@ config = [{
}, },
{ {
'name': 'host', 'name': 'host',
'default': 'http://nzb.su', 'default': 'nzb.su',
'description': 'The hostname of your newznab provider' 'description': 'The hostname of your newznab provider'
}, },
{ {

2
couchpotato/core/providers/nzb/newznab/static/newznab.js

@ -72,7 +72,7 @@ var MultipleNewznab = new Class({
if(has_empty) return; if(has_empty) return;
self.add_empty_timeout = setTimeout(function(){ self.add_empty_timeout = setTimeout(function(){
self.createItem(false); self.createItem(false, null, null);
}, 10); }, 10);
}, },

10
couchpotato/static/scripts/couchpotato.js

@ -29,7 +29,7 @@ var CouchPotato = new Class({
else else
self.openPage(window.location.pathname); self.openPage(window.location.pathname);
self.c.addEvent('click:relay(a)', self.pushState.bind(self)); self.c.addEvent('click:relay(a:not([target=_blank]))', self.pushState.bind(self));
}, },
pushState: function(e){ pushState: function(e){
@ -100,6 +100,14 @@ var CouchPotato = new Class({
getPage: function(name){ getPage: function(name){
return this.pages[name] return this.pages[name]
},
shutdown: function(){
Api.request('app.shutdown');
},
restart: function(){
Api.request('app.restart');
} }
}); });

4
couchpotato/static/scripts/library/form_replacement/form_check.js

@ -96,14 +96,14 @@ Form.Check = new Class({
this.fireEvent('removeHighlight', this); this.fireEvent('removeHighlight', this);
}, },
keyToggle: function(e) { keyToggle: function(e) {
var evt = new Event(e); var evt = (e);
if (evt.key === 'space') { this.toggle(e); } if (evt.key === 'space') { this.toggle(e); }
}, },
toggle: function(e) { toggle: function(e) {
var evt; var evt;
if (this.disabled) { return this; } if (this.disabled) { return this; }
if (e) { if (e) {
evt = new Event(e).stopPropagation(); evt = (e).stopPropagation();
if (evt.target.tagName.toLowerCase() !== 'a') { if (evt.target.tagName.toLowerCase() !== 'a') {
evt.stop(); evt.stop();
} }

2
couchpotato/static/scripts/library/form_replacement/form_dropdown.js

@ -117,7 +117,7 @@ Form.Dropdown = new Class({
}, },
expand: function(e) { expand: function(e) {
clearTimeout(this.collapseInterval); clearTimeout(this.collapseInterval);
var evt = e ? new Event(e).stop() : null; var evt = e ? (e).stop() : null;
this.open = true; this.open = true;
this.input.focus(); this.input.focus();
this.element.addClass('active').addClass('dropdown-active'); this.element.addClass('active').addClass('dropdown-active');

2
couchpotato/static/scripts/library/form_replacement/form_radio.js

@ -22,7 +22,7 @@ Form.Radio = new Class({
toggle: function(e) { toggle: function(e) {
if (this.element.hasClass('checked') || this.disabled) { return; } if (this.element.hasClass('checked') || this.disabled) { return; }
var evt; var evt;
if (e) { evt = new Event(e).stop(); } if (e) { evt = (e).stop(); }
if (this.checked) { if (this.checked) {
this.uncheck(); this.uncheck();
} else { } else {

970
couchpotato/static/scripts/library/mootools.js

File diff suppressed because it is too large

2
couchpotato/static/scripts/page/settings.js

@ -184,7 +184,7 @@ Page.Settings = new Class({
'text': (group.label || group.name).capitalize() 'text': (group.label || group.name).capitalize()
}).adopt( }).adopt(
new Element('span.hint', { new Element('span.hint', {
'html': group.description 'html': group.description || ''
}) })
) )
) )

4
couchpotato/static/scripts/page/wanted.js

@ -8,11 +8,11 @@ Page.Wanted = new Class({
indexAction: function(param){ indexAction: function(param){
var self = this; var self = this;
if(!self.list){ if(!self.wanted){
// Wanted movies // Wanted movies
self.wanted = new MovieList({ self.wanted = new MovieList({
'status': ['active', 'snatched'], 'status': 'active',
'actions': MovieActions 'actions': MovieActions
}); });
$(self.wanted).inject(self.el); $(self.wanted).inject(self.el);

22
couchpotato/static/style/main.css

@ -1,6 +1,7 @@
/* @override /* @override
http://localhost:5000/static/style/main.css http://localhost:5000/static/style/main.css
http://192.168.1.20:5000/static/style/main.css http://192.168.1.20:5000/static/style/main.css
http://127.0.0.1:5000/static/style/main.css
*/ */
html { html {
@ -212,6 +213,27 @@ form {
color: #b1d8dc; color: #b1d8dc;
} }
.header .message {
text-align: center;
position: relative;
top: -70px;
padding: 15px 0 20px;
background: #ff6134;
font-size: 26px;
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-radius: 0 0 5px 5px;
box-shadow: 0 2px 1px rgba(0,0,0, 0.3);
-moz-box-shadow: 0 2px 1px rgba(0,0,0, 0.3);
-webkit-box-shadow: 0 2px 1px rgba(0,0,0, 0.3);
}
.header .message a {
padding: 0 10px;
}
/*** Global Styles ***/ /*** Global Styles ***/
.check { .check {
display: inline-block; display: inline-block;

11
libs/axl/axel.py

@ -11,7 +11,10 @@
# Source: http://pypi.python.org/pypi/axel # Source: http://pypi.python.org/pypi/axel
# Docs: http://packages.python.org/axel # Docs: http://packages.python.org/axel
import sys, threading, Queue from couchpotato.core.helpers.variable import natcmp
import Queue
import sys
import threading
class Event(object): class Event(object):
""" """
@ -100,7 +103,7 @@ class Event(object):
self.handlers = {} self.handlers = {}
self.memoize = {} self.memoize = {}
def handle(self, handler): def handle(self, handler, priority = 0):
""" Registers a handler. The handler can be transmitted together """ Registers a handler. The handler can be transmitted together
with two arguments as a list or dictionary. The arguments are: with two arguments as a list or dictionary. The arguments are:
@ -118,7 +121,7 @@ class Event(object):
event += {'handler':handler, 'memoize':True, 'timeout':1.5} event += {'handler':handler, 'memoize':True, 'timeout':1.5}
""" """
handler_, memoize, timeout = self._extract(handler) handler_, memoize, timeout = self._extract(handler)
self.handlers[hash(handler_)] = (handler_, memoize, timeout) self.handlers['%s.%s' % (priority, hash(handler_))] = (handler_, memoize, timeout)
return self return self
def unhandle(self, handler): def unhandle(self, handler):
@ -144,7 +147,7 @@ class Event(object):
t.daemon = True t.daemon = True
t.start() t.start()
for handler in self.handlers: for handler in sorted(self.handlers.iterkeys(), cmp = natcmp):
self.queue.put(handler) self.queue.put(handler)
if self.asynchronous: if self.asynchronous:

Loading…
Cancel
Save