MOD avancement dans le module 'communication'
[euphorik.git] / js / client.js
1 // coding: utf-8
2 // Copyright 2008 Grégory Burri
3 //
4 // This file is part of Euphorik.
5 //
6 // Euphorik is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // Euphorik is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Euphorik. If not, see <http://www.gnu.org/licenses/>.
18
19 /*jslint laxbreak:true */
20
21 /**
22 * Représente l'utilisateur du site.
23 */
24 euphorik.Client = function(util, communication) {
25 this.util = util;
26 this.communication = communication
27
28 this.cookie = null;
29 this.regexCookie = /^cookie=([^;]*)/;
30
31 // données personnels
32 this.resetDonneesPersonnelles();
33
34 this.setStatut(euphorik.Client.statutType.deconnected);
35
36 // si true alors chaque modification du client est mémorisé sur le serveur
37 this.autoflush = $.browser.opera;
38 };
39
40 // les statuts possibes du client
41 euphorik.Client.statutType = {
42 // mode enregistré, peut poster des messages et modifier son profile
43 auth_registered : 0,
44 // mode identifié, peut poster des messages mais n'a pas accès au profile
45 auth_not_registered : 1,
46 // mode déconnecté, ne peut pas poster de message
47 deconnected : 2
48 };
49
50 euphorik.Client.prototype.resetDonneesPersonnelles = function() {
51 this.id = 0;
52 this.pseudo = euphorik.conf.pseudoDefaut;
53 this.login = "";
54 this.password = "";
55 this.email = "";
56 this.css = $("link#cssPrincipale").attr("href");
57 this.chatOrder = "reverse";
58 this.nickFormat = "nick";
59 this.viewTimes = true;
60 this.viewTooltips = true;
61 this.cookie = undefined;
62
63 this.pagePrincipale = 1;
64 this.ekMaster = false;
65 this.ostentatiousMaster = "light";
66
67 // les conversations, une conversation est un objet possédant les propriétés suivantes :
68 // - root (entier)
69 // - page (entier)
70 // - reduit (bool)
71 this.conversations = [];
72 };
73
74 euphorik.Client.prototype.setCss = function(css) {
75 if (this.css === css || !css) {
76 return;
77 }
78
79 this.css = css;
80 $("link#cssPrincipale").attr("href", this.css);
81 if (this.autoflush) {
82 this.flush(true);
83 }
84 };
85
86 euphorik.Client.prototype.pageSuivante = function(numConv) {
87 if (numConv < 0 && this.pagePrincipale > 1) {
88 this.pagePrincipale -= 1;
89 } else if (this.conversations[numConv].page > 1) {
90 this.conversations[numConv].page -= 1;
91 }
92 };
93
94 euphorik.Client.prototype.pagePrecedente = function(numConv) {
95 if (numConv < 0) {
96 this.pagePrincipale += 1;
97 } else {
98 this.conversations[numConv].page += 1;
99 }
100 };
101
102 /**
103 * Définit la première page pour la conversation donnée.
104 * @return true si la page a changé sinon false
105 */
106 euphorik.Client.prototype.goPremierePage = function(numConv)
107 {
108 if (numConv < 0) {
109 if (this.pagePrincipale === 1) {
110 return false;
111 }
112 this.pagePrincipale = 1;
113 } else {
114 if (this.conversations[numConv].page === 1) {
115 return false;
116 }
117 this.conversations[numConv].page = 1;
118 }
119 return true;
120 };
121
122 /**
123 * Ajoute une conversation à la vue de l'utilisateur.
124 * Le profile de l'utilisateur est directement sauvegardé sur le serveur.
125 * @param racines la racine de la conversation (integer)
126 * @return true si la conversation a été créée sinon false (par exemple si la conv existe déjà)
127 */
128 euphorik.Client.prototype.ajouterConversation = function(racine) {
129 // vérification s'il elle n'existe pas déjà
130 var existe = false;
131 this.conversations.each(function(i, conv) {
132 if (conv.root === racine) {
133 existe = true;
134 }
135 });
136 if (existe) {
137 return false;
138 }
139
140 this.conversations.push({root : racine, page : 1, reduit : false});
141 if (this.autoflush) {
142 this.flush(true);
143 }
144
145 return true;
146 };
147
148 euphorik.Client.prototype.supprimerConversation = function(num) {
149 if (num < 0 || num >= this.conversations.length) {
150 return;
151 }
152
153 // décalage TODO : supprimer le dernier élément
154 for (var i = num; i < this.conversations.length - 1; i++) {
155 this.conversations[i] = this.conversations[i+1];
156 }
157 this.conversations.pop();
158
159 if (this.autoflush) {
160 this.flush(true);
161 }
162 };
163
164 euphorik.Client.prototype.getJSONLogin = function(login, password) {
165 return {
166 "header" : { "action" : "authentification", "version" : euphorik.conf.versionProtocole },
167 "login" : login,
168 "password" : password
169 };
170 };
171
172 euphorik.Client.prototype.getJSONLoginCookie = function() {
173 return {
174 "header" : { "action" : "authentification", "version" : euphorik.conf.versionProtocole },
175 "cookie" : this.cookie
176 };
177 };
178
179 /**
180 * le couple (login, password) est facultatif. S'il n'est pas fournit alors il ne sera pas possible
181 * de s'autentifier avec (login, password).
182 */
183 euphorik.Client.prototype.getJSONEnregistrement = function(login, password) {
184 var mess = {
185 "header" : { "action" : "register","version" : euphorik.conf.versionProtocole }
186 };
187
188 if (login && password) {
189 mess.login = login;
190 mess.password = password;
191 }
192
193 mess.profile = this.getJSONProfileInfos();
194
195 return mess;
196 };
197
198 euphorik.Client.prototype.getJSONConversations = function() {
199 var conversations = [];
200 this.conversations.each(function(i, conv) {
201 conversations.push({ "root" : conv.root, "minimized" : conv.reduit });
202 });
203 return conversations;
204 };
205
206 euphorik.Client.prototype.getJSONProfile = function() {
207 return {
208 "header" : { "action" : "set_profile", "version" : euphorik.conf.versionProtocole },
209 "cookie" : this.cookie,
210 "login" : this.login,
211 "password" : this.password,
212 "profile" : this.getJSONProfileInfos()
213 };
214 };
215
216 euphorik.Client.prototype.getJSONProfileInfos = function() {
217 return {
218 "nick" : this.pseudo,
219 "email" : this.email,
220 "css" : this.css,
221 "chat_order" : this.chatOrder,
222 "nick_format" : this.nickFormat,
223 "view_times" : this.viewTimes,
224 "view_tooltips" : this.viewTooltips,
225 "conversations" : this.getJSONConversations(),
226 "ostentatious_master" : this.ostentatiousMaster
227 };
228 };
229
230 /**
231 * .
232 */
233 euphorik.Client.prototype.getCookie = function() {
234 var cookie = this.regexCookie.exec(document.cookie);
235 if (cookie) {
236 this.cookie = cookie[1];
237 } else {
238 this.cookie = undefined;
239 }
240 };
241
242 euphorik.Client.prototype.delCookie = function() {
243 document.cookie = "cookie=; max-age=0";
244 this.cookie = undefined;
245 };
246
247 euphorik.Client.prototype.setCookie = function() {
248 if (!this.cookie) {
249 return;
250 }
251
252 // ne fonctionne pas sous IE....
253 /*document.cookie = "cookie=" + this.cookie + "; max-age=" + (60 * 60 * 24 * 365) */
254
255 document.cookie =
256 "cookie="+this.cookie+"; expires=" + new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365).toUTCString();
257 };
258
259 euphorik.Client.prototype.authentifie = function() {
260 return this.statut === euphorik.Client.statutType.auth_registered || this.statut === euphorik.Client.statutType.auth_not_registered;
261 };
262
263 euphorik.Client.prototype.setStatut = function(statut)
264 {
265 // conversation en "enum" si en "string"
266 if (typeof(statut) === "string") {
267 statut =
268 statut === "auth_registered" ?
269 euphorik.Client.statutType.auth_registered :
270 (statut === "auth_not_registered" ? euphorik.Client.statutType.auth_not_registered : euphorik.Client.statutType.deconnected);
271 }
272
273 if (statut === this.statut) {
274 return;
275 }
276
277 this.statut = statut;
278
279 this.majMenu();
280 this.majLogo();
281 };
282
283 /**
284 * Effectue la connexion vers le serveur.
285 * Cette fonction est bloquante tant que la connexion n'a pas été établie.
286 * S'il existe un cookie en local on s'authentifie directement avec lui.
287 * Si il n'est pas possible de s'authentifier alors on affiche un captcha anti-bot.
288 */
289 euphorik.Client.prototype.connexionCookie = function() {
290 this.getCookie();
291 if (!this.cookie) {
292 return false;
293 }
294 return this.connexion(this.getJSONLoginCookie());
295 };
296
297 euphorik.Client.prototype.connexionLogin = function(login, password) {
298 return this.connexion(this.getJSONLogin(login, password));
299 };
300
301 euphorik.Client.prototype.enregistrement = function(login, password) {
302 if (this.authentifie()) {
303 this.login = login;
304 this.password = password;
305 if(this.flush()) {
306 this.setStatut(euphorik.Client.statutType.auth_registered);
307 return true;
308 }
309 return false;
310 } else {
311 return this.connexion(this.getJSONEnregistrement(login, password));
312 }
313 };
314
315 /**
316 * Connexion. Réalisée de manière synchrone.
317 */
318 euphorik.Client.prototype.connexion = function(action, messageJson) {
319 var thisClient = this;
320
321 this.communication.requete(
322 action,
323 messageJson,
324 function(data) {
325 thisClient.chargerDonnees(data);
326 },
327 function() {
328 thisClient.util.messageDialogue(data.error_message);
329 thisClient.delCookie(); // suppression du cookie actuel, cas où le cookie du client ne permet pas une authentification
330 }
331 );
332 return this.authentifie();
333 };
334
335 euphorik.Client.prototype.deconnexion = function() {
336 this.flush(true);
337 this.delCookie();
338 this.resetDonneesPersonnelles();
339 this.setStatut(euphorik.Client.statutType.deconnected); // deconnexion
340 };
341
342 euphorik.Client.prototype.chargerDonnees = function(data) {
343 // la modification du statut qui suit met à jour le menu, le menu dépend (page admin)
344 // de l'état ekMaster
345 this.ekMaster = data.ek_master ? data.ek_master : false;
346
347 this.setStatut(data.status);
348
349 if (this.authentifie()) {
350 this.cookie = data.cookie;
351 this.setCookie();
352
353 this.id = data.id;
354 this.login = data.login;
355 this.pseudo = data.profile.nick;
356 this.email = data.profile.email;
357 this.setCss(data.profile.css);
358 this.chatOrder = data.profile.chat_order;
359 this.nickFormat = data.profile.nick_format;
360 this.viewTimes = data.profile.view_times;
361 this.viewTooltips = data.profile.view_tooltips;
362 this.ostentatiousMaster = data.profile.ostentatious_master;
363
364 // la page de la conversation principale
365 this.pagePrincipale = 1;
366
367 // les conversations
368 this.conversations = data.profile.conversations;
369 this.conversations.map(function(conv) {
370 return { root : conv.root, page : 1, reduit : conv.minimized };
371 });
372
373 this.majBulle();
374 this.majCssSelectionee();
375 }
376 };
377
378 /**
379 * Met à jour les données personne sur serveur.
380 * @param async de manière asynchrone ? défaut = true
381 * @return false si le flush n'a pas pû se faire sinon true
382 */
383 euphorik.Client.prototype.flush = function(async) {
384 async = async || false;
385
386 if (!this.authentifie()) {
387 return false;
388 }
389
390 var thisClient = this;
391 var ok = true;
392 jQuery.ajax({
393 async: async,
394 type: "POST",
395 url: "request",
396 dataType: "json",
397 data: this.util.jsonVersAction(this.getJSONProfile()),
398 success:
399 function(data) {
400 if (data.reply === "error") {
401 thisClient.util.messageDialogue(data.error_message);
402 ok = false;
403 } else {
404 thisClient.majBulle();
405 }
406 }
407 });
408
409 return ok;
410 };
411
412 euphorik.Client.prototype.majMenu = function() {
413 var displayType = "block";
414
415 $("#menu .admin").css("display", this.ekMaster ? displayType : "none");
416
417 // met à jour le menu
418 if (this.statut === euphorik.Client.statutType.auth_registered) {
419 $("#menu .profile").css("display", displayType).text("profile");
420 $("#menu .logout").css("display", displayType);
421 $("#menu .register").css("display", "none");
422 } else if (this.statut === euphorik.Client.statutType.auth_not_registered) {
423 $("#menu .profile").css("display", "none");
424 $("#menu .logout").css("display", displayType);
425 $("#menu .register").css("display", displayType);
426 } else {
427 $("#menu .profile").css("display", displayType).text("login");
428 $("#menu .logout").css("display", "none");
429 $("#menu .register").css("display", displayType);
430 }
431 };
432
433 /**
434 * Met à jour l'affichage ou non des infos bulles en fonction du profile.
435 */
436 euphorik.Client.prototype.majBulle = function() {
437 this.util.bulleActive = this.viewTooltips;
438 };
439
440 /**
441 * Met à jour la css sélectionnée, lors du chargement des données.
442 */
443 euphorik.Client.prototype.majCssSelectionee = function() {
444 // extraction du numéro de la css courante
445 var numCssCourante = this.css.match(/^.*?\/(\d)\/.*$/);
446 if (numCssCourante && numCssCourante[1]) {
447 $("#menuCss option").removeAttr("selected");
448 $("#menuCss option[value=" + numCssCourante[1]+ "]").attr("selected", "selected");
449 }
450 };
451
452 /**
453 * Change la "class" du logo en fonction du statut de ekMaster.
454 */
455 euphorik.Client.prototype.majLogo = function() {
456 if (this.ekMaster) {
457 $("#logo").addClass("ekMaster");
458 } else {
459 $("#logo").removeClass("ekMaster");
460 }
461 };
462
463 euphorik.Client.prototype.slap = function(userId, raison) {
464 var thisClient = this;
465
466 jQuery.ajax({
467 type: "POST",
468 url: "request",
469 dataType: "json",
470 data: this.util.jsonVersAction({
471 "header" : { "action" : "slap", "version" : euphorik.conf.versionProtocole },
472 "cookie" : thisClient.cookie,
473 "user_id" : userId,
474 "reason" : raison
475 }),
476 success:
477 function(data) {
478 if (data.reply === "error") {
479 thisClient.util.messageDialogue(data.error_message);
480 }
481 }
482 });
483 };
484
485 euphorik.Client.prototype.ban = function(userId, raison, minutes)
486 {
487 var thisClient = this;
488
489 // par défaut un ban correspond à 3 jours
490 minutes = minutes || euphorik.conf.tempsBan;
491
492 jQuery.ajax({
493 type: "POST",
494 url: "request",
495 dataType: "json",
496 data: this.util.jsonVersAction({
497 "header" : { "action" : "ban", "version" : euphorik.conf.versionProtocole },
498 "cookie" : thisClient.cookie,
499 "duration" : minutes,
500 "user_id" : userId,
501 "reason" : raison
502 }),
503 success:
504 function(data) {
505 if (data.reply === "error") {
506 thisClient.util.messageDialogue(data.error_message);
507 }
508 }
509 });
510 };
511
512 euphorik.Client.prototype.kick = function(userId, raison) {
513 this.ban(userId, raison, euphorik.conf.tempsKick);
514 };