diff --git a/plugins/Sidebar/SidebarPlugin.py b/plugins/Sidebar/SidebarPlugin.py
index 934bd6f9..ab258822 100644
--- a/plugins/Sidebar/SidebarPlugin.py
+++ b/plugins/Sidebar/SidebarPlugin.py
@@ -201,6 +201,55 @@ class UiWebsocketPlugin(object):
""".format(**locals()))
+
+ def sidebarRenderOptionalFileStats(self, body, site):
+ size_total = 0.0
+ size_downloaded = 0.0
+ for content in site.content_manager.contents.values():
+ if "files_optional" not in content:
+ continue
+ for file_name, file_details in content["files_optional"].items():
+ size_total += file_details["size"]
+ if site.content_manager.hashfield.hasHash(file_details["sha512"]):
+ size_downloaded += file_details["size"]
+
+
+ if not size_total:
+ return False
+
+ percent_downloaded = size_downloaded / size_total
+
+ size_formatted_total = size_total / 1024 / 1024
+ size_formatted_downloaded = size_downloaded / 1024 / 1024
+
+ body.append("""
+
+
+
+
+ - Downloaded:{size_formatted_downloaded:.2f}MB
+ - Total:{size_formatted_total:.2f}MB
+
+
+ """.format(**locals()))
+
+ return True
+
+ def sidebarRenderOptionalFileSettings(self, body, site):
+ if self.site.settings.get("autodownloadoptional"):
+ checked = "checked='checked'"
+ else:
+ checked = ""
+ body.append("""
+
+
+
+
+ """.format(**locals()))
+
def sidebarRenderDbOptions(self, body, site):
if not site.storage.db:
return False
@@ -232,7 +281,7 @@ class UiWebsocketPlugin(object):
checked = ""
body.append("""
- Owned site settings
+ This is my site
""".format(**locals()))
@@ -296,6 +345,9 @@ class UiWebsocketPlugin(object):
self.sidebarRenderTransferStats(body, site)
self.sidebarRenderFileStats(body, site)
self.sidebarRenderSizeLimit(body, site)
+ has_optional = self.sidebarRenderOptionalFileStats(body, site)
+ if has_optional:
+ self.sidebarRenderOptionalFileSettings(body, site)
self.sidebarRenderDbOptions(body, site)
self.sidebarRenderIdentity(body, site)
@@ -405,3 +457,12 @@ class UiWebsocketPlugin(object):
if "ADMIN" not in permissions:
return self.response(to, "You don't have permission to run this command")
self.site.settings["own"] = bool(owned)
+
+
+ def actionSiteSetAutodownloadoptional(self, to, owned):
+ permissions = self.getPermissions(to)
+ if "ADMIN" not in permissions:
+ return self.response(to, "You don't have permission to run this command")
+ self.site.settings["autodownloadoptional"] = bool(owned)
+ self.site.update()
+ self.site.worker_manager.removeGoodFileTasks()
diff --git a/plugins/Sidebar/media/Scrollable.js b/plugins/Sidebar/media/Scrollable.js
index acee6746..689a5719 100644
--- a/plugins/Sidebar/media/Scrollable.js
+++ b/plugins/Sidebar/media/Scrollable.js
@@ -15,9 +15,9 @@ window.initScrollable = function () {
// *Calculation of how tall scroller should be
var visibleRatio = scrollContainer.offsetHeight / scrollContentWrapper.scrollHeight;
if (visibleRatio == 1)
- scroller.style.display = "none"
+ scroller.style.display = "none";
else
- scroller.style.display = "block"
+ scroller.style.display = "block";
return visibleRatio * scrollContainer.offsetHeight;
}
@@ -32,13 +32,13 @@ window.initScrollable = function () {
normalizedPosition = evt.pageY;
contentPosition = scrollContentWrapper.scrollTop;
scrollerBeingDragged = true;
- window.addEventListener('mousemove', scrollBarScroll)
- return false
+ window.addEventListener('mousemove', scrollBarScroll);
+ return false;
}
function stopDrag(evt) {
scrollerBeingDragged = false;
- window.removeEventListener('mousemove', scrollBarScroll)
+ window.removeEventListener('mousemove', scrollBarScroll);
}
function scrollBarScroll(evt) {
@@ -51,7 +51,7 @@ window.initScrollable = function () {
}
function updateHeight() {
- scrollerHeight = calculateScrollerHeight()-10;
+ scrollerHeight = calculateScrollerHeight() - 10;
scroller.style.height = scrollerHeight + 'px';
}
@@ -62,9 +62,9 @@ window.initScrollable = function () {
scroller.className = 'scroller';
// determine how big scroller should be based on content
- scrollerHeight = calculateScrollerHeight()-10;
+ scrollerHeight = calculateScrollerHeight() - 10;
- if (scrollerHeight / scrollContainer.offsetHeight < 1){
+ if (scrollerHeight / scrollContainer.offsetHeight < 1) {
// *If there is a need to have scroll bar based on content size
scroller.style.height = scrollerHeight + 'px';
@@ -87,5 +87,5 @@ window.initScrollable = function () {
// *** Listeners ***
scrollContentWrapper.addEventListener('scroll', moveScroller);
- return updateHeight
+ return updateHeight;
};
\ No newline at end of file
diff --git a/plugins/Sidebar/media/Sidebar.coffee b/plugins/Sidebar/media/Sidebar.coffee
index 869b426f..6b7f20f8 100644
--- a/plugins/Sidebar/media/Sidebar.coffee
+++ b/plugins/Sidebar/media/Sidebar.coffee
@@ -220,6 +220,14 @@ class Sidebar extends Class
@updateHtmlTag()
return false
+ # Owned checkbox
+ @tag.find("#checkbox-owned").on "click", =>
+ wrapper.ws.cmd "siteSetOwned", [@tag.find("#checkbox-owned").is(":checked")]
+
+ # Owned checkbox
+ @tag.find("#checkbox-autodownloadoptional").on "click", =>
+ wrapper.ws.cmd "siteSetAutodownloadoptional", [@tag.find("#checkbox-autodownloadoptional").is(":checked")]
+
# Change identity button
@tag.find("#button-identity").on "click", =>
wrapper.ws.cmd "certSelect"
diff --git a/plugins/Sidebar/media/Sidebar.css b/plugins/Sidebar/media/Sidebar.css
index 7710305a..bd7bced2 100644
--- a/plugins/Sidebar/media/Sidebar.css
+++ b/plugins/Sidebar/media/Sidebar.css
@@ -21,7 +21,10 @@
.sidebar .fields { padding: 0px; list-style-type: none; width: 355px; }
.sidebar .fields > li, .sidebar .fields .settings-owned > li { margin-bottom: 30px }
.sidebar .fields > li:after, .sidebar .fields .settings-owned > li:after { clear: both; content: ''; display: block }
-.sidebar .fields label { font-family: Consolas, monospace; text-transform: uppercase; font-size: 13px; color: #ACACAC; display: block; margin-bottom: 10px; }
+.sidebar .fields label {
+ font-family: Consolas, monospace; text-transform: uppercase; font-size: 13px; color: #ACACAC; display: inline-block; margin-bottom: 10px;
+ vertical-align: text-bottom; margin-right: 10px;
+}
.sidebar .fields label small { font-weight: normal; color: white; text-transform: none; }
.sidebar .fields .text { background-color: black; border: 0px; padding: 10px; color: white; border-radius: 3px; width: 250px; font-family: Consolas, monospace; }
.sidebar .fields .text.long { width: 330px; font-size: 72%; }
@@ -52,7 +55,7 @@
/* GRAPH */
.graph { padding: 0px; list-style-type: none; width: 351px; background-color: black; height: 10px; border-radius: 8px; overflow: hidden; position: relative;}
-.graph li { height: 100%; position: absolute; }
+.graph li { height: 100%; position: absolute; transition: all 0.3s; }
.graph-stacked li { position: static; float: left; }
.graph-legend { padding: 0px; list-style-type: none; margin-top: 13px; font-family: Consolas, "Andale Mono", monospace; font-size: 13px; text-transform: capitalize; }
diff --git a/plugins/Sidebar/media/all.css b/plugins/Sidebar/media/all.css
index 2eb760ee..6496d130 100644
--- a/plugins/Sidebar/media/all.css
+++ b/plugins/Sidebar/media/all.css
@@ -75,7 +75,10 @@
.sidebar .fields { padding: 0px; list-style-type: none; width: 355px; }
.sidebar .fields > li, .sidebar .fields .settings-owned > li { margin-bottom: 30px }
.sidebar .fields > li:after, .sidebar .fields .settings-owned > li:after { clear: both; content: ''; display: block }
-.sidebar .fields label { font-family: Consolas, monospace; text-transform: uppercase; font-size: 13px; color: #ACACAC; display: block; margin-bottom: 10px; }
+.sidebar .fields label {
+ font-family: Consolas, monospace; text-transform: uppercase; font-size: 13px; color: #ACACAC; display: inline-block; margin-bottom: 10px;
+ vertical-align: text-bottom; margin-right: 10px;
+}
.sidebar .fields label small { font-weight: normal; color: white; text-transform: none; }
.sidebar .fields .text { background-color: black; border: 0px; padding: 10px; color: white; -webkit-border-radius: 3px; -moz-border-radius: 3px; -o-border-radius: 3px; -ms-border-radius: 3px; border-radius: 3px ; width: 250px; font-family: Consolas, monospace; }
.sidebar .fields .text.long { width: 330px; font-size: 72%; }
@@ -106,7 +109,7 @@
/* GRAPH */
.graph { padding: 0px; list-style-type: none; width: 351px; background-color: black; height: 10px; -webkit-border-radius: 8px; -moz-border-radius: 8px; -o-border-radius: 8px; -ms-border-radius: 8px; border-radius: 8px ; overflow: hidden; position: relative;}
-.graph li { height: 100%; position: absolute; }
+.graph li { height: 100%; position: absolute; -webkit-transition: all 0.3s; -moz-transition: all 0.3s; -o-transition: all 0.3s; -ms-transition: all 0.3s; transition: all 0.3s ; }
.graph-stacked li { position: static; float: left; }
.graph-legend { padding: 0px; list-style-type: none; margin-top: 13px; font-family: Consolas, "Andale Mono", monospace; font-size: 13px; text-transform: capitalize; }
diff --git a/plugins/Sidebar/media/all.js b/plugins/Sidebar/media/all.js
index 7e86061f..ecc738fb 100644
--- a/plugins/Sidebar/media/all.js
+++ b/plugins/Sidebar/media/all.js
@@ -77,9 +77,9 @@ window.initScrollable = function () {
// *Calculation of how tall scroller should be
var visibleRatio = scrollContainer.offsetHeight / scrollContentWrapper.scrollHeight;
if (visibleRatio == 1)
- scroller.style.display = "none"
+ scroller.style.display = "none";
else
- scroller.style.display = "block"
+ scroller.style.display = "block";
return visibleRatio * scrollContainer.offsetHeight;
}
@@ -94,13 +94,13 @@ window.initScrollable = function () {
normalizedPosition = evt.pageY;
contentPosition = scrollContentWrapper.scrollTop;
scrollerBeingDragged = true;
- window.addEventListener('mousemove', scrollBarScroll)
- return false
+ window.addEventListener('mousemove', scrollBarScroll);
+ return false;
}
function stopDrag(evt) {
scrollerBeingDragged = false;
- window.removeEventListener('mousemove', scrollBarScroll)
+ window.removeEventListener('mousemove', scrollBarScroll);
}
function scrollBarScroll(evt) {
@@ -113,7 +113,7 @@ window.initScrollable = function () {
}
function updateHeight() {
- scrollerHeight = calculateScrollerHeight()-10;
+ scrollerHeight = calculateScrollerHeight() - 10;
scroller.style.height = scrollerHeight + 'px';
}
@@ -124,9 +124,9 @@ window.initScrollable = function () {
scroller.className = 'scroller';
// determine how big scroller should be based on content
- scrollerHeight = calculateScrollerHeight()-10;
+ scrollerHeight = calculateScrollerHeight() - 10;
- if (scrollerHeight / scrollContainer.offsetHeight < 1){
+ if (scrollerHeight / scrollContainer.offsetHeight < 1) {
// *If there is a need to have scroll bar based on content size
scroller.style.height = scrollerHeight + 'px';
@@ -149,7 +149,7 @@ window.initScrollable = function () {
// *** Listeners ***
scrollContentWrapper.addEventListener('scroll', moveScroller);
- return updateHeight
+ return updateHeight;
};
@@ -398,6 +398,16 @@ window.initScrollable = function () {
return false;
};
})(this));
+ this.tag.find("#checkbox-owned").on("click", (function(_this) {
+ return function() {
+ return wrapper.ws.cmd("siteSetOwned", [_this.tag.find("#checkbox-owned").is(":checked")]);
+ };
+ })(this));
+ this.tag.find("#checkbox-autodownloadoptional").on("click", (function(_this) {
+ return function() {
+ return wrapper.ws.cmd("siteSetAutodownloadoptional", [_this.tag.find("#checkbox-autodownloadoptional").is(":checked")]);
+ };
+ })(this));
this.tag.find("#button-identity").on("click", (function(_this) {
return function() {
wrapper.ws.cmd("certSelect");
diff --git a/plugins/Stats/StatsPlugin.py b/plugins/Stats/StatsPlugin.py
index 799f3ec5..8ee87133 100644
--- a/plugins/Stats/StatsPlugin.py
+++ b/plugins/Stats/StatsPlugin.py
@@ -133,7 +133,7 @@ class UiRequestPlugin(object):
("%.0fkB", site.settings.get("bytes_sent", 0) / 1024),
("%.0fkB", site.settings.get("bytes_recv", 0) / 1024),
])
- yield "" % site.address
+ yield " |
" % site.address
for key, peer in site.peers.items():
if peer.time_found:
time_found = int(time.time()-peer.time_found)/60
@@ -143,6 +143,7 @@ class UiRequestPlugin(object):
connection_id = peer.connection.id
else:
connection_id = None
+ yield "Optional files: %s " % len(peer.hashfield)
yield "(#%s, err: %s, found: %s min ago) %22s - " % (connection_id, peer.connection_error, time_found, key)
yield "
|
"
yield ""
diff --git a/src/Config.py b/src/Config.py
index 8d7de4f8..d26dd899 100644
--- a/src/Config.py
+++ b/src/Config.py
@@ -8,7 +8,7 @@ class Config(object):
def __init__(self, argv):
self.version = "0.3.2"
- self.rev = 562
+ self.rev = 571
self.argv = argv
self.action = None
self.createParser()
diff --git a/src/Content/ContentManager.py b/src/Content/ContentManager.py
index c9a68921..65e5d1c8 100644
--- a/src/Content/ContentManager.py
+++ b/src/Content/ContentManager.py
@@ -62,12 +62,38 @@ class ContentManager(object):
if old_hash != new_hash:
changed.append(content_inner_dir + relative_path)
+ # Check changed optional files
+ for relative_path, info in new_content.get("files_optional", {}).items():
+ file_inner_path = content_inner_dir + relative_path
+ new_hash = info["sha512"]
+ if old_content and old_content.get("files_optional", {}).get(relative_path): # We have the file in the old content
+ old_hash = old_content["files_optional"][relative_path].get("sha512")
+ if old_hash != new_hash and self.site.settings.get("autodownloadoptional"):
+ changed.append(content_inner_dir + relative_path) # Download new file
+ elif old_hash != new_hash and not self.site.settings.get("own"):
+ try:
+ self.site.storage.delete(file_inner_path)
+ self.log.debug("Deleted changed optional file: %s" % file_inner_path)
+ except Exception, err:
+ self.log.debug("Error deleting file %s: %s" % (file_inner_path, err))
+ else: # The file is not in the old content
+ if self.site.settings.get("autodownloadoptional"):
+ changed.append(content_inner_dir + relative_path) # Download new file
+
# Check deleted
if old_content:
- deleted = [
- content_inner_dir + key for key in old_content.get("files", {}) if key not in new_content.get("files", {})
- ]
- if deleted:
+ old_files = dict(
+ old_content.get("files", {}),
+ **old_content.get("files_optional", {})
+ )
+
+ new_files = dict(
+ new_content.get("files", {}),
+ **new_content.get("files_optional", {})
+ )
+
+ deleted = [content_inner_dir + key for key in old_files if key not in new_files]
+ if deleted and not self.site.settings.get("own"):
# Deleting files that no longer in content.json
for file_inner_path in deleted:
try:
diff --git a/src/File/FileRequest.py b/src/File/FileRequest.py
index 418e7637..39f0f793 100644
--- a/src/File/FileRequest.py
+++ b/src/File/FileRequest.py
@@ -72,6 +72,8 @@ class FileRequest(object):
self.actionFindHashIds(params)
elif cmd == "setHashfield":
self.actionSetHashfield(params)
+ elif cmd == "siteReload":
+ self.actionSiteReload(params)
elif cmd == "ping":
self.actionPing()
else:
@@ -314,6 +316,17 @@ class FileRequest(object):
peer.hashfield.replaceFromString(params["hashfield_raw"])
self.response({"ok": "Updated"})
+ def actionSiteReload(self, params):
+ if self.connection.ip != "127.0.0.1" and self.connection.ip != config.ip_external:
+ self.response({"error": "Only local host allowed"})
+
+ site = self.sites.get(params["site"])
+ site.content_manager.loadContent(params["inner_path"], add_bad_files=False)
+ site.storage.verifyFiles(quick_check=True)
+ site.updateWebsocket()
+
+ self.response({"ok": "Reloaded"})
+
# Send a simple Pong! answer
def actionPing(self):
self.response("Pong!")
diff --git a/src/Peer/Peer.py b/src/Peer/Peer.py
index 87c58a3b..a543d581 100644
--- a/src/Peer/Peer.py
+++ b/src/Peer/Peer.py
@@ -1,5 +1,6 @@
import logging
import time
+import sys
import gevent
@@ -60,7 +61,11 @@ class Peer(object):
self.connection = None
try:
- self.connection = self.site.connection_server.getConnection(self.ip, self.port)
+ if self.site:
+ self.connection = self.site.connection_server.getConnection(self.ip, self.port)
+ else:
+ self.connection = sys.modules["main"].file_server.getConnection(self.ip, self.port)
+
except Exception, err:
self.onConnectionError()
self.log("Getting connection error: %s (connection_error: %s, hash_failed: %s)" %
diff --git a/src/Site/Site.py b/src/Site/Site.py
index 8938268d..4acd754a 100644
--- a/src/Site/Site.py
+++ b/src/Site/Site.py
@@ -130,6 +130,15 @@ class Site:
if res is not True and res is not False: # Need downloading and file is allowed
file_threads.append(res) # Append evt
+ # Optionals files
+ if self.settings.get("autodownloadoptional"):
+ for file_relative_path in self.content_manager.contents[inner_path].get("files_optional", {}).keys():
+ file_inner_path = content_inner_dir + file_relative_path
+ # Start download and dont wait for finish, return the event
+ res = self.needFile(file_inner_path, blocking=False, update=self.bad_files.get(file_inner_path), peer=peer)
+ if res is not True and res is not False: # Need downloading and file is allowed
+ file_threads.append(res) # Append evt
+
# Wait for includes download
include_threads = []
for file_relative_path in self.content_manager.contents[inner_path].get("includes", {}).keys():
@@ -212,6 +221,7 @@ class Site:
# Wait for peers
if not self.peers:
+ self.announce()
for wait in range(10):
time.sleep(5+wait)
self.log.debug("Waiting for peers...")
@@ -258,10 +268,7 @@ class Site:
self.log.debug("Fallback to old-style update")
self.redownloadContents()
- if self.settings["own"]:
- self.storage.verifyFiles(quick_check=True) # Check files (need for optional files)
- else:
- self.storage.checkFiles(quick_check=True) # Quick check and mark bad files based on file size
+ self.storage.checkFiles(quick_check=True) # Quick check and mark bad files based on file size
changed, deleted = self.content_manager.loadContent("content.json")
diff --git a/src/Site/SiteStorage.py b/src/Site/SiteStorage.py
index f9a4c3aa..bc276b3d 100644
--- a/src/Site/SiteStorage.py
+++ b/src/Site/SiteStorage.py
@@ -250,7 +250,7 @@ class SiteStorage:
return inner_path
# Verify all files sha512sum using content.json
- def verifyFiles(self, quick_check=False): # Fast = using file size
+ def verifyFiles(self, quick_check=False, add_optional=False, add_changed=True):
bad_files = []
if not self.site.content_manager.contents.get("content.json"): # No content.json, download it first
@@ -277,7 +277,8 @@ class SiteStorage:
if not ok:
self.log.debug("[CHANGED] %s" % file_inner_path)
- bad_files.append(file_inner_path)
+ if add_changed:
+ bad_files.append(file_inner_path)
# Optional files
optional_added = 0
@@ -288,6 +289,8 @@ class SiteStorage:
file_path = self.getPath(file_inner_path)
if not os.path.isfile(file_path):
self.site.content_manager.hashfield.removeHash(content["files_optional"][file_relative_path]["sha512"])
+ if add_optional:
+ bad_files.append(file_inner_path)
continue
if quick_check:
@@ -301,6 +304,8 @@ class SiteStorage:
else:
self.site.content_manager.hashfield.removeHash(content["files_optional"][file_relative_path]["sha512"])
optional_removed += 1
+ if add_optional:
+ bad_files.append(file_inner_path)
self.log.debug("[OPTIONAL CHANGED] %s" % file_inner_path)
self.log.debug(
@@ -313,10 +318,15 @@ class SiteStorage:
# Check and try to fix site files integrity
def checkFiles(self, quick_check=True):
s = time.time()
- bad_files = self.verifyFiles(quick_check)
+ bad_files = self.verifyFiles(
+ quick_check,
+ add_optional=self.site.settings.get("autodownloadoptional"),
+ add_changed=not self.site.settings.get("own") # Don't overwrite changed files if site owned
+ )
+ self.site.bad_files = {}
if bad_files:
for bad_file in bad_files:
- self.site.bad_files[bad_file] = self.site.bad_files.get("bad_file", 0) + 1
+ self.site.bad_files[bad_file] = 1
self.log.debug("Checked files in %.2fs... Quick:%s" % (time.time() - s, quick_check))
# Delete site's all file
diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py
index 4d762ccd..674de84d 100644
--- a/src/Ui/UiRequest.py
+++ b/src/Ui/UiRequest.py
@@ -138,6 +138,7 @@ class UiRequest(object):
headers = []
headers.append(("Version", "HTTP/1.1"))
headers.append(("Connection", "Keep-Alive"))
+ headers.append(("Keep-Alive", "max=25, timeout=30"))
headers.append(("Access-Control-Allow-Origin", "*")) # Allow json access
if self.env["REQUEST_METHOD"] == "OPTIONS":
# Allow json access
@@ -145,11 +146,11 @@ class UiRequest(object):
headers.append(("Access-Control-Allow-Credentials", "true"))
cacheable_type = (
- content_type == "text/css" or content_type.startswith("image") or
+ content_type == "text/css" or content_type.startswith("image") or content_type.startswith("video") or
self.env["REQUEST_METHOD"] == "OPTIONS" or content_type == "application/javascript"
)
- if status == 200 and cacheable_type: # Cache Css, Js, Image files for 10min
+ if status in (200, 206) and cacheable_type: # Cache Css, Js, Image files for 10min
headers.append(("Cache-Control", "public, max-age=600")) # Cache 10 min
else:
headers.append(("Cache-Control", "no-cache, no-store, private, must-revalidate, max-age=0")) # No caching at all
@@ -380,7 +381,7 @@ class UiRequest(object):
range_end = int(re.match(".*?-([0-9]+)", range).group(1))+1
else:
range_end = file_size
- extra_headers["Content-Length"] = range_end - range_start
+ extra_headers["Content-Length"] = str(range_end - range_start)
extra_headers["Content-Range"] = "bytes %s-%s/%s" % (range_start, range_end-1, file_size)
if range:
status = 206
diff --git a/src/Ui/UiWebsocket.py b/src/Ui/UiWebsocket.py
index eb0a50b9..523d762b 100644
--- a/src/Ui/UiWebsocket.py
+++ b/src/Ui/UiWebsocket.py
@@ -152,6 +152,7 @@ class UiWebsocket(object):
if content: # Remove unnecessary data transfer
content = content.copy()
content["files"] = len(content.get("files", {}))
+ content["files_optional"] = len(content.get("files_optional", {}))
content["includes"] = len(content.get("includes", {}))
if "sign" in content:
del(content["sign"])
diff --git a/src/Worker/WorkerManager.py b/src/Worker/WorkerManager.py
index ac7ce935..b969e07b 100644
--- a/src/Worker/WorkerManager.py
+++ b/src/Worker/WorkerManager.py
@@ -114,6 +114,18 @@ class WorkerManager:
continue # No peers found yet for the optional task
return task
+ def removeGoodFileTasks(self):
+ for task in self.tasks[:]:
+ if task["inner_path"] not in self.site.bad_files:
+ self.log.debug("No longer in bad_files, marking as good: %s" % task["inner_path"])
+ task["done"] = True
+ task["evt"].set(True)
+ self.tasks.remove(task)
+ if not self.tasks:
+ self.started_task_num = 0
+ self.site.updateWebsocket()
+
+
# New peers added to site
def onPeers(self):
self.startWorkers()
diff --git a/src/main.py b/src/main.py
index 045cb676..88be7682 100644
--- a/src/main.py
+++ b/src/main.py
@@ -226,18 +226,28 @@ class Actions(object):
global file_server
from Site import SiteManager
from File import FileServer # We need fileserver to handle incoming file requests
+ from Peer import Peer
logging.info("Creating FileServer....")
file_server = FileServer()
file_server_thread = gevent.spawn(file_server.start, check_sites=False) # Dont check every site integrity
file_server.openport()
+
site = SiteManager.site_manager.list()[address]
site.settings["serving"] = True # Serving the site even if its disabled
+
+ # Notify local client on new content
+ if config.ip_external:
+ logging.info("Sending siteReload")
+ my_peer = Peer(config.ip_external, config.fileserver_port)
+ logging.info(my_peer.request("siteReload", {"site": site.address, "inner_path": inner_path}))
+
if peer_ip: # Announce ip specificed
site.addPeer(peer_ip, peer_port)
else: # Just ask the tracker
logging.info("Gathering peers from tracker")
site.announce() # Gather peers
+
published = site.publish(20, inner_path) # Push to 20 peers
if published > 0:
time.sleep(3)