Remove the weekly troll.
authorUmmon <greg.burri@gmail.com>
Mon, 23 Mar 2015 08:14:41 +0000 (09:14 +0100)
committerUmmon <greg.burri@gmail.com>
Mon, 23 Mar 2015 08:14:41 +0000 (09:14 +0100)
22 files changed:
js/chat/commandes.js
js/chat/conversation.js
js/chat/conversations.js
js/chat/message.js
js/communication.js
js/pageAdmin.js
js/pageMinichat.js
js/util.js
modules/Makefile
modules/erl/euphorik_bd.erl
modules/erl/euphorik_bd_admin.erl
modules/erl/euphorik_common.erl
modules/erl/euphorik_daemon.erl
modules/erl/euphorik_minichat_conversation.erl
modules/erl/euphorik_protocole.erl
modules/erl/euphorik_requests.erl
modules/erl/euphorik_test.erl
modules/include/euphorik_bd.hrl
modules/include/euphorik_defines.hrl
tools/start_tv.erl
tools/tools.erl [changed mode: 0644->0755]
tools/tools.old.rb [changed mode: 0644->0755]

index 0c3d23b..871e22b 100644 (file)
 //
 // You should have received a copy of the GNU General Public License
 // along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
+
  /*jslint laxbreak:true */
 
 /**
   * Permet d'executer des commandes tapées par l'utilisateur.
   * les commandes sont entrées directement dans la ligne de saisie du message sous la forme :
   *  /<commande> <paramètres>
-  * 
+  *
   * Voici les commandes supportées :
   *  /nick <nouveau nick>
   *  Modifie le nick courant
@@ -34,7 +34,7 @@ euphorik.Commandes = function(client, pageMinichat, util, formater) {
    this.pageMinichat = pageMinichat;
    this.util = util;
    this.formater = formater;
-   
+
    // construction du texte d'aide (liste des commandes) de manière statique
    this.texteAide = "<div id=\"aideCommandes\"><h1>Commandes</h1><ul>";
    objectEach(
@@ -53,14 +53,14 @@ euphorik.Commandes.liste = {
       description : "Change le nick courant",
       usage : "/nick <nouveau nick>",
       exec : function(args, client) {
-         
+
          if (args.length === 0) {
             return [euphorik.Commandes.statut.erreur_commande, 'Utilisation de la commande : ' + this.usage];
          }
-   
+
          client.nick = args[0];
          $("form#posterMessage input.nick").val(client.nick);
-   
+
          return [euphorik.Commandes.statut.ok, ''];
       }
    },
@@ -88,15 +88,15 @@ euphorik.Commandes.liste = {
   */
 euphorik.Commandes.prototype.exec = function(chaine) {
    chaine = chaine.trim();
-   
+
    var fragments = chaine.split(/\s+/);
    if (fragments.length === 0 || fragments[0].charAt(0) != '/') {
       return [euphorik.Commandes.statut.pas_une_commande, ''];
    }
-   
+
    var commandName = fragments[0].slice(1);
    var args = fragments.slice(1);
-   
+
    if (commandName === "") {
       return [euphorik.Commandes.statut.erreur_commande, 'La commande est vide'];
    }
@@ -111,10 +111,10 @@ euphorik.Commandes.prototype.exec = function(chaine) {
       );
       return [euphorik.Commandes.statut.ok, ''];
    }
-   
+
    if (euphorik.Commandes.liste.hasOwnProperty(commandName)) {
       return euphorik.Commandes.liste[commandName].exec(args, this.client, this.pageMinichat);
    }
-   
+
    return [euphorik.Commandes.statut.erreur_commande, 'La commande /' + commandName + ' est inconnue'];
 };
index 5321380..8c11752 100644 (file)
@@ -15,7 +15,7 @@
 //\r
 // You should have received a copy of the GNU General Public License\r
 // along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
\r
+\r
  /*jslint laxbreak:true */\r
 \r
 /**\r
   */\r
 euphorik.Conversation = function(conversations, num) {\r
    this.conversations = conversations;\r
-   \r
+\r
    // peut changer au cours de la vie de la conversation, n'est pas un id !\r
    this.num = num;\r
-   \r
+\r
    this.id = Math.floor(Math.random() * 1000000).toString(36);\r
-   \r
+\r
    this.util = this.conversations.util;\r
    this.formater = this.conversations.formater;\r
    this.client = this.conversations.client;\r
-   \r
+\r
    this.idDernierMessageAffiche = 0;\r
    this.racine = undefined;\r
-   \r
+\r
    this.messages = [];\r
    this.messagesParId = {};\r
-   \r
+\r
    this.nbMessageMax = euphorik.conf.nbMessageAffiche; // Le nombre de message affiché par page\r
 \r
    var messagesXHTML = '<div class="messages"></div>';\r
    var messageRacineXHTML = '<div class="messageRacine"></div>';\r
    var reverse = this.client.chatOrder === "reverse";\r
-    \r
-   var XHTML = \r
+\r
+   var XHTML =\r
       '<td class="conversation" id="' + this.getId() + '">' +\r
          (reverse ? messagesXHTML : "") +\r
          '<div class="titre">' +\r
@@ -64,24 +64,24 @@ euphorik.Conversation = function(conversations, num) {
          (reverse ? "" : messagesXHTML) +\r
          //'<div class="messageReduit" style="height:200px; width:50px"></div>' +\r
       '</td>';\r
-    \r
+\r
    $("#conversations tr").append(XHTML);\r
-   \r
+\r
    // les infos bulles\r
    this.util.infoBulle("Aller à la première page", $("#" + this.getId() + " .titre .numPage"), euphorik.Util.positionBulleType.haut);\r
    if (this.num !== 0) {\r
       this.util.infoBulle("Créer un lien vers la conversation", $("#" + this.getId() + " .titre .creerLien"));\r
       this.util.infoBulle("Close the conversation", $("#" + this.getId() + " .titre .close"));\r
    }\r
-   \r
+\r
     // les différents événements liés à la conversation\r
-   var thisConversation = this;   \r
+   var thisConversation = this;\r
    $("#" + this.getId() + " .titre .creerLien").click(function() {\r
         thisConversation.util.replaceSelection(\r
            $("form#posterMessage input.message")[0],\r
            "{" + thisConversation.client.conversations[thisConversation.num - 1].root.toString(36) + "}"\r
         );\r
-   });   \r
+   });\r
    $("#" + this.getId() + " .titre .close").click(function() {\r
       thisConversation.conversations.supprimerConversation(thisConversation.num);\r
    });\r
