summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/plugins/addon_plugin.rst4
-rw-r--r--module/AddonManager.py18
-rw-r--r--module/Api.py10
-rw-r--r--module/FileManager.py9
-rw-r--r--module/api/CoreApi.py5
-rw-r--r--module/config/ConfigManager.py2
-rw-r--r--module/interaction/EventManager.py80
-rw-r--r--module/plugins/Hoster.py2
-rw-r--r--module/remote/apitypes.py11
-rw-r--r--module/remote/apitypes_debug.py3
-rw-r--r--module/remote/pyload.thrift21
-rw-r--r--module/remote/wsbackend/AsyncHandler.py27
-rw-r--r--module/web/static/js/models/File.js7
-rw-r--r--module/web/static/js/models/ServerStatus.js81
-rw-r--r--module/web/static/js/views/dashboardView.js19
-rw-r--r--module/web/static/js/views/headerView.js19
-rw-r--r--module/web/static/js/views/linkGrabberModal.js3
-rw-r--r--module/web/templates/default/base.html21
-rwxr-xr-xpyload.py2
19 files changed, 169 insertions, 175 deletions
diff --git a/docs/plugins/addon_plugin.rst b/docs/plugins/addon_plugin.rst
index c2258f2aa..e18bd6b0f 100644
--- a/docs/plugins/addon_plugin.rst
+++ b/docs/plugins/addon_plugin.rst
@@ -59,7 +59,7 @@ What a basic excerpt would look like: ::
Your Hook code here.
"""
- def coreReady(self):
+ def activate(self):
print "Yay, the core is ready let's do some work."
def downloadFinished(self, pyfile):
@@ -147,7 +147,7 @@ Just store everything in ``self.info``. ::
def setup(self):
self.info = {"running": False}
- def coreReady(self):
+ def activate(self):
self.info["running"] = True
Usable with: ::
diff --git a/module/AddonManager.py b/module/AddonManager.py
index 7d3852274..cc2181767 100644
--- a/module/AddonManager.py
+++ b/module/AddonManager.py
@@ -44,14 +44,14 @@ class AddonManager:
self.createIndex()
# manage addons on config change
- self.addEvent("configChanged", self.manageAddons)
+ self.addEvent("config:changed", self.manageAddons)
@lock
- def callInHooks(self, event, *args):
+ def callInHooks(self, event, eventName, *args):
""" Calls a method in all addons and catch / log errors"""
for plugin in self.plugins.itervalues():
self.call(plugin, event, *args)
- self.dispatchEvent(event, *args)
+ self.dispatchEvent(eventName, *args)
def call(self, addon, f, *args):
try:
@@ -179,22 +179,22 @@ class AddonManager:
self.call(plugin, "deactivate")
def downloadPreparing(self, pyfile):
- self.callInHooks("downloadPreparing", pyfile)
+ self.callInHooks("downloadPreparing", "download:preparing", pyfile)
def downloadFinished(self, pyfile):
- self.callInHooks("downloadFinished", pyfile)
+ self.callInHooks("downloadFinished", "download:finished", pyfile)
def downloadFailed(self, pyfile):
- self.callInHooks("downloadFailed", pyfile)
+ self.callInHooks("downloadFailed", "download:failed", pyfile)
def packageFinished(self, package):
- self.callInHooks("packageFinished", package)
+ self.callInHooks("packageFinished", "package:finished", package)
def beforeReconnecting(self, ip):
- self.callInHooks("beforeReconnecting", ip)
+ self.callInHooks("beforeReconnecting", "reconnecting:before", ip)
def afterReconnecting(self, ip):
- self.callInHooks("afterReconnecting", ip)
+ self.callInHooks("afterReconnecting", "reconnecting:after", ip)
@lock
def startThread(self, function, *args, **kwargs):
diff --git a/module/Api.py b/module/Api.py
index 96b10be9c..27d3e8ffe 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -131,16 +131,6 @@ class Api(Iface):
return self.user_apis[uid]
- def getEvents(self, uuid):
- """Lists occurred events, may be affected to changes in future.
-
- :param uuid: self assigned string uuid which has to be unique
- :return: list of `Events`
- """
- # TODO: permissions?
- # TODO
- pass
-
#############################
# Auth+User Information
#############################
diff --git a/module/FileManager.py b/module/FileManager.py
index 082bdb4d4..0d8a35a64 100644
--- a/module/FileManager.py
+++ b/module/FileManager.py
@@ -292,7 +292,6 @@ class FileManager:
return pyfile
- #TODO
def getDownloadStats(self, user=None):
""" return number of downloads """
if user not in self.downloadstats:
@@ -377,7 +376,9 @@ class FileManager:
def updateFile(self, pyfile):
"""updates file"""
self.db.updateFile(pyfile)
- self.evm.dispatchEvent("file:updated", pyfile.fid, pyfile.packageid)
+
+ # This event is thrown with pyfile or only fid
+ self.evm.dispatchEvent("file:updated", pyfile)
def updatePackage(self, pypack):
"""updates a package"""
@@ -395,7 +396,7 @@ class FileManager:
# TODO: user context?
if not self.getQueueStats(None, True)[0]:
- self.core.addonManager.dispatchEvent("downloads:finished")
+ self.core.addonManager.dispatchEvent("download:allFinished")
self.core.log.debug("All downloads finished")
return True
@@ -409,7 +410,7 @@ class FileManager:
# TODO: user context?
if not self.db.processcount(fid):
- self.core.addonManager.dispatchEvent("downloads:processed")
+ self.core.addonManager.dispatchEvent("download:allProcessed")
self.core.log.debug("All downloads processed")
return True
diff --git a/module/api/CoreApi.py b/module/api/CoreApi.py
index 9338954d0..a86197813 100644
--- a/module/api/CoreApi.py
+++ b/module/api/CoreApi.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from module.Api import Api, RequirePerm, Permission, ServerStatus, PackageStats
+from module.Api import Api, RequirePerm, Permission, ServerStatus
from module.utils.fs import join, free_space
from module.utils import compare_time
@@ -32,7 +32,8 @@ class CoreApi(ApiComponent):
total = self.core.files.getDownloadStats(self.primaryUID)
serverStatus = ServerStatus(0,
- PackageStats(total[0], total[0] - queue[0], total[1], total[1] - queue[1]),
+ total[0], queue[0],
+ total[1], queue[1],
0,
not self.core.threadManager.pause and self.isTimeDownload(),
self.core.threadManager.pause,
diff --git a/module/config/ConfigManager.py b/module/config/ConfigManager.py
index eb96a49f6..8d908abaf 100644
--- a/module/config/ConfigManager.py
+++ b/module/config/ConfigManager.py
@@ -98,7 +98,7 @@ class ConfigManager(ConfigParser):
self.values[user, section][option] = value
self.saveValues(user, section)
- if changed: self.core.evm.dispatchEvent("configChanged", section, option, value)
+ if changed: self.core.evm.dispatchEvent("config:changed", section, option, value)
return changed
def saveValues(self, user, section):
diff --git a/module/interaction/EventManager.py b/module/interaction/EventManager.py
index 976a92413..b25514b6a 100644
--- a/module/interaction/EventManager.py
+++ b/module/interaction/EventManager.py
@@ -2,9 +2,6 @@
from threading import Lock
from traceback import print_exc
-from time import time
-
-from module.utils import lock
class EventManager:
"""
@@ -16,30 +13,25 @@ class EventManager:
===================== ================ ===========================================================
Name Arguments Description
===================== ================ ===========================================================
- metaEvent eventName, *args Called for every event, with eventName and original args
- downloadPreparing fid A download was just queued and will be prepared now.
- downloadStarts fid A plugin will immediately start the download afterwards.
- linksAdded links, pid Someone just added links, you are able to modify these links.
- allDownloadsProcessed All links were handled, pyLoad would idle afterwards.
- allDownloadsFinished All downloads in the queue are finished.
- unrarFinished folder, fname An Unrar job finished
- configChanged sec, opt, value The config was changed.
+ event eventName, *args Called for every event, with eventName and original args
+ download:preparing fid A download was just queued and will be prepared now.
+ download:start fid A plugin will immediately start the download afterwards.
+ download:allProcessed All links were handled, pyLoad would idle afterwards.
+ download:allFinished All downloads in the queue are finished.
+ config:changed sec, opt, value The config was changed.
===================== ================ ===========================================================
| Notes:
- | allDownloadsProcessed is *always* called before allDownloadsFinished.
- | configChanged is *always* called before pluginConfigChanged.
+ | download:allProcessed is *always* called before download:allFinished.
"""
- CLIENT_EVENTS = ("packageUpdated", "packageInserted", "linkUpdated", "packageDeleted")
-
def __init__(self, core):
self.core = core
self.log = core.log
# uuid : list of events
self.clients = {}
- self.events = {"metaEvent": []}
+ self.events = {"event": []}
self.lock = Lock()
@@ -66,12 +58,12 @@ class EventManager:
def dispatchEvent(self, event, *args):
"""dispatches event with args"""
- for f in self.events["metaEvent"]:
+ for f in self.events["event"]:
try:
f(event, *args)
except Exception, e:
self.log.warning("Error calling event handler %s: %s, %s, %s"
- % ("metaEvent", f, args, str(e)))
+ % ("event", f, args, str(e)))
if self.core.debug:
print_exc()
@@ -83,54 +75,4 @@ class EventManager:
self.log.warning("Error calling event handler %s: %s, %s, %s"
% (event, f, args, str(e)))
if self.core.debug:
- print_exc()
-
- self.updateClients(event, args)
-
- @lock
- def updateClients(self, event, args):
- # append to client event queue
- if event in self.CLIENT_EVENTS:
- for uuid, client in self.clients.items():
- if client.delete():
- del self.clients[uuid]
- else:
- client.append(event, args)
-
- def removeFromEvents(self, func):
- """ Removes func from all known events """
- for name, events in self.events.iteritems():
- if func in events:
- events.remove(func)
-
-
-
-class Client:
-
- # delete clients after this time
- TIMEOUT = 60 * 60
- # max events, if this value is reached you should assume that older events were dropped
- MAX = 30
-
- def __init__(self):
- self.lastActive = time()
- self.events = []
-
- def delete(self):
- return self.lastActive + self.TIMEOUT < time()
-
- def append(self, event, args):
- ev = (event, args)
- if ev not in self.events:
- self.events.insert(0, ev)
-
- del self.events[self.MAX:]
-
-
- def get(self):
- self.lastActive = time()
-
- events = self.events
- self.events = []
-
- return [(ev, [str(x) for x in args]) for ev, args in events] \ No newline at end of file
+ print_exc() \ No newline at end of file
diff --git a/module/plugins/Hoster.py b/module/plugins/Hoster.py
index 1c53807b7..fbe1c7480 100644
--- a/module/plugins/Hoster.py
+++ b/module/plugins/Hoster.py
@@ -279,7 +279,7 @@ class Hoster(Base):
filename = join(location, name)
- self.core.addonManager.dispatchEvent("downloadStarts", self.pyfile, url, filename)
+ self.core.addonManager.dispatchEvent("download:start", self.pyfile, url, filename)
try:
newname = self.req.httpDownload(url, filename, get=get, post=post, ref=ref, cookies=cookies,
diff --git a/module/remote/apitypes.py b/module/remote/apitypes.py
index aaec2b3ce..83368c6de 100644
--- a/module/remote/apitypes.py
+++ b/module/remote/apitypes.py
@@ -297,11 +297,14 @@ class ProgressInfo(BaseObject):
self.download = download
class ServerStatus(BaseObject):
- __slots__ = ['speed', 'files', 'notifications', 'paused', 'download', 'reconnect']
+ __slots__ = ['speed', 'linkstotal', 'linksqueue', 'sizetotal', 'sizequeue', 'notifications', 'paused', 'download', 'reconnect']
- def __init__(self, speed=None, files=None, notifications=None, paused=None, download=None, reconnect=None):
+ def __init__(self, speed=None, linkstotal=None, linksqueue=None, sizetotal=None, sizequeue=None, notifications=None, paused=None, download=None, reconnect=None):
self.speed = speed
- self.files = files
+ self.linkstotal = linkstotal
+ self.linksqueue = linksqueue
+ self.sizetotal = sizetotal
+ self.sizequeue = sizequeue
self.notifications = notifications
self.paused = paused
self.download = download
@@ -427,8 +430,6 @@ class Iface(object):
pass
def getCoreConfig(self):
pass
- def getEvents(self, uuid):
- pass
def getFileInfo(self, fid):
pass
def getFileTree(self, pid, full):
diff --git a/module/remote/apitypes_debug.py b/module/remote/apitypes_debug.py
index 6d30f1da6..4fab11f96 100644
--- a/module/remote/apitypes_debug.py
+++ b/module/remote/apitypes_debug.py
@@ -37,7 +37,7 @@ classes = {
'PackageInfo' : [int, basestring, basestring, int, int, basestring, basestring, basestring, int, (list, basestring), int, bool, int, PackageStats, (list, int), (list, int)],
'PackageStats' : [int, int, int, int],
'ProgressInfo' : [basestring, basestring, basestring, int, int, int, (None, DownloadProgress)],
- 'ServerStatus' : [int, PackageStats, int, bool, bool, bool],
+ 'ServerStatus' : [int, int, int, int, int, int, bool, bool, bool],
'ServiceDoesNotExists' : [basestring, basestring],
'ServiceException' : [basestring],
'TreeCollection' : [PackageInfo, (dict, int, FileInfo), (dict, int, PackageInfo)],
@@ -82,7 +82,6 @@ methods = {
'getConfig': (dict, basestring, ConfigHolder),
'getConfigValue': basestring,
'getCoreConfig': (list, ConfigInfo),
- 'getEvents': (list, EventInfo),
'getFileInfo': FileInfo,
'getFileTree': TreeCollection,
'getFilteredFileTree': TreeCollection,
diff --git a/module/remote/pyload.thrift b/module/remote/pyload.thrift
index dc6b1c406..06add4208 100644
--- a/module/remote/pyload.thrift
+++ b/module/remote/pyload.thrift
@@ -196,11 +196,14 @@ struct LinkStatus {
struct ServerStatus {
1: ByteCount speed,
- 2: PackageStats files,
- 3: i16 notifications,
- 4: bool paused,
- 5: bool download,
- 6: bool reconnect,
+ 2: i16 linkstotal,
+ 3: i16 linksqueue,
+ 4: ByteCount sizetotal,
+ 5: ByteCount sizequeue,
+ 6: i16 notifications,
+ 7: bool paused,
+ 8: bool download,
+ 9: bool reconnect,
}
struct InteractionTask {
@@ -257,7 +260,7 @@ struct ConfigInfo {
struct EventInfo {
1: string eventname,
- 2: list<JSONString> event_args,
+ 2: list<JSONString> event_args, //will contain json objects
}
struct UserData {
@@ -481,12 +484,6 @@ service Pyload {
list<InteractionTask> getNotifications(),
///////////////////////
- // Event Handling
- ///////////////////////
-
- list<EventInfo> getEvents(1: string uuid),
-
- ///////////////////////
// Account Methods
///////////////////////
diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py
index 2f9b43ad2..5c08aa96d 100644
--- a/module/remote/wsbackend/AsyncHandler.py
+++ b/module/remote/wsbackend/AsyncHandler.py
@@ -16,11 +16,13 @@
# @author: RaNaN
###############################################################################
+import re
from Queue import Queue, Empty
from threading import Lock
from mod_pywebsocket.msgutil import receive_message
+from module.Api import EventInfo
from module.utils import lock
from AbstractHandler import AbstractHandler
@@ -41,31 +43,40 @@ class AsyncHandler(AbstractHandler):
COMMAND = "start"
PROGRESS_INTERVAL = 2
- STATUS_INTERVAL = 60
+ EVENT_PATTERN = re.compile(r"^(package|file)", re.I)
def __init__(self, api):
AbstractHandler.__init__(self, api)
self.clients = []
self.lock = Lock()
+ self.core.evm.addEvent("event", self.add_event)
+
@lock
def on_open(self, req):
req.queue = Queue()
req.interval = self.PROGRESS_INTERVAL
+ req.events = self.EVENT_PATTERN
req.mode = Mode.STANDBY
self.clients.append(req)
@lock
def on_close(self, req):
try:
+ del req.queue
self.clients.remove(req)
except ValueError: # ignore when not in list
pass
@lock
- def add_event(self, event):
+ def add_event(self, event, *args):
+ # Convert arguments to json suited instance
+ event = EventInfo(event, [x.toInfoData() if hasattr(x, 'toInfoData') else x for x in args])
+
for req in self.clients:
- req.queue.put(event)
+ if req.events.search(event.eventname):
+ self.log.debug("Pushing event %s" % event)
+ req.queue.put(event)
def transfer_data(self, req):
while True:
@@ -100,6 +111,8 @@ class AsyncHandler(AbstractHandler):
if func == "setInterval":
req.interval = args[0]
+ elif func == "setEvents":
+ req.events = re.compile(args[0], re.I)
elif func == self.COMMAND:
req.mode = Mode.RUNNING
@@ -108,7 +121,13 @@ class AsyncHandler(AbstractHandler):
""" Listen for events, closes socket when returning True """
try:
ev = req.queue.get(True, req.interval)
- self.send(req, ev)
+ try:
+ self.send(req, ev)
+ except TypeError:
+ self.log.debug("Event %s not converted" % ev)
+ ev.event_args = []
+ # Resend the event without arguments
+ self.send(req, ev)
except Empty:
# TODO: server status is not enough
diff --git a/module/web/static/js/models/File.js b/module/web/static/js/models/File.js
index fa0945713..2ac6c05f5 100644
--- a/module/web/static/js/models/File.js
+++ b/module/web/static/js/models/File.js
@@ -31,6 +31,13 @@ define(['jquery', 'backbone', 'underscore', 'utils/apitypes'], function($, Backb
},
+ fetch: function(options){
+ options || (options = {});
+ options.url = 'api/getFileInfo/' + this.get('fid');
+
+ return Backbone.Model.prototype.fetch.call(this, options);
+ },
+
destroy: function(options) {
options || (options = {});
// TODO: as post data
diff --git a/module/web/static/js/models/ServerStatus.js b/module/web/static/js/models/ServerStatus.js
index 2430a9ffd..9242bdf95 100644
--- a/module/web/static/js/models/ServerStatus.js
+++ b/module/web/static/js/models/ServerStatus.js
@@ -1,47 +1,46 @@
define(['jquery', 'backbone', 'underscore'],
function($, Backbone, _) {
- return Backbone.Model.extend({
+ return Backbone.Model.extend({
+
+ defaults: {
+ speed: 0,
+ linkstotal: 0,
+ linksqueue: 0,
+ sizetotal: 0,
+ sizequeue: 0,
+ notifications: -1,
+ paused: false,
+ download: false,
+ reconnect: false
+ },
+
+ // Model Constructor
+ initialize: function() {
+
+ },
+
+ fetch: function() {
+ options || (options = {});
+ options.url = 'api/getServerStatus';
+
+ return Backbone.Model.prototype.fetch.call(this, options);
+ },
+
+ toJSON: function(options) {
+ var obj = Backbone.Model.prototype.toJSON.call(this, options);
+
+ obj.linksdone = obj.linkstotal - obj.linksqueue;
+ obj.sizedone = obj.sizetotal - obj.sizequeue;
+ if (obj.speed && obj.speed > 0)
+ obj.eta = Math.round(obj.sizequeue / obj.speed);
+ else if (obj.sizequeue > 0)
+ obj.eta = Infinity;
+ else
+ obj.eta = 0;
- defaults: {
- speed: 0,
- files: null,
- notifications: -1,
- paused: false,
- download: false,
- reconnect: false
- },
-
- // Model Constructor
- initialize: function() {
-
- },
-
- fetch: function() {
- options || (options = {});
- options.url = 'api/getServerStatus';
-
- return Backbone.Model.prototype.fetch.call(this, options);
- },
-
- toJSON: function(options) {
- var obj = Backbone.Model.prototype.toJSON.call(this, options);
-
- // stats are not available
- if (obj.files === null)
return obj;
+ }
- obj.files.linksleft = obj.files.linkstotal - obj.files.linksdone;
- obj.files.sizeleft = obj.files.sizetotal - obj.files.sizedone;
- if (obj.speed && obj.speed > 0)
- obj.files.eta = Math.round(obj.files.sizeleft / obj.speed);
- else if (obj.files.sizeleft > 0)
- obj.files.eta = Infinity;
- else
- obj.files.eta = 0;
-
- return obj;
- }
-
- });
-}); \ No newline at end of file
+ });
+ }); \ No newline at end of file
diff --git a/module/web/static/js/views/dashboardView.js b/module/web/static/js/views/dashboardView.js
index d9ff1c5fc..58a50777c 100644
--- a/module/web/static/js/views/dashboardView.js
+++ b/module/web/static/js/views/dashboardView.js
@@ -35,7 +35,11 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/TreeCollection',
self.tree.fetch();
});
- // TODO file:added
+ App.vent.on('file:updated', _.bind(this.fileUpdated, this));
+
+ // TODO: file:added
+ // TODO: package:deleted
+ // TODO: package:updated
},
init: function() {
@@ -48,7 +52,7 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/TreeCollection',
self.tree.get('packages').on('add', function(pack) {
console.log('Package ' + pack.get('pid') + ' added to tree');
self.appendPackage(pack, 0, true);
-
+ self.openPackage(pack);
});
}});
@@ -144,6 +148,17 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/TreeCollection',
//TODO: show placeholder when nothing is displayed (filtered content empty)
this.fileUL.fadeIn();
App.vent.trigger('dashboard:updated');
+ },
+
+ // Refresh the file if it is currently shown
+ fileUpdated: function(data) {
+ // this works with ids and object
+ var file = this.files.get(data);
+ if (file)
+ if (_.isObject(data)) // update directly
+ file.set(data);
+ else // fetch from server
+ file.fetch();
}
});
}); \ No newline at end of file
diff --git a/module/web/static/js/views/headerView.js b/module/web/static/js/views/headerView.js
index c22f173c4..35df06003 100644
--- a/module/web/static/js/views/headerView.js
+++ b/module/web/static/js/views/headerView.js
@@ -12,6 +12,7 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
},
templateStatus: _.compile($('#template-header-status').html()),
+ templateProgress: _.compile($('#template-header-progress').html()),
// Will hold the link grabber
grabber: null,
@@ -100,11 +101,15 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
},
render: function() {
-// console.log('Render header');
+ // TODO: what should be displayed in the header
+ // queue/processing size?
this.$('.status-block').html(
this.templateStatus(this.status.toJSON())
);
+
+ // TODO: render progress
+ this.$('.progress-list');
},
toggle_taskList: function() {
@@ -132,10 +137,10 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
if (data['@class'] === "ServerStatus") {
this.status.set(data);
}
- else if (data['@class'] === 'progress')
+ else if (_.isArray(data))
this.onProgressUpdate(data);
- else if (data['@class'] === 'event')
- this.onEvent(data);
+ else if (data['@class'] === 'EventInfo')
+ this.onEvent(data.eventname, data.event_args);
else
console.log('Unknown Async input');
@@ -145,8 +150,10 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
},
- onEvent: function(event) {
-
+ onEvent: function(event, args) {
+ args.unshift(event);
+ console.log('Core send event', args);
+ App.vent.trigger.apply(App.vent, args);
}
});
diff --git a/module/web/static/js/views/linkGrabberModal.js b/module/web/static/js/views/linkGrabberModal.js
index ea11aa339..9f7a5882d 100644
--- a/module/web/static/js/views/linkGrabberModal.js
+++ b/module/web/static/js/views/linkGrabberModal.js
@@ -30,7 +30,8 @@ define(['jquery', 'underscore', 'app', 'views/abstract/modalView', 'text!tpl/def
type: 'POST',
data: {
name: JSON.stringify($('#inputPackageName').val()),
- links: JSON.stringify(['http://download.pyload.org/random.bin', 'invalid link', 'invalid link 2', 'invalid link 3', 'inavlid link 4',
+ links: JSON.stringify(['http://download.pyload.org/random.bin', 'http://download.pyload.org/random100.bin',
+ 'invalid link', 'invalid link 2', 'invalid link 3', 'inavlid link 4',
'http://download.pyload.org/random.bin', 'http://download.pyload.org/random.bin', 'http://download.pyload.org/random.bin',
'A really really long invalid url that should exceed length of most of the urls by far and split into two lines'])
},
diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html
index 71b913f9e..2046dd36d 100644
--- a/module/web/templates/default/base.html
+++ b/module/web/templates/default/base.html
@@ -40,10 +40,25 @@
</script>
<script type="text/template" id="template-header-status">
- <span class="pull-right eta"><% formatTime files.eta %></span><br>
- <span class="pull-right remeaning"><% formatSize files.sizeleft %></span><br>
+ <span class="pull-right eta"><% formatTime eta %></span><br>
+ <span class="pull-right remeaning"><% formatSize sizequeue %></span><br>
<span class="pull-right"><span
- style="font-weight:bold;color: #fff !important;"><% files.linksleft %></span> of <% files.linkstotal %></span>
+ style="font-weight:bold;color: #fff !important;"><% linksqueue %></span> of <% linkstotal %></span>
+ </script>
+
+ <script type="text/template" id="template-header-progress">
+ <li> {# background-image for logo #}
+ Some Download
+ <span class="pull-right">YouTube</span>
+
+ <div class="progress">
+ <div class="bar" style="width: 25%"></div>
+ </div>
+ 20 Kb of 23 MB (500 kb/s)
+ <span class="pull-right">
+ 50%
+ </span>
+ </li>
</script>
{% block head %}
diff --git a/pyload.py b/pyload.py
index 55a62f182..e6d095827 100755
--- a/pyload.py
+++ b/pyload.py
@@ -447,7 +447,7 @@ class Core(object):
self.addonManager.activateAddons()
self.log.info(_("pyLoad is up and running"))
- self.eventManager.dispatchEvent("coreReady")
+ self.eventManager.dispatchEvent("core:ready")
#test api
# from module.common.APIExerciser import startApiExerciser