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