From 0addc61527e5be88292c0e98c691d969ceaf1f62 Mon Sep 17 00:00:00 2001 From: Gonzalo Odiard Date: Wed, 08 May 2013 17:55:45 +0000 Subject: Notify to the server when one object was successfully downloaded After download a object and save it in the Journal, the client send a message and the server update the metadata to include downloader information. The view is not updated yet. Signed-off-by: Gonzalo Odiard --- diff --git a/activity.py b/activity.py index e40ead8..18cc31b 100644 --- a/activity.py +++ b/activity.py @@ -67,7 +67,7 @@ class JournalShare(activity.Activity): # master is the activity in the activity who started the communication self._master = False - self._ip = '0.0.0.0' + self.ip = '0.0.0.0' if not self.shared_activity: # Get a free socket @@ -183,7 +183,7 @@ class JournalShare(activity.Activity): logging.error('temp_path %s', tmp_path) packaged_file_path = utils.package_ds_object( jobject, tmp_path) - url = 'ws://%s:%d/websocket/upload' % (self._ip, + url = 'ws://%s:%d/websocket/upload' % (self.ip, self.port) uploader = utils.Uploader(packaged_file_path, url) uploader.connect('uploaded', self.__uploaded_cb) @@ -227,11 +227,11 @@ class JournalShare(activity.Activity): assert isinstance(addr[0], str) assert isinstance(addr[1], (int, long)) assert addr[1] > 0 and addr[1] < 65536 - self._ip = addr[0] + self.ip = addr[0] self.port = int(addr[1]) self.view.load_uri('http://%s:%d/web/index.html' % - (self._ip, self.port)) + (self.ip, self.port)) return False def _start_sharing(self): @@ -423,6 +423,24 @@ class JournalManager(GObject.GObject): logging.error('INFO %s', info) return json.dumps(info) + def add_downloader(self, object_id, name, icon): + """ + Add to the metadata downloaded_by field, the information + about who downloaded one object + """ + dsobj = datastore.get(object_id) + downloaded_by = [] + if 'downloaded_by' in dsobj.metadata: + downloaded_by = json.loads(dsobj.metadata['downloaded_by']) + # add the user data + user_data = {} + user_data['from'] = name + user_data['icon'] = icon + downloaded_by.append(user_data) + dsobj.metadata['downloaded_by'] = json.dumps(downloaded_by) + datastore.write(dsobj) + self._update_temporary_files() + def create_object(self, file_path, metadata, preview_content): new_dsobject = datastore.create() #Set the file_path in the datastore. @@ -485,6 +503,6 @@ class JournalManager(GObject.GObject): results.append({'title': str(title), 'desc': str(desc), 'comment': comment, 'id': str(object_id), 'shared_by': shared_by, - 'downloaded-by': downloaded_by}) + 'downloaded_by': downloaded_by}) logging.error(results) return json.dumps(results) diff --git a/downloadmanager.py b/downloadmanager.py index 9e23acc..1708a8c 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -170,7 +170,16 @@ class Download(object): if self._dest_path.endswith('.journal'): - utils.unpackage_ds_object(self._dest_path, self.dl_jobject) + metadata, preview_data, file_path = \ + utils.unpackage_ds_object(self._dest_path) + original_object_id = metadata['original_object_id'] + for key in metadata.keys(): + self.dl_jobject.metadata[key] = metadata[key] + + self.dl_jobject.metadata['preview'] = dbus.ByteArray( + preview_data) + + self.dl_jobject.file_path = file_path datastore.write(self.dl_jobject, transfer_ownership=True, @@ -178,6 +187,14 @@ class Download(object): error_handler=self.__internal_error_cb, timeout=360) + # notify to the server, the object was successfully downloaded + url = 'ws://%s:%d/websocket' % (self._activity.ip, + self._activity.port) + messanger = utils.Messanger(url) + data = utils.get_user_data() + data['object_id'] = original_object_id + messanger.send_message('DOWNLOADED', data) + else: self.dl_jobject.metadata['title'] = \ self._download.get_suggested_filename() diff --git a/server.py b/server.py index a86e17c..602082d 100644 --- a/server.py +++ b/server.py @@ -27,6 +27,7 @@ from gi.repository import GLib import utils import tempfile import base64 +import json class DatastoreHandler(web.StaticFileHandler): @@ -34,6 +35,7 @@ class DatastoreHandler(web.StaticFileHandler): def set_extra_headers(self, path): """For subclass to add extra headers to the response""" self.set_header("Content-Type", 'application/journal') + self._path = path class JournalWebSocketHandler(websocket.WebSocketHandler): @@ -59,7 +61,17 @@ class JournalWebSocketHandler(websocket.WebSocketHandler): logging.error("WebSocket opened") def on_message(self, message): - self.write_message(u"You said: " + message) + logging.error('RECEIVED MSG: %s', message) + message_data = json.loads(message) + if message_data['type_message'] == 'DOWNLOADED': + message = message_data['message'] + object_id = message['object_id'] + name = message['from'] + icon = message['icon'] + logging.error('OBJECT %s WAS DOWNLOADED SUCCESSFULLY', object_id) + GLib.idle_add(self._jm.add_downloader, object_id, name, icon) + else: + self.write_message(u"You said: " + message) def on_close(self): logging.error("WebSocket closed") @@ -90,7 +102,7 @@ class WebSocketUploadHandler(websocket.WebSocketHandler): self._decoded_tmp_file.flush() metadata, preview_data, file_path = \ - utils.unpackage_ds_object(self._decoded_tmp_file.name, None) + utils.unpackage_ds_object(self._decoded_tmp_file.name) logging.error('METADATA %s', metadata) GLib.idle_add(self._jm.create_object, file_path, metadata, diff --git a/utils.py b/utils.py index 637d411..5ac0a13 100644 --- a/utils.py +++ b/utils.py @@ -22,6 +22,7 @@ import json import dbus from zipfile import ZipFile import logging +from threading import Thread import websocket import tempfile @@ -51,7 +52,6 @@ class Uploader(GObject.GObject): self._chunk = str(self._file.read(CHUNK_SIZE)) def start(self): - from threading import Thread upload_looop = Thread(target=self._ws.run_forever) upload_looop.setDaemon(True) upload_looop.start() @@ -78,6 +78,35 @@ class Uploader(GObject.GObject): GObject.idle_add(self.emit, 'uploaded') +class Messanger(GObject.GObject): + + __gsignals__ = {'sent': (GObject.SignalFlags.RUN_FIRST, None, ([str]))} + + def __init__(self, url): + GObject.GObject.__init__(self) + logging.error('websocket url %s', url) + self._ws = websocket.WebSocketApp(url, + on_open=self._on_open, + on_message=self._on_message, + on_error=self._on_error) + + def send_message(self, type_message, message): + self._message_data = {'type_message': type_message, 'message': message} + message_looop = Thread(target=self._ws.run_forever) + message_looop.setDaemon(True) + message_looop.start() + + def _on_open(self, ws): + self._ws.send(json.dumps(self._message_data)) + + def _on_message(self, ws, message): + message_data = json.loads(message) + GObject.idle_add(self.emit, 'sent', message_data) + + def _on_error(self, ws, error): + pass + + def get_user_data(): """ Create this structure: @@ -127,6 +156,7 @@ def package_ds_object(dsobj, destination_path): for key in dsobj.metadata.keys(): if key not in ('object_id', 'preview', 'progress'): metadata[key] = dsobj.metadata[key] + metadata['original_object_id'] = dsobj.object_id metadata_file.write(json.dumps(metadata)) metadata_file.close() @@ -145,7 +175,7 @@ def package_ds_object(dsobj, destination_path): return file_path -def unpackage_ds_object(origin_path, dsobj=None): +def unpackage_ds_object(origin_path): """ Receive a path of a zipped file, unzip it, and save the data, preview and metadata on a journal object @@ -156,12 +186,4 @@ def unpackage_ds_object(origin_path, dsobj=None): preview_data = zipped.read('preview') zipped.extract('data', tmp_path) - if dsobj is not None: - for key in metadata.keys(): - dsobj.metadata[key] = metadata[key] - - dsobj.metadata['preview'] = dbus.ByteArray(preview_data) - - dsobj.file_path = os.path.join(tmp_path, 'data') - else: - return metadata, preview_data, os.path.join(tmp_path, 'data') + return metadata, preview_data, os.path.join(tmp_path, 'data') diff --git a/web/index.html b/web/index.html index 66f58cf..303aec8 100644 --- a/web/index.html +++ b/web/index.html @@ -8,7 +8,20 @@ local = (window.location.hostname == '0.0.0.0'); - function add_tr(id, title, desc, shared_by) { + function add_tr(item) { + id = item.id; + title = item.title; + desc = item.desc; + shared_by = item.shared_by; + downloaded_by = item.downloaded_by; + downloaded_list = ''; + if (downloaded_by.length > 0) { + for (var i = 0; i < downloaded_by.length; i++) { + user_data = downloaded_by[i]; + downloaded_list += downloaded_list.concat(user_data.from); + } + } + $('#journaltable').append("" + ""+ ""+ @@ -16,7 +29,9 @@ "" + title + ""+ (shared_by.from != '' ? "Shared by " + shared_by.from + "" : "") + - "" + desc + ""+ + (desc != '' ? "" + desc + "" : "")+ + (downloaded_list != '' ? "Downloaded by " + downloaded_list + + "" : "") + (!local ? ""+ ""+ "Download" : "") + @@ -35,9 +50,7 @@ $.getJSON("/datastore/selected.json", function(selected) { for (var i = 0; i < selected.length; i++) { - id = selected[i].id; - add_tr(id, selected[i].title, selected[i].desc, - selected[i].shared_by); + add_tr(selected[i]); } if (selected.length == 0) { @@ -50,7 +63,6 @@ } - // test websockets websocket_url = "ws://" + window.location.hostname + ":" + window.location.port + "/websocket"; @@ -62,8 +74,7 @@ for (var i = 0; i < new_list.length; i++) { id = new_list[i].id; if ($('#' + id).length == 0) { - add_tr(id, new_list[i].title, new_list[i].desc, - new_list[i].shared_by); + add_tr(new_list[i]); } } }; -- cgit v0.9.1