Commits

Fred T-H committed 52ec555

refactored to add the basic listen behaviour

Comments (0)

Files changed (2)

 	url: {
 		base: 'http://localhost:8080',
 		listen: function(user_id){
-			return Chut.url.base+"/listen?id="+escape(user_id);
+			return Chut.url.base+"/listen?id="+escape(user_id)+'&'+Math.random();
 		},
 		message: function(from, to, msg){
 			from = escape(from);
 			to = escape(to);
 			msg = escape(msg);
-			return Chut.url.base+"/msg?from="+from+"&to="+to+"&msg="+msg;
+			return Chut.url.base+"/message?from="+from+"&to="+to+"&msg="+msg+'&'+Math.random();
 		},
 		history: function(user_id){
-			return Chut.url.base+"/hist?id="+escape(user_id);
+			return Chut.url.base+"/history?id="+escape(user_id)+'&'+Math.random();
 		}
 	},
 	callbacks: {
 		error: function(){
 			alert('cake is a lie?');
 		},
-		listen: function(e){
+		listen: function(Val){
 			ScriptCommunicator.callback_called = true;
-			alert('received: ' + e);
+			$.map(Val,function(Msg){
+				var Box = $('#chut_'+Msg.to);
+				if(Box.length > 0) {
+					Box.append("<dl><dd>"+Msg.action+": "+Msg.to+"</dd><dt>"+Msg.message+"</dt></dl>");
+				} else {
+					Chut.ui.add_chutbox('#chut',Msg.to);
+					Chut.callbacks.listen(Val);
+				}
+			});
 		},
 		message: function(e){
 			ScriptCommunicator.callback_called = true;
 			$(el).append(txt);
 			// bind events!
 			$('#chut_'+user_id+'_send').click(function(){
-				var from = escape($('#chut_nick').val());
-				var msg = escape($('#chut_'+user_id+'_msg').val());
+				var from = $('#chut_nick').val();
+				var msg = $('#chut_'+user_id+'_msg').val();
 				Chut.message(from, user_id, msg);
 			});
 		}
 	}
 	// events about logging on?
 	/* Reserved IDs
-	 * #chut:           general chut container
-	 * #chut_nick:      user_id
+	 * #chut:		   general chut container
+	 * #chut_nick:	  user_id
 	 * #chut_<id>_to:   user_id of message receiver
 	 * #chut_<id>_msg:  message to send to a user
-	 * #chut_<id>:      chat box of a discussion with a given user
+	 * #chut_<id>:	  chat box of a discussion with a given user
 	 */
 	$('#connect').click(function(){
 		var nickbox = $('#chut_nick');
 		if(nickbox.val() !== ''){
-			var nick = escape(nickbox.val());
+			var nick = nickbox.val();
 			nickbox.attr('readonly','readonly');
 			$('#connect').remove();
 			Chut.history(nick);

src/web_server.erl

 -module(web_server).
-
 -behaviour(gen_server).
-
 -define(SERVER, ?MODULE).
--define(OK, <<"ok">>).
 
 %% API
 -export([start_link/1, dispatch_requests/1, stop/0]).
-
 %% gen_server callbacks
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
-     terminate/2, code_change/3]).
+         terminate/2, code_change/3]).
 
 start_link(Port) ->
-  gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).
+    gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).
 
 init([Port]) ->
-  process_flag(trap_exit, true),
-  io:format("~p (~p) starting...~n", [?MODULE, self()]),
-  mochiweb_http:start([{port, Port},
-               {loop, fun(Req) ->
-                  dispatch_requests(Req) end}]),
-  {ok, []}.
+    process_flag(trap_exit, true),
+    io:format("~p (~p) starting...~n", [?MODULE, self()]),
+    mochiweb_http:start([{port, Port},
+                         {loop, fun(Req) -> dispatch_requests(Req) end}]),
+    {ok, []}.
 
 stop() ->
-  gen_server:cast(?SERVER, stop).
+    gen_server:cast(?SERVER, stop).
 
 dispatch_requests(Req) ->
-  Path = Req:get(path),
-  Action = clean_path(Path),
-  handle(Action, Req).
+    Path = Req:get(path),
+    handle(Path, Req).
 
 handle_call(_Request, _From, State) ->
-  Reply = ok,
-  {reply, Reply, State}.
+    Reply = ok,
+    {reply, Reply, State}.
 
 handle_cast(stop, State) ->
