From e739fb25d60a6f1eba2edb6b7b9ebb04b3b88dff Mon Sep 17 00:00:00 2001 From: SeekDaSky Date: Fri, 8 Dec 2017 00:39:17 +0100 Subject: [PATCH] fix: Interop operation pour le canal emergency --- src/Channel.kt | 2 +- src/Channels/Emergency.kt | 126 +++++++++++++++++++++++-------------- src/Collections/Message.kt | 1 + src/Collections/Stack.kt | 8 ++- src/Interop/DelMessage.kt | 39 ++++++++++++ src/Interop/PostMessage.kt | 39 +++++++++--- src/Interop/UpdMessage.kt | 44 +++++++++++++ src/Main.kt | 4 ++ 8 files changed, 207 insertions(+), 56 deletions(-) create mode 100644 src/Interop/DelMessage.kt create mode 100644 src/Interop/UpdMessage.kt diff --git a/src/Channel.kt b/src/Channel.kt index 271d730..3709819 100644 --- a/src/Channel.kt +++ b/src/Channel.kt @@ -98,7 +98,7 @@ class Channel : AsynchronousListener { jsonMessage.put("error",false); jsonMessage.put("msg",array); for(c in this.clients){ - if(c != e.client && c.data["IsLogged"] == true){ + if(c.data["IsLogged"] == true){ c.send(buildTextMessage(jsonMessage.toString())); } } diff --git a/src/Channels/Emergency.kt b/src/Channels/Emergency.kt index edc4baa..e3e347f 100644 --- a/src/Channels/Emergency.kt +++ b/src/Channels/Emergency.kt @@ -54,59 +54,31 @@ class Emergency : AsynchronousListener { c.data["IsLogged"] = false; } - fun manuallyDispatchMessage(channel : String, msg : String, username : String, location : List){ - val message = Message(); - message.location = location.toMutableList(); - message.message = msg; - message.user = username; - message.timestamp = System.currentTimeMillis() / 1000; + fun manuallyDispatchMessage(channel : String, msg : Message, operation : String){ val channelStack = this.messages[channel]; if(channelStack != null){ synchronized(channelStack, { - channelStack.push(Pair(username,message)); + channelStack.push(Pair(msg.user,msg)); }) - val array = JSONArray(); - array.put(message.toJSON()) - - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - jsonMessage.put("data",array); - - for(c in this.clients){ - if(c.data["IsLogged"] == true && c.data["emergencyChannel"] == channel){ - c.send(buildTextMessage(jsonMessage.toString())); - } - } + this.dispatchMessage(channel,msg,operation); }else if (channel == ""){ //broadcast for(c in this.messages.values){ synchronized(c,{ - c.push(Pair(username,message)); + c.push(Pair(msg.user,msg)); }) } - val array = JSONArray(); - array.put(message.toJSON()) - - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - jsonMessage.put("data",array); - - for(c in this.clients){ - if(c.data["IsLogged"] == true){ - c.send(buildTextMessage(jsonMessage.toString())); - } - } + this.dispatchMessage(channel,msg,operation); } } override fun processEvent(e: Event) { - System.out.println(e.message.toString()); try{ val json = JSONObject(e.message.getString()) @@ -133,13 +105,13 @@ class Emergency : AsynchronousListener { e.client.send(buildTextMessage(jsonLogin.toString())); //give the client the list of the most recent messages - val array = JSONArray(); + val array = JSONObject(); val chanMessages = this.messages[e.client.data["emergencyChannel"]]; if(chanMessages != null){ synchronized(chanMessages,{ chanMessages.toList().forEach { - array.put(it.second.toJSON()) + array.put(it.second.id,it.second.toJSON()) } }) } @@ -147,7 +119,7 @@ class Emergency : AsynchronousListener { //build JSON val jsonMessage = JSONObject(); jsonMessage.put("error",false); - jsonMessage.put("data",array); + jsonMessage.put("add",array); e.client.send(buildTextMessage(jsonMessage.toString())); }else{ @@ -173,9 +145,10 @@ class Emergency : AsynchronousListener { if(chanMessages != null){ message.user = e.client.data["Username"].toString(); message.message = json.getString("message"); + message.id = "-1"; - var lat = 0F; - var lng = 0F; + var lat : Float; + var lng : Float; //javascript may send float as integer so we double check that try { @@ -197,16 +170,13 @@ class Emergency : AsynchronousListener { }); } - val array = JSONArray(); - array.put(message.toJSON()) + var chanName = ""; + if(e.client.data["emergencyChannel"] != null){ + chanName = e.client.data["emergencyChannel"].toString(); + } - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - jsonMessage.put("data",array); for(c in this.clients){ - if(c.data["IsLogged"] == true && c.data["emergencyChannel"] == e.client.data["emergencyChannel"]){ - c.send(buildTextMessage(jsonMessage.toString())); - } + this.dispatchMessage(chanName,message,"add"); } }else{ System.out.println("unknown JSON: "+json.toString()); @@ -216,4 +186,68 @@ class Emergency : AsynchronousListener { e.printStackTrace(); } } + + fun dispatchMessage(channel: String,message: Message, operation : String){ + + val authorizedOperations = listOf("add","upd","del"); + + if(!authorizedOperations.contains(operation)){ + throw Exception("Unauthorized operation"); + } + + val array = JSONObject(); + array.put(message.id,message.toJSON()) + + val jsonMessage = JSONObject(); + jsonMessage.put("error",false); + + //all operations must be present but can be empty + for (op in authorizedOperations){ + if(op == operation){ + jsonMessage.put(op,array); + }else{ + jsonMessage.put(op,JSONArray()); + } + } + + for(c in this.clients){ + //dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast) + if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){ + c.send(buildTextMessage(jsonMessage.toString())); + } + } + } + + fun deleteMessage(id : String){ + this.messages.keys.forEach { + val key = it; + val array = this.messages[it]; + array?.toList()?.forEach{ + if(it.second.id == id){ + array.remove(it); + val msg = Message() + msg.id = id; + this.dispatchMessage(key,msg,"del"); + } + } + } + } + + fun updateMessage(msg : Message){ + this.messages.keys.forEach { + val key = it; + val array = this.messages[it]; + var index = 0; + array?.toList()?.forEach{ + if(it.second.id == msg.id){ + msg.user = it.second.user; + msg.location = it.second.location; + msg.timestamp = it.second.timestamp; + array.set(index,Pair(it.first,msg)); + this.dispatchMessage(key,msg,"upd"); + } + index++; + } + } + } } \ No newline at end of file diff --git a/src/Collections/Message.kt b/src/Collections/Message.kt index 4f4ecef..337a2c3 100644 --- a/src/Collections/Message.kt +++ b/src/Collections/Message.kt @@ -9,6 +9,7 @@ class Message { var message = ""; var timestamp = 0L; var location = mutableListOf(); + var id = ""; constructor(){ diff --git a/src/Collections/Stack.kt b/src/Collections/Stack.kt index 9035eb0..a7c9719 100644 --- a/src/Collections/Stack.kt +++ b/src/Collections/Stack.kt @@ -28,12 +28,16 @@ class Stack(size : Int){ } } + fun set(index : Int, item : T){ + this.items.set(index,item); + } + fun remove(item : T){ this.items.remove(item); } - fun toList() : List{ - return this.items.toList(); + fun toList() : MutableList{ + return this.items.toMutableList(); } } \ No newline at end of file diff --git a/src/Interop/DelMessage.kt b/src/Interop/DelMessage.kt new file mode 100644 index 0000000..c873b1d --- /dev/null +++ b/src/Interop/DelMessage.kt @@ -0,0 +1,39 @@ +package Interop + +import Channels.Emergency +import org.json.JSONObject +import seekdasky.kWebSocket.InteropEvent +import seekdasky.kWebSocket.Listeners.InteropListener + +class DelMessage : InteropListener { + + val emergencyController : Emergency; + + constructor(emergency : Emergency){ + this.emergencyController = emergency; + } + + override fun filter(e: InteropEvent): Boolean { + + val json = JSONObject(e.message.string); + + return json.has("operation") && + json.getString("operation") == "DelMessage"; + } + + override fun processEvent(e: InteropEvent) { + + try { + val json = JSONObject(e.message.string); + + + if(json.getString("channelType") == "Emergency"){ + this.emergencyController.deleteMessage(json.getString("id")); + } + + + }catch(e : Exception){ + e.printStackTrace() + } + } +} \ No newline at end of file diff --git a/src/Interop/PostMessage.kt b/src/Interop/PostMessage.kt index 4e8fd15..bebed30 100644 --- a/src/Interop/PostMessage.kt +++ b/src/Interop/PostMessage.kt @@ -1,6 +1,7 @@ package Interop import Channels.Emergency +import Collections.Message import org.json.JSONObject import seekdasky.kWebSocket.InteropEvent import seekdasky.kWebSocket.Listeners.InteropListener @@ -26,14 +27,38 @@ class PostMessage : InteropListener { try { val json = JSONObject(e.message.string); - val location = listOf((json.getJSONArray("location")[0] as Double).toFloat(), (json.getJSONArray("location")[1] as Double).toFloat()); + //javascript may send float as integer so we double check that + var lat : Float; + var lng : Float + try { + lat = (json.getJSONArray("location")[0] as Double).toFloat(); + }catch(e : Exception){ + lat = (json.getJSONArray("location")[0] as Integer).toFloat(); + } - this.emergencyController.manuallyDispatchMessage( - json.getString("channelName"), - json.getString("message"), - json.getString("username"), - location - ) + try { + lng = (json.getJSONArray("location")[1] as Double).toFloat(); + }catch(e : Exception){ + lng = (json.getJSONArray("location")[1] as Integer).toFloat(); + } + + val location = mutableListOf(lat, lng); + + val message = Message(); + message.location = location; + message.message = json.getString("message"); + message.user = json.getString("username"); + message.id = json.getString("id"); + message.timestamp = System.currentTimeMillis() / 1000; + + + if(json.getString("channelType") == "Emergency"){ + this.emergencyController.manuallyDispatchMessage( + json.getString("channelName"), + message, + "add" + ); + } }catch(e : Exception){ diff --git a/src/Interop/UpdMessage.kt b/src/Interop/UpdMessage.kt new file mode 100644 index 0000000..b65fea8 --- /dev/null +++ b/src/Interop/UpdMessage.kt @@ -0,0 +1,44 @@ +package Interop + +import Channels.Emergency +import Collections.Message +import org.json.JSONObject +import seekdasky.kWebSocket.InteropEvent +import seekdasky.kWebSocket.Listeners.InteropListener + +class UpdMessage : InteropListener { + + val emergencyController : Emergency; + + constructor(emergency : Emergency){ + this.emergencyController = emergency; + } + + override fun filter(e: InteropEvent): Boolean { + + val json = JSONObject(e.message.string); + + return json.has("operation") && + json.getString("operation") == "UpdMessage"; + } + + override fun processEvent(e: InteropEvent) { + + try { + val json = JSONObject(e.message.string); + + + if(json.getString("channelType") == "Emergency"){ + + val message = Message(); + message.message = json.getString("message"); + message.id = json.getString("id"); + + this.emergencyController.updateMessage(message); + } + + }catch(e : Exception){ + e.printStackTrace() + } + } +} \ No newline at end of file diff --git a/src/Main.kt b/src/Main.kt index 4ffe45f..bff7226 100644 --- a/src/Main.kt +++ b/src/Main.kt @@ -1,5 +1,7 @@ import Channels.Emergency +import Interop.DelMessage import Interop.PostMessage +import Interop.UpdMessage import seekdasky.kWebSocket.Server @@ -12,6 +14,8 @@ fun main(args: Array){ server.addListener(Channel(server,"/chat")); server.addListener(emergencyChannel); server.addInteropListener(PostMessage(emergencyChannel)); + server.addInteropListener(DelMessage(emergencyChannel)); + server.addInteropListener(UpdMessage(emergencyChannel)); server.addInteropListener(ConnectChannel); server.startServer();