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