% coding: utf-8
-% Ce module gére les différents message envoyé par le client (javascript)
+% Ce module gére les différents message envoyé par le client (javascript) via AJAX.
% Par exemple le client peut demander les derniers messages du minichat.
% Les messages sont au format XML, la plus part des fonctions accepte un xmlDocument() et renvoie un string()
% qui est la réponse XML.\r
-% Example XML : http://www.erlang.org/doc/apps/xmerl/xmerl_ug.html
-% Auteur : G.Burri
-% Date : 29.10.2007
+% Example XML : http://www.erlang.org/doc/apps/xmerl/xmerl_ug.html.
+% @author G.Burri
-module(euphorik_protocole).
-export([
- generation_captcha/1,
- nouveau_user_captcha/1,
nouveau_user_login/1,
login/1,
logout/1,
profile/1,
refreshMessage/1,
- message/1
-]).
+ message/1,
+ erreur/1
+]).\r
+
-include_lib("xmerl/include/xmerl.hrl").
-include("../include/euphorik_bd.hrl").\r
--include("../include/euphorik_defines.hrl").
-%-compile(export_all).\r
-
+-include("../include/euphorik_defines.hrl").\r
-% Génère un nouveau captchat dans ?DOSSIER_CAPTCHA
-generation_captcha(_) ->
- {Mot_crypt, Nom_fichier} = captcha:create(5, ?DOSSIER_CAPTCHA),
- simple_xml_to_string(xml_reponse_generation_captcha(?DOSSIER_CAPTCHA_RELATIF "/" ++ Nom_fichier, Mot_crypt)).
-
-\r
-% Un nouvel utilisateur doit être créé
-% Action est un xmlElement()
-nouveau_user_captcha(Action) ->
- simple_xml_to_string(\r
- case {xmerl_xpath:string("captchaCrypt", Action), xmerl_xpath:string("captchaInput", Action)} of\r
- {[#xmlElement{content = [#xmlText{value = C1}]}], [#xmlElement{content = [#xmlText{value = C2}]}]} ->\r
- C2_crypt = common:crypt(C2),\r
- if C1 =:= C2_crypt ->\r
- Cookie = generer_cookie(),\r
- User = minichat:nouveau_user("Paul", Cookie),\r
- xml_reponse_login_ok(User);\r
- true ->
- xml_reponse_login_pas_ok("Captcha incorrect")\r
- end;
- _ ->
- xml_reponse_login_pas_ok("XML malformé")\r
- end
- ).
-nouveau_user_login(Action) ->\r
+% Une utilisateur s'enregistre avec un tuple {Login, Password}.
+register([]) ->\r
{Login, Password, Login_deja_pris} = case {xmerl_xpath:string("login", Action), xmerl_xpath:string("password", Action)} of\r
{[#xmlElement{content = [#xmlText{value = L}]}], [#xmlElement{content = [#xmlText{value = P}]}]} ->\r
- {L, P, case minichat:get_user_by_login(L) of {ok, _} -> true; _ -> false end};\r
+ {L, P, case euphorik_minichat:user_by_login(L) of {ok, _} -> true; _ -> false end};\r
_ -> {[], [], false}\r
end,
simple_xml_to_string(\r
xml_reponse_login_pas_ok("Login déjà pris");\r
true ->\r
Cookie = generer_cookie(),\r
- User = minichat:nouveau_user(Login, Password, Cookie),\r
+ User = euphorik_minichat:nouveau_user(Login, Password, Cookie),\r
xml_reponse_login_ok(User) \r
end
).\r
\r
-% Un utilisateur se logge
-login(Action) ->
- case xmerl_xpath:string("cookie", Action) of
- [#xmlElement{content = [#xmlText{value = Cookie}]}] ->
- loginUser(minichat:get_user_by_cookie(Cookie));
- _ ->
- case {xmerl_xpath:string("login", Action), xmerl_xpath:string("password", Action)} of
- {[#xmlElement{content = [#xmlText{value = Login}]}], [#xmlElement{content = [#xmlText{value = Password}]}]} ->
- loginUser(minichat:get_user_by_login_password(Login, Password));
- _ ->
- simple_xml_to_string(xml_reponse_login_pas_ok("XML malformé"))
- end
- end.
+% Un utilisateur se logge (avec un couple {login, mot de passe})
+login([{login, Login}, {password, Password}]) ->
+ loginUser(euphorik_minichat:user_by_login_password(Login, Password));
+% Un utilisateur se logge (avec un cookie)
+login([{cookie, Cookie}]) ->
+ loginUser(euphorik_minichat:user_by_cookie(Cookie)).
+
loginUser({ok, User}) ->
- minichat:update_date_derniere_connexion(User#user.id),
- simple_xml_to_string(xml_reponse_login_ok(User));
+ euphorik_minichat:update_date_derniere_connexion(User#user.id),
+ json_reponse_login_ok(User);
loginUser(_) ->
- simple_xml_to_string(xml_reponse_login_pas_ok("Erreur de login")).
+ erreur("Erreur login").
\r
% Renvoie un string() représentant un cookie en base 36. Il y a 10^32 possibillités.\r
% Modification du profile.
-profile(Action) ->
- simple_xml_to_string(
- case xmerl_xpath:string("cookie", Action) of
- [#xmlElement{content = [#xmlText{value = Cookie}]}] ->
- Login = case xmerl_xpath:string("login", Action) of [#xmlElement{content = [#xmlText{value = L}]}] -> L; _ -> undefined end,
- Password = case xmerl_xpath:string("password", Action) of [#xmlElement{content = [#xmlText{value = P}]}] -> P; _ -> undefined end,
- Pseudo = case xmerl_xpath:string("pseudo", Action) of [#xmlElement{content = [#xmlText{value = P2}]}] -> P2; _ -> Login end,
- Email = case xmerl_xpath:string("email", Action) of [#xmlElement{content = [#xmlText{value = E}]}] -> E; _ -> undefined end,
- Css = case xmerl_xpath:string("css", Action) of [#xmlElement{content = [#xmlText{value = C}]}] -> C; _ -> undefined end,
- case minichat:set_profile(Cookie, Login, Password, Pseudo, Email, Css) of
- ok ->
- xml_reponse_profile_ok();\r
- login_deja_pris ->\r
- xml_reponse_profile_pas_ok("Login déjà pris");
- _ ->
- xml_reponse_profile_pas_ok("Impossible de mettre à jour le profile")
- end;
- _ ->
- xml_reponse_profile_pas_ok("XML malformé")
- end
- ).
-
+profile(
+ [
+ {cookie, Cookie},
+ {login, Login},
+ {password, Password},
+ {pseudo, Pseudo},
+ {email, Email},
+ {css, Css},
+ {main_page, Main_page},
+ {conversations, {array, Conversations_json}}
+ ]
+) ->
+ % est-ce que les messages auquel on répond existent ?
+ Conversations = lists:foldr(
+ fun([struct, {root, Root}, {page, Page}], Acc) ->
+ Message_existe = euphorik_minichat:message_existe(Root),
+ if Message_existe ->
+ [{Root, Page} | Acc];
+ true ->
+ Acc
+ end,
+ [],
+ Conversations_json
+ ),
+ case euphorik_minichat:set_profile(Cookie, Login, Password, Pseudo, Email, Css, Main_page, Conversations) of
+ ok ->
+ json_reponse_ok();
+ login_deja_pris ->
+ erreur("Login déjà pris");
+ _ ->
+ erreur("Impossible de mettre à jour le profile")
+ end.
+
% Renvoie les messages appropriés.
-refreshMessage(Action) ->\r
- simple_xml_to_string(
- case {
- xmerl_xpath:string("nombreMessage", Action), % le nombre de message qu'affiche le client
- xmerl_xpath:string("page", Action) % la page désiré, la première (les derniers messages) étant la 1
- } of
- {
- [#xmlElement{content = [#xmlText{value = Nb_message_str}]}],
- [#xmlElement{content = [#xmlText{value = Page_str}]}]
- } ->
- Nb_message = list_to_integer(Nb_message_str),
- Page = list_to_integer(Page_str),
- Dernier_id = case xmerl_xpath:string("dernierMessageId", Action) of % l'id du dernier message que connait le client
- [#xmlElement{content = [#xmlText{value = D}]}] -> erlang:list_to_integer(D, 36);
- _ -> 0
- end,
- User = case xmerl_xpath:string("cookie", Action) of
- [#xmlElement{content = [#xmlText{value = Cookie}]}] ->
- case minichat:get_user_by_cookie(Cookie) of
- {ok, U} -> U;
- _ -> inconnu
- end;
- _ -> inconnu
- end,\r
- % accrochez-vous ca va siouxer ;)\r
- Mess = lists:map(\r
- fun(Mess) ->\r
- Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id,\r
- A_repondu_a_message = User =/= inconnu andalso minichat:a_repondu_a_message(User#user.id, Mess#minichat.id),\r
- Est_une_reponse_a_user = User =/= inconnu andalso minichat:est_une_reponse_a_user(User#user.id, Mess#minichat.id),
- User_mess = if Mess#minichat.auteur_id =:= 0 -> inconnu; true ->
- {ok, U2} = minichat:get_user_by_id(Mess#minichat.auteur_id),
- U2
- end, \r
- {message, [{id, erlang:integer_to_list(Mess#minichat.id, 36)}],\r
- [\r
- {date, [], [format_date(Mess#minichat.date)]},
- {systeme, [], [atom_to_list(Mess#minichat.auteur_id =:= 0)]},\r
- {proprietaire, [], [atom_to_list(Est_proprietaire)]},\r
- {repondu, [], [atom_to_list(A_repondu_a_message)]},\r
- {reponse, [], [atom_to_list(Est_une_reponse_a_user)]},\r
- {pseudo, [], [Mess#minichat.pseudo]},
- {login, [], [if User_mess =:= inconnu -> Mess#minichat.pseudo; true -> User_mess#user.login end]},\r
- {contenu, [], [Mess#minichat.contenu]},\r
- {repondA, [], xml_repond_a(Mess#minichat.id)}\r
- ]\r
- }\r
- end,\r
- get_dernieres_messages(Dernier_id, Nb_message, Page)\r
- ),
+wait_event(
+ [
+ {cookie, Cookie},
+ {message_count, Message_count} | Reste
+ ]
+) ->
+ % Last message id est facultatif
+ Last_message_id = case lists:keysearch(last_message_id, 1, Reste) of
+ {Id, _} -> Id;
+ _ -> 0
+ end,
+ {Main_page, _} = lists:keysearch(main_page, 1, Reste),
+ {{array, Conversations_json}, _} = lists:keysearch(conversations, 1, Reste),
+ User = case euphorik_minichat:user_by_cookie(Cookie) of\r
+ {ok U} -> U;\r
+ _ -> inconnu\r
+ end,\r
+ {stuct, [\r
+ {reply, "new_message"},\r
+ {conversations, {array,\r
+ TODO ...\r
+ } \r
+ ]}
+ \r
+ % accrochez-vous ca va siouxer ;)
[{reponse, [{name, "refreshMessages"}],\r
- % la fonction get_nb_page DOIT être évalué après get_dernieres_messages (merci les effets de bord)
- [{nbPage, [], [integer_to_list(minichat:get_nb_page(Nb_message))]} | Mess]
+ lists:map(\r
+ fun({Conv, Plus}) ->
+ {conversation, [],
+ [{autresPages, [], [atom_to_list(Plus)]} |
+ lists:map(
+ fun({Mess, Repond_a}) -> \r
+ Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id,\r
+ A_repondu_a_message = User =/= inconnu andalso euphorik_minichat:a_repondu_a_message(User#user.id, Mess#minichat.id),\r
+ Est_une_reponse_a_user = User =/= inconnu andalso euphorik_minichat:est_une_reponse_a_user(User#user.id, Mess#minichat.id),
+ User_mess =
+ if Mess#minichat.auteur_id =:= 0 ->
+ inconnu;
+ true ->
+ {ok, U2} = euphorik_minichat:user_by_id(Mess#minichat.auteur_id),
+ U2
+ end,\r
+ {message, [{id, erlang:integer_to_list(Mess#minichat.id, 36)}],\r
+ [\r
+ {date, [], [format_date(Mess#minichat.date)]},
+ {systeme, [], [atom_to_list(Mess#minichat.auteur_id =:= 0)]},\r
+ {proprietaire, [], [atom_to_list(Est_proprietaire)]},\r
+ {repondu, [], [atom_to_list(A_repondu_a_message)]},\r
+ {reponse, [], [atom_to_list(Est_une_reponse_a_user)]},\r
+ {pseudo, [], [Mess#minichat.pseudo]},
+ {login, [], [if User_mess =:= inconnu -> Mess#minichat.pseudo; true -> User_mess#user.login end]},\r
+ {contenu, [], [Mess#minichat.contenu]},\r
+ {repondA, [], xml_repond_a(Repond_a)}\r
+ ]\r
+ }
+ end,
+ Conv
+ )
+ ]
+ }\r
+ end,
+ euphorik_minichat_conversation:conversations(
+ if User =/= inconnu -> User#user.conversations; true -> [] end,
+ Nb_message,
+ Dernier_id,
+ if User =/= inconnu -> User#user.page_principale; true -> 1 end
+ )\r
+ )
}];
_ ->
[{reponse, [{name, "refreshMessages"}], [{erreur, [], ["erreur"]}]}]
end\r
).
-
-% Renvoie les dernies messages, s'il n'y en a pas on effectue une attente.
-get_dernieres_messages(Dernier_id, Nb_message, Page) ->
- Messages = minichat:messages(Dernier_id, Nb_message, Page),
- if Messages =:= [] ->
- minichat:attends_nouveau_messages(),
- minichat:messages(Dernier_id, Nb_message, Page);
- true ->
- Messages
- end.
-\r
+ \r
% Prend une liste de xml text node et en resort un string()\r
% xmerl : "test & test" devient deux fragments de texte : "test " et "& test", il faut donc rassembler les morceaux...\r
defragmenter(Text_nodes) ->\r
[#xmlElement{content = Pseudo_fragments}],
[#xmlElement{content = Contenu_fragments}]
} -> \r
- case minichat:get_user_by_cookie(Cookie) of\r
+ case euphorik_minichat:user_by_cookie(Cookie) of\r
{ok, U} ->\r
Pseudo = defragmenter(Pseudo_fragments),\r
Contenu = defragmenter(Contenu_fragments),\r
% met à jour le pseudo du user\r
- minichat:update_pseudo_user(U#user.id, Pseudo),\r
+ euphorik_minichat:update_pseudo_user(U#user.id, Pseudo),\r
Reponses = case xmerl_xpath:string("reponses", Action) of\r
[#xmlElement{content = C}] ->\r
lists:map(\r
Contenu_strip = string:strip(Contenu),
if Contenu_strip =:= [] -> xml_reponse_message(pas_ok);
true ->
- case minichat:nouveau_message(Contenu, U#user.id, Reponses) of
+ case euphorik_minichat:nouveau_message(Contenu, U#user.id, Reponses) of
erreur -> xml_reponse_message(pas_ok);
_ -> xml_reponse_message(ok)
end
end\r
).\r
+
+% Construit une erreur
+erreur(Message) ->
+ {
+ struct, [
+ {reply, "error"},
+ {error_message, Message}
+ ]
+ }.
+
\r
% Formatage d'une heure\r
% local_time() -> string\r
io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Heure, Minute, Seconde]).
-%%%%%%%%% <Réponses XML> %%%%%%%%%
-simple_xml_to_string(XML) ->
- lists:flatten(xmerl:export_simple(XML, xmerl_xml, [{prolog, ["<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"]}])).
+%%%%%%%%% <Réponses JSON> %%%%%%%%%
+json_reponse_ok() ->
+ {struct, [{reply, "ok"}]}.
+
% Construit une réponse positive à un login
% si Enregistre vaut true alors cela veut dire que la personne s'est enregistré (elle possède au moins un login et un password)
{pseudo, [User#user.pseudo]},
{login, [User#user.login]},
{email, [User#user.email]},
- {css, [User#user.css]}
- ]
+ {css, [User#user.css]},
+ {pagePrincipale, [integer_to_list(User#user.page_principale)]}
+ ] ++
+ lists:map(
+ fun(C) ->
+ {conversation,
+ [
+ {racine, [erlang:integer_to_list(element(1, C), 36)]},
+ {page, [integer_to_list(element(2, C))]}
+ ]
+ }
+ end,
+ User#user.conversations
+ )
}].
+json_reponse_login_ok(User) ->
+ {
+ struct, [
+ {reply, "login"},
+ {status, if (User#user.password =/= []) and (User#user.login =/= []) -> "enregistre"; true -> "identifie" end},
+ {cookie, User#user.cookie},
+ {id, User#user.id},
+ {pseudo, User#user.pseudo},
+ {login, User#user.login},
+ {email, User#user.email},
+ {css, User#user.css},
+ {main_page, User#user.page_principale},
+ {conversations,
+ {array,
+ lists:map(
+ fun(C) ->
+ {struct,
+ {root, element(1, C)},
+ {page, element(2, C)}
+ }
+ end,
+ User#user.conversations
+ )
+ }
+ }
+ ]
+ }.
+
+
% Construit un réponse négative à un login
xml_reponse_login_pas_ok(Message) ->
[{reponse, [{name, "login"}],
{information, [Message]}
]
}].
-
-
-xml_reponse_profile_ok() ->
- [{reponse, [{name, "profile"}],
- [
- {statut, ["ok"]}
- ]
- }].
-
-
-xml_reponse_profile_pas_ok(Message) ->
- [{reponse, [{name, "profile"}],
- [
- {statut, ["pas ok"]},
- {information, [Message]}
- ]
- }].
% Pas utilisé
% Renvoie un element XML representant une liste de messages auquel le message M_id repond
-xml_repond_a(Mess_id) ->
+xml_repond_a(Reponses) ->
lists:map(
- fun(M) ->
- {ok, User} = minichat:get_user_by_id(M#minichat.auteur_id),
+ fun(Id_mess) ->
+ {ok, M} = euphorik_minichat:message_by_id(Id_mess),
+ {ok, User} = euphorik_minichat:user_by_mess(Id_mess),
{id, [{id, erlang:integer_to_list(M#minichat.id, 36)}, {pseudo, M#minichat.pseudo}, {login, User#user.login}], []}
end,
- minichat:repond_a(Mess_id)
+ Reponses
).\r
\r
\r
]\r
}\r
].
-
-xml_reponse_generation_captcha(Chemin, Captcha) ->
- [
- {reponse, [{name, "generationCaptcha"}],
- [
- {chemin, [], [Chemin]},
- {captchaCrypt, [], [Captcha]}
- ]
- }
- ].
-%%%%%%%%% </réponses XML> %%%%%%%%%
-
-
-
+%%%%%%%%% </réponses XML> %%%%%%%%%