-  {stop, normal, State};
+    {stop, normal, State};
 
 handle_cast(_Msg, State) ->
-  {noreply, State}.
+    {noreply, State}.
 
 handle_info({'DOWN', _, _, {mochiweb_http, _}, _}, State) ->
-  {stop, normal, State};
+    {stop, normal, State};
 
 handle_info(_Info, State) ->
-  {noreply, State}.
+    {noreply, State}.
 
 terminate(_Reason, _State) ->
-  mochiweb_http:stop(),
-  ok.
+    mochiweb_http:stop(),
+    ok.
 
 code_change(_OldVsn, State, _Extra) ->
-  {ok, State}.
+    {ok, State}.
 
 %% Internal functions
-handle("/", Req) ->
-    Page = 
-    <<"<html>
-        <head>
-            <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />
-            <title>Test chat</title>
-            <style type=\"text/css\">
-                .sent { font-style:italic; color:#999; }
-                .received { font-style: italic; color: #333; }
-            </style>
-            <script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></script>
-            <script type=\"text/javascript\" src=\"client.js\"></script>
-        </head>
-        <body>
-            <h1>Chat client demo</h1>
-            <div id=\"content\">
-                <p>Demo par Fred T-H</p>
-            </div>
-        </body>
-    </html>">>,
-    success(Req, Page);
-handle("/client.js", Req) ->
-    Req:serve_file("client.js", ".");
-handle("/favicon.ico", Req) -> %% auto-request from browsers!
-    Req:serve_file("favicon.ico", ".");
 handle("/message", Req) ->
     Params = Req:parse_qs(),
-    From = proplists:get_value("nick", Params),
+    From = proplists:get_value("from", Params),
     To = proplists:get_value("to", Params),
     Message = proplists:get_value("msg", Params),
     {ok, H} = client:connect(From),
     %% listen call gets the right message process, a backlog gets printed to
     %% the user.
     lib:flush_receive(),
-    success(Req, ?OK);
+    reply(Req, mochijson2:encode(ok), Params);
 
 handle("/listen", Req) ->
     Params = Req:parse_qs(),
-    Nick = proplists:get_value("nick", Params),
+    Nick = proplists:get_value("id", Params),
     {ok,Handler} = client:connect(Nick),
-    Msgs = client:listen(Nick),
-    Ret = [json_prepare(M) || M <- Msgs],
+    Msgs = client:listen(Nick,Handler),
+    JSON = mochijson2:encode([json_prepare(M) || M <- Msgs]),
     client:disconnect(Nick, Handler),
-    json(Req, Ret);
+    %% mochiweb uses a process pool. We work around that here. aack :(
+    unlink(global:whereis_name({manager,Nick})),
+    reply(Req, JSON, Params);
 
-handle(_, Req) ->
-  error(Req, "").
+handle("/history", Req) ->
+    Params = Req:parse_qs(),
+    reply(Req, mochijson2:encode(ok), Params);
 
-error(Req, Body) when is_binary(Body) ->
-  Req:respond({500, [{"Content-Type", "text/plain"}], Body}).
-
-success(Req, Body) when is_binary(Body) ->
-  Req:respond({200, [{"Content-Type", "text/html"}], Body}).
-
-json(Req, Body) ->
-  JSON = mochijson2:encode(Body),
-  Req:respond({200, [{"Content-Type", "application/json"}], JSON}).
-
-clean_path(Path) ->
-  case string:str(Path, "?") of
-    0 ->
-      Path;
-    N ->
-      string:substr(Path, 1, string:len(Path) - (N + 1))
-  end.
+handle(Path, Req) ->
+    Params = Req:parse_qs(),
+    reply(Req, mochijson2:encode([error,list_to_binary(Path)]), Params).
 
 %% have to convert lists to binaries to be strings in json
 %% also gotta change the internal format of things to make it fit
 json_prepare({Verb,To,Msg=[_|_]}) -> json_prepare({Verb,To,unicode:characters_to_binary(Msg)});
 json_prepare({Verb,To,Msg}) ->
     {struct, [{action,Verb},{to,To},{message,Msg}]}.
+
+reply(Req, JSON, Params) ->
+    Callback = proplists:get_value("callback", Params),
+    Req:respond({200, [{"Content-Type", "text/javascript"}],
+                [Callback,$(,JSON,$),$;]}).