@@ -118,7 +118,7 @@ euphorik.Conversation.prototype.majRacine = function() {
    if (!this.racine) {\r
       return;\r
    }\r
-     \r
+\r
    if (!(this.racine.id in this.messagesParId)) {\r
       this.messagesParId[this.racine.id] = this.racine;\r
       var element = $(this.racine.XHTML(true, this.getId()));\r
@@ -176,7 +176,7 @@ euphorik.Conversation.prototype.setPage = function(pageCourante, dernierePage) {
   */\r
 euphorik.Conversation.prototype.setFunPage = function(funNext, funPrev, funReset) {\r
    var thisConversation = this;\r
-   \r
+\r
    $("#" + this.getId() + " .next").click(\r
       function() { funNext(thisConversation.num); }\r
    );\r
@@ -201,12 +201,12 @@ euphorik.Conversation.prototype.getId = function() {
 euphorik.Conversation.prototype.ajouterMessage = function(message) {\r
    this.messages.push(message);\r
    this.messagesParId[message.id] = message;\r
-   \r
+\r
    // enlève le message exedentaire si nécessaire\r
    if (this.messages.length > this.nbMessageMax) {\r
       delete this.messagesParId[this.messages.shift().id];\r
    }\r
-   \r
+\r
    // met à jour le membre 'estReponduPar' des messages de la conversation\r
    for (var i = 0; i < this.messages.length - 1; i++) {\r
      var autreMess = this.messages[i];\r
@@ -224,7 +224,7 @@ euphorik.Conversation.prototype.viderMessages = function() {
    this.messagesParId = {};\r
    this.idDernierMessageAffiche = 0;\r
    $("#" + this.getId() + " .messages .message").remove();\r
-   \r
+\r
    // enlève également la racine\r
    $("#" + this.getId() + " .titre .messageRacine").empty();\r
 };\r
@@ -244,35 +244,35 @@ euphorik.Conversation.prototype.flush = function() {
 \r
    var messagePair = (this.idDernierMessageAffiche === 0 ? true :\r
       ($("#" + this.getId() + " .messages div:" + (reverse ? "first" : "last")).attr("class").search("messagePair") === -1)\r
-   );
-   
-   // permet d'itérer sur les nouveaux messages à afficher
-   var pourChaqueNouveauMessage = function(f) {
-      thisConversation.messages.each(function(i, mess) {
-         if (mess.id > thisConversation.idDernierMessageAffiche) {
-            f(mess);
-         }
-      });
+   );\r
+\r
+   // permet d'itérer sur les nouveaux messages à afficher\r
+   var pourChaqueNouveauMessage = function(f) {\r
+      thisConversation.messages.each(function(i, mess) {\r
+         if (mess.id > thisConversation.idDernierMessageAffiche) {\r
+            f(mess);\r
+         }\r
+      });\r
    };\r
-      \r
+\r
    // construction de l'XHTML des messages\r
-   var XHTML = "";
+   var XHTML = "";\r
    pourChaqueNouveauMessage(function(mess) {\r
       XHTML += mess.XHTML(messagePair, thisConversation.getId());\r
       messagePair = !messagePair;\r
    });\r
-   \r
-   var DOM = $(XHTML);       \r
-       \r
+\r
+   var DOM = $(XHTML);\r
+\r
    // pour chaque nouveau message au niveau du document on lui assigne ses événements\r
    DOM.each(function() { thisConversation.attacherEventsSurMessage(this); });\r
-   \r
+\r
    if (reverse) {\r
       DOM.prependTo("#" + this.getId() + " .messages");\r
    } else {\r
       DOM.appendTo("#" + this.getId() + " .messages");\r
    }\r
-   \r
+\r
    // enlève les messages exedentaires au niveau du document\r
    var nbMessagesAffiche = $("#" + this.getId() + " .messages .message").size();\r
    if (nbMessagesAffiche > this.nbMessageMax) {\r
@@ -281,26 +281,26 @@ euphorik.Conversation.prototype.flush = function() {
       } else {\r
          $("#" + this.getId() + " .messages .message").slice(0, nbMessagesAffiche - this.nbMessageMax).remove();\r
       }\r
-   }
-  
-   // met à jour la classe des messages auquels repondent les nouveaux messages
-   // dans le cas où ce message appartient au client courant (c'est un peu de la triche) TODO : ya mieux ?    
-   pourChaqueNouveauMessage(function(mess) {
-      if (mess.auteurId === thisConversation.client.id) {
-         objectEach(mess.repondA, function(messId) {
-            var mess = thisConversation.messagesParId[messId];
-            if (mess) {
-               mess.clientARepondu = true;
-               $("#conversations #" + mess.getId(thisConversation.getId())).addClass("repondu");
-            }
-         });
-      }
+   }\r
+\r
+   // met à jour la classe des messages auquels repondent les nouveaux messages\r
+   // dans le cas où ce message appartient au client courant (c'est un peu de la triche) TODO : ya mieux ?\r
+   pourChaqueNouveauMessage(function(mess) {\r
+      if (mess.auteurId === thisConversation.client.id) {\r
+         objectEach(mess.repondA, function(messId) {\r
+            var mess = thisConversation.messagesParId[messId];\r
+            if (mess) {\r
+               mess.clientARepondu = true;\r
+               $("#conversations #" + mess.getId(thisConversation.getId())).addClass("repondu");\r
+            }\r
+         });\r
+      }\r
    });\r
-   \r
+\r
    if (this.messages.length > 0) {\r
       this.idDernierMessageAffiche = this.messages[this.messages.length-1].id;\r
-   }
-  \r
+   }\r
+\r
    // met à jour la racine de la conversation\r
    this.majRacine();\r
 };\r
@@ -313,11 +313,11 @@ euphorik.Conversation.prototype.flush = function() {
 euphorik.Conversation.prototype.attacherEventsSurMessage = function(element) {\r
    // l'id du message\r
    var idMess = this.idMessageFromString($(element).attr("id"));\r
-   \r
+\r
    if (idMess in this.conversations.messagesRepond) {\r
       $(element).addClass("repondEnEvidence");\r
    }\r
-   \r
+\r
    var thisConversation = this;\r
    $(".conversationLink", element).click(\r
       function(event) {\r
@@ -327,7 +327,7 @@ euphorik.Conversation.prototype.attacherEventsSurMessage = function(element) {
          return false;\r
       }\r
    );\r
-       \r
+\r
    $(element).click(function(event) {\r
       if ($(event.target).is("a") || $(event.target).parents("#outilsBan").length > 0) {\r
          return;\r
@@ -386,7 +386,7 @@ euphorik.Conversation.prototype.attacherEventsSurMessage = function(element) {
    // les outils de bannissement (uniquement pour les ekMaster)\r
    if (thisConversation.client.ekMaster) {\r
       $(".nick", element).hover(\r
-         function(e) {     \r
+         function(e) {\r
             var userId = parseInt($(".id", this).text(), 10);\r
             var nick = $(this);\r
             var h = nick.outerHeight();\r
@@ -422,22 +422,22 @@ euphorik.Conversation.prototype.attacherEventsSurMessage = function(element) {
       );\r
    }\r
 };\r
-  \r
+\r
 /**\r
   * Etablit une liste des messages à mettre en evidence et des messages à cacher.\r
   * Puis applique un plan diabolique.\r
   * @param id l'id du message\r
   */\r
-euphorik.Conversation.prototype.afficherConversation = function(id) {   \r
+euphorik.Conversation.prototype.afficherConversation = function(id) {\r
    var thisConversation = this;\r
-    \r
+\r
    var message = this.messagesParId[id];\r
    if (!message) {\r
       return;\r
    }\r
 \r
    var mess = message.getConversation(this);\r
-   \r
+\r
    // FIXME : cet appel est très lent\r
    $("#" + this.getId() + " .messages .message").each(\r
       function() {\r
index 3f9fe2d..ea7e742 100644 (file)
@@ -15,7 +15,7 @@
 //\r
 // You should have received a copy of the GNU General Public License\r
 // along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
\r
+\r
 /*jslint laxbreak:true */\r
 \r
 /**\r
@@ -26,16 +26,14 @@ euphorik.Conversations = function(client, formater, util, communication, fragmen
    this.formater = formater;\r
    this.util = util;\r
    this.fragment = fragment;\r
-   \r
+\r
    // un ensemble des messages (id) auquel l'utilisateur répond (vider après l'envoie du message courant)\r
    this.messagesRepond = {};\r
-   \r
+\r
    this.conversations = []; // les conversations, la première représente la conversation principale\r
-   \r
+\r
    this.nouvelleConversation(0);\r
-   \r
-   this.trollIdCourant = 0;\r
-   \r
+\r
    this.comet = communication.createCometConnection("chat");\r
 };\r
 \r
@@ -47,13 +45,13 @@ euphorik.Conversations.prototype.prefixIdMessage = "rep";
   * Permet de définir un message comme étant ou n'étant plus un message auquel l'utilisateur\r
   * répond.\r
   */\r
-euphorik.Conversations.prototype.toggleMessageRepond = function(mess) {   \r
+euphorik.Conversations.prototype.toggleMessageRepond = function(mess) {\r
    // est-ce que l'on répond déjà à ce message ? si oui alors on l'enlève de la liste\r
    if (mess.id in this.messagesRepond) {\r
       this.enleverMessageRepond(mess);\r
       return;\r
    }\r
-   \r
+\r
    this.ajouterMessageRepond(mess);\r
 };\r
 \r
@@ -74,11 +72,11 @@ euphorik.Conversations.prototype.mettreAJourFragment = function() {
   */\r
 euphorik.Conversations.prototype.enleverMessagesRepond = function() {\r
    var thisConversations = this;\r
-   \r
+\r
    objectEach(this.messagesRepond, function(messId, mess) {\r
       thisConversations.enleverMessageRepond(mess);\r
    });\r
-    \r
+\r
    // on réinitialise pour être sur que tout est bien enlevé\r
    this.messagesRepond = {};\r
    $("#conversations .message").removeClass("repondEnEvidence");\r
@@ -100,7 +98,7 @@ euphorik.Conversations.prototype.enleverMessageRepond = function(mess) {
   */\r
 euphorik.Conversations.prototype.ajouterMessageRepond = function(mess) {\r
    var thisConversations = this;\r
-    \r
+\r
    // est-ce que le message fait partie de la même conversation que les autres messages ?\r
    // TODO : solution plus élégante pour prendre un mess parmis messagesRepond !?\r
    var mess2;\r
@@ -110,19 +108,19 @@ euphorik.Conversations.prototype.ajouterMessageRepond = function(mess) {
          break;\r
       }\r
    }\r
-   \r
+\r
    if (mess2 && mess2.racineId !== mess.racineId) {\r
       this.util.messageDialog("Impossible de répondre à deux messages ne faisant pas partie de la même conversation");\r
       return;\r
    }\r
-   \r
+\r
    $("form#posterMessage #repondA .messages").append(mess.XHTML(undefined, this.prefixIdMessage));\r
    this.messagesRepond[mess.id] = mess;\r
-   \r
+\r
    // ajout la classe 'repondEnEvidence' au message. comme il peut se trouver potentiellement dans\r
    // chaque conversation on construit tous les id potentiels\r
    $(mess.getId(this.prefixIdMessage) + ", " + this.exprIdsPotentiels(mess)).addClass("repondEnEvidence");\r
-   \r
+\r
    $("#" + mess.getId(this.prefixIdMessage)).click(\r
       function() {\r
          $(this).fadeOut("normal", function() {\r
@@ -152,9 +150,9 @@ euphorik.Conversations.prototype.exprIdsPotentiels = function(mess) {
 euphorik.Conversations.prototype.rafraichireNombreMessagesRepond = function() {\r
    // TODO : ya pas mieux pour trouver le nombre d'objet ?\r
    var nb = objectMemberCount(this.messagesRepond);\r
-   \r
+\r
    $("#posterMessage #repondA .nb").text(nb);\r
-   \r
+\r
    var boite = $("#posterMessage #repondA");\r
    if (nb > 0) {\r
       boite.show();\r
@@ -182,22 +180,21 @@ euphorik.Conversations.prototype.getJSONrafraichirMessages = function() {
    var mess =  {\r
       "message_count" : euphorik.conf.nbMessageAffiche,\r
       "main_page" : this.client.mainConversationPage,\r
-      "conversations" : this.getJSONConversations(),\r
-      "troll_id" : this.trollIdCourant\r
+      "conversations" : this.getJSONConversations()\r
    };\r
-   \r
+\r
    if (this.client.cookie) {\r
       mess.cookie = this.client.cookie;\r
    }\r
    mess.last_message_id = this.conversations[0].idDernierMessageAffiche;\r
-   \r
+\r
    return mess;\r
 };\r
 \r
 euphorik.Conversations.prototype.getJSONConversations = function() {\r
    var thisConversations = this;\r
    var clientConv = [];\r
-   \r
+\r
    this.client.conversations.each(function(i, conv) {\r
       clientConv.push({\r
          root : conv.root,\r
@@ -218,7 +215,7 @@ euphorik.Conversations.prototype.ajouterMessages = function(elements, numConvers
    if (!elements.messages.length) {\r
       return this.conversations[numConversation] !== undefined;\r
    }\r
-   \r
+\r
    for (var i = 0; i < elements.messages.length; i++) {\r
       if (this.ajouterMessage(elements.messages[i], numConversation)) {\r
          // si une nouvelle conversation a été créée alors on lui donne la racine\r
@@ -227,15 +224,15 @@ euphorik.Conversations.prototype.ajouterMessages = function(elements, numConvers
          this.mettreAJourFragment();\r
       }\r
    }\r
-         \r
+\r
    this.flush(numConversation);\r
-   \r
+\r
    // renseigne la conversation sur la page courante et si c'est la dernière\r
    this.conversations[numConversation].setPage(\r
       numConversation === 0 ? this.client.mainConversationPage : this.client.conversations[numConversation - 1].page,\r
       elements.last_page\r
    );\r
-   \r
+\r
    return true;\r
 };\r
 \r
@@ -246,16 +243,16 @@ euphorik.Conversations.prototype.ajouterMessages = function(elements, numConvers
   * @param numConversation le numéro de la conversation, 0 = principale\r
   * @return true si une nouvelle conversation a été créée sinon false\r
   */\r
-euphorik.Conversations.prototype.ajouterMessage = function(element, numConversation) {   \r
-   var message = \r
+euphorik.Conversations.prototype.ajouterMessage = function(element, numConversation) {\r
+   var message =\r
       new euphorik.Message(\r
          this.client,\r
          this.formater,\r
          element\r
       );\r
-   \r
+\r
    var nouvelleConversation = false;\r
-   \r
+\r
    if (!this.conversations[numConversation]) {\r
       nouvelleConversation = true;\r
       this.nouvelleConversation(numConversation);\r
@@ -269,7 +266,7 @@ euphorik.Conversations.prototype.nouvelleConversation = function(num) {
    var thisConversations = this;\r
 \r
    this.conversations[num] = new euphorik.Conversation(this, num);\r
-      \r
+\r
    this.conversations[num].setFunPage(\r
       function(num) { // page suivante\r
          thisConversations.client.nextPage(num - 1);\r
@@ -285,7 +282,7 @@ euphorik.Conversations.prototype.nouvelleConversation = function(num) {
          }\r
       }\r
    );\r
-   \r
+\r
    this.ajusterLargeurConversations();\r
 };\r
 \r
@@ -297,7 +294,7 @@ euphorik.Conversations.prototype.supprimerConversation = function(num) {
       return; // la numéro 0 ne peut être supprimé\r
    }\r
    this.conversations[num].supprimer();\r
-   \r
+\r
    // les numéros sont réassigné\r
    for (var i = num; i < this.conversations.length - 1; i++) {\r
       this.conversations[i] = this.conversations[i+1];\r
@@ -305,9 +302,9 @@ euphorik.Conversations.prototype.supprimerConversation = function(num) {
    }\r
    this.conversations.pop();\r
    this.ajusterLargeurConversations();\r
-      \r
+\r
    this.client.supprimerConversation(num - 1);\r
-      \r
+\r
    this.rafraichirMessages(true);\r
    this.mettreAJourFragment();\r
 };\r
@@ -322,7 +319,7 @@ euphorik.Conversations.prototype.ajusterLargeurConversations = function() {
    // le "- 0.01" evite que IE se chie dessus lamentablement et affiche les conversations les unes au dessus des autres\r
    //if($.browser["msie"])\r
    //    largeurPourcent -= 0.05\r
-   \r
+\r
    $("#conversations td").css("width", largeurPourcent + "%");\r
 };\r
 \r
@@ -338,10 +335,10 @@ euphorik.Conversations.prototype.flushAll = function() {
 /**\r
   * Demande à une conversation de se flusher.\r
   */\r
-euphorik.Conversations.prototype.flush = function(numConv) {   \r
+euphorik.Conversations.prototype.flush = function(numConv) {\r
    this.conversations[numConv].flush();\r
 };\r
-  \r
+\r
 euphorik.Conversations.prototype.ouvrirConversation = function(racine) {\r
    if (this.client.ajouterConversation(racine)) {\r
       this.rafraichirMessages(true);\r
@@ -363,38 +360,26 @@ euphorik.Conversations.prototype.viderMessages = function() {
   */\r
 euphorik.Conversations.prototype.rafraichirMessages = function(vider) {\r
    var thisConversations = this;\r
-   \r
+\r
    vider = vider || false;\r
-   \r
+\r
    if (vider) {\r
       this.conversations.each(function(i, conv) {\r
          conv.idDernierMessageAffiche = 0;\r
       });\r
    }\r
-   
-   thisConversations.util.showWaitBar(); // pour faire patienter le user :)
-   \r
+\r
+   thisConversations.util.showWaitBar(); // pour faire patienter le user :)\r
+\r
    this.comet.waitEvent(\r
-      function() { return thisConversations.getJSONrafraichirMessages(); },\r
       {\r
-         "new_troll" :\r
-            function(data) {\r
-               thisConversations.trollIdCourant = data.troll_id;\r
-               $("#trollCourant .troll").html(thisConversations.formater.completeProcessing(data.content)).unbind("click").click(\r
-                  function() {\r
-                     thisConversations.ouvrirConversation(data.message_id);\r
-                  }\r
-               );\r
-               \r
-               $("#trollCourant .troll a[@rel*=lightbox]").lightBox();\r
-            },\r
          "new_messages" :\r
-            function(data) {
-               \r
+            function(data) {\r
+\r
                if (vider) {\r
                   thisConversations.viderMessages();\r
                }\r
-               \r
+\r
                // ajoute les messages reçus à leur conversation respective\r
                data.conversations.each(function(numConv, conv) {\r
                   if (!thisConversations.ajouterMessages(conv, numConv)) {\r
@@ -402,15 +387,16 @@ euphorik.Conversations.prototype.rafraichirMessages = function(vider) {
                      thisConversations.client.supprimerConversation(numConv - 1);\r
                   }\r
                });\r
-               \r
+\r
                if (vider) {\r
                   thisConversations.afficherMessagesRepondConversations();\r
                }\r
-               \r
-               vider = false;
-               
+\r
+               vider = false;\r
+\r
                thisConversations.util.hideWaitBar();\r
             }\r
-      }\r
+      },\r
+      function() { return thisConversations.getJSONrafraichirMessages(); }\r
    );\r
 };\r
index 51d84b9..b3e5f12 100644 (file)
@@ -15,7 +15,7 @@
 //\r
 // You should have received a copy of the GNU General Public License\r
 // along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
\r
+\r
 euphorik.Reponse = function(id, nick, login) {\r
    this.id = id;\r
    this.nick = nick || "";\r
@@ -28,7 +28,7 @@ euphorik.Reponse = function(id, nick, login) {
 euphorik.Message = function(client, formater, element) {\r
    this.client = client;\r
    this.formater = formater;\r
-   \r
+\r
    this.id = element.id;\r
    this.auteurId = element.user_id;\r
    this.racineId = element.root;\r
@@ -36,11 +36,11 @@ euphorik.Message = function(client, formater, element) {
    this.nick = element.nick;\r
    this.login = element.login;\r
    this.contenu = element.content;\r
-   \r
+\r
    // l'ensemble des id des messages qui reponde à ce message, exemple : {45:true, 32:true} (le 'true' ne sert à rien ^_^)\r
    // mis à jour au fur à mesure que des messages sont ajoutés aux conversations\r
    this.estReponduPar = {};\r
-   \r
+\r
    this.appartientAuClient = element.owner;\r
    this.clientARepondu = element.answered;\r
    this.estUneReponse = element.is_a_reply;\r
@@ -63,7 +63,7 @@ euphorik.Message.prototype.getId = function(pre) {
 euphorik.Message.prototype.setRepondA = function(repondAJSON) {\r
    var thisMessage = this;\r
    this.repondA = {};\r
-   \r
+\r
    repondAJSON.each(function(i, reponse) {\r
       thisMessage.repondA[reponse.id] = new euphorik.Reponse(reponse.id, reponse.nick, reponse.login);\r
    });\r
@@ -81,7 +81,7 @@ euphorik.Message.prototype.getConversation = function(messages) {
    // les messages faisant partie de la conversation\r
    var messagesEnEvidence = {};\r
    messagesEnEvidence[this.id] = 1;\r
-   \r
+\r
    // parcours en profondeur\r
    var f = function(ids, premierNiveau, ensemble, evidence) {\r
       objectEach(ids, function(id) {\r
@@ -94,13 +94,13 @@ euphorik.Message.prototype.getConversation = function(messages) {
          }\r
       });\r
    };\r
-   \r
+\r
    // remonte le temps\r
    f(this.estReponduPar, true, "estReponduPar", 2);\r
-   \r
+\r
    // descent le temps\r
-   f(this.repondA, true, "repondA", 3);       \r
-   \r
+   f(this.repondA, true, "repondA", 3);\r
+\r
    return messagesEnEvidence;\r
 };\r
 \r
@@ -113,13 +113,13 @@ euphorik.Message.prototype.XHTML = function(messagePair, pre) {
       messagePair =  true;\r
    }\r
    pre = pre || "";\r
-   \r
+\r
    thisMessage = this;\r
-      \r
+\r
    // construit l'identifiant de la personne\r
-   var identifiant = \r
-      this.client.nickFormat === "nick" || this.login === "" ? this.formater.completeProcessing(this.nick) : \r
-      (this.client.nickFormat === "login" ? this.formater.completeProcessing(this.login) : \r
+   var identifiant =\r
+      this.client.nickFormat === "nick" || this.login === "" ? this.formater.completeProcessing(this.nick) :\r
+      (this.client.nickFormat === "login" ? this.formater.completeProcessing(this.login) :\r
       this.formater.completeProcessing(this.nick) + "<span class=\"login\">(" + this.formater.completeProcessing(this.login) +")</span>" );\r
 \r
    var XHTMLrepondA = "";\r
@@ -134,7 +134,7 @@ euphorik.Message.prototype.XHTML = function(messagePair, pre) {
    if (XHTMLrepondA) {\r
       XHTMLrepondA = "<span class=\"repondA\">" + XHTMLrepondA + "</span><span class=\"delimitationRepondA\"></span>";\r
    }\r
-   \r
+\r
    return "<div id=\"" + this.getId(pre) + "\" class=\"" + (messagePair ? "messagePair" : "messageImpair") + " message" +\r
          (this.appartientAuClient ? " proprietaire" : "")  +\r
          (this.clientARepondu ? " repondu" : "") +\r
@@ -145,7 +145,7 @@ euphorik.Message.prototype.XHTML = function(messagePair, pre) {
          "<span class=\"entete\">" +\r
             "<span class=\"dateComplete\">[<span class=\"date\">" + this.date + "</span>]</span>" +\r
             "<span class=\"nick\"><span class=\"id\" style=\"display: none\">" + this.auteurId + "</span><span class=\"ident\">" + identifiant + "</span></span>" +\r
-         "</span>" + \r
+         "</span>" +\r
          "<span class=\"delimitationEntete\"></span>" +\r
          XHTMLrepondA +\r
          "<span class=\"contenu\">" + this.formater.completeProcessing(this.contenu, this.nick) + "</span>" +\r
index 5ef2d88..64ebf40 100644 (file)
 // Regroupe la partie communication JSON client -> serveur de euphorik.\r
 // Voir : http://dev.euphorik.ch/wiki/euk/Protocole\r
 \r
-/**
-  * Les fonctions debutReq et finReq servent, par exemple, à afficher à l'utilisateur
+/**\r
+  * Les fonctions debutReq et finReq servent, par exemple, à afficher à l'utilisateur\r
   * qu'une communication est en cours.\r
-  * @param funError un fonction executée lors d'un réponse 'error' de la part du serveur, peut être redéfinit pour une requête.
-  * @param funDebutReq fonction appelée au début d'une requête (facultatif)
+  * @param funError un fonction executée lors d'un réponse 'error' de la part du serveur, peut être redéfinit pour une requête.\r
+  * @param funDebutReq fonction appelée au début d'une requête (facultatif)\r
   * @param funFinReq fonction appelée à la fin d'une requête (facultatif)\r
   */\r
 euphorik.Communication = function(funError, funDebutReq, funFinReq) {\r
-   this.funError = funError;
-   this.funDebutReq = funDebutReq;
+   this.funError = funError;\r
+   this.funDebutReq = funDebutReq;\r
    this.funFinReq = funFinReq;\r
-};
-
-/**
-  * Charge un fichier depuis une url et retourne son contenu.
-  */
-euphorik.Communication.prototype.load = function(url) {
-   if (this.funDebutReq) {
-      this.funDebutReq();
-   }
-   var contenu = "";
-   $.ajax({async: false, url: url, success : function(page) { contenu += page; }});
-   if (this.funFinReq) {
-      this.funFinReq();
-   }   
-   return contenu;
 };\r
-
-/**
-  * Effectue une requête JSON auprès du serveur.
-  * @param action une chaine spécifiant l'action, par exemple "put_message"
-  * @param json les données à envoyer associé à l'action, par exemple {"cookie" : "LKJDLAKSJBFLKASN", "nick" : "Paul", "content" : "Bonjour", "answer_to" : [] }
-  * @param funOk la fonction exécuté après réception des données du serveur
-  * @param funError la fonction exécuté si une erreur arrive (facultatif)
-  * @param asynchrone true pour une communication asychrone (facultatif, truepar défaut)
-  * @param paramsSupp un objet contenant des paramètres supplémentaire pour la fonction ajax de jQuery (facultatif)
+\r
+/**\r
+  * Charge un fichier depuis une url et retourne son contenu.\r
+  */\r
+euphorik.Communication.prototype.load = function(url) {\r
+   if (this.funDebutReq) {\r
+      this.funDebutReq();\r
+   }\r
+   var contenu = "";\r
+   $.ajax({async: false, url: url, success : function(page) { contenu += page; }});\r
+   if (this.funFinReq) {\r
+      this.funFinReq();\r
+   }\r
+   return contenu;\r
+};\r
+\r
+/**\r
+  * Effectue une requête JSON auprès du serveur.\r
+  * @param action une chaine spécifiant l'action, par exemple "put_message"\r
+  * @param json les données à envoyer associé à l'action, par exemple {"cookie" : "LKJDLAKSJBFLKASN", "nick" : "Paul", "content" : "Bonjour", "answer_to" : [] }\r
+  * @param funOk la fonction exécuté après réception des données du serveur\r
+  * @param funError la fonction exécuté si une erreur arrive (facultatif)\r
+  * @param asynchrone true pour une communication asychrone (facultatif, truepar défaut)\r
+  * @param paramsSupp un objet contenant des paramètres supplémentaire pour la fonction ajax de jQuery (facultatif)\r
   */\r
 euphorik.Communication.prototype.requete = function(action, json, funOk, funError, asynchrone, paramsSupp) {\r
    var thisCommunication = this;\r
@@ -65,12 +65,12 @@ euphorik.Communication.prototype.requete = function(action, json, funOk, funErro
    var mess = this.getBase(action);\r
    objectEach(json, function(name, val) {\r
       mess[name] = val;\r
-   });
-   
-   if (this.funDebutReq) {
-      this.funDebutReq();
+   });\r
+\r
+   if (this.funDebutReq) {\r
+      this.funDebutReq();\r
    }\r
-      \r
+\r
    paramsAjax = {\r
       async: asynchrone,\r
       type: "POST",\r
@@ -78,9 +78,9 @@ euphorik.Communication.prototype.requete = function(action, json, funOk, funErro
       dataType: "json",\r
       data: { action : JSON.stringify(mess) },\r
       success:\r
-         function(data) {            
-            if (thisCommunication.funFinReq) {
-               thisCommunication.funFinReq();
+         function(data) {\r
+            if (thisCommunication.funFinReq) {\r
+               thisCommunication.funFinReq();\r
             }\r
             if (data.reply === "error") {\r
                if (funError) {\r
@@ -91,131 +91,133 @@ euphorik.Communication.prototype.requete = function(action, json, funOk, funErro
             } else if (funOk) {\r
                funOk(data);\r
             }\r
-         },
-      error:
-         function(data) {
-            if (thisCommunication.funFinReq) {
-               thisCommunication.funFinReq();
-            }
+         },\r
+      error:\r
+         function(data) {\r
+            if (thisCommunication.funFinReq) {\r
+               thisCommunication.funFinReq();\r
+            }\r
          }\r
    };\r
-   \r
+\r
    if (paramsSupp) {\r
       objectEach(paramsSupp, function(name, val) {\r
          paramsAjax[name] = val;\r
       });\r
    }\r
-   \r
+\r
    jQuery.ajax(paramsAjax);\r
 };\r
-
-euphorik.Communication.prototype.createCometConnection = function(name) {
-   return new Comet(name, this.getBase);
-};
+\r
+euphorik.Communication.prototype.createCometConnection = function(name) {\r
+   return new Comet(name, this.getBase);\r
+};\r
 \r
 euphorik.Communication.prototype.getBase = function(action) {\r
    return {\r
       "header" : { "action" : action, "version" : euphorik.conf.versionProtocole }\r
    };\r
-};
-
-/**
-  * Permet de gérer les événements (push serveur).
-  * Principe de fonctionnement :
-  *  - La page courante créer un objet euphorik.Comet en indiquant le nom de la page et la version du protocole.
-  *  - La page courante attend un événement en appelant 'waitEvent' (non-bloquant) et en donnant deux fonctions :
-  *    - 'funSend' une fonction qui renvoie l'objet à envoyer avant l'attente, par exemple {"dernierMess" : 23}
-  *       ("header" et "page" sont automatiquement ajoutés à l'objet)
-  *    - 'funsReceive' un ensemble de fonctions à appeler en fonction du "reply" du serveur, par exemple {"set_nom" : function(data) { print("ok : " + data.nom); } }
-  *
-  * l'information envoyée est sous la forme :
-  *  {
-  *     "header" : {"action" : "wait_event", "version" : <v> },
-  *     "page" : <page>
-  *     [..]
-  *  }
-  * l'information reçue est sous la forme :
-  *  {
-  *     "reply" : <reply>
-  *     [..]
-  *  }
-  * <reply> et <page> sont de type chaine
-  *
-  * @page [string] la page courante pour laquelle on écoute des événements (un string)
-  * @util [int] la version
-  */
-Comet = function(page, getBase) {
-   this.page = page;
-   this.getBase = getBase;
-   
-   // l'objet JSONHttpRequest représentant la connexion d'attente
-   this.attenteCourante = undefined;
-   
-   // le multhreading du pauvre, merci javascript de m'offrire autant de primitives pour la gestion de la concurrence...
-   this.stop = false;
-};
-
-/**
-  * Arrête l'attente courante s'il y en a une.
-  */
-Comet.prototype.stopAttenteCourante = function() {
-   this.stop = true;
-         
-   if (this.attenteCourante) {
-      this.attenteCourante.abort();
-   }
-};
-
-/**
-  * Attend un événement lié à la page. Non-bloquant. 
-  * @funSend une fonction renvoyant les données json à envoyer
-  * @funsReceive est un objet comprenant les fonctions à appeler en fonction du "reply"
-  * les fonctions acceptent un paramètre correspondant au données reçues.
-  * exemple : {"new_message" : function(data){ ... }}
-  */
-Comet.prototype.waitEvent = function(funSend, funsReceive) {
-   this.stopAttenteCourante();   
-   this.stop = false;   
-   var thisComet = this;
-      
-   // on doit conserver l'ordre des valeurs de l'objet JSON (le serveur les veut dans l'ordre définit dans le protocole)
-   // TODO : ya pas mieux ?
-   var dataToSend = this.getBase("wait_event")
-   dataToSend["page"] = this.page;
-   
-   var poulpe = funSend();
-   objectEach(poulpe, function(k, v) {
-      dataToSend[k] = v;
-   });
-   
-   this.attenteCourante = jQuery.ajax({
-      type: "POST",
-      url: "request",
-      dataType: "json",
-      // TODO : doit disparaitre
-      timeout: 180000, // timeout de 3min. Gros HACK pas beau. FIXME problème décrit ici : http://groups.google.com/group/jquery-en/browse_thread/thread/8724e64af3333a76
-      data: { action : JSON.stringify(dataToSend) },
-      success:
-         function(data) {
-            funsReceive[data.reply](data);
-         
-            // rappel de la fonction dans 100 ms
-            setTimeout(function(){ thisComet.waitEvent2(funSend, funsReceive); }, 100);
-         },
-      error:
-         function(XMLHttpRequest, textStatus, errorThrown) {
-            ;; console.log("Connexion perdue dans Comet.prototype.waitEvent() : \n" + textStatus);
-            setTimeout(function(){ thisComet.waitEvent2(funSend, funsReceive); }, 1000);
-         }
-   });
-};
-
-/**
-  * Si un stopAttenteCourante survient un peu n'importe quand il faut imédiatement arreter de boucler.
-  */
-Comet.prototype.waitEvent2 = function(funSend, funsReceive) {
-   if (this.stop) {
-      return;
-   }
-   this.waitEvent(funSend, funsReceive);
+};\r
+\r
+/**\r
+  * Permet de gérer les événements (push serveur).\r
+  * Principe de fonctionnement :\r
+  *  - La page courante créer un objet euphorik.Comet en indiquant le nom de la page et la version du protocole.\r
+  *  - La page courante attend un événement en appelant 'waitEvent' (non-bloquant) et en donnant deux fonctions :\r
+  *    - 'funsReceive' un ensemble de fonctions à appeler en fonction du "reply" du serveur, par exemple {"set_nom" : function(data) { print("ok : " + data.nom); } }\r
+  *    - 'funSend' une fonction qui renvoie l'objet à envoyer avant l'attente, par exemple {"dernierMess" : 23}\r
+  *       ("header" et "page" sont automatiquement ajoutés à l'objet)\r
+  *\r
+  * l'information envoyée est sous la forme :\r
+  *  {\r
+  *     "header" : {"action" : "wait_event", "version" : <v> },\r
+  *     "page" : <page>\r
+  *     [..]\r
+  *  }\r
+  * l'information reçue est sous la forme :\r
+  *  {\r
+  *     "reply" : <reply>\r
+  *     [..]\r
+  *  }\r
+  * <reply> et <page> sont de type chaine\r
+  *\r
+  * @page [string] la page courante pour laquelle on écoute des événements (un string)\r
+  * @util [int] la version\r
+  */\r
+Comet = function(page, getBase) {\r
+   this.page = page;\r
+   this.getBase = getBase;\r
+\r
+   // l'objet JSONHttpRequest représentant la connexion d'attente\r
+   this.attenteCourante = undefined;\r
+\r
+   // le multhreading du pauvre, merci javascript de m'offrire autant de primitives pour la gestion de la concurrence...\r
+   this.stop = false;\r
+};\r
+\r
+/**\r
+  * Arrête l'attente courante s'il y en a une.\r
+  */\r
+Comet.prototype.stopAttenteCourante = function() {\r
+   this.stop = true;\r
+\r
+   if (this.attenteCourante) {\r
+      this.attenteCourante.abort();\r
+   }\r
+};\r
+\r
+/**\r
+  * Attend un événement lié à la page. Non-bloquant.\r
+  * @funsReceive est un objet comprenant les fonctions à appeler en fonction du "reply"\r
+  * les fonctions acceptent un paramètre correspondant au données reçues.\r
+  * exemple : {"new_message" : function(data){ ... }}\r
+  * @funSend une fonction renvoyant les données json à envoyer (optional)\r
+  */\r
+Comet.prototype.waitEvent = function(funsReceive, funSend) {\r
+   this.stopAttenteCourante();\r
+   this.stop = false;\r
+   var thisComet = this;\r
+\r
+   // on doit conserver l'ordre des valeurs de l'objet JSON (le serveur les veut dans l'ordre définit dans le protocole)\r
+   // TODO : ya pas mieux ?\r
+   var dataToSend = this.getBase("wait_event")\r
+   dataToSend["page"] = this.page;\r
+\r
+   if (funSend !== undefined) {\r
+      var tmp = funSend();\r
+      objectEach(tmp, function(k, v) {\r
+         dataToSend[k] = v;\r
+      });\r
+   }\r
+\r
+   this.attenteCourante = jQuery.ajax({\r
+      type: "POST",\r
+      url: "request",\r
+      dataType: "json",\r
+      // TODO : doit disparaitre\r
+      timeout: 180000, // timeout de 3min. Gros HACK pas beau. FIXME problème décrit ici : http://groups.google.com/group/jquery-en/browse_thread/thread/8724e64af3333a76\r
+      data: { action : JSON.stringify(dataToSend) },\r
+      success:\r
+         function(data) {\r
+            funsReceive[data.reply](data);\r
+\r
+            // rappel de la fonction dans 100 ms\r
+            setTimeout(function(){ thisComet.waitEvent2(funsReceive, funSend); }, 100);\r
+         },\r
+      error:\r
+         function(XMLHttpRequest, textStatus, errorThrown) {\r
+            // console.log("Connexion perdue dans Comet.prototype.waitEvent() : \n" + textStatus);\r
+            setTimeout(function(){ thisComet.waitEvent2(funsReceive, funSend); }, 1000);\r
+         }\r
+   });\r
+};\r
+\r
+/**\r
+  * Si un stopAttenteCourante survient un peu n'importe quand il faut imédiatement arreter de boucler.\r
+  */\r
+Comet.prototype.waitEvent2 = function(funsReceive, funSend) {\r
+   if (this.stop) {\r
+      return;\r
+   }\r
+   this.waitEvent(funsReceive, funSend);\r
 };
\ No newline at end of file
index 608a7ec..fe464b8 100644 (file)
@@ -15,7 +15,7 @@
 //
 // You should have received a copy of the GNU General Public License
 // along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
-// 
+//
 // La page d'administation, ne peut être accédée que par les ekMaster (admins)
 
 /*jslint laxbreak:true */
 
 euphorik.PageAdmin = function(client, formater, util, communication) {
    this.name = "admin";
-   
+
    this.client = client;
    this.formater = formater;
    this.util = util;
    this.communication = communication;
-   
+
    this.comet = this.communication.createCometConnection("admin");
-   
+
    // a timer which will periodically refresh the banned IP list
    this.timeoutIDmajIPs = null;
 };
@@ -39,42 +39,18 @@ euphorik.PageAdmin = function(client, formater, util, communication) {
   * Interface des pages.
   */
 euphorik.PageAdmin.prototype.contenu = function() {
-   return '<h1>Trolls</h1>' +
-   '<p>Un troll est un sujet à débat, en général une question, affiché sur la page principale.</p>' +
-   '<p>Chaque semaine un troll est choisi au hasard parmis les trolls proposés et devient le troll de la semaine.</p>' +
-   '<form action="" id="nouveauTroll">' +
-   '   <p>' +
-   '      <input class="troll" name="troll" type="text" maxlength="500" value=""></input>' +
-   '      <button class="return" value="return">poster</button>' +
-   '   </p>' +
-   '</form>' +
-   '<div id="trolls"></div>' +
-   '<h1>IPs bannies</h1>' +
-   '<div id="ips"></div>';
+   return '<h1>IPs bannies</h1><div id="ips"></div>';
 };
 
 /**
   * Interface des pages.
   */
-euphorik.PageAdmin.prototype.charger = function() {      
-   $("#page form#nouveauTroll").submit(function(){ return false; });
-      
+euphorik.PageAdmin.prototype.charger = function() {
    var thisPage = this;
-   
-   // la liste des trolls proposés par les ekMasters
-   this.trolls = new euphorik.Trolls(this.client, this.util, this.formater, this.communication);
-   
+
    this.waitEvent();
-   
+
    this.majIPs();
-   
-   $("#page form#nouveauTroll  input.troll").focus();
-   
-   $("#page form#nouveauTroll button.return").click(
-      function() {
-         thisPage.posterTroll();
-      }
-   );
 };
 
 /**
@@ -82,36 +58,13 @@ euphorik.PageAdmin.prototype.charger = function() {
   */
 euphorik.PageAdmin.prototype.decharger = function() {
    this.comet.stopAttenteCourante();
-   
+
    // supprime le rafraichissement période des ips
    if (this.timeoutIDmajIPs) {
       clearTimeout(this.timeoutIDmajIPs);
    }
 };
 
-/**
-  * Post un troll, le contenu est lu à partir de "input.troll".
-  */
-euphorik.PageAdmin.prototype.posterTroll = function() {
-   var thisPageAdmin = this;
-   
-   var content = $("#page form#nouveauTroll input.troll").val();
-   
-   content = content.trim();
-   if (content === "") {
-      this.util.messageDialog("Le troll est vide");
-      return;
-   }
-
-   this.communication.requete(
-      "put_troll",
-      {"cookie" : this.client.cookie, "content" : content},
-      function(data) {
-         $("#page form#nouveauTroll input.troll").val("");
-      }
-   );
-};
-
 /**
   * Met à jour la liste des IP bannies.
   */
@@ -121,11 +74,11 @@ euphorik.PageAdmin.prototype.majIPs = function() {
    }
 
    var thisPageAdmin = this;
-   
+
    this.communication.requete(
       "list_banned_ips",
       {"cookie" : this.client.cookie},
-      function(data) {   
+      function(data) {
          var XHTML = "";
          data.list.each(function(i, ip) {
             XHTML += '<div class="ban"><span class="ip">' + ip.ip + '</span>|' +
@@ -139,13 +92,13 @@ euphorik.PageAdmin.prototype.majIPs = function() {
             });
             XHTML += '<span class="deban">débannir</span></div>';
          });
-         
+
          if (data.list.length === 0) {
             XHTML += '<p>Aucune IP bannie</p>';
          }
-            
+
          $("#ips").html(XHTML);
-         
+
          $(".ban").each(function() {
             var ip = $(".ip", this).html();
             $(".deban", this).click(
@@ -160,7 +113,7 @@ euphorik.PageAdmin.prototype.majIPs = function() {
                }
             );
          });
-            
+
          // rafraichissement toutes les minutes (je sais c'est mal)
          // le problème est le rafraichissement des temps restant de bannissement qui doit être fait du coté client
          thisPageAdmin.timeoutIDmajIPs = setTimeout(function(){ thisPageAdmin.majIPs(); }, 60 * 1000);
@@ -173,9 +126,9 @@ euphorik.PageAdmin.prototype.majIPs = function() {
   */
 euphorik.PageAdmin.prototype.deban = function(ip) {
    var thisPageAdmin = this;
-   
+
    this.communication.requete(
-      "unban", 
+      "unban",
       {"cookie" : this.client.cookie, "ip" : ip}
    );
 };
@@ -185,148 +138,14 @@ euphorik.PageAdmin.prototype.deban = function(ip) {
   */
 euphorik.PageAdmin.prototype.waitEvent = function() {
    var thisPageAdmin = this;
-         
+
    this.comet.waitEvent(
-      function() { return { "last_troll" : thisPageAdmin.trolls.dernierTroll }; },
       {
-         "troll_added" : function(data){ thisPageAdmin.trolls.ajouterTrollEvent(data); },
-         "troll_modified" : function(data){ thisPageAdmin.trolls.modifierTrollEvent(data); },
-         "troll_deleted" : function(data){ thisPageAdmin.trolls.supprimerTrollEvent(data); },
          "banned_ips_refresh" : function(data){ thisPageAdmin.majIPs(); },
          "error" :
             function(data) {
-               thisTrolls.util.messageDialog(data.error_message);
-            }
-      }
-   );
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
-  * Représente un troll, pas grand chose finalement.
-  */
-euphorik.Troll = function(content, author) {
-   this.content = content;
-   this.author = author;
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-euphorik.Trolls = function(client, util, formater, communication) {
-   this.client = client;
-   this.util = util;
-   this.formater = formater;
-   this.communication = communication;
-   this.dernierTroll = 0;
-   
-   this.trolls = {};
-};
-
-euphorik.Trolls.prototype.ajouterTrollEvent = function(data) {
-   var thisTrolls = this;
-
-   var XHTML = "";
-   data.trolls.each(function(i, trollData) {
-      var troll = new euphorik.Troll(trollData.content, trollData.author);
-      var trollId = trollData.troll_id;
-      thisTrolls.trolls[trollId] = troll;
-      
-      XHTML +=
-         '<div id="troll' + trollId + '" class="troll">' +
-         '<span class="content">' + thisTrolls.formater.completeProcessing(troll.content, troll.author) + '</span>' +
-         '<span class="author"> - ' + thisTrolls.formater.completeProcessing(troll.author) + '</span>' +
-         (trollData.author_id === thisTrolls.client.id ? '<span class="editTroll">éditer</span><span class="delTroll">Supprimer</span>' : '') +
-         '</div>';
-   });
-   $("#trolls").append(XHTML);
-   $("#trolls .troll").filter(function() { return parseInt($(this).attr("id").substr(5), 10) > thisTrolls.dernierTroll; }).each(
-      function() {
-         var troll = this;
-         var id = parseInt($(this).attr("id").substr(5), 10);
-         
-         $("a[@rel*=lightbox]", this).lightBox();
-         
-         $(this).keypress(
-            function(e) {
-               if (e.which === 13) { // return
-                  $(".modifier", this).click();
-               }
-            }
-         );
-         
-         $(".delTroll", this).click(
-            function() {
-               thisTrolls.util.messageDialog(
-                  "Êtes-vous sur de vouloir supprimer le troll \"" + thisTrolls.trolls[id].content + "\" ?",
-                  euphorik.Util.messageType.question,
-                  {
-                     "oui" : function() {
-                           thisTrolls.supprimer(id);
-                        },
-                     "non" : function(){}
-                  }
-               );
-            }
-         );
-         
-         $(".editTroll", this).click(
-            function() {
-               $("span", troll).css("display", "none");
-               $(troll).append(
-                  '<form><p><input class="content" type="text" size="50" maxlength="500" value="' +
-                  thisTrolls.trolls[id].content +
-                  '"></input><span class="modifier">modifier</span><span class="annuler">annuler</span></p></form>'
-               );
-               $("form input.content").focus();
-               
-               var virerLeFormulaire = function() {
-                  $('form', troll).remove();
-                  $('span', troll).css("display", "inline");
-               };
-               $("span.modifier", troll).click(
-                  function() {
-                     var content = $("form input.content", troll).val();
-                     virerLeFormulaire();
-                     thisTrolls.modifier(id, content);
-                  }
-               );
-               $("span.annuler", troll).click( virerLeFormulaire );
-               $("form", troll).submit(function(){ return false; });
+               thisPage.util.messageDialog(data.error_message);
             }
-         );
       }
    );
-   
-   if (data.trolls.length > 0) {
-      thisTrolls.dernierTroll = data.trolls[data.trolls.length - 1].troll_id;
-   }
-};
-
-euphorik.Trolls.prototype.modifierTrollEvent = function(data) {
-   var thisTrolls = this;
-   $("#trolls #troll" + data.troll_id + " .content").html(thisTrolls.formater.completeProcessing(data.content, thisTrolls.trolls[data.troll_id].author));
-   $("#trolls #troll" + data.troll_id + " a[@rel*=lightbox]").lightBox();
-   thisTrolls.trolls[data.troll_id].content = data.content;
-};
-
-euphorik.Trolls.prototype.supprimerTrollEvent = function(data) {
-   $("#trolls #troll" + data.troll_id).remove();
-};
-
-euphorik.Trolls.prototype.modifier = function(id, content) {
-   this.communication.requete(
-      "mod_troll",
-      {"cookie" : this.client.cookie, "troll_id" : id, "content" : content}
-   );
-};
-
-/**
-  * Supprime un troll en fonction de son id.
-  */
-euphorik.Trolls.prototype.supprimer = function(id) {
-   this.communication.requete(
-      "del_troll",
-      {"cookie" : this.client.cookie, "troll_id" : id}
-   );
-};
+};
\ No newline at end of file
index 86c059e..13f3375 100755 (executable)
 //
 // You should have received a copy of the GNU General Public License
 // along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
+
 /*jslint laxbreak:true */
 
 euphorik.PageMinichat = function(client, formater, util, communication) {
    this.name = "minichat";
-   
+
    this.client = client;
    this.formater = formater;
    this.util = util;
    this.communication = communication;
    this.commandes = new euphorik.Commandes(this.client, this, this.util, this.formater);
-   
+
    // permet d'éviter d'envoyer plusieurs messages simultanément en pressant
    // rapidement sur "enter" par exemple
    this.envoieMessageEnCours = false;
@@ -45,14 +45,13 @@ euphorik.PageMinichat.prototype.contenu = function() {
       '  <button class="return"></button>' +
       ' </p>' +
       '</form>';
-      
-   var trollXHTML = '<div id="trollCourant">Troll de la semaine : <span class="troll"></span></div>';
+
    var conversationXHTML = '<table id="conversations"><tr></tr></table>';
-    
+
    if (this.client.chatOrder === "reverse") {
-      return trollXHTML + formulaireXHTML + conversationXHTML;
+      return formulaireXHTML + conversationXHTML;
    } else {
-      return trollXHTML + conversationXHTML + formulaireXHTML;
+      return conversationXHTML + formulaireXHTML;
    }
 };
 
@@ -62,20 +61,20 @@ euphorik.PageMinichat.prototype.classes = function() {
 
 euphorik.PageMinichat.prototype.charger = function() {
    thisPage = this;
-   
+
    $("#posterMessage input.nick").val(this.client.nick);
-   
+
    // cet appel ne doit pas être fait avant l'appel à 'charger'
-   this.conversations = new euphorik.Conversations(this.client, this.formater, this.util, this.communication, this.fragment);   
-   
+   this.conversations = new euphorik.Conversations(this.client, this.formater, this.util, this.communication, this.fragment);
+
    this.chargerConversationsFragment();
-   
-   this.conversations.rafraichirMessages(true);   
+
+   this.conversations.rafraichirMessages(true);
 
    this.util.setCaretToEnd($("form#posterMessage input.message")[0]);
 
    // les outils de bannissement (uniquement pour les ekMaster)
-   if (this.client.ekMaster) {    
+   if (this.client.ekMaster) {
       // TODO : augmentation un peu space, à revoir
       this.util.outilsBan = $(
          '<span id="outilsBan">' +
@@ -86,16 +85,15 @@ euphorik.PageMinichat.prototype.charger = function() {
          ' <img id="slap" src="img/slap.gif" alt="Avertissement" />' +
          '</span>'
       );
-      
+
       this.util.infoBulle("Slap", $("#slap", this.util.outilsBan));
       this.util.infoBulle("Kick (" + euphorik.conf.tempsKick + "min)", $("#kick", this.util.outilsBan));
       this.util.infoBulle("Ban (" + euphorik.conf.tempsBan / 24 / 60 + " jours)", $("#ban", this.util.outilsBan));
       this.util.infoBulle("La raison", $("input", this.util.outilsBan));
    }
-   
+
    // la barre d'outils liée à chaque message
-   this.util.outilsMessage = $('<div id="outilsMess"><div class="extraire"></div><div class="extraireCompletement"></div></div>').prependTo("#page.minichat");   
-   this.util.infoBulle("Ouvrir la conversation liée au troll de la semaine", $("#trollCourant .troll"));   
+   this.util.outilsMessage = $('<div id="outilsMess"><div class="extraire"></div><div class="extraireCompletement"></div></div>').prependTo("#page.minichat");
    this.util.infoBulle("Cliquer sur les messages pour les enlevers de la liste",
       $("form#posterMessage #repondA").hover(
          function() {
@@ -112,7 +110,7 @@ euphorik.PageMinichat.prototype.charger = function() {
             if ($(e.target).is(".nb")) {
                thisPage.conversations.enleverMessagesRepond();
             }
-         }     
+         }
       ),
       euphorik.Util.positionBulleType.droite
    );
@@ -145,19 +143,19 @@ euphorik.PageMinichat.prototype.charger = function() {
       }
    );
    // </smiles>
-      
+
    // événements
-   var nouveauMessage = 
-      function() {  
+   var nouveauMessage =
+      function() {
          // captcha anti bot
          if ($("form#posterMessage input.captcha").val() !== "") {
             return;
          }
-         
+
          var message = $("form#posterMessage input.message").val();
-         
+
          // traitement des commandes..
-         var retCommandes = thisPage.commandes.exec(message);         
+         var retCommandes = thisPage.commandes.exec(message);
          switch (retCommandes[0]) {
             case euphorik.Commandes.statut.pas_une_commande :
                thisPage.envoyerMessage(message);
@@ -168,11 +166,11 @@ euphorik.PageMinichat.prototype.charger = function() {
             case euphorik.Commandes.statut.ok :
                $("form#posterMessage input.message").val("");
                break;
-         }         
-            
+         }
+
          $("form#posterMessage input.message").focus();
       };
-      
+
    $("form#posterMessage").keypress(
       function(e) {
          if (e.which === 13) { // return
@@ -180,12 +178,12 @@ euphorik.PageMinichat.prototype.charger = function() {
          }
       }
    );
-   
+
    $("form#posterMessage button.return").click(nouveauMessage);
-   
+
    // interdiction de submiter le formulaire
    $("form#posterMessage").submit(function(){ return false; });
-   
+
    $("input.nick").click(
       function() {
          var input = $("input.nick")[0];
@@ -197,8 +195,8 @@ euphorik.PageMinichat.prototype.charger = function() {
 };
 
 euphorik.PageMinichat.prototype.chargerConversationsFragment = function() {
-   var thisPageMinichat = this; 
-   
+   var thisPageMinichat = this;
+
    // attention : "conv" doit être un tableau d'entier
    try {
       var conv = this.fragment.getVal("conv");
@@ -211,12 +209,12 @@ euphorik.PageMinichat.prototype.chargerConversationsFragment = function() {
       ;; console.log(e)
    }
 };
-  
+
 euphorik.PageMinichat.prototype.decharger = function() {
    this.conversations.comet.stopAttenteCourante();
-   
+
    $("body #smiles").remove();
-   
+
     this.fragment.delVal("conv");
 };
 
@@ -224,46 +222,46 @@ euphorik.PageMinichat.prototype.decharger = function() {
   * Envoie un nouve message donné, le nick utilisé est celui se trouvant
   * dans la zone de saisie (form#posterMessage input.nick).
   */
-euphorik.PageMinichat.prototype.envoyerMessage = function(message) {   
-   var thisPageMinichat = this;   
+euphorik.PageMinichat.prototype.envoyerMessage = function(message) {
+   var thisPageMinichat = this;
    var nick = $("form#posterMessage input.nick").val();
 
    // (un nick vide est autorisé)
    nick = this.formater.formatNick(nick);
-   
+
    if (nick === euphorik.conf.defaultNick) {
-      this.util.messageDialog("Le nick ne peut pas être " + euphorik.conf.defaultNick);
+      this.util.messageDialog("Choose a nickname");
       return;
    }
-   
+
    message = message.trim();
    if (!message) {
-      this.util.messageDialog("Le message est vide");
+      this.util.messageDialog("The message is empty");
       return;
    }
-   
+
    if (!this.client.authentifie()) {
       if (!this.client.enregistrement()) {
-         this.util.messageDialog("login impossible");
+         this.util.messageDialog("unable to login");
          return;
       }
    }
-      
+
    // évite le double post
    if (this.envoieMessageEnCours) {
       this.util.messageDialog("Message en cours d'envoie...");
       return;
    }
    this.envoieMessageEnCours = true;
-   
+
    this.client.nick = nick;
-   
+
    this.communication.requete(
       "put_message",
       this.getJSONMessage(this.client.nick, message),
       function() {
          $("form#posterMessage input.message").val("");
-         thisPageMinichat.conversations.enleverMessagesRepond(); 
+         thisPageMinichat.conversations.enleverMessagesRepond();
          thisPageMinichat.envoieMessageEnCours = false;
       },
       function(data) {
@@ -284,7 +282,7 @@ euphorik.PageMinichat.prototype.getJSONMessage = function(nick, message) {
    objectEach(this.conversations.messagesRepond, function(id) {
       repondA.push(parseInt(id, 10));
    });
-      
+
    return {
       "cookie" : this.client.cookie,
       "nick" : nick,
index 7ca5760..5feacb5 100644 (file)
@@ -29,9 +29,9 @@ euphorik.Util = function (formater) {
    $("#info .close").click(function() {\r
       $("#info").slideUp(50);\r
    });\r
-   \r
+\r
    $("body").append('<div id="tooltipArrow"></div>').append('<div id="tooltipMessage"><p></p></div>');\r
-   \r
+\r
    this.formater = formater;\r
    this.bulleActive = true;\r
 };\r
@@ -45,7 +45,7 @@ euphorik.Util.messageType = {informatif: 0, question: 1, erreur: 2};
   * @buttons An object where the properties are the labels and the values are functions which will be executed when a button is clicked.\r
   * @format [bool] The message should be formated. (see 'formater.js')\r
   * @time The time while the message is displayed. -1 for infinity.\r
-  */  \r
+  */\r
 euphorik.Util.prototype.messageDialog = function(message, type, buttons, format, time) {\r
    var thisUtil = this;\r
 \r
@@ -55,26 +55,26 @@ euphorik.Util.prototype.messageDialog = function(message, type, buttons, format,
    if (this.timeoutMessageDialog) {\r
       clearTimeout(this.timeoutMessageDialog);\r
    }\r
-      \r
+\r
    var close = function() { $("#info").slideUp(100); };\r
    close();\r
 \r
    $("#info .message").html(!thisUtil.formater || !format ? message : thisUtil.formater.completeProcessing(message));\r
-   \r
+\r
    switch(type) {\r
       case euphorik.Util.messageType.informatif : $("#info #icone").attr("class", "information"); break;\r
       case euphorik.Util.messageType.question : $("#info #icone").attr("class", "interrogation"); break;\r
       case euphorik.Util.messageType.erreur : $("#info #icone").attr("class", "exclamation"); break;\r
    }\r
-   \r
+\r
    $("#info .buttons").html("");\r
    objectEach(buttons, function(name, bouton) {\r
       $("#info .buttons").append("<div>" + name + "</div>").find("div:last").click(bouton).click(close);\r
    });\r
-   \r
-   $("#info").slideDown(200);
+\r
+   $("#info").slideDown(200);\r
    if (time !== -1) {\r
-      this.timeoutMessageDialog = setTimeout(close, time || euphorik.conf.tooltipDisplayDefaultTime);
+      this.timeoutMessageDialog = setTimeout(close, time || euphorik.conf.tooltipDisplayDefaultTime);\r
    }\r
 };\r
 \r
@@ -93,38 +93,38 @@ euphorik.Util.prototype.afficherBoite = function(boite, cible, positionX, positi
     var positionCible = cible.offset();\r
     var positionBoite = {\r
          left : positionX === euphorik.Util.positionTypeX.gauche ? positionCible.left - boite.width() :\r
-            (positionX === euphorik.Util.positionTypeX.gaucheRecouvrement ? positionCible.left - boite.width() + cible.width() : \r
+            (positionX === euphorik.Util.positionTypeX.gaucheRecouvrement ? positionCible.left - boite.width() + cible.width() :\r
             (positionX === euphorik.Util.positionTypeX.droitelsRecouvrement ? positionCible.left :\r
             (positionX === euphorik.Util.positionTypeX.droite ? positionCible.left + cible.width() :\r
             positionCible.left + cible.width() / 2 - boite.width() / 2 ))), // centre\r
          top : positionY === euphorik.Util.positionTypeY.haut ? positionCible.top - boite.height() :\r
-            (positionY === euphorik.Util.positionTypeY.hautRecouvrement ? positionCible.top - boite.height() + cible.height() : \r
+            (positionY === euphorik.Util.positionTypeY.hautRecouvrement ? positionCible.top - boite.height() + cible.height() :\r
             (positionY === euphorik.Util.positionTypeY.basRecouvrement ? positionCible.top :\r
             (positionY === euphorik.Util.positionTypeY.bas ? positionCible.top + cible.height() :\r
             positionCible.top + cible.height() / 2 - boite.height() / 2 ))) // centre\r
       };\r
-      \r
+\r
     // calcul les décalages en x et en y pour éviter que la boite ne sorte de la fenêtre, tient compte de la position des barres de défilement\r
-    var marge = 10; \r
+    var marge = 10;\r
     positionBoite.left = positionBoite.left < marge + window.pageXOffset ? marge + window.pageXOffset :\r
       (boite.width() - $(window).width() + (positionBoite.left - window.pageXOffset) + marge > 0 ? $(window).width() - boite.width() - marge + window.pageXOffset : positionBoite.left);\r
     positionBoite.top = positionBoite.top < marge + window.pageYOffset ? marge + window.pageYOffset :\r
       (boite.height() - $(window).height() + (positionBoite.top - window.pageYOffset) + marge > 0 ? $(window).height() - boite.height() - marge + window.pageYOffset : positionBoite.top);\r
-    \r
+\r
     boite.css("top", positionBoite.top).css("left", positionBoite.left).show();\r
 };\r
 \r
 euphorik.Util.positionBulleType = {haut : 0, droite : 1, bas : 2, gauche : 3};\r
-
-/**
-  * Affiche ou cache la barre d'attente.
-  */
-euphorik.Util.prototype.showWaitBar = function() {
-   $("#waitbar").show();
-};
-euphorik.Util.prototype.hideWaitBar = function() {
-   $("#waitbar").hide();
-};
+\r
+/**\r
+  * Affiche ou cache la barre d'attente.\r
+  */\r
+euphorik.Util.prototype.showWaitBar = function() {\r
+   $("#waitbar").show();\r
+};\r
+euphorik.Util.prototype.hideWaitBar = function() {\r
+   $("#waitbar").hide();\r
+};\r
 \r
 /**\r
   * Affiche un info bulle lorsque le curseur survole l'élément donné.\r
@@ -134,11 +134,11 @@ euphorik.Util.prototype.hideWaitBar = function() {
   */\r
 euphorik.Util.prototype.infoBulle = function(message, element, position) {\r
    var thisUtil = this;\r
-   var cacherBulle = function() {   \r
+   var cacherBulle = function() {\r
       $("#tooltipArrow").hide();\r
       $("#tooltipMessage").hide();\r
    };\r
-   \r
+\r
    position = position || euphorik.Util.positionBulleType.haut;\r
 \r
    element.hover(\r
@@ -150,16 +150,16 @@ euphorik.Util.prototype.infoBulle = function(message, element, position) {
          var m = $("#tooltipMessage");\r
          var f = $("#tooltipArrow");\r
          f.removeClass().addClass(position === euphorik.Util.positionBulleType.haut ? "tooltipArrowTop" :\r
-            (position === euphorik.Util.positionBulleType.droite ? "tooltipArrowRight" : \r
+            (position === euphorik.Util.positionBulleType.droite ? "tooltipArrowRight" :\r
             (position === euphorik.Util.positionBulleType.bas ? "tooltipArrowBottom" : "tooltipArrowLeft" )));\r
-         \r
+\r
          // remplie le paragraphe de la bulle avec le message\r
          $("p", m).html(message);\r
-         \r
+\r
          // réinitialise la position, évite le cas ou la boite est collé à droite et remplie avec un texte la faisant dépassé\r
          // dans ce cas la hauteur n'est pas calculé correctement\r
          m.css("top", 0).css("left", 0);\r
-         \r
+\r
          var positionFleche = {\r
             left : position === euphorik.Util.positionBulleType.haut || position === euphorik.Util.positionBulleType.bas ?\r
                 element.offset().left + element.outerWidth() / 2 - f.width() / 2 :\r
@@ -182,7 +182,7 @@ euphorik.Util.prototype.infoBulle = function(message, element, position) {
          } else if (positionMessage.left < 0) {\r
             positionMessage.left = 0;\r
          }\r
-         \r
+\r
          m.css("top", positionMessage.top).css("left", positionMessage.left).show();\r
          f.css("top", positionFleche.top).css("left", positionFleche.left).show();\r
       },\r
@@ -233,7 +233,7 @@ euphorik.Util.prototype.replaceSelection = function(input, replaceString) {
       var selectionStart = input.selectionStart;\r
       var selectionEnd = input.selectionEnd;\r
       input.value = input.value.substring(0, selectionStart) + replaceString + input.value.substring(selectionEnd);\r
-      \r
+\r
       if (selectionStart != selectionEnd) { // has there been a selection\r
          this.setSelectionRange(input, selectionStart, selectionStart + replaceString.length);\r
       } else { // set caret\r
@@ -253,7 +253,7 @@ euphorik.Util.prototype.replaceSelection = function(input, replaceString) {
 };\r
 \r
 /**\r
-  * Applies rot13 to a given string. See : http://en.wikipedia.org/wiki/ROT13.
+  * Applies rot13 to a given string. See : http://en.wikipedia.org/wiki/ROT13.\r
   * @param str the string.\r
   */\r
 euphorik.Util.prototype.rot13 = function(str) {\r
@@ -268,7 +268,7 @@ euphorik.Util.prototype.rot13 = function(str) {
       if (pos === ch.length) {\r
          return "";\r
       }\r
-      \r
+\r
       var c = ch.charCodeAt(pos);\r
       return String.fromCharCode(\r
          c +\r
index 1e68f2b..f3dc5aa 100755 (executable)
@@ -1,61 +1,62 @@
 # coding: utf-8\r
 # For more informations about the modules listed here see : http://dev.euphorik.ch/wiki/euk/Home\r
 \r
-# Directory where the compiled modules will be put
-rep_ebin = ebin
+# Directory where the compiled modules will be put\r
+rep_ebin = ebin\r
 \r
-# Directory where the sources are
-rep_erl = erl
+# Directory where the sources are\r
+rep_erl = erl\r
 \r
-# Directory which contains the hrl files (records definition)
-rep_include = include
+# Directory which contains the hrl files (records definition)\r
+rep_include = include\r
+rep_include_yaws = /usr/lib/yaws/include\r
 \r
 # Arguments for the compilator\r
-# It's possible to compile in native mode with :
-#  $ make NATIVE=true
-ifdef NATIVE
-   erlc_params = +native -I $(rep_include) -o $(rep_ebin) $<
-else
-   erlc_params = -I $(rep_include) -o $(rep_ebin) $<
-endif
-
+# It's possible to compile in native mode with :\r
+#  $ make NATIVE=true\r
+ifdef NATIVE\r
+   erlc_params = +native -I $(rep_include) -I $(rep_include_yaws) -o $(rep_ebin) $<\r
+else\r
+   erlc_params = -I $(rep_include) -I $(rep_include_yaws) -o $(rep_ebin) $<\r
+endif\r
+\r
 all: $(rep_ebin)/smtp.beam \\r
-$(rep_ebin)/euphorik_bd.beam \
-$(rep_ebin)/euphorik_minichat_conversation.beam \
-$(rep_ebin)/euphorik_requests.beam \
-$(rep_ebin)/euphorik_protocole.beam \
-$(rep_ebin)/euphorik_daemon.beam \
-$(rep_ebin)/euphorik_bd.beam \
-$(rep_ebin)/euphorik_bd_admin.beam \
-$(rep_ebin)/euphorik_common.beam \
-$(rep_ebin)/euphorik_test.beam
+$(rep_ebin)/euphorik_bd.beam \\r
+$(rep_ebin)/euphorik_minichat_conversation.beam \\r
+$(rep_ebin)/euphorik_requests.beam \\r
+$(rep_ebin)/euphorik_protocole.beam \\r
+$(rep_ebin)/euphorik_daemon.beam \\r
+$(rep_ebin)/euphorik_bd.beam \\r
+$(rep_ebin)/euphorik_bd_admin.beam \\r
+$(rep_ebin)/euphorik_common.beam \\r
+$(rep_ebin)/euphorik_test.beam\r
 \r
 $(rep_ebin)/smtp.beam: $(rep_erl)/smtp.erl\r
        erlc $(erlc_params)\r
-
-$(rep_ebin)/euphorik_bd.beam: $(rep_erl)/euphorik_bd.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl
-       erlc $(erlc_params)
-   
-$(rep_ebin)/euphorik_bd_admin.beam: $(rep_erl)/euphorik_bd_admin.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl
-       erlc $(erlc_params)
-
-$(rep_ebin)/euphorik_minichat_conversation.beam: $(rep_erl)/euphorik_minichat_conversation.erl $(rep_include)/euphorik_bd.hrl
-       erlc $(erlc_params)
-       
-$(rep_ebin)/euphorik_requests.beam: $(rep_erl)/euphorik_requests.erl $(rep_include)/euphorik_defines.hrl
-       erlc $(erlc_params)
-       
-$(rep_ebin)/euphorik_protocole.beam: $(rep_erl)/euphorik_protocole.erl $(rep_include)/euphorik_defines.hrl
-       erlc $(erlc_params)
-         
-$(rep_ebin)/euphorik_daemon.beam: $(rep_erl)/euphorik_daemon.erl $(rep_include)/euphorik_defines.hrl
-       erlc $(erlc_params)
-   
-$(rep_ebin)/euphorik_common.beam: $(rep_erl)/euphorik_common.erl
-       erlc $(erlc_params)
-   
-$(rep_ebin)/euphorik_test.beam: $(rep_erl)/euphorik_test.erl $(rep_include)/euphorik_bd.hrl
-       erlc $(erlc_params)
-
-clean:
-       rm ebin/*.beam
+\r
+$(rep_ebin)/euphorik_bd.beam: $(rep_erl)/euphorik_bd.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_bd_admin.beam: $(rep_erl)/euphorik_bd_admin.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_minichat_conversation.beam: $(rep_erl)/euphorik_minichat_conversation.erl $(rep_include)/euphorik_bd.hrl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_requests.beam: $(rep_erl)/euphorik_requests.erl $(rep_include)/euphorik_defines.hrl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_protocole.beam: $(rep_erl)/euphorik_protocole.erl $(rep_include)/euphorik_defines.hrl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_daemon.beam: $(rep_erl)/euphorik_daemon.erl $(rep_include)/euphorik_defines.hrl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_common.beam: $(rep_erl)/euphorik_common.erl\r
+       erlc $(erlc_params)\r
+\r
+$(rep_ebin)/euphorik_test.beam: $(rep_erl)/euphorik_test.erl $(rep_include)/euphorik_bd.hrl\r
+       erlc $(erlc_params)\r
+\r
+clean:\r
+       rm ebin/*.beam\r
index f1d5a60..6c3485d 100755 (executable)
@@ -15,7 +15,7 @@
 %\r
 % You should have received a copy of the GNU General Public License\r
 % along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
 % Ce module permet de gérer les données persistantes lié au site d'euphorik.ch.\r
 % Il permet d'ajouter des message, de demande les messages sur une page donnée, etc..\r
 % Ce module utilise une base mnesia.\r
 \r
 \r
 -module(euphorik_bd).\r
--export([   \r
+-export([\r
    % texte :\r
    get_texte/1,\r
    get_texte/2,\r
-   \r
+\r
    % users :\r
    nouveau_user/2,\r
    nouveau_user/4,\r
    update_date_derniere_connexion/1,\r
    update_ip/2,\r
    update_pseudo_user/2,\r
-   user_by_cookie/1,   \r
-   user_by_id/1,   \r
+   user_by_cookie/1,\r
+   user_by_id/1,\r
    user_by_login/1,\r
    user_by_login_password/2,\r
    user_by_mess/1,\r
    css_from_user_cookie/1,\r
    is_ek_master_from_cookie/1,\r
-   \r
+\r
    % messages :\r
    nouveau_message/3,\r
    nouveau_message_sys/1,\r
    est_une_reponse_a_user/2,\r
    a_repondu_a_message/2,\r
    possede_message/2,\r
-   \r
+\r
    % ip :\r
    list_ban/0,\r
    ban/2,\r
    deban/1,\r
    est_banni/1,\r
    can_register/1,\r
-   \r
-   % trolls :\r
-   trolls/0,\r
-   trolls/1,\r
-   put_troll/2,\r
-   mod_troll/2,\r
-   del_troll/1,\r
-   troll_by_id/1,\r
-   current_troll/0,\r
-   elire_troll/0,\r
-   \r
+\r
    % utiles :\r
-   resultat_transaction/1,
+   resultat_transaction/1,\r
    get_tuples/3 % must be in a transaction\r
 ]).\r
 -import(qlc, [e/2, q/1, cursor/2]).\r
@@ -111,8 +101,8 @@ nouveau_user(Cookie, Profile) ->
       User\r
    end,\r
   resultat_transaction(mnesia:transaction(F)).\r
-  \r
-  \r
+\r
+\r
 % Ajoute un nouveau user et le renvoie\r
 nouveau_user(Login, Password, Cookie, Profile) ->\r
    F = fun() ->\r
@@ -122,7 +112,7 @@ nouveau_user(Login, Password, Cookie, Profile) ->
       User\r
    end,\r
   resultat_transaction(mnesia:transaction(F)).\r
-  \r
+\r
 \r
 % Définit les données du profile d'une utilisateur.\r
 set_profile(Cookie, Login, Password, Profile) ->\r
@@ -174,13 +164,13 @@ update_ip(User_id, IP) ->
                mnesia:abort("update_ip: User inconnu")\r
           end\r
       end\r
-   ).   \r
-   \r
-  \r
+   ).\r
+\r
+\r
 % Met à jour le pseudo du user\r
 update_pseudo_user(UserId, Pseudo) ->\r
    mnesia:transaction(\r
-      fun() ->      \r
+      fun() ->\r
          case mnesia:wread({user, UserId}) of\r
             [#user{profile = Profile} = User] when Profile#profile.pseudo =/= Pseudo ->\r
                mnesia:write(User#user{profile = Profile#profile { pseudo = Pseudo } });\r
@@ -189,7 +179,7 @@ update_pseudo_user(UserId, Pseudo) ->
           end\r
       end\r
    ).\r
-  \r
+\r
 \r
 % Est-ce qu'un utilisateur existe en fonction de son cookie ?\r
 % Renvoie {ok, User} ou erreur\r
@@ -202,8 +192,8 @@ user_by_cookie(Cookie) ->
          end\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 user_by_id(ID) ->\r
    resultat_transaction(mnesia:transaction(\r
       fun() ->\r
@@ -217,8 +207,8 @@ user_by_id(ID) ->
          end\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 user_by_login(Login) ->\r
    resultat_transaction(mnesia:transaction(\r
       fun() ->\r
@@ -229,24 +219,24 @@ user_by_login(Login) ->
          end\r
       end\r
    )).\r
-   \r
+\r
 \r
 % Renvoie une chaine représentant le cookie ou undefined si pas trouvé.\r
 css_from_user_cookie(Cookie) ->\r
-   case user_by_cookie(Cookie) of \r
+   case user_by_cookie(Cookie) of\r
       {ok, #user{profile = Profile}} ->\r
          Profile#profile.css;\r
       _ ->\r
          undefined\r
    end.\r
-   \r
-   \r
+\r
+\r
 is_ek_master_from_cookie(Cookie) ->\r
    case user_by_cookie(Cookie) of\r
       {ok, #user{ek_master = true}} -> true;\r
       _ -> false\r
    end.\r
-   \r
+\r
 \r
 user_by_login_password(Login, Password) ->\r
    resultat_transaction(mnesia:transaction(\r
@@ -257,8 +247,8 @@ user_by_login_password(Login, Password) ->
          end\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Renvoie {ok, User} où User est un #user possédant le message donné.\r
 user_by_mess(Id) ->\r
    resultat_transaction(mnesia:transaction(\r
@@ -269,26 +259,26 @@ user_by_mess(Id) ->
          end\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Ajoute un message. Repond_A est une liste d'id auquel le message répond\r
 % retourne soit l'id du message soit {erreur, <raison>}.\r
 nouveau_message(Mess, Auteur_id, Repond_A_ids) ->\r
    % regarde si les id 'Repond_A' existent\r
-   F = fun() ->         \r
+   F = fun() ->\r
       Repond_a = lists:foldr(\r
          fun(Repond_a_id, Acc) ->\r
-            case mnesia:read({minichat, Repond_a_id}) of
+            case mnesia:read({minichat, Repond_a_id}) of\r
                [M] -> [M | Acc];\r
-               _ -> Acc % le message n'est pas trouvé
+               _ -> Acc % le message n'est pas trouvé\r
             end\r
-         end,
+         end,\r
          [],\r
          Repond_A_ids\r
       ),\r
       Racine_id = case Repond_a of\r
          [] -> undefined;\r
-         [M | _] -> \r
+         [M | _] ->\r
             Une_racine = M#minichat.racine_id,\r
             % vérification que tout les messages de Repond_a possède la même racine (même conversation)\r
             case lists:all(fun(R) -> R#minichat.racine_id =:= Une_racine end, Repond_a) of\r
@@ -297,9 +287,9 @@ nouveau_message(Mess, Auteur_id, Repond_A_ids) ->
                _ ->\r
                   {erreur, "Les messages ne font pas partie de la même conversation"}\r
             end\r
-      end,      
-      if length(Repond_a) =/= length(Repond_A_ids) ->
-            {erreur, "Un ou plusieurs messages introuvable"};
+      end,\r
+      if length(Repond_a) =/= length(Repond_A_ids) ->\r
+            {erreur, "Un ou plusieurs messages introuvable"};\r
          true ->\r
             case Racine_id of\r
                {erreur, E} -> {erreur, E};\r
@@ -321,7 +311,7 @@ nouveau_message(Mess, Auteur_id, Repond_A_ids) ->
                               nouveau_message_sys("\"" ++ Profile#profile.pseudo ++ if Auteur#user.login =/= [] -> " (" ++ Auteur#user.login ++ ")"; true -> "" end ++ "\" est bloqué pour " ++ integer_to_list(trunc(?DUREE_BLOCAGE_SPAM / 1000)) ++ " secondes pour cause de flood.");\r
                            Auteur#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM ->\r
                               {erreur, "Bloqué pour cause de flood"};\r
-                           true ->     \r
+                           true ->\r
                               mnesia:write(Auteur_maj),\r
                               Id = nouvel_id(minichat),\r
                               inserer_reponses(Id, Repond_A_ids),\r
@@ -338,19 +328,19 @@ nouveau_message(Mess, Auteur_id, Repond_A_ids) ->
                      _ ->\r
                         {erreur, "L'auteur du message est introuvable"}\r
                   end\r
-            end
+            end\r
       end\r
    end,\r
    resultat_transaction(mnesia:transaction(F)).\r
-   \r
+\r
 % Définit Id_repondant comme étant la réponse à Ids. Ids est une liste d'id.\r
 inserer_reponses(Id_repondant, [Id_mess | Reste]) ->\r
    mnesia:write(#reponse_minichat{repondant = Id_repondant, cible = Id_mess}),\r
    inserer_reponses(Id_repondant, Reste);\r
 inserer_reponses(_, []) ->\r
    ok.\r
-   \r
\r
+\r
+\r
 % Permet de créer un message système.\r
 % Renvoie l'id du message système\r
 nouveau_message_sys(Mess) ->\r
@@ -362,62 +352,51 @@ nouveau_message_sys(Mess) ->
          Id\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Renvoie N messages se trouvant sur la première page\r
-messages(N) ->  \r
+messages(N) ->\r
    messages(N, 1).\r
 \r
 \r
-% Renvoie N messages se trouvant sur la page P
+% Renvoie N messages se trouvant sur la page P\r
 % TODO FIXME : fonction en O(N * P) !\r
 messages(N, P) ->\r
-   F = fun() ->
-      % % #minichat{contenu = contenu_message(E)}
+   F = fun() ->\r
       get_tuples(minichat, mnesia:table_info(minichat, size) - N * P + 1, N)\r
    end,\r
-   resultat_transaction(mnesia:transaction(F)).
-   
-
-get_tuples(Table, First_id, N) ->
-   lists:foldr(
-      fun(Id, Acc) ->
-         case mnesia:read({Table, Id}) of
-            [T] -> [T | Acc];
-            _ -> Acc
-         end
-      end,
-      [],
-      lists:seq(First_id, First_id + N - 1)
-   ).
-   \r
+   resultat_transaction(mnesia:transaction(F)).\r
+\r
+\r
+get_tuples(Table, First_id, N) ->\r
+   lists:foldr(\r
+      fun(Id, Acc) ->\r
+         case mnesia:read({Table, Id}) of\r
+            [T] -> [T | Acc];\r
+            _ -> Acc\r
+         end\r
+      end,\r
+      [],\r
+      lists:seq(First_id, First_id + N - 1)\r
+   ).\r
+\r
 \r
 % Renvoie les messages manquants pour la page P en sachant qu'il y a N message\r
 % par page et que le dernier message que l'on possède est Id\r
 messages(Id, N, P) ->\r
    lists:filter(fun (M) -> M#minichat.id > Id end, messages(N, P)).\r
-   \r
-   \r
+\r
+\r
 % Renvoie {ok, #minichat} (voir #minichat de euphorik_bd.hrl) à partir de son id.\r
 message_by_id(Id) ->\r
    resultat_transaction(mnesia:transaction(\r
       fun() ->\r
          case mnesia:read({minichat, Id}) of\r
-            [M] -> {ok, M#minichat{contenu = contenu_message(M)}};\r
+            [M] -> {ok, M};\r
             _ -> erreur\r
          end\r
       end\r
    )).\r
-   \r
-   \r
-% Renvoie le contenu d'un message donnée en fonction du troll associé, à utiliser à l'intérieur d'une transaction.\r
-% TODO : Cette fonction pourrait être remplacée par un "outer-join", est-ce possible avec qlc ?\r
-contenu_message(E) ->\r
-   case mnesia:index_read(troll, E#minichat.id, #troll.id_minichat) of\r
-      [] -> E#minichat.contenu;\r
-      [T] -> E#minichat.contenu ++ T#troll.content\r
-   end.\r
-  \r
 \r
 % Renvoie une liste de message (voir #minichat de euphorik_bd.hrl) à partir d'une liste d'id (Ids).\r
 % TODO : optimisations ? serait-ce du O(n) ?\r
@@ -432,7 +411,7 @@ messages_by_ids(Ids) ->
          ),[{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
       end\r
    )).\r
-   \r
+\r
 \r
 % Est-ce qu'un message existe ? Renvoie un boolean.\r
 % TODO : ya pas plus simple ?\r
@@ -440,16 +419,16 @@ message_existe(Id) ->
    resultat_transaction(mnesia:transaction(fun() ->\r
       length(e(q([E#minichat.id || E <- mnesia:table(minichat), E#minichat.id =:= Id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])) =:= 1\r
    end)).\r
-   \r
-   \r
+\r
+\r
 % Renvoie les reponses (utilisé normalement uniquement pendant le debug).\r
 reponses() ->\r
    F = fun() ->\r
       e(q([E || E <- mnesia:table(reponse_minichat)]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
    end,\r
    resultat_transaction(mnesia:transaction(F)).\r
-   \r
-   \r
+\r
+\r
 % Renvoie les messages auquel M_id répond.\r
 parents(M_id) ->\r
    resultat_transaction(mnesia:transaction(\r
@@ -461,8 +440,8 @@ parents(M_id) ->
             M#minichat.id =:= R#reponse_minichat.cible]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Renvoie les message qui repondent à M_id\r
 enfants(M_id) ->\r
    resultat_transaction(mnesia:transaction(\r
@@ -474,8 +453,8 @@ enfants(M_id) ->
             M#minichat.id =:= R#reponse_minichat.repondant]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Renvoie les id des parents d'un message M (les messages auquels répond M)\r
 % ordrés du plus petit au plus grand..\r
 % On évite d'utiliser qlc pour des raisons de performance\r
@@ -488,11 +467,11 @@ parents_id(M_id) ->
                fun(#reponse_minichat{cible = Cible}) -> Cible end,\r
                Parents\r
             ));\r
-         _ -> []            \r
+         _ -> []\r
       end\r
    end)).\r
-   \r
-   \r
+\r
+\r
 % Renvoie les id des enfants d'un message M (les messages qui répondent à M)\r
 % ordrés du plus petit au plus grand.\r
 % @spec enfants_id(integer()) -> [integer()]\r
@@ -504,10 +483,10 @@ enfants_id(M_id) ->
                fun(#reponse_minichat{repondant = Repondant}) -> Repondant end,\r
                Enfants\r
             ));\r
-         _ -> []            \r
+         _ -> []\r
       end\r
    end)).\r
-     \r
+\r
 \r
 % Est-ce que le message Id_mess est une réponse d'une message de Id_user ?\r
 % On evite d'utiliser qlc (ce qui était fait avant) pour des raisons de performance.\r
@@ -530,7 +509,7 @@ est_une_reponse_a_user(Id_user, Id_mess) ->
       end\r
    )).\r
 \r
-   \r
+\r
 % Est-ce que Id_user à répondu au message Id_mess\r
 % On evite d'utiliser qlc (ce qui était fait avant) pour des raisons de performance.\r
 a_repondu_a_message(Id_user, Id_mess) ->\r
@@ -551,8 +530,8 @@ a_repondu_a_message(Id_user, Id_mess) ->
          end\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Est-ce que Id_user possède Id_mess ?\r
 possede_message(Id_user, Id_mess) ->\r
    case mnesia:transaction(\r
@@ -563,8 +542,8 @@ possede_message(Id_user, Id_mess) ->
       {atomic, [Id_user | []]} -> true;\r
       _ -> false\r
    end.\r
-   \r
-   \r
+\r
+\r
 % renvoie la liste des ip bannies\r
 % liste de {ip, temps_restant(en minutes), Users} ou Users est une liste de {pseudo, login}\r
 % TODO : déterminer la complexité de cette fonction. (Il n'y a pas d'index sur #user.last_ip)\r
@@ -597,13 +576,13 @@ ban(IP, Duration) ->
           end\r
       end\r
    ).\r
-   \r
+\r
 \r
 % Débanni une ip\r
 deban(IP) ->\r
    ban(IP, 0).\r
 \r
-   \r
+\r
 % Renvoie soit {true, Temps} où Temps est le temps en minutes pendant lequel le user est encore banni\r
 % ou false.\r
 est_banni(User_id) ->\r
@@ -629,8 +608,8 @@ est_banni(User_id) ->
          end\r
       end\r
    )).\r
-   \r
-   \r
+\r
+\r
 % Ban est une date tel que retourner par now().\r
 % Ban_duration est un temps en minutes.\r
 % retourne une date.\r
@@ -638,16 +617,16 @@ date_plus_minutes(Ban, Ban_duration) ->
    Duration_sec = Ban_duration * 60,\r
    {MegaSec, Sec, MicroSec} = Ban,\r
    {MegaSec + if Sec + Duration_sec >= 1000000 -> 1; true -> 0 end,(Sec + Duration_sec) rem 1000000, MicroSec}.\r
-   \r
 \r
-% Si deux enregistrements consequtifs de la même IP sont fait en moins d'une seconde alors \r
+\r
+% Si deux enregistrements consequtifs de la même IP sont fait en moins d'une seconde alors\r
 % ip_table.nb_try_register est incrémenté de 1 sinon il est décrémenté de 1 (jusqu'a 0).\r
 % Si ip_table.nb_try_register vaut 5 alors l'ip ne peux plus s'enregistrer pour une heure.\r
 can_register(IP) ->\r
    resultat_transaction(mnesia:transaction(\r
       fun() ->\r
          case e(q([I || I <- mnesia:table(ip_table), I#ip_table.ip =:= IP]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of\r
-            [] -> \r
+            [] ->\r
                mnesia:write(#ip_table{ip = IP, date_last_try_register = now()}),\r
                true;\r
             [T] ->\r
@@ -665,144 +644,8 @@ can_register(IP) ->
          end\r
       end\r
    )).\r
-   \r
-\r
-% Renvoie tous les trolls\r
-trolls() ->\r
-   resultat_transaction(mnesia:transaction(\r
-      fun() ->\r
-         e(qlc:keysort(#troll.id, q([T || T <- mnesia:table(troll)])), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
-      end\r
-   )).\r
-   \r
-   \r
-% Renvoie les trolls manquants posté après Last_id.\r
-trolls(Last_id) ->\r
-   resultat_transaction(mnesia:transaction(\r
-      fun() ->\r
-         e(qlc:keysort(#troll.id, q([T || T <- mnesia:table(troll), T#troll.id > Last_id, T#troll.date_post =:= undefined])), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
-      end\r
-   )).\r
-   \r
\r
- % Crée un nouveau troll.\r
- % Renvoie l'id du nouveau troll\r
- % ou max_troll_reached_per_user si le nombre de troll posté par l'utilisateur max a été atteind\r
- % ou max_troll_reached si le nombre de troll posté max a été atteind\r
- % ou user_unknown\r
-put_troll(User_id, Content) ->\r
-   resultat_transaction(mnesia:transaction(\r
-      fun() ->\r
-         % control le nombre de troll déjà posté\r
-         Nb_troll_poste_par_user = length(e(q(\r
-            [\r
-               E#troll.id || E <- mnesia:table(troll),\r
-               E#troll.id_user =:= User_id,\r
-               E#troll.date_post =:= undefined\r
-            ]\r
-         ), [{tmpdir, ?KEY_SORT_TEMP_DIR}])),\r
-         Nb_troll_poste_total = length(e(q(\r
-            [\r
-               E#troll.id || E <- mnesia:table(troll),\r
-               E#troll.date_post =:= undefined\r
-            ]\r
-         ), [{tmpdir, ?KEY_SORT_TEMP_DIR}])),\r
-         User = user_by_id(User_id),\r
-         case User of\r
-            {ok, _} ->\r
-               if Nb_troll_poste_par_user >= ?NB_MAX_TROLL_WAITING_BY_USER ->\r
-                     max_troll_reached_per_user;\r
-                  Nb_troll_poste_total >= ?NB_MAX_TROLL_WAITING ->\r
-                     max_troll_reached;\r
-                  true ->\r
-                     Id = nouvel_id(troll),\r
-                     mnesia:write(#troll{id = Id, id_user = User_id, date_create = now(), content = Content}),\r
-                     Id\r
-               end;\r
-            _ ->\r
-               user_unknown\r
-         end\r
-      end\r
-   )).\r
-\r
-\r
-% renvoie ok | erreur\r
-mod_troll(Troll_id, Content) ->\r
-   mnesia:transaction(\r
-      fun() ->\r
-         case mnesia:wread({troll, Troll_id}) of\r
-            [Troll = #troll{date_post = undefined}] ->\r
-               mnesia:write(Troll#troll{content = Content});\r
-            _ ->\r
-               mnesia:abort("mod_troll: Troll inconnu ou déjà posté")\r
-          end\r
-      end\r
-   ).\r
-   \r
-   \r
-del_troll(Troll_id) ->\r
-   mnesia:transaction(\r
-      fun() ->\r
-         case mnesia:wread({troll, Troll_id}) of\r
-            [#troll{date_post = undefined}] ->\r
-               mnesia:delete({troll, Troll_id});\r
-            _ ->\r
-               mnesia:abort("mod_troll: Troll inconnu ou déjà posté")\r
-          end\r
-      end\r
-   ).\r
\r
\r
-troll_by_id(Troll_id) ->\r
-   resultat_transaction(mnesia:transaction(\r
-      fun() ->\r
-         case e(q([T || T <- mnesia:table(troll), T#troll.id =:= Troll_id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of\r
-            [T] -> {ok, T};\r
-            _ ->\r
-               erreur\r
-         end\r
-      end\r
-   )).\r
-   \r
-\r
-% Renvoie le troll actuel qui se trouve sur la page principale.\r
-% Renvois aucun si pas de troll courant.\r
-current_troll() ->\r
-   resultat_transaction(mnesia:transaction(\r
-      fun() ->\r
-         C = cursor(qlc:keysort(#troll.date_post, q([T || T <- mnesia:table(troll), T#troll.date_post =/= undefined]), [{order, descending}]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]),\r
-         R = case qlc:next_answers(C, 1) of\r
-            [T] -> T;\r
-            _ -> aucun\r
-         end,\r
-         qlc:delete_cursor(C),\r
-         R\r
-      end\r
-   )).\r
 \r
 \r
-% Elit un troll au hasard parmis les trolls en attente (leur date_post =:= undefined)\r
-% Un message est posté par 'Sys' et le troll elu est lié à ce message\r
-% met à jour sa date de post.\r
-% renvoie plus_de_trolls si il n'y a aucun troll en attente.\r
-elire_troll() ->       \r
-   {A1,A2,A3} = now(),\r
-   random:seed(A1, A2, A3),\r
-   mnesia:transaction(\r
-      fun() ->\r
-         case e(q([T || T <- mnesia:table(troll), T#troll.date_post =:= undefined]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of\r
-            [] ->\r
-               plus_de_trolls;\r
-            Trolls ->\r
-               Troll = lists:nth(random:uniform(length(Trolls)), Trolls),\r
-               Id_message = nouveau_message_sys("Troll de la semaine : "),\r
-               Troll2 = Troll#troll{date_post = now(), id_minichat = Id_message},\r
-               mnesia:write(Troll2)\r
-         end\r
-      end\r
-   ).\r
-   \r
-   \r
 % Renvoie le résultat d'une transaction (en décomposant le tuple fournit)\r
 resultat_transaction({_, T}) ->\r
    T.\r
@@ -811,4 +654,3 @@ resultat_transaction({_, T}) ->
 % Renvoie un nouvel id pour une table donnée\r
 nouvel_id(Table) ->\r
    mnesia:dirty_update_counter(counter, Table, 1).\r
-   
\ No newline at end of file
index 4a559c8..31be4b4 100644 (file)
-% coding: utf-8
-% Copyright 2008 Grégory Burri
-%
-% This file is part of Euphorik.
-%
-% Euphorik is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Euphorik is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
-% 
-% Module mettant à disposition tout un tas de fonction pour l'administration de la base de données euphorik comme :
-%  - Création de la BD
-%  - Mise à jour de la BD
-%  - Backup et restauration
-%  - Copie de la BD à partir d'un autre noeud
-%
-% @author G.Burri
-
-
--module(euphorik_bd_admin).
--export([
-   version_bd/0,
-   create/0,
-   connect/0,
-   connect/1,
-   reset/0,
-   update/0,
-   
-   backup/1,
-   restore/1,
-   change_node_name/4,
-   
-   toggle_ek_master/1,
-   print_users/0,
-   print_users/1,
-   print_user/1
-]).
--import(qlc, [e/2, q/1, cursor/2]).
--include("../include/euphorik_bd.hrl").
--include("../include/euphorik_defines.hrl").
--include_lib("stdlib/include/qlc.hrl").
-
-
-% Renvoie la version courante de la BD.
-version_bd() ->
-   euphorik_bd:resultat_transaction(mnesia:transaction(
-      fun() ->
-         mnesia:read({proprietes, version})
-      end
-   )).
-   
-
-% Instructions pour créer une nouvelle base : 
-% $erl -sname yaws -mnesia dir '"/projets/euphorik/BD"'
-% voir doc/installation.txt
-% >l(euphorik_bd).
-% >euphorik_bd:create().
-create() ->
-   mnesia:stop(),
-   mnesia:delete_schema([node()]),
-   mnesia:create_schema([node()]), % nécessaire pour les tables sur disc
-   mnesia:start(),
-   create_tables(),
-   reset().
-   
-create_tables() ->
-   mnesia:create_table(counter, [
-      {attributes, record_info(fields, counter)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(proprietes, [
-      {attributes, record_info(fields, proprietes)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(texte, [
-      {attributes, record_info(fields, texte)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(minichat, [
-      {type, ordered_set},
-      {attributes, record_info(fields, minichat)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(reponse_minichat, [
-      {type, bag},
-      {attributes, record_info(fields, reponse_minichat)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(user, [
-      {attributes, record_info(fields, user)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(ip_table, [
-      {attributes, record_info(fields, ip_table)},
-      {disc_copies, [node()]}
-   ]),
-   mnesia:create_table(troll, [
-      {attributes, record_info(fields, troll)},
-      {disc_copies, [node()]}
-   ]),
-   creer_indexes().
-   
-   
-% mis à part car lors de la reprise de données avec load_textfile les indexes ne sont pas recréés
-creer_indexes() ->
-   % commence par supprimer les anciens indexes
-   lists:foreach(fun(T) ->
-         lists:foreach(fun(P) ->
-               mnesia:del_table_index(T, P)
-            end,
-            mnesia:table_info(T, index)
-         )
-      end,   
-      ?TABLES
-   ),
-   mnesia:add_table_index(minichat, auteur_id),
-   mnesia:add_table_index(reponse_minichat, cible),
-   mnesia:add_table_index(user, cookie),
-   mnesia:add_table_index(user, login),
+% coding: utf-8\r
+% Copyright 2008 Grégory Burri\r
+%\r
+% This file is part of Euphorik.\r
+%\r
+% Euphorik is free software: you can redistribute it and/or modify\r
+% it under the terms of the GNU General Public License as published by\r
+% the Free Software Foundation, either version 3 of the License, or\r
+% (at your option) any later version.\r
+%\r
+% Euphorik is distributed in the hope that it will be useful,\r
+% but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+% GNU General Public License for more details.\r
+%\r
+% You should have received a copy of the GNU General Public License\r
+% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
+%\r
+% Module mettant à disposition tout un tas de fonction pour l'administration de la base de données euphorik comme :\r
+%  - Création de la BD\r
+%  - Mise à jour de la BD\r
+%  - Backup et restauration\r
+%  - Copie de la BD à partir d'un autre noeud\r
+%\r
+% @author G.Burri\r
+\r
+\r
+-module(euphorik_bd_admin).\r
+-export([\r
+   version_bd/0,\r
+   create/0,\r
+   connect/0,\r
+   connect/1,\r
+   reset/0,\r
+   update/0,\r
+\r
+   backup/1,\r
+   restore/1,\r
+   change_node_name/4,\r
+\r
+   toggle_ek_master/1,\r
+   print_users/0,\r
+   print_users/1,\r
+   print_user/1\r
+]).\r
+-import(qlc, [e/2, q/1, cursor/2]).\r
+-include("../include/euphorik_bd.hrl").\r
+-include("../include/euphorik_defines.hrl").\r
+-include_lib("stdlib/include/qlc.hrl").\r
+\r
+\r
+% Renvoie la version courante de la BD.\r
+version_bd() ->\r
+   euphorik_bd:resultat_transaction(mnesia:transaction(\r
+      fun() ->\r
+         mnesia:read({proprietes, version})\r
+      end\r
+   )).\r
+\r
+\r
+% Instructions pour créer une nouvelle base :\r
+% $erl -sname yaws -mnesia dir '"/projets/euphorik/BD"'\r
+% voir doc/installation.txt\r
+% >l(euphorik_bd).\r
+% >euphorik_bd:create().\r
+create() ->\r
+   mnesia:stop(),\r
+   mnesia:delete_schema([node()]),\r
+   mnesia:create_schema([node()]), % nécessaire pour les tables sur disc\r
+   mnesia:start(),\r
+   create_tables(),\r
+   reset().\r
+\r
+create_tables() ->\r
+   mnesia:create_table(counter, [\r
+      {attributes, record_info(fields, counter)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   mnesia:create_table(proprietes, [\r
+      {attributes, record_info(fields, proprietes)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   mnesia:create_table(texte, [\r
+      {attributes, record_info(fields, texte)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   mnesia:create_table(minichat, [\r
+      {type, ordered_set},\r
+      {attributes, record_info(fields, minichat)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   mnesia:create_table(reponse_minichat, [\r
+      {type, bag},\r
+      {attributes, record_info(fields, reponse_minichat)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   mnesia:create_table(user, [\r
+      {attributes, record_info(fields, user)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   mnesia:create_table(ip_table, [\r
+      {attributes, record_info(fields, ip_table)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   % This table is not used anymore.\r
+   mnesia:create_table(troll, [\r
+      {attributes, record_info(fields, troll)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   creer_indexes().\r
+\r
+\r
+% mis à part car lors de la reprise de données avec load_textfile les indexes ne sont pas recréés\r
+creer_indexes() ->\r
+   % commence par supprimer les anciens indexes\r
+   lists:foreach(fun(T) ->\r
+         lists:foreach(fun(P) ->\r
+               mnesia:del_table_index(T, P)\r
+            end,\r
+            mnesia:table_info(T, index)\r
+         )\r
+      end,\r
+      ?TABLES\r
+   ),\r
+   mnesia:add_table_index(minichat, auteur_id),\r
+   mnesia:add_table_index(reponse_minichat, cible),\r
+   mnesia:add_table_index(user, cookie),\r
+   mnesia:add_table_index(user, login),\r
    mnesia:add_table_index(troll, date_post),\r
-   mnesia:add_table_index(troll, id_minichat).
-   
-   
-% Connexion à la base de données de yaws sur overnux
-connect() ->
-   connect(yaws@flynux).
-connect(Node) ->
-   mnesia:start(),
-   mnesia:change_config(extra_db_nodes, [Node]).
-
-
-% Efface toutes les données de la base de données.
-reset() ->
-   mnesia:clear_table(counter),
-   mnesia:clear_table(proprietes),
-   mnesia:clear_table(texte),
-   mnesia:clear_table(user),
-   mnesia:clear_table(reponse_minichat),
-   mnesia:clear_table(minichat),
-   mnesia:clear_table(troll),
-   mnesia:clear_table(ip_table),
-   % crée l'utilisateur root
-   mnesia:transaction(fun() ->
-      mnesia:write(#proprietes{nom = version, valeur = ?VERSION_BD}),
-      User = #user{id = 0, profile = #profile{pseudo = "Sys"}, login = "Sys", date_creation = now(), date_derniere_connexion = now(), ek_master = true},
-      mnesia:write(User),
-      User
-   end),
-   peupler_texte().
-   
-   
-peupler_texte() ->
-   mnesia:transaction(fun() ->
-      mnesia:write(#texte{ id = 10, fr = "Login déjà existant"}),
-      mnesia:write(#texte{ id = 20, fr = "Trop de register (flood)"}),
-      mnesia:write(#texte{ id = 30, fr = "Couple login/pass introuvable"}),
-      mnesia:write(#texte{ id = 40, fr = "Authentification impossible par cookie"}),
-      mnesia:write(#texte{ id = 50, fr = "Impossible de mettre à jour le profile"}),
-      mnesia:write(#texte{ id = 60, fr = "timeout"}),
-      mnesia:write(#texte{ id = 70, fr = "Page inconnue"}),
-      mnesia:write(#texte{ id = 80, fr = "Vous êtes banni pour encore ~s"}),
-      mnesia:write(#texte{ id = 90, fr = "Message vide"}),
-      mnesia:write(#texte{ id = 100, fr = "Impossible d'ajouter un nouveau message. Raison : ~s"}),
-      mnesia:write(#texte{ id = 110, fr = "Utilisateur inconnu"}),
-      mnesia:write(#texte{ id = 120, fr = "Il n'est pas possible de s'auto bannir"}),
-      mnesia:write(#texte{ id = 130, fr = "L'utilisateur est lui même un ekMaster"}),
-      mnesia:write(#texte{ id = 140, fr = "Utilisateur à bannir inconnu"}),
-      mnesia:write(#texte{ id = 150, fr = "Utilisateur inconnu ou non ek master"}),
-      mnesia:write(#texte{ id = 160, fr = "Utilisateur à slaper inconnu"}),
-      mnesia:write(#texte{ id = 170, fr = "Utilisateur inconnu ou non ek master"}),
-      mnesia:write(#texte{ id = 180, fr = "Le nombre de troll maximum par utilisateur est atteint : ~w "}),
-      mnesia:write(#texte{ id = 190, fr = "Le nombre de troll maximum en attente est atteint : ~w "}),
-      mnesia:write(#texte{ id = 200, fr = "Seul les ekMaster peuvent proposer des trolls"}),
-      mnesia:write(#texte{ id = 210, fr = "Vous ne posséder pas ce troll"}),
-      mnesia:write(#texte{ id = 220, fr = "Seul les ekMaster peuvent proposer des trolls"}),
-      mnesia:write(#texte{ id = 230, fr = "Seul les ekMaster peuvent connaitre la liste des ips bannies"})
-   end).
-
-
-% Met à jour la bd, compare ?VERSION_BD avec la version dans la table 'proprietes'
-% et exécute les patchs nécessaires.
-update() ->
-   case mnesia:dirty_read({proprietes, version}) of
-      [#proprietes{valeur = Version}] ->
-         update(Version);
-      _ ->
-         erreur
-   end.
-   
-
-% Mise à jour de la BD.
-% attention : il est nécessaire de se trouver dans une transaction.
-update(?VERSION_BD) -> fini;
-update(Version) ->
-   case mnesia:backup(fichier_backup(Version)) of
-      ok ->
-         case patch(Version) of
-            ok ->
-               mnesia:dirty_write(#proprietes{nom = version, valeur = Version + 1}),
-               update(Version + 1);
-            Erreur ->
-               Erreur
-         end;
-      {error, Raison} -> {error, lists:flatten(io_lib:format("Erreur de création du backup de la version ~w : ~w", [Version, Raison]))}
-   end.
-   
-   
-% Applique une modification de la BD pour passer d'une version à la suivante.
-% crée un backup avant l'application du patch
-% dans BD/backups nommé "backup<num>" où <num> et le numéro de la version.
-% 1 -> 2
+   mnesia:add_table_index(troll, id_minichat).\r
+\r
+\r
+% Connexion à la base de données de yaws sur overnux\r
+connect() ->\r
+   connect(yaws@flynux).\r
+connect(Node) ->\r
+   mnesia:start(),\r
+   mnesia:change_config(extra_db_nodes, [Node]).\r
+\r
+\r
+% Efface toutes les données de la base de données.\r
+reset() ->\r
+   mnesia:clear_table(counter),\r
+   mnesia:clear_table(proprietes),\r
+   mnesia:clear_table(texte),\r
+   mnesia:clear_table(user),\r
+   mnesia:clear_table(reponse_minichat),\r
+   mnesia:clear_table(minichat),\r
+   mnesia:clear_table(troll),\r
+   mnesia:clear_table(ip_table),\r
+   % crée l'utilisateur root\r
+   mnesia:transaction(fun() ->\r
+      mnesia:write(#proprietes{nom = version, valeur = ?VERSION_BD}),\r
+      User = #user{id = 0, profile = #profile{pseudo = "Sys"}, login = "Sys", date_creation = now(), date_derniere_connexion = now(), ek_master = true},\r
+      mnesia:write(User),\r
+      User\r
+   end),\r
+   peupler_texte().\r
+\r
+\r
+peupler_texte() ->\r
+   mnesia:transaction(fun() ->\r
+      mnesia:write(#texte{ id = 10, fr = "Login déjà existant"}),\r
+      mnesia:write(#texte{ id = 20, fr = "Trop de register (flood)"}),\r
+      mnesia:write(#texte{ id = 30, fr = "Couple login/pass introuvable"}),\r
+      mnesia:write(#texte{ id = 40, fr = "Authentification impossible par cookie"}),\r
+      mnesia:write(#texte{ id = 50, fr = "Impossible de mettre à jour le profile"}),\r
+      mnesia:write(#texte{ id = 60, fr = "timeout"}),\r
+      mnesia:write(#texte{ id = 70, fr = "Page inconnue"}),\r
+      mnesia:write(#texte{ id = 80, fr = "Vous êtes banni pour encore ~s"}),\r
+      mnesia:write(#texte{ id = 90, fr = "Message vide"}),\r
+      mnesia:write(#texte{ id = 100, fr = "Impossible d'ajouter un nouveau message. Raison : ~s"}),\r
+      mnesia:write(#texte{ id = 110, fr = "Utilisateur inconnu"}),\r
+      mnesia:write(#texte{ id = 120, fr = "Il n'est pas possible de s'auto bannir"}),\r
+      mnesia:write(#texte{ id = 130, fr = "L'utilisateur est lui même un ekMaster"}),\r
+      mnesia:write(#texte{ id = 140, fr = "Utilisateur à bannir inconnu"}),\r
+      mnesia:write(#texte{ id = 150, fr = "Utilisateur inconnu ou non ek master"}),\r
+      mnesia:write(#texte{ id = 160, fr = "Utilisateur à slaper inconnu"}),\r
+      mnesia:write(#texte{ id = 170, fr = "Utilisateur inconnu ou non ek master"}),\r
+      mnesia:write(#texte{ id = 230, fr = "Seul les ekMaster peuvent connaitre la liste des ips bannies"})\r
+   end).\r
+\r
+\r
+% Met à jour la bd, compare ?VERSION_BD avec la version dans la table 'proprietes'\r
+% et exécute les patchs nécessaires.\r
+update() ->\r
+   case mnesia:dirty_read({proprietes, version}) of\r
+      [#proprietes{valeur = Version}] ->\r
+         update(Version);\r
+      _ ->\r
+         erreur\r
+   end.\r
+\r
+\r
+% Mise à jour de la BD.\r
+% attention : il est nécessaire de se trouver dans une transaction.\r
+update(?VERSION_BD) -> fini;\r
+update(Version) ->\r
+   case mnesia:backup(fichier_backup(Version)) of\r
+      ok ->\r
+         case patch(Version) of\r
+            ok ->\r
+               mnesia:dirty_write(#proprietes{nom = version, valeur = Version + 1}),\r
+               update(Version + 1);\r
+            Erreur ->\r
+               Erreur\r
+         end;\r
+      {error, Raison} -> {error, lists:flatten(io_lib:format("Erreur de création du backup de la version ~w : ~w", [Version, Raison]))}\r
+   end.\r
+\r
+\r
+% Applique une modification de la BD pour passer d'une version à la suivante.\r
+% crée un backup avant l'application du patch\r
+% dans BD/backups nommé "backup<num>" où <num> et le numéro de la version.\r
+% 1 -> 2\r
 patch(1) ->\r
    % Prend un chemin vers la feuille de style de type "css/1/euphorik.css"\r
    % et renvoie "styles/1/euphorik.css"\r
-   Transforme_css = fun("css" ++ Reste) ->
+   Transforme_css = fun("css" ++ Reste) ->\r
          "styles" ++ Reste;\r
          (F) -> F\r
    end,\r
@@ -236,10 +232,10 @@ patch(1) ->
          )\r
       end,\r
       F(F, M)\r
-   end,
+   end,\r
    % Prend un chemin vers la feuille de style de type "css/1/euphorik.css"\r
    % et renvoie "styles/1/euphorik.css"\r
-   Transforme_css = fun("css" ++ Reste) ->
+   Transforme_css = fun("css" ++ Reste) ->\r
          "styles" ++ Reste;\r
          (F) -> F\r
    end,\r
@@ -255,37 +251,37 @@ patch(1) ->
          )\r
       end,\r
       F(F, M)\r
-   end,
-   mnesia:create_table(texte, [
-      {attributes, record_info(fields, texte)},
-      {disc_copies, [node()]}
-   ]),
-   peupler_texte(),
-   % traitement des users   
-   mnesia:transform_table(
-      user,
-      fun({user, Id, Cookie, Pseudo, Login, Password, Email, Date_creation, Date_derniere_connexion, Css, Nick_format, View_times, View_tooltips, Indice_flood, _Page_principale, Conversations, Ek_master, Last_ip}) ->
-            {user, Id, Cookie, Login, Password, {profile, Pseudo, Email, Transforme_css(Css), Nick_format, View_times, View_tooltips, light, reverse, lists:map(fun({R, _}) -> {R, false} end, Conversations)}, Date_creation, Date_derniere_connexion, Indice_flood, Ek_master, Last_ip}
-      end,
-      record_info(fields, user)
-   ),
-   mnesia:transform_table(
-      minichat,
-      fun({minichat, Id, Auteur_id, Date, Pseudo, Contenu, Troll_id}) ->
-            {minichat, Id, Auteur_id, Date, Pseudo, Contenu, Troll_id, Id}
-      end,
-      record_info(fields, minichat)
-   ),
-   case mnesia:transaction(
-      fun() ->
-         % met à jour les enfants des racines
-         % idéalement : utiliser un cursor mais je crois qu'il n'est pas possible de faire des modifs en itérant en même temps avec un cursor, a voir..
-         Messages = e(q([M || M <- mnesia:table(minichat), euphorik_bd:parents(M#minichat.id) =:= []]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]),
-         lists:foreach(fun(M) -> Traiter_message(M, M#minichat.id) end, Messages)
-      end
-   ) of
-      {aborted, Raison} -> {erreur, Raison};
-      {atomic, _} -> ok
+   end,\r
+   mnesia:create_table(texte, [\r
+      {attributes, record_info(fields, texte)},\r
+      {disc_copies, [node()]}\r
+   ]),\r
+   peupler_texte(),\r
+   % traitement des users\r
+   mnesia:transform_table(\r
+      user,\r
+      fun({user, Id, Cookie, Pseudo, Login, Password, Email, Date_creation, Date_derniere_connexion, Css, Nick_format, View_times, View_tooltips, Indice_flood, _Page_principale, Conversations, Ek_master, Last_ip}) ->\r
+            {user, Id, Cookie, Login, Password, {profile, Pseudo, Email, Transforme_css(Css), Nick_format, View_times, View_tooltips, light, reverse, lists:map(fun({R, _}) -> {R, false} end, Conversations)}, Date_creation, Date_derniere_connexion, Indice_flood, Ek_master, Last_ip}\r
+      end,\r
+      record_info(fields, user)\r
+   ),\r
+   mnesia:transform_table(\r
+      minichat,\r
+      fun({minichat, Id, Auteur_id, Date, Pseudo, Contenu, Troll_id}) ->\r
+            {minichat, Id, Auteur_id, Date, Pseudo, Contenu, Troll_id, Id}\r
+      end,\r
+      record_info(fields, minichat)\r
+   ),\r
+   case mnesia:transaction(\r
+      fun() ->\r
+         % met à jour les enfants des racines\r
+         % idéalement : utiliser un cursor mais je crois qu'il n'est pas possible de faire des modifs en itérant en même temps avec un cursor, a voir..\r
+         Messages = e(q([M || M <- mnesia:table(minichat), euphorik_bd:parents(M#minichat.id) =:= []]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]),\r
+         lists:foreach(fun(M) -> Traiter_message(M, M#minichat.id) end, Messages)\r
+      end\r
+   ) of\r
+      {aborted, Raison} -> {erreur, Raison};\r
+      {atomic, _} -> ok\r
    end;\r
 % 2 -> 3\r
 patch(2) ->\r
@@ -308,179 +304,179 @@ patch(2) ->
          {minichat, Id, Auteur_id, Date, Pseudo, Contenu, Racine_id, normal}\r
       end,\r
       record_info(fields, minichat)\r
-   ),
-   mnesia:transaction(fun() ->
-      % comble les trous entre les id non-contigues
-      lists:foreach(fun(Id) ->
-            case mnesia:read({minichat, Id}) of
-               [] -> 
-                  {ok, #user{profile = Profile}} = euphorik_bd:user_by_id(0),
-                  mnesia:write(#minichat{id = Id, auteur_id = 0, date = undefined, pseudo = Profile#profile.pseudo, contenu = "Comblement...", racine_id = Id, status = deleted});
-               _ -> rien
-            end
-         end,
-         lists:seq(1, mnesia:table_info(minichat, size))
-      ),
-      % la table troll utilise maintenant son index et pas celui de la table minichat (correction d'un vieux bug)
-      mnesia:write(#counter{key = troll, value = mnesia:table_info(minichat, size)})
+   ),\r
+   mnesia:transaction(fun() ->\r
+      % comble les trous entre les id non-contigues\r
+      lists:foreach(fun(Id) ->\r
+            case mnesia:read({minichat, Id}) of\r
+               [] ->\r
+                  {ok, #user{profile = Profile}} = euphorik_bd:user_by_id(0),\r
+                  mnesia:write(#minichat{id = Id, auteur_id = 0, date = undefined, pseudo = Profile#profile.pseudo, contenu = "Comblement...", racine_id = Id, status = deleted});\r
+               _ -> rien\r
+            end\r
+         end,\r
+         lists:seq(1, mnesia:table_info(minichat, size))\r
+      ),\r
+      % la table troll utilise maintenant son index et pas celui de la table minichat (correction d'un vieux bug)\r
+      mnesia:write(#counter{key = troll, value = mnesia:table_info(minichat, size)})\r
    end),\r
-   creer_indexes(). % uniquement pour l'indice sur id_minichat de la table troll
-
-
-% Renvoie le dossier dans lequel les backups sont effectué, ce dossier doit être en écriture.
-dossier_backups() ->
-   mnesia:system_info(directory) ++ "/backups/".
-
-
-% Renvoie le fichier (avec le chemin) correspondant à la version Version, par exemple : "/var/euphorik/BD/backups/backup1"
-fichier_backup(Version) when is_integer(Version) -> 
-   dossier_backups() ++ "backup" ++ integer_to_list(Version).
-\r
-
-% crée un backup dont le nom est fournit dans le repertoire backups qui se trouve dans le repertoire de la BD.
-backup(Fichier) ->
-   mnesia:backup(dossier_backups() ++ Fichier).
-   
-   
-% Restaure un backup de la BD.
-restore(Fichier) when is_list(Fichier) ->
-   mnesia:restore(dossier_backups() ++ Fichier, []);
-% Reviens à une version précédente de la base de données.
-% (les données insérées durant les versions plus récentes sont perdues).
-restore(Version) when is_integer(Version) ->
-   mnesia:restore(fichier_backup(Version), []). % [{default_op, recreate_tables}]).
-   
-
-% Change le nom du noeud d'un backup.
-% provient d'ici : http://www.erlang.org/doc/apps/mnesia/Mnesia_chap7.html#6.9
-% From : l'ancien nom
-% To : le nouveau nom
-% Source : le nom du fichier de backup
-% Target : le nom du fichier du nouveau backup
-change_node_name(From, To, Source, Target) ->
-    Switch =
-        fun(Node) when Node == From -> To;
-           (Node) when Node == To -> throw({error, already_exists});
-           (Node) -> Node
-        end,
-    Convert =
-        fun({schema, db_nodes, Nodes}, Acc) ->
-                {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};
-           ({schema, version, Version}, Acc) ->
-                {[{schema, version, Version}], Acc};
-           ({schema, cookie, Cookie}, Acc) ->
-                {[{schema, cookie, Cookie}], Acc};
-           ({schema, Tab, CreateList}, Acc) ->
-                Keys = [ram_copies, disc_copies, disc_only_copies],
-                OptSwitch =
-                    fun({Key, Val}) ->
-                            case lists:member(Key, Keys) of
-                                true -> {Key, lists:map(Switch, Val)};
-                                false-> {Key, Val}
-                            end
-                    end,
-                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
-           (Other, Acc) ->
-                {[Other], Acc}
-        end,
-    mnesia:traverse_backup(Source, Target, Convert, switched).
-
-
-% Obsolète
-%~ backup_text(File) ->
-   %~ mnesia:dump_to_textfile(File).
-%~ restore_text(File) -> 
-   %~ mnesia:stop(),
-   %~ mnesia:delete_schema([node()]),
-   %~ mnesia:start(),
-   %~ create_tables(),
-   %~ case mnesia:load_textfile(File) of
-      %~ {atomic, ok} ->
-         %~ update(),
-         %~ creer_indexes();
-      %~ Erreur ->
-         %~ Erreur
-   %~ end.
-
-
-toggle_ek_master(User_id) ->
-   euphorik_bd:resultat_transaction(mnesia:transaction(
-      fun() ->
-         Users = e(q([E || E <- mnesia:table(user), E#user.id =:= User_id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]),
-         case Users of
-            [User] ->
-               mnesia:write(User#user{ek_master = not User#user.ek_master});
-            _ -> erreur
-         end
-      end
-   )).
-   
-
-% Affiche N user trié par leur date de dernière connexion.
-% Opt est une liste d'option d'affichage :
-%  * ekmaster : n'affiche que les admins
-print_users(N, Opt) ->
-   AfficheQueLesEkMaster = lists:any(fun(O) -> O =:= ekmaster end, Opt),
-   euphorik_bd:resultat_transaction(mnesia:transaction(fun() ->
-      C = cursor(
-         qlc:keysort(
-            #user.date_derniere_connexion, 
-            if AfficheQueLesEkMaster ->
-               q([E || E <- mnesia:table(user), E#user.ek_master =:= true]);
-            true ->
-               q([E || E <- mnesia:table(user)])
-            end,
-            [{order, descending}]
-         ),
-         [{tmpdir, ?KEY_SORT_TEMP_DIR}]
-      ),
-      Users = qlc:next_answers(C, N),
-      lists:foreach(
-         fun(U) ->
-            print_user(U)
-         end,
-         Users
-      ),
-      qlc:delete_cursor(C)
-   end)).
-   
-   
-% Affiche tous les users.
-print_users(Opt) ->
-   print_users(all_remaining, Opt).
-
-% Affiche tous les users.
-print_users() ->
-   print_users(all_remaining, []).
-   
-print_user(User) when is_record(User, user) ->
-   #user{id = Id, profile = #profile{pseudo = Pseudo}, login = Login, ek_master = Ek_master, date_derniere_connexion = Date, last_ip = IP} = User,
-   {{Annee, Mois, Jour}, {Heure, Min, _}} = calendar:now_to_local_time(Date),
-   io:format(
-      % id        pseudo     (login)        IP  Jour  Mois   Année  Heure Minute
-      "~4w : ~10.10..s(~10.10..s) ~s ~2w.~2.2.0w.~w - ~2wh~2.2.0w~n",
-      [  
-         Id,
-         if Ek_master -> "*"; true -> "" end ++ Pseudo,
-         Login,
-         euphorik_common:serialize_ip(IP),
-         Jour, Mois, Annee, Heure, Min
-      ]
-   );
-% Affichage d'un user en fonction de son login
-print_user(Login) when is_list(Login) ->
-   case euphorik_bd:user_by_login(Login) of
-      {ok, User} ->
-         print_user(User);
-      _ ->
-         {erreur, "Login pas trouvé : " ++ Login}
-   end;
-% Affichage d'un user en fonction de son id
-print_user(Id) when is_integer(Id) -> 
-   case euphorik_bd:user_by_id(Id) of 
-      {ok, User} ->
-         print_user(User);
-      _ ->
-         {erreur, "Id pas trouvé : " ++ integer_to_list(Id)}
-   end.
-   
+   creer_indexes(). % uniquement pour l'indice sur id_minichat de la table troll\r
+\r
+\r
+% Renvoie le dossier dans lequel les backups sont effectué, ce dossier doit être en écriture.\r
+dossier_backups() ->\r
+   mnesia:system_info(directory) ++ "/backups/".\r
+\r
+\r
+% Renvoie le fichier (avec le chemin) correspondant à la version Version, par exemple : "/var/euphorik/BD/backups/backup1"\r
+fichier_backup(Version) when is_integer(Version) ->\r
+   dossier_backups() ++ "backup" ++ integer_to_list(Version).\r
+\r
+\r
+% crée un backup dont le nom est fournit dans le repertoire backups qui se trouve dans le repertoire de la BD.\r
+backup(Fichier) ->\r
+   mnesia:backup(dossier_backups() ++ Fichier).\r
+\r
+\r
+% Restaure un backup de la BD.\r
+restore(Fichier) when is_list(Fichier) ->\r
+   mnesia:restore(dossier_backups() ++ Fichier, []);\r
+% Reviens à une version précédente de la base de données.\r
+% (les données insérées durant les versions plus récentes sont perdues).\r
+restore(Version) when is_integer(Version) ->\r
+   mnesia:restore(fichier_backup(Version), []). % [{default_op, recreate_tables}]).\r
+\r
+\r
+% Change le nom du noeud d'un backup.\r
+% provient d'ici : http://www.erlang.org/doc/apps/mnesia/Mnesia_chap7.html#6.9\r
+% From : l'ancien nom\r
+% To : le nouveau nom\r
+% Source : le nom du fichier de backup\r
+% Target : le nom du fichier du nouveau backup\r
+change_node_name(From, To, Source, Target) ->\r
+    Switch =\r
+        fun(Node) when Node == From -> To;\r
+           (Node) when Node == To -> throw({error, already_exists});\r
+           (Node) -> Node\r
+        end,\r
+    Convert =\r
+        fun({schema, db_nodes, Nodes}, Acc) ->\r
+                {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};\r
+           ({schema, version, Version}, Acc) ->\r
+                {[{schema, version, Version}], Acc};\r
+           ({schema, cookie, Cookie}, Acc) ->\r
+                {[{schema, cookie, Cookie}], Acc};\r
+           ({schema, Tab, CreateList}, Acc) ->\r
+                Keys = [ram_copies, disc_copies, disc_only_copies],\r
+                OptSwitch =\r
+                    fun({Key, Val}) ->\r
+                            case lists:member(Key, Keys) of\r
+                                true -> {Key, lists:map(Switch, Val)};\r
+                                false-> {Key, Val}\r
+                            end\r
+                    end,\r
+                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};\r
+           (Other, Acc) ->\r
+                {[Other], Acc}\r
+        end,\r
+    mnesia:traverse_backup(Source, Target, Convert, switched).\r
+\r
+\r
+% Obsolète\r
+%~ backup_text(File) ->\r
+   %~ mnesia:dump_to_textfile(File).\r
+%~ restore_text(File) ->\r
+   %~ mnesia:stop(),\r
+   %~ mnesia:delete_schema([node()]),\r
+   %~ mnesia:start(),\r
+   %~ create_tables(),\r
+   %~ case mnesia:load_textfile(File) of\r
+      %~ {atomic, ok} ->\r
+         %~ update(),\r
+         %~ creer_indexes();\r
+      %~ Erreur ->\r
+         %~ Erreur\r
+   %~ end.\r
+\r
+\r
+toggle_ek_master(User_id) ->\r
+   euphorik_bd:resultat_transaction(mnesia:transaction(\r
+      fun() ->\r
+         Users = e(q([E || E <- mnesia:table(user), E#user.id =:= User_id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]),\r
+         case Users of\r
+            [User] ->\r
+               mnesia:write(User#user{ek_master = not User#user.ek_master});\r
+            _ -> erreur\r
+         end\r
+      end\r
+   )).\r
+\r
+\r
+% Affiche N user trié par leur date de dernière connexion.\r
+% Opt est une liste d'option d'affichage :\r
+%  * ekmaster : n'affiche que les admins\r
+print_users(N, Opt) ->\r
+   AfficheQueLesEkMaster = lists:any(fun(O) -> O =:= ekmaster end, Opt),\r
+   euphorik_bd:resultat_transaction(mnesia:transaction(fun() ->\r
+      C = cursor(\r
+         qlc:keysort(\r
+            #user.date_derniere_connexion,\r
+            if AfficheQueLesEkMaster ->\r
+               q([E || E <- mnesia:table(user), E#user.ek_master =:= true]);\r
+            true ->\r
+               q([E || E <- mnesia:table(user)])\r
+            end,\r
+            [{order, descending}]\r
+         ),\r
+         [{tmpdir, ?KEY_SORT_TEMP_DIR}]\r
+      ),\r
+      Users = qlc:next_answers(C, N),\r
+      lists:foreach(\r
+         fun(U) ->\r
+            print_user(U)\r
+         end,\r
+         Users\r
+      ),\r
+      qlc:delete_cursor(C)\r
+   end)).\r
+\r
+\r
+% Affiche tous les users.\r
+print_users(Opt) ->\r
+   print_users(all_remaining, Opt).\r
+\r
+% Affiche tous les users.\r
+print_users() ->\r
+   print_users(all_remaining, []).\r
+\r
+print_user(User) when is_record(User, user) ->\r
+   #user{id = Id, profile = #profile{pseudo = Pseudo}, login = Login, ek_master = Ek_master, date_derniere_connexion = Date, last_ip = IP} = User,\r
+   {{Annee, Mois, Jour}, {Heure, Min, _}} = calendar:now_to_local_time(Date),\r
+   io:format(\r
+      % id        pseudo     (login)        IP  Jour  Mois   Année  Heure Minute\r
+      "~4w : ~10.10..s(~10.10..s) ~s ~2w.~2.2.0w.~w - ~2wh~2.2.0w~n",\r
+      [\r
+         Id,\r
+         if Ek_master -> "*"; true -> "" end ++ Pseudo,\r
+         Login,\r
+         euphorik_common:serialize_ip(IP),\r
+         Jour, Mois, Annee, Heure, Min\r
+      ]\r
+   );\r
+% Affichage d'un user en fonction de son login\r
+print_user(Login) when is_list(Login) ->\r
+   case euphorik_bd:user_by_login(Login) of\r
+      {ok, User} ->\r
+         print_user(User);\r
+      _ ->\r
+         {erreur, "Login pas trouvé : " ++ Login}\r
+   end;\r
+% Affichage d'un user en fonction de son id\r
+print_user(Id) when is_integer(Id) ->\r
+   case euphorik_bd:user_by_id(Id) of\r
+      {ok, User} ->\r
+         print_user(User);\r
+      _ ->\r
+         {erreur, "Id pas trouvé : " ++ integer_to_list(Id)}\r
+   end.\r
+\r
index 3806df3..e516322 100644 (file)
@@ -15,8 +15,8 @@
 %
 % You should have received a copy of the GNU General Public License
 % along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
-% 
-% Module avec plein de bordel utile à l'intérieur.
+%
+% Module with some useful stuffs.
 % @author G.Burri
 
 
@@ -40,7 +40,7 @@ ceiling(X) ->
       Pos when Pos > 0 -> T + 1;
       _ -> T
    end.
-   
+
 
 % Retourne la difference entre deux timestamp (erlang:now()) en miliseconde
 delta_date_ms(D1, D2) ->
@@ -50,14 +50,14 @@ delta_date_ms(D1, D2) ->
 % Retourne la différence entre deux timestamp (erlang:now) en minutes
 delta_date_minute(D1, D2) ->
    trunc(delta_date_ms(D1, D2) / 1000 / 60).
-   
+
 
 serialize_ip(undefined) ->
    "<unknown IP>";
 serialize_ip(IP) ->
    lists:flatten(io_lib:format("~w.~w.~w.~w", tuple_to_list(IP))).
-   
-   
+
+
 unserialize_ip(IP) ->
    case io_lib:fread("~d.~d.~d.~d", IP) of
       {ok, [A, B, C, D], []} -> {A, B, C, D};
index 68765e7..b802bbe 100755 (executable)
@@ -15,9 +15,8 @@
 %\r
 % You should have received a copy of the GNU General Public License\r
 % along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
 % Module tournant en background s'occupant periodiquement de certaines tâches :\r
-%  - sélection du prochain troll chaque semaine\r
 %  - rechargement des modules lors d'une mise en production\r
 % Date : 05.11.2007\r
 % @author G.Burri\r
 start(_A) ->\r
    register(euphorik_daemon, self()),\r
    loop().\r
-   \r
-   \r
+\r
+\r
 loop() ->\r
-   % on attend une minute de plus pour prevenir une dérive négative (ce qui pourrait engendrer une double élection)\r
    receive\r
       switch -> % permet de substituer le code du process par un nouveau code, voir reload_euphorik\r
-         euphorik_daemon:loop()    \r
-      after 1000 * (trunc(temps_prochaine_election() + 60)) ->\r
-         euphorik_bd:elire_troll(),\r
          euphorik_daemon:loop()\r
    end.\r
 \r
-   \r
-% Renvoie le nombre de seconde qu'il reste jusque au prochain lundi à l'heure donnée (l'heure est sur 24heures)\r
-% 86400 est le nombre de seconde dans un jour\r
-temps_prochaine_election() ->\r
-   {Date, {H,M,S}} = calendar:local_time(),\r
-   Delta = (?JOUR_ELECTION_TROLL - 1) * 86400 + ?HEURE_ELECTION_TROLL * 60 * 60\r
-      -((calendar:day_of_the_week(Date) - 1) * 86400 + H * 60 * 60 + M * 60 + S),\r
-   % attention au cas où deux dates (maintenant et la date d'élection) ne se trouvent pas dans la même semaine.\r
-   if Delta =< 0 -> Delta + 7 * 86400; true -> Delta end.\r
-\r
-\r
 % Recharge tous les modules euphorik.\r
 % Appelé lors d'une mise en prod.\r
 % TODO : récupérer les noms à partir des .beam dans /modules/ebin\r
@@ -76,4 +60,3 @@ reload_euphorik() ->
    % changement du code du daemon\r
    euphorik_daemon ! switch,\r
    ok.\r
-   
\ No newline at end of file
index 5cf9a0a..156eaac 100755 (executable)
 %\r
 % You should have received a copy of the GNU General Public License\r
 % along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
 % Ce module permet la gestion des conversations du minichat d'euphorik.\r
 % Un message (enfant) peut répondre à des messages (ses parents).\r
 % Un message (parent) peut avoir plusieurs réponses (enfants)\r
 % @author G.Burri\r
-% \r
+%\r
 % Les conversation se compose d'une liste de tuple comprenant la conversation, du premier message de la conversation,\r
 % et d'un booleen indiquant s'il y a encore des messages\r
 % @type Conversations() = [{Conversation(), Message(), bool()}]\r
-% \r
+%\r
 % Une conversation est simplement une liste de messages\r
 % @type Conversation() = [Message()]\r
 %\r
 % Un message est un tuple représentant le message et la liste des id\r
 % des messages auquels il répond\r
 % @type Message() = {#minichat, [int()]}\r
-
+\r
 \r
 -module(euphorik_minichat_conversation).\r
 -export([\r
@@ -42,8 +42,8 @@
 -import(lists, [reverse/1, any/2, map/2, sublist/3, filter/2]).\r
 -import(euphorik_bd, [resultat_transaction/1]).\r
 -import(mnesia, [table/1, transaction/1]).\r
-  \r
-   \r
+\r
+\r
 % Renvoie les conversations.\r
 % Chaque racine est un tuple {R, P, D}\r
 % R : l'id de la racine\r
@@ -69,7 +69,7 @@ conversations(Racines, N, D, P) ->
          true ->\r
             mise_en_forme_conversations(Conversations)\r
       end.\r
-     \r
+\r
 \r
 % Mise en forme des conversations pour l'utilisateur du module.\r
 % @type Conversation_principale() = {[integer()], bool}\r
@@ -78,8 +78,8 @@ conversations(Racines, N, D, P) ->
 mise_en_forme_conversations([]) -> [];\r
 mise_en_forme_conversations([{Principale, Plus_principale} | Conversations]) ->\r
    [{mise_en_forme_conversation(Principale), Plus_principale} | map(fun({_, Cn, _, Plus}) -> {mise_en_forme_conversation(Cn), Plus} end, Conversations)].\r
-   \r
-   \r
+\r
+\r
 % Mise en forme d'une liste d'id de messages : [4, 9, 8, ...] -> [{#minichat, [5, 6]}, ...].\r
 % Ajoute les parents de chaque message.\r
 % @spec mise_en_forme_conversation([integer()]) -> [{#minichat, [integer()]}]\r
@@ -101,20 +101,20 @@ mise_en_forme_conversation(Messages) ->
       end\r
    )).\r
 \r
-   \r
+\r
 % Renvoie une liste de conversations, le première élément correspond à la conversation principale.\r
 % Les autres éléments sont des tuples {C, Cn, X, Plus}, voir conversation/4 pour plus d'infos.\r
 % Racines est une liste de tuple {Id, P} des racines des conversations ou P est la page et Id l'id du message.\r
 % @spec conversations_detailees([{integer(), integer()}], integer(), integer(), integer()) -> [[{integer(), bool()}] | Conversation_detailee()]\r
-conversations_detailees(Racines, N, D, P) ->   \r
+conversations_detailees(Racines, N, D, P) ->\r
    Conversations = map(fun({Racine, P_conv, Dernier}) -> conversation(Racine, N, Dernier, P_conv) end, Racines),\r
-   Conversation_principale = resultat_transaction(transaction(fun() ->
+   Conversation_principale = resultat_transaction(transaction(fun() ->\r
       Dernier_id = mnesia:table_info(minichat, size),\r
       {CP, Plus} = conversation_principale(Dernier_id, Conversations, N, P),\r
       {[M || M <- CP, M > D], Plus} % filtre en fonction de D\r
    end)),\r
    [Conversation_principale | Conversations].\r
-   \r
+\r
 \r
 % Construit la conversation principale en fonction d'un id de message initialement placé sur le dernier message\r
 % et la liste de conversations.\r
@@ -134,28 +134,28 @@ conversation_principale(Id, Conversations, N, P) ->
       end,\r
       Plus\r
    }.\r
-      \r
-      \r
+\r
+\r
 % Id est l'id d'un message, voir ce dessus\r
 % 'Messages' sont les messages que l'on doit enlever de la conversation\r
 % S est le nombre de messages qu'il faut sauter.\r
 % @spec conversation_principale2(integer(), [integer()], integer(), integer()) -> [integer()]\r
 conversation_principale2(_, _, 0, _) ->\r
-   [];
+   [];\r
 conversation_principale2(0, _, _, _) ->\r
    [];\r
-conversation_principale2(Id, Messages, N, S) ->
+conversation_principale2(Id, Messages, N, S) ->\r
    % traitement message par message (pas des plus performant :/)\r
    Doit_etre_saute = any(fun(E) -> E == Id end, Messages),\r
-   if  Doit_etre_saute -> \r
+   if  Doit_etre_saute ->\r
          conversation_principale2(Id - 1, Messages, N, S); % le message ne fait pas partie de la conversation\r
       S =:= 0 ->\r
          [Id | conversation_principale2(Id - 1, Messages, N - 1, S)]; % ok : le message fait partie de la conversation\r
       true ->\r
          conversation_principale2(Id - 1, Messages, N, S - 1) % on n'a pas encore atteint le début de la page\r
       end.\r
-   \r
-   \r
+\r
+\r
 % Renvoie un tuple {C, Cn, X, Plus} où\r
 % C : La conversation complète\r
 % Cn : La conversation tronqué en fonction de N, D et P\r
@@ -181,10 +181,10 @@ conversation(R, N, D, P) ->
             )\r
       end,\r
       reverse(X),\r
-      Decalage + N - 1 < length(C) \r
+      Decalage + N - 1 < length(C)\r
    }.\r
-   \r
-   \r
+\r
+\r
 % Renvoie un tuple {C, X} où C est la conversation complète et X les messages répondant à des mess qui ne font pas partie de la conversation\r
 % Attention : les messages de C et de X sont ordrés du plus grand Id au plus petit.\r
 % @spec conversation([integer()], [integer()], [integer()]) -> {[int()], [int()]}\r
@@ -201,7 +201,7 @@ conversation(Conv, [M | Reste], X) ->
    end;\r
 conversation(Messages, [], X) ->\r
    {Messages, X}.\r
-   \r
+\r
 \r
 % Intersection entre deux listes : [1, 3, 4] n [2, 4, 7] = [4]\r
 % @spec intersection(list(term()), list(term())) -> list(term())\r
index 947a18b..ad80c27 100755 (executable)
@@ -15,7 +15,7 @@
 %\r
 % You should have received a copy of the GNU General Public License\r
 % along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
 % Ce module gére les différents messages envoyés par le client (javascript) via AJAX.\r
 % Les messages donnés ainsi que les réponses sont au format JSON.\r
 % @author G.Burri\r
@@ -30,9 +30,6 @@
    put_message/1,\r
    ban/1,\r
    slap/1,\r
-   put_troll/1,\r
-   mod_troll/1,\r
-   del_troll/1,\r
    unban_ip/1,\r
    list_banned_ips/1,\r
    erreur/1\r
@@ -57,7 +54,7 @@ register([{login, Login}, {password, Password}, {profile, Profile_json}], IP) ->
          erreur_register_flood()\r
    end;\r
 % Enregistrement sans {Login, Password}\r
-register([{profile, Profile_json}], IP) ->   \r
+register([{profile, Profile_json}], IP) ->\r
    Can_register = euphorik_bd:can_register(IP),\r
    if Can_register ->\r
          Profile = profile_from_json(Profile_json),\r
@@ -67,17 +64,17 @@ register([{profile, Profile_json}], IP) ->
       true ->\r
          erreur_register_flood()\r
    end.\r
-   \r
+\r
 erreur_register_flood() ->\r
    erreur(20).\r
-   \r
+\r
 \r
 % Un utilisateur se logge (avec un couple {login, mot de passe})\r
 login([{login, Login}, {password, Password}], IP) ->\r
    case euphorik_bd:user_by_login_password(Login, Password) of\r
       {ok, User} ->\r
          loginUser(User, IP);\r
-      _ -> \r
+      _ ->\r
          timer:sleep(?TEMPS_ATTENTE_ERREUR_LOGIN),\r
          erreur(30)\r
    end;\r
@@ -90,15 +87,15 @@ login([{cookie, Cookie}], IP) ->
          timer:sleep(?TEMPS_ATTENTE_ERREUR_LOGIN),\r
          erreur(40)\r
    end.\r
-   \r
-   \r
+\r
+\r
 % L'utilisateur donné se logge avec l'ip donnée.\r
 loginUser(User, IP) ->\r
    euphorik_bd:update_ip(User#user.id, IP),\r
    euphorik_bd:update_date_derniere_connexion(User#user.id),\r
    json_reponse_login_ok(User).\r
-   \r
-   \r
+\r
+\r
 % Renvoie un string() représentant un cookie en base 36. Il y a 10^32 possibillités.\r
 generer_cookie() ->\r
    {A1, A2, A3} = now(),\r
@@ -164,12 +161,12 @@ profile_from_json(
    Chat_order_valide = lists:any(fun(E) -> E =:= Chat_order end, [reverse, chrono]),\r
    if not Chat_order_valide ->\r
          {erreur, Chat_order_str ++ " n'est pas une valeur acceptée pour 'chat_order'"};\r
-      true -> \r
+      true ->\r
          Nick_format = list_to_atom(Nick_format_str),\r
          Nick_format_valide = lists:any(fun(E) -> E =:= Nick_format end, [nick, login, nick_login]),\r
          if not Nick_format_valide ->\r
                {erreur, Nick_format_str ++ " n'est pas une valeur acceptée pour 'nick_format'"};\r
-            true -> \r
+            true ->\r
                Ostentatious_master = list_to_atom(Ostentatious_master_str),\r
                Ostentatious_master_valide = lists:any(fun(E) -> E =:= Ostentatious_master end, [invisible, light, heavy]),\r
                if not Ostentatious_master_valide ->\r
@@ -187,7 +184,7 @@ profile_from_json(
                         ostentatious_master = Ostentatious_master\r
                      }\r
                end\r
-         end      \r
+         end\r
    end.\r
 \r
 \r
@@ -199,7 +196,6 @@ wait_event([{page, "chat"} | Data]) ->
    Last_message_id = case lists:keysearch(last_message_id, 1, Data) of {value, {_, Id}} -> Id; _ -> 0 end,\r
    {value, {_, Message_count}} = lists:keysearch(message_count, 1, Data),\r
    Main_page = case lists:keysearch(main_page, 1, Data) of {value, {_, P}} -> P; _ -> 1 end,\r
-   Troll_id = case lists:keysearch(troll_id, 1, Data) of {value, {_, T}} -> T; _ -> 0 end,\r
    {value, {_, {array, Conversations_json}}} = lists:keysearch(conversations, 1, Data),\r
    Racines_conversations = lists:map(\r
       fun({struct, [{root, Racine}, {page, Page} | Reste]}) ->\r
@@ -212,62 +208,23 @@ wait_event([{page, "chat"} | Data]) ->
       {ok, U} -> U;\r
       _ -> inconnu\r
    end,\r
-   case {mnesia:subscribe({table, minichat, detailed}), mnesia:subscribe({table, troll, detailed})} of\r
-      {{error, E}, _} -> E;\r
-      {_, {error, E}} -> E;\r
+   case mnesia:subscribe({table, minichat, detailed}) of\r
+      {error, E} -> E;\r
       _ ->\r
          % attente d'événements\r
-         R = wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id),\r
+         R = wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page),\r
          mnesia:unsubscribe({table, minichat, detailed}),\r
-         mnesia:unsubscribe({table, troll, detailed}),\r
          R\r
    end;\r
 % Attend un événement pour la page "Admin"\r
-wait_event([{page, "admin"}, {last_troll, Last_troll}]) ->\r
-   case wait_event_page_admin(Last_troll) of\r
+wait_event([{page, "admin"}]) ->\r
+   case wait_event_page_admin() of\r
       banned_ips_refresh ->\r
-         {struct, \r
-            [\r
-               {reply, "banned_ips_refresh"}\r
-            ]\r
-         };\r
-      {mod, Troll} ->\r
          {struct,\r
             [\r
-               {reply, "troll_modified"},\r
-               {troll_id, Troll#troll.id},\r
-               {content, Troll#troll.content}\r
+               {reply, "banned_ips_refresh"}\r
             ]\r
          };\r
-      {add, Trolls} ->\r
-         {struct,\r
-            [\r
-               {reply, "troll_added"},\r
-               {trolls, {array, \r
-                  lists:map(\r
-                     fun(T) ->                        \r
-                        {ok, #user{profile = Profile} = User} = euphorik_bd:user_by_id(T#troll.id_user),\r
-                        {struct,\r
-                           [\r
-                              {troll_id, T#troll.id},\r
-                              {content, T#troll.content},\r
-                              {author, Profile#profile.pseudo},\r
-                              {author_id, User#user.id}\r
-                           ]\r
-                        }\r
-                     end,\r
-                     Trolls\r
-                  )\r
-               }}\r
-            ]\r
-         };         \r
-      {del, Troll_id} ->\r
-         {struct,\r
-            [\r
-               {reply, "troll_deleted"},\r
-               {troll_id, Troll_id}\r
-            ]\r
-         };                  \r
       _ ->\r
          erreur(60)\r
    end;\r
@@ -275,71 +232,60 @@ wait_event(_) ->
    erreur(70).\r
 \r
 \r
-% Attend un événement pour la page "Chat" et renvoie soit un troll soit les messages manquants au client.\r
-wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id) ->\r
-   % est-ce que le troll est à jour ?\r
-   case euphorik_bd:current_troll() of\r
-      Current when is_record(Current, troll), Current#troll.id =/= Troll_id ->\r
-         {struct, [\r
-            {reply, "new_troll"},\r
-            {troll_id, Current#troll.id},\r
-            {message_id, Current#troll.id_minichat},\r
-            {content, Current#troll.content}\r
-         ]};\r
-      _ ->\r
-         % est-ce qu'il y a des nouveaux messages ?\r
-         case euphorik_minichat_conversation:conversations(Racines_conversations, Message_count, Last_message_id, Main_page) of\r
-            vide ->            \r
-               wait_event_bd_page_chat(),\r
-               wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id);\r
-            Conversations ->\r
-               % accrochez-vous ca va siouxer ;)\r
-               {struct, [\r
-                  {reply, "new_messages"},\r
-                  {conversations, {array,\r
-                     lists:map(\r
-                        fun({Racine, {Conv, Plus}}) ->\r
-                           {struct, [\r
-                              {last_page, not Plus},\r
-                              {first, % le premier message de la conversation\r
-                                 if Racine =:= undefined orelse Conv =:= [] ->\r
-                                       null;\r
-                                    true ->\r
-                                       {Racine_id, _, _} = Racine,\r
-                                       case euphorik_bd:message_by_id(Racine_id) of\r
-                                          {ok, Mess} ->\r
-                                             json_message(Mess, euphorik_bd:parents_id(Racine_id), User);\r
-                                          _ ->\r
-                                             null\r
-                                       end\r
-                                 end\r
-                              },\r
-                              {messages, {array,\r
-                                 lists:map(\r
-                                    fun({Mess, Repond_a}) ->\r
-                                       json_message(Mess, Repond_a, User)\r
-                                    end,\r
-                                    Conv\r
-                                 )\r
-                              }}\r
-                           ]}\r
-                        end,\r
-                        % on ajoute un 'undefined' correspondant à la premier conversation qui ne possède pas de racine\r
-                        % TODO : peut être à revoir car un peu lourd est compliqué\r
-                        aggregation_racines_conversations([undefined | Racines_conversations], Conversations)\r
-                     )\r
-                  }}\r
-               ]}\r
-         end\r
+% Attend un événement pour la page "Chat" et renvoie les messages manquants au client.\r
+wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page) ->\r
+      % est-ce qu'il y a des nouveaux messages ?\r
+      case euphorik_minichat_conversation:conversations(Racines_conversations, Message_count, Last_message_id, Main_page) of\r
+         vide ->\r
+            wait_event_bd_page_chat(),\r
+            wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page);\r
+         Conversations ->\r
+            % Accrochez-vous ca va siouxer ;).\r
+            {struct, [\r
+               {reply, "new_messages"},\r
+               {conversations, {array,\r
+                  lists:map(\r
+                     fun({Racine, {Conv, Plus}}) ->\r
+                        {struct, [\r
+                           {last_page, not Plus},\r
+                           {first, % le premier message de la conversation\r
+                              if Racine =:= undefined orelse Conv =:= [] ->\r
+                                    null;\r
+                                 true ->\r
+                                    {Racine_id, _, _} = Racine,\r
+                                    case euphorik_bd:message_by_id(Racine_id) of\r
+                                       {ok, Mess} ->\r
+                                          json_message(Mess, euphorik_bd:parents_id(Racine_id), User);\r
+                                       _ ->\r
+                                          null\r
+                                    end\r
+                              end\r
+                           },\r
+                           {messages, {array,\r
+                              lists:map(\r
+                                 fun({Mess, Repond_a}) ->\r
+                                    json_message(Mess, Repond_a, User)\r
+                                 end,\r
+                                 Conv\r
+                              )\r
+                           }}\r
+                        ]}\r
+                     end,\r
+                     % on ajoute un 'undefined' correspondant à la premier conversation qui ne possède pas de racine\r
+                     % TODO : peut être à revoir car un peu lourd est compliqué\r
+                     aggregation_racines_conversations([undefined | Racines_conversations], Conversations)\r
+                  )\r
+               }}\r
+            ]}\r
    end.\r
-   \r
 \r
-aggregation_racines_conversations(L1, L2) -> \r
+\r
+aggregation_racines_conversations(L1, L2) ->\r
    aggregation_racines_conversations(L1, L2, []).\r
 aggregation_racines_conversations([], [], L) -> lists:reverse(L);\r
 aggregation_racines_conversations([E1|R1], [E2|R2], L) ->\r
    aggregation_racines_conversations(R1, R2, [{E1, E2} | L]).\r
-   \r
+\r
 \r
 \r
 % Attend un événement lié à la page 'chat'.\r
@@ -347,71 +293,42 @@ wait_event_bd_page_chat() ->
    receive % attente d'un post\r
       {mnesia_table_event, {write, minichat, _Message, [], _}} ->\r
          ok;\r
-      {mnesia_table_event, {write, troll, Troll, [Old_troll | _], _}} when Troll#troll.date_post =/= undefined, Old_troll#troll.date_post == undefined ->\r
-         ok;\r
       {tcp_closed, _} ->\r
          exit(normal);\r
       _ ->\r
          wait_event_bd_page_chat()\r
    % 60 minutes de timeout (on ne sais jamais)\r
    % Après 60 minutes de connexion, le client doit donc reétablir une connexion\r
-   after 1000 * 60 * 60 -> \r
+   after 1000 * 60 * 60 ->\r
       timeout\r
    end.\r
 \r
 \r
 % Attent un événement concernant la page admin\r
-% Renvoie les trolls manquants posté après Last_id ou banned_ips_refresh.\r
-% Si pas de trolls alors attend un événement tel qu'un ajout, une modification ou une suppression.\r
-% renvoie :\r
-%  {mod, Troll}\r
-% ou {add, [Trolls]}\r
-% ou {del, Troll_id}\r
-% ou banned_ips_refresh\r
+% banned_ips_refresh\r
 % ou timeout\r
-wait_event_page_admin(Last_id) ->\r
-   case {mnesia:subscribe({table, troll, detailed}), mnesia:subscribe({table, ip_table, detailed})} of\r
-      {{error, E}, _ } -> E;\r
-      {_, {error, E}} -> E;\r
-      _ ->\r
-         R = case euphorik_bd:trolls(Last_id) of\r
-               [] -> % pas de trolls\r
-                  wait_event_page_admin();\r
-               Trolls ->\r
-                  {add, Trolls}\r
-         end,\r
-         mnesia:unsubscribe({table, troll, detailed}),\r
-         mnesia:unsubscribe({table, ip_table, detailed}),\r
-         R\r
-   end.\r
-   \r
 wait_event_page_admin() ->\r
-   % s'il n'y a pas de trolls que l'utilisateur n'a pas connaissance alors on attend un événement\r
-   receive\r
-      % cas où un troll est choisit comme courant\r
-      {mnesia_table_event, {write, troll, Troll, [Old_troll | _], _}}\r
-         when Old_troll#troll.date_post =:= undefined, Troll#troll.date_post =/= undefined ->\r
-         {del, Troll#troll.id};\r
-      {mnesia_table_event, {write, troll, Troll, [_Old_troll | _], _}} ->\r
-         {mod, Troll};\r
-      {mnesia_table_event, {write, troll, Troll, [], _}} ->\r
-         {add, [Troll]};\r
-      {mnesia_table_event, {delete, troll, {troll, Id}, _, _}} ->\r
-         {del, Id};\r
-      {mnesia_table_event, {write, ip_table, IP, [Old_IP | _], _}}\r
-         when Old_IP#ip_table.ban =/= IP#ip_table.ban; Old_IP#ip_table.ban_duration =/= IP#ip_table.ban_duration ->\r
-         banned_ips_refresh;\r
-      {tcp_closed, _} ->\r
-         exit(normal);\r
+   case mnesia:subscribe({table, ip_table, detailed}) of\r
+      {error, E} -> E;\r
       _ ->\r
-         wait_event_page_admin()\r
-   % 60 minutes de timeout (on ne sais jamais)\r
-   % Après 60 minutes de connexion, le client doit donc reétablir une connexion\r
-   after 1000 * 60 * 60 -> \r
-      timeout\r
+      R = receive\r
+         {mnesia_table_event, {write, ip_table, IP, [Old_IP | _], _}}\r
+            when Old_IP#ip_table.ban =/= IP#ip_table.ban; Old_IP#ip_table.ban_duration =/= IP#ip_table.ban_duration ->\r
+            banned_ips_refresh;\r
+         {tcp_closed, _} ->\r
+            exit(normal);\r
+         _ ->\r
+            wait_event_page_admin()\r
+         % 60 minutes de timeout (on ne sais jamais)\r
+         % Après 60 minutes de connexion, le client doit donc reétablir une connexion\r
+      after 1000 * 60 * 60 ->\r
+         timeout\r
+      end,\r
+      mnesia:unsubscribe({table, ip_table, detailed}),\r
+      R\r
    end.\r
-         \r
-         \r
+\r
+\r
 % Un utilisateur envoie un message\r
 % Answer_to est une liste d'id (int)\r
 put_message(\r
@@ -480,7 +397,7 @@ ban(
          _ ->\r
             erreur(150)\r
       end.\r
-      \r
+\r
 \r
 % slapage d'un user (avertissement)\r
 slap(\r
@@ -494,7 +411,7 @@ slap(
          {ok, User1 = #user{ek_master = true, profile = Profile1}} ->\r
             case euphorik_bd:user_by_id(User_id) of\r
                {ok, User1} ->\r
-                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s s'auto slap~s.", \r
+                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s s'auto slap~s.",\r
                      [\r
                         Profile1#profile.pseudo,\r
                         if Reason =/= [] -> " - Raison: " ++ Reason; true -> "" end\r
@@ -518,75 +435,8 @@ slap(
          _ ->\r
             erreur(170)\r
       end.\r
-      \r
\r
-put_troll(\r
-   [\r
-      {cookie, Cookie},\r
-      {content, Content}\r
-   ]\r
-) ->\r
-   % controle que l'utilisateur est un admin\r
-   case euphorik_bd:user_by_cookie(Cookie) of\r
-      {ok, User = #user{ek_master = true}} ->\r
-         case euphorik_bd:put_troll(User#user.id, Content) of\r
-            max_troll_reached_per_user ->\r
-               erreur(180, [?NB_MAX_TROLL_WAITING_BY_USER]);\r
-            max_troll_reached ->\r
-               erreur(190, [?NB_MAX_TROLL_WAITING]);\r
-            _Id ->\r
-               json_reponse_ok()\r
-         end;\r
-      _ ->\r
-         erreur(200)\r
-   end.\r
-   \r
-   \r
-mod_troll(\r
-   [\r
-      {cookie, Cookie},\r
-      {troll_id, Troll_id},\r
-      {content, Content}\r
-   ]\r
-) ->\r
-   % controle que l'utilisateur est un admin\r
-   case euphorik_bd:user_by_cookie(Cookie) of\r
-      {ok, User = #user{ek_master = true}} ->\r
-         User_id = User#user.id,\r
-         case euphorik_bd:troll_by_id(Troll_id) of\r
-            {ok, #troll{id_user = User_id}} ->\r
-               euphorik_bd:mod_troll(Troll_id, Content),\r
-               json_reponse_ok();\r
-            _ ->\r
-               erreur(210)\r
-         end;\r
-      _ ->\r
-         erreur(220)\r
-      end.\r
 \r
-   \r
-del_troll(\r
-   [\r
-      {cookie, Cookie},\r
-      {troll_id, Troll_id}\r
-   ]\r
-) -> \r
-   % controle que l'utilisateur est un admin\r
-   case euphorik_bd:user_by_cookie(Cookie) of\r
-      {ok, User = #user{ek_master = true}} ->\r
-         User_id = User#user.id,\r
-         case euphorik_bd:troll_by_id(Troll_id) of\r
-            {ok, #troll{id_user = User_id}} ->\r
-               euphorik_bd:del_troll(Troll_id),\r
-               json_reponse_ok();\r
-            _ ->\r
-               erreur(210)\r
-         end;\r
-      _ ->\r
-         erreur(220)\r
-   end.\r
-   \r
-   \r
+\r
 unban_ip(\r
    [\r
       {cookie, Cookie},\r
@@ -600,8 +450,8 @@ unban_ip(
       _ ->\r
          erreur(230)\r
    end.\r
-   \r
-   \r
+\r
+\r
 list_banned_ips(\r
    [\r
       {cookie, Cookie}\r
@@ -645,12 +495,12 @@ list_banned_ips(
 % Construit une erreur\r
 erreur(Num, Args) ->\r
    erreur_json(Num, lists:flatten(io_lib:format(euphorik_bd:get_texte(Num), Args))).\r
-   \r
-   \r
+\r
+\r
 erreur(Num) ->\r
    erreur_json(Num, euphorik_bd:get_texte(Num)).\r
-   \r
-   \r
+\r
+\r
 erreur_json(Num, Mess) ->\r
    {\r
       struct, [\r
@@ -659,8 +509,8 @@ erreur_json(Num, Mess) ->
          {error_message, Mess}\r
       ]\r
    }.\r
-   \r
-   \r
+\r
+\r
 % Formatage de minutes.\r
 % par exemple : "1min", "45min", "1h23min", "1jour 2h34min"\r
 format_minutes(Min) ->\r
@@ -674,8 +524,8 @@ format_minutes(Min) ->
       true ->\r
          " " ++ integer_to_list(Minutes) ++ " minute"  ++ if Minutes > 1 -> "s"; true -> "" end\r
    end.\r
-   \r
-   \r
+\r
+\r
 % Formatage d'une heure\r
 % local_time() -> string\r
 format_date(Date) ->\r
@@ -690,7 +540,7 @@ format_date(Date) ->
          Hier ->\r
             "Hier ";\r
          Annee =:= AnneeNow ->\r
-            io_lib:format("~2.10.0B/~2.10.0B ", [Jour, Mois]);         \r
+            io_lib:format("~2.10.0B/~2.10.0B ", [Jour, Mois]);\r
          true ->\r
             io_lib:format("~2.10.0B/~2.10.0B/~B ", [Jour, Mois, Annee])\r
       end ++\r
@@ -700,8 +550,8 @@ format_date(Date) ->
 \r
 json_reponse_ok() ->\r
    {struct, [{reply, "ok"}]}.\r
-   \r
-   \r
+\r
+\r
 json_reponse_login_ok(#user{profile = Profile} = User) ->\r
    {\r
       struct, [\r
@@ -731,7 +581,7 @@ json_reponse_login_ok(#user{profile = Profile} = User) ->
          }}\r
       ]\r
    }.\r
-   \r
+\r
 % Renvoie le message formaté en JSON.\r
 % Mess est de type #minichat\r
 % Repond_a est une liste d'id des messages auquel répond Mess\r
@@ -754,7 +604,7 @@ json_message(Mess, Repond_a, User) ->
       {content, Mess#minichat.contenu},\r
       {root, Mess#minichat.racine_id},\r
       {answer_to, {array, lists:map(\r
-         fun(Id_mess) ->  \r
+         fun(Id_mess) ->\r
             {ok, M} = euphorik_bd:message_by_id(Id_mess),\r
             {ok, User_reponse} = euphorik_bd:user_by_mess(M#minichat.id),\r
             {struct, [{id, M#minichat.id}, {nick, M#minichat.pseudo}, {login, User_reponse#user.login}]}\r
index 3ec70f3..42fb87f 100755 (executable)
@@ -15,7 +15,7 @@
 %\r
 % You should have received a copy of the GNU General Public License\r
 % along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
 % Ce module est fait pour répondre à des requêtes JSON via 'AJAX'.\r
 % Il est définit comme 'appmods' pour l'url "request" dans Yaws.\r
 % Par exemple http://www.euphorik.ch/request abouti sur la fonction out/1 de ce module.\r
 \r
 -module(euphorik_requests).\r
 -export([out/1]).\r
--include_lib("yaws/include/yaws_api.hrl").\r
+-include_lib("yaws_api.hrl").\r
 -include("../include/euphorik_defines.hrl").\r
 \r
 \r
 % Point d'entrée pour les requêtes AJAX sur http://www.euphorik.ch/request.\r
-out(A) ->      \r
+out(A) ->\r
    IP = case inet:peername(A#arg.clisock) of\r
       {ok, {Adresse, _Port}} -> Adresse;\r
       _ -> inconnue\r
@@ -55,7 +55,7 @@ traiter_message(Contenu, IP) ->
             )))\r
       end\r
    ).\r
-   \r
+\r
 \r
 % Authentification d'un client.\r
 traiter_action("authentification", JSON, IP) ->\r
@@ -78,19 +78,9 @@ traiter_action("ban", JSON, _) ->
 % Un ekMaster slap un utilisateur.\r
 traiter_action("slap", JSON, _) ->\r
    euphorik_protocole:slap(JSON);\r
-% Un ekMaster envoie un nouveau troll.\r
-traiter_action("put_troll", JSON, _) ->\r
-   euphorik_protocole:put_troll(JSON);\r
-% Un ekMaster modifie un troll.\r
-traiter_action("mod_troll", JSON, _) ->\r
-   euphorik_protocole:mod_troll(JSON);\r
-% Un ekMaster supprime un troll.\r
-traiter_action("del_troll", JSON, _) ->\r
-   euphorik_protocole:del_troll(JSON);\r
 % Un ekMaster demande la liste des ips bannies.\r
 traiter_action("list_banned_ips", JSON, _) ->\r
    euphorik_protocole:list_banned_ips(JSON);\r
 % Un ekMaster débannie une ip.\r
 traiter_action("unban", JSON, _) ->\r
    euphorik_protocole:unban_ip(JSON).\r
\ No newline at end of file
index 2cbc1ec..7b2d9a1 100644 (file)
-% coding: utf-8
-% Copyright 2008 Grégory Burri
-%
-% This file is part of Euphorik.
-%
-% Euphorik is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Euphorik is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
-%
-% Module de test de euphorik.
-% Crée un certain nombre d'utilisateur et post des messages aléatoire.
-
-
--module(euphorik_test).
--export([
-   bench_write_minichat/1,
-   start/2,
-   stop/1,
-   bench_get_messages/0,
-   bench_get_messages_avec_2_conversations/0
-]).
--include("../include/euphorik_bd.hrl").
+% coding: utf-8\r
+% Copyright 2008 Grégory Burri\r
+%\r
+% This file is part of Euphorik.\r
+%\r
+% Euphorik is free software: you can redistribute it and/or modify\r
+% it under the terms of the GNU General Public License as published by\r
+% the Free Software Foundation, either version 3 of the License, or\r
+% (at your option) any later version.\r
+%\r
+% Euphorik is distributed in the hope that it will be useful,\r
+% but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+% GNU General Public License for more details.\r
+%\r
+% You should have received a copy of the GNU General Public License\r
+% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
+%\r
+% Module de test de euphorik.\r
+% Crée un certain nombre d'utilisateur et post des messages aléatoire.\r
+\r
+\r
+-module(euphorik_test).\r
+-export([\r
+   bench_write_minichat/1,\r
+   start/2,\r
+   stop/1,\r
+   bench_get_messages/0,\r
+   bench_get_messages_avec_2_conversations/0\r
+]).\r
+-include("../include/euphorik_bd.hrl").\r
 \r
 % les intervalles en seconde min en max entre deux postes de message d'un utilisateur\r
 % le temps d'attente est choisi au hasard entre ces deux valeurs\r
 -define(INTERVALLE_MIN, 2).\r
--define(INTERVALLE_MAX, 5).
-
-
-% N est le nombre d'utilisateur
-% M est le nombre de message que chaque utilisateur va poster
-start(N, M) ->
-   Ids = creer_users(N),
-   lists:map(
-      fun(Id) ->
-         timer:sleep(100),
-         spawn(
-            fun() -> 
-               {A1, A2, A3} = now(),
-               random:seed(A1, A2, A3),
-               loop(Id, M)
-            end
-         )
-      end,
-      Ids
-   ).
-   
-stop(Pids) ->
-   lists:foreach(fun(Pid) -> exit(Pid, kill) end, Pids).
-   
-% des trucs qui trainent
-bench_get_messages() ->
-   T = [
-      {page,"chat"},
-      {cookie,"5G84A5CJXMCPEHNI8T5A9"},
-      {message_count,40},
-      {last_message_id,0},
-      {main_page,1},
-      {troll_id,0},
-      {conversations,{array,[]}}
-   ],
-   moyenne_temps(euphorik_protocole, wait_event, [T], 20).
-bench_get_messages_avec_2_conversations() ->
-   T = [
-      {page,"chat"},
-      {cookie,"5G84A5CJXMCPEHNI8T5A9"},
-      {message_count,40},
-      {last_message_id,0},
-      {main_page,1},
-      {troll_id,0},
-      {conversations,{array, [
-         {struct, [
-            {root, 921},
-            {page,1},
-            {last_message_id,0}
-         ]},
-         {struct, [
-            {root, 772},
-            {page, 1},
-            {last_message_id, 0}
-         ]}
-      ]}}
-   ],
-   moyenne_temps(euphorik_protocole, wait_event, [T], 20).
-moyenne_temps(Module, Fun, Args, N) ->
-   moyenne_temps(Module, Fun, Args, N, N, 0).
-moyenne_temps(_, _, _, 0, Total, Temps_acc) ->
-   Temps_acc / Total;
-moyenne_temps(Module, Fun, Args, N, Total, Temps_acc) ->
-   {Temps, _} = timer:tc(Module, Fun, Args),
-   moyenne_temps(Module, Fun, Args, N - 1, Total, Temps_acc + Temps).
-   
-   
-% Crée N user avec des noms aléatoires et renvoie la liste des id.
-creer_users(N) ->
-   creer_users(N, []).
-creer_users(0, Ids) -> lists:map(fun(#user{id = Id}) -> Id end, Ids);
-creer_users(N, Ids) ->
-   creer_users(N - 1, [euphorik_bd:nouveau_user(mot_rand(random:uniform(4) + 4), "", "", #profile{}) | Ids ]).
-
-
-% crée un message aléatoire et le renvoie
-message_rand() ->
-   lists:flatten(message_rand(random:uniform(10), [])).
-message_rand(0, Mots) -> Mots;
-message_rand(N, Mots) -> 
-   message_rand(N - 1, [mot_rand(random:uniform(2) + 5), $  | Mots]).
-
-
-% Renvoie une succession de lettre aléatoire
-mot_rand(L) ->
-   mot_rand(L, []).
-mot_rand(0, Mot) -> Mot;
-mot_rand(L, Mot) ->
-   mot_rand(L - 1, [random:uniform($z - $a + 1) + $a - 1 | Mot]).
-   
-
-% Tire au hasard de 0 à 3 messages sur les 10 derniers postés, renvoie une liste de int()
-% répartition : 
-%  0 : 0.1
-%  1 : 0.95
-%  2 : 0.04
-%  3 : 0.01
-messages_id_rand() ->
-   R = random:uniform(),
-   if R =< 0.1 ->
-         [];
-      true ->
-         Messages = lists:map(fun(#minichat{id = Id}) -> Id end, euphorik_bd:messages(8)),
-         if
-            R > 0.1 andalso R =< 0.95 ->
-               tire_element_rand(1, Messages);
-            R > 0.95 andalso R =< 0.99 ->
-               tire_element_rand(2, Messages);
-            true ->
-               tire_element_rand(3, Messages)
-         end
-   end.
-
-
-% tire N element distinct parmis la liste L proposée
-tire_element_rand(N, L) when N =< length(L) ->
-   tire_element_rand(N, L, []);
-tire_element_rand(_, _) ->
-   [].
-tire_element_rand(0, _, Elements) -> Elements;
-tire_element_rand(N, L, Elements) ->
-   E = lists:nth(random:uniform(length(L)), L),
-   E_se_trouve_dans_Elements = lists:any(fun(E2) -> E2 =:= E end, Elements),
-   if E_se_trouve_dans_Elements -> % si E a déjà été tiré on recommence sans rien changer
-         tire_element_rand(N, L, Elements);
-      true ->
-         tire_element_rand(N-1, L, [E | Elements])
-   end.
-
-loop(User_id, 0) ->
-   io:format("~p a fini~n", [User_id]);
-loop(User_id, M) -> 
-   % attend un temp aléatoire compris entre INTERVALLE_MIN sec et INTERVALLE_MAX sec
-   timer:sleep(1000 * (random:uniform(?INTERVALLE_MAX - ?INTERVALLE_MIN + 1) + ?INTERVALLE_MIN - 1)),
-   % poste un message aléatoire par une personne aléatoire répondant à des messages aléatoires
-   {Message, Repond_a} = {message_rand(), messages_id_rand()},
-   % io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]),   
-   case euphorik_bd:nouveau_message(Message, User_id, Repond_a) of
-      {erreur, E} -> 
-         io:format("~p : erreur : ~p~n", [User_id, E]),
-         loop(User_id, M);
-      _ ->
-         loop(User_id, M - 1)
-   end.
-   
-   
-% Permet de tester la vitesse d'écriture en fonction de la 
-% taille de la BD
-% voir : http://erlang.org/pipermail/erlang-questions/2008-October/038697.html
-bench_write_minichat(Filename) ->
-   Times = bench_write_minichat(1, []),
-   {ok, File} = file:open(Filename, [write]),
-   lists:foreach(
-      fun({Id, Time}) ->
-         io:format(File, "~w ~w~n", [Id, Time])
-      end,
-      Times
-   ),
-   file:close(File).   
-bench_write_minichat(100000, Temps) -> Temps;
-bench_write_minichat(N, Temps) ->
-   {T, _} = timer:tc(mnesia, transaction, [fun() ->
-      Id = mnesia:dirty_update_counter(counter, minichat, 1),
-      mnesia:write(#minichat{
-         id = Id,
-         auteur_id = random:uniform(10000),
-         date = now(),
-         pseudo = "Test",
-         contenu = "Blabla blabla bla.",
-         racine_id = random:uniform(10000)
-      })
-   end]),
-   bench_write_minichat(N + 1, if N rem 500 =:= 0 -> [{N, T} | Temps]; true -> Temps end).
-   
-
-   
-   
\ No newline at end of file
+-define(INTERVALLE_MAX, 5).\r
+\r
+\r
+% N est le nombre d'utilisateur\r
+% M est le nombre de message que chaque utilisateur va poster\r
+start(N, M) ->\r
+   Ids = creer_users(N),\r
+   lists:map(\r
+      fun(Id) ->\r
+         timer:sleep(100),\r
+         spawn(\r
+            fun() ->\r
+               {A1, A2, A3} = now(),\r
+               random:seed(A1, A2, A3),\r
+               loop(Id, M)\r
+            end\r
+         )\r
+      end,\r
+      Ids\r
+   ).\r
+\r
+stop(Pids) ->\r
+   lists:foreach(fun(Pid) -> exit(Pid, kill) end, Pids).\r
+\r
+% des trucs qui trainent\r
+bench_get_messages() ->\r
+   T = [\r
+      {page,"chat"},\r
+      {cookie,"5G84A5CJXMCPEHNI8T5A9"},\r
+      {message_count,40},\r
+      {last_message_id,0},\r
+      {main_page,1},\r
+      {conversations,{array,[]}}\r
+   ],\r
+   moyenne_temps(euphorik_protocole, wait_event, [T], 20).\r
+bench_get_messages_avec_2_conversations() ->\r
+   T = [\r
+      {page,"chat"},\r
+      {cookie,"5G84A5CJXMCPEHNI8T5A9"},\r
+      {message_count,40},\r
+      {last_message_id,0},\r
+      {main_page,1},\r
+      {conversations,{array, [\r
+         {struct, [\r
+            {root, 921},\r
+            {page,1},\r
+            {last_message_id,0}\r
+         ]},\r
+         {struct, [\r
+            {root, 772},\r
+            {page, 1},\r
+            {last_message_id, 0}\r
+         ]}\r
+      ]}}\r
+   ],\r
+   moyenne_temps(euphorik_protocole, wait_event, [T], 20).\r
+moyenne_temps(Module, Fun, Args, N) ->\r
+   moyenne_temps(Module, Fun, Args, N, N, 0).\r
+moyenne_temps(_, _, _, 0, Total, Temps_acc) ->\r
+   Temps_acc / Total;\r
+moyenne_temps(Module, Fun, Args, N, Total, Temps_acc) ->\r
+   {Temps, _} = timer:tc(Module, Fun, Args),\r
+   moyenne_temps(Module, Fun, Args, N - 1, Total, Temps_acc + Temps).\r
+\r
+\r
+% Crée N user avec des noms aléatoires et renvoie la liste des id.\r
+creer_users(N) ->\r
+   creer_users(N, []).\r
+creer_users(0, Ids) -> lists:map(fun(#user{id = Id}) -> Id end, Ids);\r
+creer_users(N, Ids) ->\r
+   creer_users(N - 1, [euphorik_bd:nouveau_user(mot_rand(random:uniform(4) + 4), "", "", #profile{}) | Ids ]).\r
+\r
+\r
+% crée un message aléatoire et le renvoie\r
+message_rand() ->\r
+   lists:flatten(message_rand(random:uniform(10), [])).\r
+message_rand(0, Mots) -> Mots;\r
+message_rand(N, Mots) ->\r
+   message_rand(N - 1, [mot_rand(random:uniform(2) + 5), $  | Mots]).\r
+\r
+\r
+% Renvoie une succession de lettre aléatoire\r
+mot_rand(L) ->\r
+   mot_rand(L, []).\r
+mot_rand(0, Mot) -> Mot;\r
+mot_rand(L, Mot) ->\r
+   mot_rand(L - 1, [random:uniform($z - $a + 1) + $a - 1 | Mot]).\r
+\r
+\r
+% Tire au hasard de 0 à 3 messages sur les 10 derniers postés, renvoie une liste de int()\r
+% répartition :\r
+%  0 : 0.1\r
+%  1 : 0.95\r
+%  2 : 0.04\r
+%  3 : 0.01\r
+messages_id_rand() ->\r
+   R = random:uniform(),\r
+   if R =< 0.1 ->\r
+         [];\r
+      true ->\r
+         Messages = lists:map(fun(#minichat{id = Id}) -> Id end, euphorik_bd:messages(8)),\r
+         if\r
+            R > 0.1 andalso R =< 0.95 ->\r
+               tire_element_rand(1, Messages);\r
+            R > 0.95 andalso R =< 0.99 ->\r
+               tire_element_rand(2, Messages);\r
+            true ->\r
+               tire_element_rand(3, Messages)\r
+         end\r
+   end.\r
+\r
+\r
+% tire N element distinct parmis la liste L proposée\r
+tire_element_rand(N, L) when N =< length(L) ->\r
+   tire_element_rand(N, L, []);\r
+tire_element_rand(_, _) ->\r
+   [].\r
+tire_element_rand(0, _, Elements) -> Elements;\r
+tire_element_rand(N, L, Elements) ->\r
+   E = lists:nth(random:uniform(length(L)), L),\r
+   E_se_trouve_dans_Elements = lists:any(fun(E2) -> E2 =:= E end, Elements),\r
+   if E_se_trouve_dans_Elements -> % si E a déjà été tiré on recommence sans rien changer\r
+         tire_element_rand(N, L, Elements);\r
+      true ->\r
+         tire_element_rand(N-1, L, [E | Elements])\r
+   end.\r
+\r
+loop(User_id, 0) ->\r
+   io:format("~p a fini~n", [User_id]);\r
+loop(User_id, M) ->\r
+   % attend un temp aléatoire compris entre INTERVALLE_MIN sec et INTERVALLE_MAX sec\r
+   timer:sleep(1000 * (random:uniform(?INTERVALLE_MAX - ?INTERVALLE_MIN + 1) + ?INTERVALLE_MIN - 1)),\r
+   % poste un message aléatoire par une personne aléatoire répondant à des messages aléatoires\r
+   {Message, Repond_a} = {message_rand(), messages_id_rand()},\r
+   % io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]),\r
+   case euphorik_bd:nouveau_message(Message, User_id, Repond_a) of\r
+      {erreur, E} ->\r
+         io:format("~p : erreur : ~p~n", [User_id, E]),\r
+         loop(User_id, M);\r
+      _ ->\r
+         loop(User_id, M - 1)\r
+   end.\r
+\r
+\r
+% Permet de tester la vitesse d'écriture en fonction de la\r
+% taille de la BD\r
+% voir : http://erlang.org/pipermail/erlang-questions/2008-October/038697.html\r
+bench_write_minichat(Filename) ->\r
+   Times = bench_write_minichat(1, []),\r
+   {ok, File} = file:open(Filename, [write]),\r
+   lists:foreach(\r
+      fun({Id, Time}) ->\r
+         io:format(File, "~w ~w~n", [Id, Time])\r
+      end,\r
+      Times\r
+   ),\r
+   file:close(File).\r
+bench_write_minichat(100000, Temps) -> Temps;\r
+bench_write_minichat(N, Temps) ->\r
+   {T, _} = timer:tc(mnesia, transaction, [fun() ->\r
+      Id = mnesia:dirty_update_counter(counter, minichat, 1),\r
+      mnesia:write(#minichat{\r
+         id = Id,\r
+         auteur_id = random:uniform(10000),\r
+         date = now(),\r
+         pseudo = "Test",\r
+         contenu = "Blabla blabla bla.",\r
+         racine_id = random:uniform(10000)\r
+      })\r
+   end]),\r
+   bench_write_minichat(N + 1, if N rem 500 =:= 0 -> [{N, T} | Temps]; true -> Temps end).\r
+\r
+\r
+\r
index 4838b30..de1c5e4 100755 (executable)
-% coding: utf-8
-% Copyright 2008 Grégory Burri
-%
-% This file is part of Euphorik.
-%
-% Euphorik is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% Euphorik is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
-%
-% @author GBurri
-
-
-% Version de la BD
--define(VERSION_BD, 3).
--define(TABLES, [counter, proprietes, minichat, reponse_minichat, user, ip_table, troll]).
-
-
-% Pour générer des id
--record(counter,
-   {
-      key,
-      value
-   }).
-   
-   
-% Mémorse toutes les propriétés, entre autre la version des données
--record(proprietes,
-   {
-      nom,
-      valeur
-   }).
-
-
-% Contient tous les textes que peut envoyer le serveur vers client.
--record(texte,
-   {
-      id,
-      fr
-   }).
-
-
-% décrit un enregistrement d'un message
--record(minichat,
-   {
-      id, % integer
-      auteur_id, % -> #user.id
-      date, % erlang:now()
-      pseudo, % chaine de caractère
-      contenu, % chaine de caractère
-      racine_id = undefined, % la racine, par défaut correspond à l'id du message
-      status = normal % can be equal to normal, censored or deleted
-   }).
-   
-   
-% type bag
-% 'repondant' repond à 'cible'
--record(reponse_minichat,
-   {
-      repondant, % -> #minichat.id
-      cible % -> #minichat.id
-   }). 
-
-
--record(profile, % attention : pas une table !
-   {
-      pseudo = [], % string()
-      email = [], % string()
-      css = [], % string()
-      nick_format = nick, %atom(), peut valoir 'nick', 'login' ou 'nick_login'
-      view_times = true,
-      view_tooltips = true,
-      ostentatious_master = light, % peut valoir invisible, light ou heavy. seulement pour ek_master
-      chat_order = reverse, % peut valoir chrono ou reverse
-      conversations = [] % [{integer(), bool}], la liste des messages correspondant au conversation {racine, reduite?}
+% coding: utf-8\r
+% Copyright 2008 Grégory Burri\r
+%\r
+% This file is part of Euphorik.\r
+%\r
+% Euphorik is free software: you can redistribute it and/or modify\r
+% it under the terms of the GNU General Public License as published by\r
+% the Free Software Foundation, either version 3 of the License, or\r
+% (at your option) any later version.\r
+%\r
+% Euphorik is distributed in the hope that it will be useful,\r
+% but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+% GNU General Public License for more details.\r
+%\r
+% You should have received a copy of the GNU General Public License\r
+% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
+%\r
+% @author GBurri\r
+\r
+\r
+% Version de la BD\r
+-define(VERSION_BD, 3).\r
+-define(TABLES, [counter, proprietes, minichat, reponse_minichat, user, ip_table, troll]).\r
+\r
+\r
+% Pour générer des id\r
+-record(counter,\r
+   {\r
+      key,\r
+      value\r
    }).\r
-   \r
-   
--record(user,
-   {
-      id,
-      cookie, % string()
-      login = [], % string()
-      password = [], % string() (md5)
-      profile = #profile{},
-      date_creation, % erlang:now()
-      date_derniere_connexion, % erlang:now(), est mis à jour lors de n'importe quelle activitée (envoie de message par exemple)
-      indice_flood = 0, % integer() est incrémenté lorsque l'utilisateur envoie trop rapidement des messages.
-      ek_master = false,
-      last_ip = undefined % integer(), undefined si inconnu
-   }).
-
-
-% identificateur : (ip)
--record(ip_table,
-   {
-      ip, % {integer(), integer(), integer(), integer()}
-      ban = undefined, % la date du dernier bannissement
-      ban_duration = 0, % le temps de ban en minute
-      nb_try_register = 0,
-      nb_try_login = 0, % pour l'instant pas utilisé
-      date_last_try_register,
-      date_last_try_login % pour l'instant pas utilisé
-   }).
-   
-   
--record(troll,
-   {
-      id,
+\r
+\r
+% Mémorse toutes les propriétés, entre autre la version des données\r
+-record(proprietes,\r
+   {\r
+      nom,\r
+      valeur\r
+   }).\r
+\r
+\r
+% Contient tous les textes que peut envoyer le serveur vers client.\r
+-record(texte,\r
+   {\r
+      id,\r
+      fr\r
+   }).\r
+\r
+\r
+% décrit un enregistrement d'un message\r
+-record(minichat,\r
+   {\r
+      id, % integer\r
+      auteur_id, % -> #user.id\r
+      date, % erlang:now()\r
+      pseudo, % chaine de caractère\r
+      contenu, % chaine de caractère\r
+      racine_id = undefined, % la racine, par défaut correspond à l'id du message\r
+      status = normal % can be equal to normal, censored or deleted\r
+   }).\r
+\r
+\r
+% type bag\r
+% 'repondant' repond à 'cible'\r
+-record(reponse_minichat,\r
+   {\r
+      repondant, % -> #minichat.id\r
+      cible % -> #minichat.id\r
+   }).\r
+\r
+\r
+-record(profile, % attention : pas une table !\r
+   {\r
+      pseudo = [], % string()\r
+      email = [], % string()\r
+      css = [], % string()\r
+      nick_format = nick, %atom(), peut valoir 'nick', 'login' ou 'nick_login'\r
+      view_times = true,\r
+      view_tooltips = true,\r
+      ostentatious_master = light, % peut valoir invisible, light ou heavy. seulement pour ek_master\r
+      chat_order = reverse, % peut valoir chrono ou reverse\r
+      conversations = [] % [{integer(), bool}], la liste des messages correspondant au conversation {racine, reduite?}\r
+   }).\r
+\r
+\r
+-record(user,\r
+   {\r
+      id,\r
+      cookie, % string()\r
+      login = [], % string()\r
+      password = [], % string() (md5)\r
+      profile = #profile{},\r
+      date_creation, % erlang:now()\r
+      date_derniere_connexion, % erlang:now(), est mis à jour lors de n'importe quelle activitée (envoie de message par exemple)\r
+      indice_flood = 0, % integer() est incrémenté lorsque l'utilisateur envoie trop rapidement des messages.\r
+      ek_master = false,\r
+      last_ip = undefined % integer(), undefined si inconnu\r
+   }).\r
+\r
+\r
+% identificateur : (ip)\r
+-record(ip_table,\r
+   {\r
+      ip, % {integer(), integer(), integer(), integer()}\r
+      ban = undefined, % la date du dernier bannissement\r
+      ban_duration = 0, % le temps de ban en minute\r
+      nb_try_register = 0,\r
+      nb_try_login = 0, % pour l'instant pas utilisé\r
+      date_last_try_register,\r
+      date_last_try_login % pour l'instant pas utilisé\r
+   }).\r
+\r
+\r
+-record(troll,\r
+   {\r
+      id,\r
       id_user,\r
-      id_minichat = undefined, % l'id du message associé
-      date_create, % erlang:now()
-      date_post = undefined, % date à laquelle le troll est affiché sur la page principale. undefined initialement puis erlang:now() quand affiché
-      content % chaine de caractère
-   }).
-   
\ No newline at end of file
+      id_minichat = undefined, % l'id du message associé\r
+      date_create, % erlang:now()\r
+      date_post = undefined, % date à laquelle le troll est affiché sur la page principale. undefined initialement puis erlang:now() quand affiché\r
+      content % chaine de caractère\r
+   }).\r
index 8d22486..37fa542 100755 (executable)
@@ -27,7 +27,7 @@
 -define(DUREE_SPAM, 1000). % ms
 % Lorsque l'indice de spam d'un utilisateur atteind cette valeur alors il ne peut plus poster pendant un moment
 -define(INDICE_SPAM_MAX, 6).
-% Un utilisateur ayant trop spamé est bloqué pendant ce temps 
+% Un utilisateur ayant trop spamé est bloqué pendant ce temps
 -define(DUREE_BLOCAGE_SPAM, 20000). % ms
 
 
@@ -36,7 +36,7 @@
 % le temps entre deux tentatives de register pour compter un flood
 -define(TEMPS_FLOOD_REGISTER, 1500). % 1500 ms
 % après 5 flood l'ip fautive est considérée comme bannie
--define(NB_MAX_FLOOD_REGISTER, 5). 
+-define(NB_MAX_FLOOD_REGISTER, 5).
 
 
 % le nombre max de troll qui peuvent être en attente d'être posté (tous les utilisateurs réunis)
index 8307a0e..d73d52d 100755 (executable)
@@ -3,7 +3,7 @@
 
 main(_) -> 
    net_kernel:start([tv, shortnames]),
-   Yaws = yaws_dev@flynux,
+   Yaws = yaws_dev@X220,
    io:format("Connexion à Yaws : ~p~n", [net_adm:ping(Yaws)]),
    mnesia:start(),
    mnesia:change_config(extra_db_nodes, nodes()),
old mode 100644 (file)
new mode 100755 (executable)
index ffab671..d5c24bf
@@ -1,5 +1,5 @@
-#!/usr/bin/env escript
-% coding: utf-8
+#!/usr/bin/env escript\r
+% coding: utf-8\r
 % Copyright 2008 Grégory Burri\r
 %\r
 % This file is part of Euphorik.\r
 % GNU General Public License for more details.\r
 %\r
 % You should have received a copy of the GNU General Public License\r
-% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.
+% along with Euphorik.  If not, see <http://www.gnu.org/licenses/>.\r
 \r
-% This file replace the old one 'tools.rb' written in a crapy language ;)
-% TODO :
-% - création de unit tests (voir eunit) et validation avant la mise en prod
+% This file replace the old one 'tools.rb' written in a crapy language ;)\r
+% TODO :\r
+% - création de unit tests (voir eunit) et validation avant la mise en prod\r
 \r
 \r
 main(Args) ->\r
@@ -44,11 +44,11 @@ main(Args) ->
 % A simple fonction to log message.\r
 log(Str) ->\r
    io:format("===== ~s =====~n", [Str]).\r
-   \r
+\r
 \r
 % Execute an OS commande and print the result to stdout.\r
 cmd(Commande_str) ->\r
-   cmd(Commande_str, []).   \r
+   cmd(Commande_str, []).\r
 cmd(Commande_str, Params) ->\r
    io:format("~s~n", [os:cmd(lists:flatten(io_lib:format(Commande_str, Params)))]).\r
 \r
@@ -94,47 +94,47 @@ in_preprod(Uri, data_path) ->
    start_server(),\r
    update_server().\r
 \r
-   \r
+\r
 % Compile the Erlang modules.\r
 compile_server_part(Uri) ->\r
    todo.\r
-   \r
+\r
 \r
 % Create the 'var' folder if it doesn't exist.\r
 make_var_directory(Uri) ->\r
    todo.\r
-   \r
-   \r
+\r
+\r
 % Copy files from developpement env to production server.\r
 copy_files(Uri) ->\r
    copy_static_part(Uri),\r
    copy_packed_js(Uri).\r
-   \r
-   \r
+\r
+\r
 % Copy all static files like modules, styles, pages, etc.\r
 copy_static_part(Uri) ->\r
    %~ creer_rep('modules')\r
    %~ system("rsync -r --exclude 'euphorik_test.beam' modules/ebin #{@uri}:#{@rep}/modules")\r
    %~ system("rsync -r modules/include #{@uri}:#{@rep}/modules")\r
    todo.\r
-   \r
+\r
 \r
 % Minify and pack JavaScript in one file then copy it to ther server.\r
 copy_packed_js(Uri) ->\r
    todo.\r
-   \r
-   \r
+\r
+\r
 % Define the rights for the copied folder et files.\r
 define_files_rights(Uri) ->\r
-   todo.   \r
-   \r
-   \r
+   todo.\r
+\r
+\r
 % Start the server if it not already started (in preproduction case only).\r
 start_server() ->\r
    todo.\r
-   \r
-   \r
-% Run a erlang script to \r
+\r
+\r
+% Run a erlang script to\r
 update_server() ->\r
    todo.\r
-
+\r
old mode 100644 (file)
new mode 100755 (executable)