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