MOD passage au JSON terminé
[euphorik.git] / modules / erl / euphorik_protocole.erl
1 % coding: utf-8
2 % Ce module gére les différents messages envoyés par le client (javascript) via AJAX.
3 % Les messages donnés ainsi que les réponses sont au format JSON.
4 % @author G.Burri
5
6 -module(euphorik_protocole).
7 -export([
8 register/1,
9 login/1,
10 logout/1,
11 profile/1,
12 wait_event/1,
13 put_message/1,
14 erreur/1
15 ]).
16
17 -include_lib("xmerl/include/xmerl.hrl").
18 -include("../include/euphorik_bd.hrl").
19 -include("../include/euphorik_defines.hrl").
20
21
22 % Une utilisateur s'enregistre avec un tuple {Login, Password}.
23 register([{login, Login}, {password, Password}]) ->
24 case euphorik_minichat:user_by_login(Login) of
25 {ok, _} ->
26 erreur("Login déjà existant");
27 _ ->
28 User = euphorik_minichat:nouveau_user(Login, Password, generer_cookie()),
29 json_reponse_login_ok(User)
30 end;
31 % Enregistrement sans {Login, Password}
32 register([]) ->
33 User = euphorik_minichat:nouveau_user("<nick>", generer_cookie()),
34 json_reponse_login_ok(User).
35
36
37 % Un utilisateur se logge (avec un couple {login, mot de passe})
38 login([{login, Login}, {password, Password}]) ->
39 loginUser(euphorik_minichat:user_by_login_password(Login, Password));
40 % Un utilisateur se logge (avec un cookie)
41 login([{cookie, Cookie}]) ->
42 loginUser(euphorik_minichat:user_by_cookie(Cookie)).
43
44 loginUser({ok, User}) ->
45 euphorik_minichat:update_date_derniere_connexion(User#user.id),
46 json_reponse_login_ok(User);
47 loginUser(_) ->
48 erreur("Erreur login").
49
50
51 % Renvoie un string() représentant un cookie en base 36. Il y a 10^32 possibillités.
52 generer_cookie() ->
53 {A1,A2,A3} = now(),
54 random:seed(A1, A2, A3),
55 erlang:integer_to_list(random:uniform(math:pow(10, 32)), 36).
56
57
58 % Un utilisateur se délogge.
59 logout(_) ->
60 do_nothing.
61
62
63 % Modification du profile.
64 profile(
65 [
66 {cookie, Cookie},
67 {login, Login},
68 {password, Password},
69 {pseudo, Pseudo},
70 {email, Email},
71 {css, Css},
72 {main_page, Main_page},
73 {conversations, Conversations_json}
74 ]
75 ) ->
76 % est-ce que les messages auquel on répond existent ?
77 Conversations = lists:foldr(
78 fun([struct, {root, Root}, {page, Page}], Acc) ->
79 Message_existe = euphorik_minichat:message_existe(Root),
80 if Message_existe ->
81 [{Root, Page} | Acc];
82 true ->
83 Acc
84 end
85 end,
86 [],
87 Conversations_json
88 ),
89 case euphorik_minichat:set_profile(Cookie, Login, Password, Pseudo, Email, Css, Main_page, Conversations) of
90 ok ->
91 json_reponse_ok();
92 login_deja_pris ->
93 erreur("Login déjà pris");
94 _ ->
95 erreur("Impossible de mettre à jour le profile")
96 end.
97
98
99 % Renvoie les messages appropriés.
100 % last_message id et cookie sont facultatifs
101 % TODO : erreur : {badmatch,false}
102 wait_event(Data) ->
103 Cookie = case lists:keysearch(cookie, 1, Data) of {value, {_, C}} -> C; _ -> inconnu end,
104 Last_message_id = case lists:keysearch(last_message_id, 1, Data) of {value, {_, Id}} -> Id; _ -> 0 end,
105 {value, {_, Message_count}} = lists:keysearch(message_count, 1, Data),
106 Main_page = case lists:keysearch(main_page, 1, Data) of {value, {_, P}} -> P; _ -> 1 end,
107 {value, {_, {array, Conversations_json}}} = lists:keysearch(conversations, 1, Data),
108 Conversations = lists:map(fun({struct, [{racine, Racine}, {page, Page}]}) -> {Racine, Page} end, Conversations_json),
109 User = case euphorik_minichat:user_by_cookie(Cookie) of
110 {ok, U} -> U;
111 _ -> inconnu
112 end,
113 {struct, [
114 {reply, "new_message"},
115 {conversations, {array,
116 % accrochez-vous ca va siouxer ;)
117 lists:map(
118 fun({Conv, Plus}) ->
119 {struct, [
120 {last_page, not Plus},
121 {messages, {array,
122 lists:map(
123 fun({Mess, Repond_a}) ->
124 Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id,
125 A_repondu_a_message = User =/= inconnu andalso euphorik_minichat:a_repondu_a_message(User#user.id, Mess#minichat.id),
126 Est_une_reponse_a_user = User =/= inconnu andalso euphorik_minichat:est_une_reponse_a_user(User#user.id, Mess#minichat.id),
127 % io:format("Repond_a : ~p~n", [Repond_a]),
128 User_mess =
129 if Mess#minichat.auteur_id =:= 0 ->
130 inconnu;
131 true ->
132 {ok, U2} = euphorik_minichat:user_by_id(Mess#minichat.auteur_id),
133 U2
134 end,
135 {struct, [
136 {id, Mess#minichat.id},
137 {date, format_date(Mess#minichat.date)},
138 {system, Mess#minichat.auteur_id =:= 0},
139 {owner, Est_proprietaire},
140 {answered, A_repondu_a_message},
141 {is_a_reply, Est_une_reponse_a_user},
142 {nick, Mess#minichat.pseudo},
143 {login, if User_mess =:= inconnu -> Mess#minichat.pseudo; true -> User_mess#user.login end},
144 {content, Mess#minichat.contenu},
145 {answer_to, {array, lists:map(
146 fun(Id_mess) ->
147 {ok, M} = euphorik_minichat:message_by_id(Id_mess),
148 {ok, User_reponse} = euphorik_minichat:user_by_mess(M#minichat.id),
149 {struct, [{id, M#minichat.id}, {nick, M#minichat.pseudo}, {login, User_reponse#user.login}]}
150 end,
151 Repond_a
152 )}}
153 ]}
154 end,
155 Conv
156 )
157 }}
158 ]}
159 end,
160 euphorik_minichat_conversation:conversations(
161 Conversations,
162 Message_count,
163 Last_message_id,
164 Main_page
165 )
166 )
167 }}
168 ]}.
169
170
171 % Un utilisateur envoie un message
172 put_message(
173 [
174 {cookie, Cookie},
175 {nick, Nick},
176 {content, Content},
177 {answer_to, {array, Answer_to}}
178 ]
179 ) ->
180 case euphorik_minichat:user_by_cookie(Cookie) of
181 {ok, User} ->
182 Strip_content = string:strip(Content),
183 if (Strip_content =:= []) ->
184 erreur("Message vide");
185 true ->
186 case euphorik_minichat:nouveau_message(Strip_content, User#user.id, Answer_to) of
187 erreur -> erreur("Impossible d'ajouter un nouveau message");
188 _ ->
189 euphorik_minichat:update_pseudo_user(User#user.id, Nick),
190 json_reponse_ok()
191 end
192 end;
193 _ ->
194 erreur("Utilisateur inconnu")
195 end.
196
197
198 % Construit une erreur
199 erreur(Message) ->
200 {
201 struct, [
202 {reply, "error"},
203 {error_message, Message}
204 ]
205 }.
206
207
208 % Formatage d'une heure
209 % local_time() -> string
210 format_date(Date) ->
211 DateLocal = calendar:now_to_local_time(Date),
212 DateNowLocal = calendar:local_time(),
213 {{Annee, Mois, Jour}, {Heure, Minute, Seconde}} = DateLocal,
214 {{AnneeNow, _, _}, {_, _, _}} = DateNowLocal,
215 Hier = calendar:date_to_gregorian_days(element(1, DateLocal)) =:= calendar:date_to_gregorian_days(element(1, DateNowLocal)) - 1,
216 lists:flatten(
217 if element(1, DateLocal) =:= element(1, DateNowLocal) ->
218 "";
219 Hier ->
220 "Hier ";
221 Annee =:= AnneeNow ->
222 io_lib:format("~2.10.0B/~2.10.0B ", [Jour, Mois]);
223 true ->
224 io_lib:format("~2.10.0B/~2.10.0B/~B ", [Jour, Mois, Annee])
225 end ++
226 io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Heure, Minute, Seconde])
227 ).
228
229
230 %%%%%%%%% <Réponses JSON> %%%%%%%%%
231
232 json_reponse_ok() ->
233 {struct, [{reply, "ok"}]}.
234
235
236 json_reponse_login_ok(User) ->
237 {
238 struct, [
239 {reply, "login"},
240 {status, if (User#user.password =/= []) and (User#user.login =/= []) -> "auth_registered"; true -> "auth_not_registered" end},
241 {cookie, User#user.cookie},
242 {id, User#user.id},
243 {nick, User#user.pseudo},
244 {login, User#user.login},
245 {email, User#user.email},
246 {css, User#user.css},
247 {main_page, User#user.page_principale},
248 {conversations,
249 {array,
250 lists:map(
251 fun(C) ->
252 {struct,
253 {root, element(1, C)},
254 {page, element(2, C)}
255 }
256 end,
257 User#user.conversations
258 )
259 }
260 }
261 ]
262 }.
263
264
265 %%%%%%%%% </réponses JSON> %%%%%%%%%