ADD trolls, fin coté serveur et début coté client
authorGreg Burri <greg.burri@gmail.com>
Sun, 11 May 2008 23:27:57 +0000 (23:27 +0000)
committerGreg Burri <greg.burri@gmail.com>
Sun, 11 May 2008 23:27:57 +0000 (23:27 +0000)
ADD possibilité de mettre un message lors d'un slapping ou d'un bannissement
MOD maj TODO

18 files changed:
css/1/euphorik.css
css/1/pageAbout.css
css/1/pageAdmin.css [new file with mode: 0644]
css/1/pageMinichat.css
css/1/pageProfileRegister.css
doc/TODO.txt
doc/protocole3.txt
index.html
js/euphorik.js
js/pageAdmin.js [new file with mode: 0644]
js/pageMinichat.js
modules/erl/euphorik_bd.erl
modules/erl/euphorik_minichat_conversation.erl
modules/erl/euphorik_protocole.erl
modules/erl/euphorik_requests.erl
modules/include/euphorik_bd.hrl
modules/include/euphorik_defines.hrl
pages/about.html

index 2630f1f..c3a4ace 100755 (executable)
@@ -1,5 +1,6 @@
 @import url(../common.css);\r
-@import url(pageMinichat.css);\r
+@import url(pageMinichat.css);
+@import url(pageAdmin.css);\r
 @import url(pageProfileRegister.css);
 @import url(pageAbout.css);
 \r
@@ -59,9 +60,51 @@ body {
 
 #page {
    position: relative;
-   padding: 25px 0px 15px 0px;
    font-size: 12px;
    background-color: #000000;
+   text-align : left;
+   padding: 30px 10px 15px 10px;
+}
+
+#page > h1 {
+   margin-top: 10px;
+   margin-left: 0px;
+   font-size: 18px;
+   color : #a6b80e
+}
+
+#page > h2 {
+   margin-top: 10px;
+   margin-left: 10px;
+   font-size: 16px;
+   color : #899714;
+}
+
+#page > h3 {
+   margin-top: 10px;
+   margin-left: 20px;
+   font-size: 14px;
+   color : #79841a;
+   background-color : #1e2201
+}
+
+#page > h4 {
+   margin-top: 10px;
+   margin-left: 25px;
+   font-size: 12px;
+   color : #646d1d
+}
+
+#page > p {
+   margin-top: 3px;
+   margin-left: 35px;
+   color : #e9e9e9
+}
+
+#page > ul {
+   margin-top: 3px;
+   margin-left: 45px;
+   color: #e9e9e9
 }
 
 #logo {
index ffb958e..e661102 100644 (file)
@@ -1,46 +1,3 @@
 
 #page.about {
-   text-align : left;
-   padding: 30px 10px 10px 10px;
-}
-
-#page.about h1 {
-   margin-top: 10px;
-   margin-left: 0px;
-   font-size: 18px;
-   color : #a6b80e
-}
-
-#page.about h2 {
-   margin-top: 10px;
-   margin-left: 10px;
-   font-size: 16px;
-   color : #899714;
-}
-
-#page.about h3 {
-   margin-top: 10px;
-   margin-left: 20px;
-   font-size: 14px;
-   color : #79841a;
-   background-color : #1e2201
-}
-
-#page.about h4 {
-   margin-top: 10px;
-   margin-left: 25px;
-   font-size: 12px;
-   color : #646d1d
-}
-
-#page.about p {
-   margin-top: 3px;
-   margin-left: 35px;
-   color : #e9e9e9
-}
-
-#page.about ul {
-   margin-top: 3px;
-   margin-left: 45px;
-   color: #e9e9e9
 }
diff --git a/css/1/pageAdmin.css b/css/1/pageAdmin.css
new file mode 100644 (file)
index 0000000..82626ef
--- /dev/null
@@ -0,0 +1,4 @@
+/* La page d'administration */
+
+#page.admin {
+}
index 234f9f5..80a2e33 100755 (executable)
@@ -1,3 +1,7 @@
+#page.minichat {
+   padding: 25px 0px 15px 0px;
+   text-align: center
+}
 
 #page.minichat img {
        margin: 0px;
        position: absolute;
        display: none;
 }
-#outilsBan img {
+#outilsBan img,
+#outilsBan form {
        float: right;
-       vertical-align: middle;
-       margin: 0px 0px 0px 0px;
+       cursor: pointer
+}
+#outilsBan p {
+       font-size: 2px;
+}
+#outilsBan input {
+       font-size: 9px;
+       margin-top: 1px;
+       margin-left: 1px
 }
 
 #page.minichat .titreSmiles:hover {
index 48f5bc9..1b8b70a 100755 (executable)
@@ -2,6 +2,4 @@
 
 #page.register,
 #page.profile {
-   text-align: left;\r
-   padding: 30px 10px 10px 10px;
 }
index f08ffbc..3c086e7 100755 (executable)
    * Pas sous Opera, apparemment Firefox recharge toute la page (donc impossible qu'il puisse remettre le message)
    * Eventuellement sauvegarder le message en rédaction dans le profile...\r
 [3] Le changement de page sous Firefox (pas essayé avec d'autre nav) es plutot moche, le texte est d'abors affiché puis le style est appliqué.
+[3] Quelques fichiers sont encore en iso-8859-1 (Makefile, euphorik_bd.hrl, etc..) tout passer en UTF-8
 [3] Un message envoyé sans être authentifié ne sera pas taggé comme appartenant à l'utilisateur.
    a) L'utilisateur attend des messages SANS donné de cookie car il n'est pas authentifié
    b) L'utilisateur envoie un message
@@ -236,6 +237,7 @@ ok : Implémenté
    * Pouvoir STFUER des personnes, lorsqu'elle envoie un message un autre truc à la con est écrit à la place
    * la phrase à la con est piché parmis une liste éditable depuis le panneau d'admin
    * La stfuation se fait depuis le panel de bannissement (slap, stfu, kick, ban)
+[4] Unifier tout le code en anglais (sauf les commentaires)
 [4] Inscrire le nom de l'image dans les les liens vers des images (à la place de simplement [jpg] ou [gif])
 [4] Réduire les pseudos trop long en mettant un ".." à la fin et permettre de le voir en entier lorsque le curseur le survol.\r
 [4] Compatible OpenID pour l'identification\r
index 99776a4..e553133 100644 (file)
@@ -128,7 +128,7 @@ ou
    <error>
 
 
-=== Wait event ===
+=== Wait event (page = chat) ===
 Si "last_message_id" est absent alors le client ne possède pas de message.
 Si "main_page" est absent alors est vaut 1.
 "cookie" n'est pas obligatoire.
@@ -140,7 +140,8 @@ c -> s
       "cookie" : "LKJDLAKSJBFLKASN",\r
       "message_count" : 10,
       "last_message_id" : 163,
-      "main_page" : 1
+      "main_page" : 1,
+      "troll_id" : 45,
       "conversations" : [
          {
             "racine" : 123,
@@ -185,26 +186,95 @@ ou
    {\r
       "reply" : "message_updated",\r
       "message_id" : 123,\r
-      "contenu" : "Salut +++ poulpe"\r
+      "content" : "Salut +++ poulpe"\r
+   }
+ou
+   {
+      "reply" : "new_troll",
+      "troll_id" : 123,
+      "content" : "Linux sera desktop ready en 2008 ?"
    }
 ou
    <error>
+
+
+=== Wait event (page = admin) ===
+c -> s
+   {
+      "action" : "wait_event",
+      "page" : "admin",
+      "last_troll" : 5
+      ]
+   }
+   
+s -> c
+   {
+      "reply" : "troll_modified",
+      "troll_id" : 3,
+      "content" : "plop"
+   }
+ou
+s -> c
+   {
+      "reply" : "troll_added",
+      "trolls" :
+         [
+            {
+               "troll_id" : 5,
+               "content" : "plop"
+            }
+         ]
+   }
+ou
+s -> c
+   {
+      "reply" : "troll_deleted",
+      "troll_id" : 2
+   }
 \r
 \r
-=== Envoie d'un troll ===
-TODO\r
+=== Envoie d'un troll ===\r
 c -> s\r
    {\r
       "action" : "put_troll",\r
       "cookie" : "LKJDLAKSJBFLKASN",\r
       "content" : "Un bon troll velu !"\r
-   }\r
-=== Modification d'un troll ===\r
-TODO\r
-=== Suppression d'un troll ===\r
-TODO\r
-=== Noter un troll ===\r
-TODO
+   }
+s -> c
+   <ok>
+ou
+   <error>
+   
+   \r
+=== Modification d'un troll ===
+c -> s
+   {
+      "action" : "mod_troll",
+      "cookie" : "LKJDLAKSJBFLKASN",
+      "troll_id" : 3,
+      "content" : "Un bon troll velu 2 !"
+   }
+s -> c
+   <ok>
+ou
+   <error>
+   
+   \r
+=== Suppression d'un troll ===
+c -> s
+   {
+      "action" : "del_troll",
+      "cookie" : "LKJDLAKSJBFLKASN",
+      "troll_id" : 3
+   }
+s -> c
+   <ok>
+ou
+   <error>
+   
 
 === Envoie message ===
 Le client envoie un message, le message peut répondre à un certain nombre d'autres messages.
@@ -226,12 +296,12 @@ ou
 
 
 === Slapage ===
-
 c -> s
    {
       "action" : "slap",
       "cookie" :  "LKJDLAKSJBFLKASN",
-      "user_id" : 67
+      "user_id" : 67,
+      "reason" : "blablabla"
    }
    
 s -> c
@@ -241,13 +311,13 @@ ou
    
 
 === Bannissement ===
-
 c -> s
    {
       "action" : "ban",
       "cookie" : "LKJDLAKSJBFLKASN",
       "duration" : 15, // en minute
-      "user_id" : 67
+      "user_id" : 67,
+      "reason" : "blablabla"
    }
    
 s -> c
index e388a93..a35a982 100755 (executable)
@@ -11,6 +11,7 @@
    <script type="text/javascript" src="js/md5.js" ></script>
    <script type="text/javascript" src="js/json2.js" ></script>
    <script type="text/javascript" src="js/pageMinichat.js" ></script>
+   <script type="text/javascript" src="js/pageAdmin.js" ></script>
    <script type="text/javascript" src="js/pageProfile.js" ></script>
    <script type="text/javascript" src="js/pageRegister.js" ></script>
    <script type="text/javascript" src="js/pageAbout.js" ></script>
@@ -21,7 +22,7 @@
          <div id="logo"></div>\r
          <div id="info" style="display:none" ><div id="icone"></div><div class="fermer" ></div><div class="message" ></div><div class="boutons"></div></div>
          <div id="menu">
-            <div class="minichat">chat</div><div class="profile"></div><div class="register">register</div><div class="logout">logout</div><div class="about">about</div>\r
+            <div class="minichat">chat</div><div class="admin" style="display:none">admin</div><div class="profile"></div><div class="register">register</div><div class="logout">logout</div><div class="about">about</div>\r
          </div>
          <form>
             <select id="menuCss">
index 7bab324..b36fbbb 100755 (executable)
@@ -748,8 +748,11 @@ Client.prototype.flush = function(async)
 
 Client.prototype.majMenu = function()
 {
+   // TODO : à virer : ne plus changer de style de display ... spa beau .. ou trouver une autre méthode
    var displayType = this.css == "css/3/euphorik.css" ? "block" : "inline" //this.client
 
+   $("#menu .admin").css("display", this.ekMaster ? "none" : "inline")
+
    // met à jour le menu   
    if (this.statut == statutType.auth_registered)
    {
@@ -772,7 +775,7 @@ Client.prototype.majMenu = function()
 }
 
 
-Client.prototype.slap = function(userId)
+Client.prototype.slap = function(userId, raison)
 {
    var thisClient = this
    
@@ -784,7 +787,8 @@ Client.prototype.slap = function(userId)
          {
             "action" : "slap",
             "cookie" : thisClient.cookie,
-            "user_id" : userId
+            "user_id" : userId,
+            "reason" : raison
          }),
       success: 
          function(data)
@@ -796,7 +800,7 @@ Client.prototype.slap = function(userId)
 }
 
 
-Client.prototype.ban = function(userId, minutes)
+Client.prototype.ban = function(userId, raison, minutes)
 {
    var thisClient = this
 
@@ -813,7 +817,8 @@ Client.prototype.ban = function(userId, minutes)
             "action" : "ban",
             "cookie" : thisClient.cookie,
             "duration" : minutes,
-            "user_id" : userId
+            "user_id" : userId,
+            "reason" : raison
          }),
       success: 
          function(data)
@@ -824,9 +829,9 @@ Client.prototype.ban = function(userId, minutes)
    })
 }
 
-Client.prototype.kick = function(userId)
+Client.prototype.kick = function(userId, raison)
 {
-   this.ban(userId, 15)
+   this.ban(userId, raison, 15)
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -862,6 +867,7 @@ $(document).ready(
       $(window).unload(function(){client.flush(false)})
       
       $("#menu .minichat").click(function(){ pages.afficherPage("minichat") })
+      $("#menu .admin").click(function(){ pages.afficherPage("admin") })
       $("#menu .profile").click(function(){ pages.afficherPage("profile") })\r
       $("#menu .logout").click(function(){
          util.messageDialogue("Êtes-vous sur de vouloir vous délogger ?", messageType.question,
@@ -878,6 +884,7 @@ $(document).ready(
       $("#menu .about").click(function(){ pages.afficherPage("about") })
 
       pages.ajouterPage(new PageMinichat(client, formateur, util))
+      pages.ajouterPage(new PageAdmin(client, formateur, util))
       pages.ajouterPage(new PageProfile(client, formateur, util))
       pages.ajouterPage(new PageRegister(client, formateur, util))
       pages.ajouterPage(new PageAbout(client, formateur, util))
diff --git a/js/pageAdmin.js b/js/pageAdmin.js
new file mode 100644 (file)
index 0000000..1611ecc
--- /dev/null
@@ -0,0 +1,40 @@
+// coding: utf-8
+
+function PageAdmin(client, formateur, util)
+{
+   this.nom = "admin"
+   
+   this.client = client
+   this.formateur = formateur
+   this.util = util
+}
+
+PageAdmin.prototype.contenu = function()
+{
+   return '<h1>Trolls</h1>\
+   <form id="nouveauTroll"><p>Nouveau troll\
+      <input class="troll" name="troll" type="text" size="80" maxlength="500" value=""></input>\
+      <button class="return" value="return">poster</button>\
+   </p></form><div id="trolls"></div>'
+}
+
+PageAdmin.prototype.charger = function()
+{      
+   $("#page form#nouveauTroll").submit(function(){return false})
+      
+   var thisPage = this
+   
+   $("#page form#nouveauTroll button.return").click(
+      function()
+      {         
+      
+      }
+   )
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+function Trolls()
+{
+
+}
\ No newline at end of file
index 6b7b340..80cd013 100755 (executable)
@@ -44,7 +44,12 @@ PageMinichat.prototype.charger = function()
    if (this.client.ekMaster)
    {    
       $("body").append(
-         "<div id=\"outilsBan\"><img id=\"ban\" alt=\"Ban de 3 jours\" src=\"img/ban.gif\" /><img id=\"kick\" alt=\"Ban de 15min\" src=\"img/kick.gif\" /><img id=\"slap\" alt=\"Avertissement\" src=\"img/slap.gif\" /></div>"
+         '<div id="outilsBan">' +
+         '<form><p><input id="raison" name="raison" type="text" size="10" maxlength="200"></input></p></form>' +
+         '<img id="ban" src="img/ban.gif" alt="Ban de 3 jours" />' +
+         '<img id="kick" src="img/kick.gif" alt="Ban de 15min" />' +
+         '<img id="slap" src="img/slap.gif" alt="Avertissement" />' +
+         '</div>'
       )
       $("#outilsBan").hover(
          function(){},
@@ -535,7 +540,7 @@ Conversation.prototype.flush = function(funClickOuvrirConv)
             }
          )
          
-         $("a[@rel*=lightbox]").lightBox()
+         $("a[@rel*=lightbox]", this).lightBox()
          
          // les outils de bannissement (uniquement pour les ekMaster)
          if (thisConversation.client.ekMaster)
@@ -546,24 +551,27 @@ Conversation.prototype.flush = function(funClickOuvrirConv)
                   var element = $(e.target)
                   var h = element.height()
                   var offset = element.offset()
-                  var outils = $("#outilsBan").css("top", offset.top - 2).css("left", offset.left - 2).height(h < 16 ? 16 : h).width(element.width() + 16 * 3 + 4).show()
+                  var outils = $("#outilsBan").css("top", offset.top - 2).css("left", offset.left - 2).height(h < 16 ? 16 : h).width(element.width() + 16 * 3 + 4 + 64).show()
                   $("img", outils).unbind()
                   $("#slap", outils).click(
                      function(e)
                      {
-                        thisConversation.client.slap(userId)
+                        thisConversation.client.slap(userId, $("#outilsBan input").val())
+                        $("#outilsBan input").val("")
                      }
                   )
                   $("#kick", outils).click(
                      function(e)
                      {
-                        thisConversation.client.kick(userId)
+                        thisConversation.client.kick(userId, $("#outilsBan input").val())
+                        $("#outilsBan input").val("")
                      }
                   )
                   $("#ban", outils).click(
                      function(e)
                      {
-                        thisConversation.client.ban(userId)
+                        thisConversation.client.ban(userId, $("#outilsBan input").val())
+                        $("#outilsBan input").val("")
                      }
                   )
                },
@@ -903,7 +911,7 @@ Messages.prototype.rafraichirMessages = function(vider)
       for (var i = 0; i < this.conversations.length; i++)
          this.conversations[i].idDernierMessageAffiche = 0\r
       
-   dumpObj(this.getJSONrafraichirMessages())
+   ;;; dumpObj(this.getJSONrafraichirMessages())
    this.attenteCourante = jQuery.ajax({
       type: "POST",
       url: "request",
@@ -920,9 +928,6 @@ Messages.prototype.rafraichirMessages = function(vider)
             // ajoute les messages reçus à leur conversation respective
             for (var numConv = 0; numConv < data["conversations"].length; numConv++)
             {
-               // ya pas de nouveaux message -> on passe à la prochaine conversation FIXME : marche pas
-               //if (data["conversations"][numConv]["messages"].length == 0) continue
-               
                if (! thisMessages.ajouterMessages(data["conversations"][numConv], numConv))
                {
                   thisMessages.util.messageDialogue("La conversation {" + thisMessages.client.conversations[numConv -1].root.toString(36) + "} n'existe pas")
index eb6f1d4..7a9b582 100755 (executable)
    est_banni/1,
    can_register/1,
    
+   % trolls :
+   trolls/0,
+   trolls/1,
+   put_troll/2,
+   mod_troll/2,
+   del_troll/1,
+   
    % versions :
    update_version/1,
    
@@ -119,6 +126,7 @@ reset() ->
    mnesia:clear_table(user),\r
    mnesia:clear_table(reponse_minichat),\r
    mnesia:clear_table(minichat),
+   mnesia:clear_table(troll),
    mnesia:clear_table(ip_table),\r
    % crée l'utilisateur root\r
    mnesia:transaction(fun() ->\r
@@ -333,7 +341,7 @@ nouveau_message(Mess, Auteur_id, Repond_A) ->
       % est-ce que l'auteur à trop floodé ?
       if Auteur#user.indice_flood =/= ?INDICE_SPAM_MAX, Auteur_maj#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM ->
          mnesia:write(Auteur#user{indice_flood = Auteur_maj#user.indice_flood}),
-         nouveau_message_sys(Auteur#user.pseudo ++ "(" ++ Auteur#user.login ++ ") est bloqué pour " ++ integer_to_list(trunc(?DUREE_BLOCAGE_SPAM / 1000)) ++ " secondes pour cause de flood..");
+         nouveau_message_sys(Auteur#user.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.");
       Auteur#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM ->
          erreur;
       true ->     
@@ -574,6 +582,121 @@ can_register(IP) ->
       end
    )).
    
+
+% Renvoie tous les trolls.
+trolls() ->
+   resultat_transaction(mnesia:transaction(
+      fun() ->
+         qlc:e(qlc:q([T || T <- mnesia:table(troll)]))
+      end
+   )).
+   
+% Renvoie les trolls manquants posté après Last_id.
+% Si pas de trolls alors attend un événement tel qu'un ajout, une modification ou une suppression.
+% renvoie :
+%  {mod, Troll}
+% ou {add, [Trolls]}
+% ou {del, Troll_id}
+% ou timeout
+trolls(Last_id) ->
+   case mnesia:subscribe({table, troll, detailed}) of
+      {error, E} = E ->
+         E;
+      _ ->
+         case resultat_transaction(mnesia:transaction(
+               fun() ->
+                  qlc:e(qlc:q([T || T <- mnesia:table(troll), T#troll.id > Last_id, T#troll.date_post =:= undefined]))
+               end
+            )) of
+               [] -> % pas de trolls
+                  attend_evenement_troll();
+               Trolls ->
+                  {add, Trolls}
+         end
+   end.
+   
+attend_evenement_troll() ->
+   % s'il n'y a pas de trolls que l'utilisateur n'a pas connaissance alors on attend un événement
+   receive
+      {mnesia_table_event, {write, troll, Troll, [_Old_troll | _], _}} ->
+         {mod, Troll};
+      {mnesia_table_event, {write, troll, Troll, [], _}} ->
+         {add, [Troll]};
+      {mnesia_table_event, {delete, troll, {troll, Id}, _, _}} ->
+         {del, Id};
+      _ ->
+         attend_evenement_troll()
+   after 1000 * 60 * 60 -> 
+      timeout
+   end.
+   
+ % Renvoie l'id du nouveau troll
+ % ou max_troll_reached_per_user si le nombre de troll posté par l'utilisateur max a été atteind
+ % ou max_troll_reached si le nombre de troll posté max a été atteind
+ % ou user_unknown
+put_troll(User_id, Content) ->
+   resultat_transaction(mnesia:transaction(
+      fun() ->
+         % control le nombre de troll déjà posté
+         Nb_troll_poste_par_user = length(qlc:e(qlc:q(
+            [
+               E#troll.id || E <- mnesia:table(troll),
+               E#troll.id_user =:= User_id,
+               E#troll.date_post =:= undefined
+            ]
+         ))),
+         Nb_troll_poste_total = length(qlc:e(qlc:q(
+            [
+               E#troll.id || E <- mnesia:table(troll),
+               E#troll.date_post =:= undefined
+            ]
+         ))),
+         User = user_by_id(User_id),
+         case User of
+            {ok, _} ->
+               if Nb_troll_poste_par_user >= ?NB_MAX_TROLL_WAITING_BY_USER ->
+                     max_troll_reached_per_user;
+                  Nb_troll_poste_total >= ?NB_MAX_TROLL_WAITING ->
+                     max_troll_reached;
+                  true ->
+                     Id = nouvel_id(minichat),
+                     mnesia:write(#troll{id = Id, id_user = User_id, date_create = now(), content = Content}),
+                     Id
+               end;
+            _ ->
+               user_unknown
+         end
+      end
+   )).
+
+
+% renvoie ok | erreur
+mod_troll(Troll_id, Content) ->
+   mnesia:transaction(
+      fun() ->
+         case mnesia:wread({troll, Troll_id}) of
+            [Troll = #troll{date_post = undefined}] ->
+               mnesia:write(Troll#troll{content = Content});
+            _ ->
+               mnesia:abort("mod_troll: Troll inconnu ou déjà posté")
+          end
+      end
+   ).
+   
+   
+del_troll(Troll_id) ->
+   mnesia:transaction(
+      fun() ->
+         case mnesia:wread({troll, Troll_id}) of
+            [#troll{date_post = undefined}] ->
+               mnesia:delete({troll, Troll_id});
+            _ ->
+               mnesia:abort("mod_troll: Troll inconnu ou déjà posté")
+          end
+      end
+   ).
    
 update_version(1) ->
    mnesia:transform_table(
index 8cddd03..d5f486f 100755 (executable)
@@ -30,8 +30,8 @@
 % @spec conversations([{integer(), integer(), integer()}], integer(), integer(), integer()) -> [Conversation()]
 conversations(Racines, N, D, P) ->
    % écoute des nouveaux messages
-   case subscribe(minichat, 2) of
-      erreur = E ->
+   case mnesia:subscribe({table, minichat, simple}) of
+      {error, E} = E ->
          E;
       _ ->
          % demande des conversations
@@ -55,31 +55,33 @@ conversations(Racines, N, D, P) ->
                Conversations
             end
          ),
-         unsubscribe(minichat),
+         mnesia:unsubscribe({table, minichat, simple}),
          Conversations_mises_en_forme
    end.
    
    
 % Ecoute les événements de modification d'une table.
 % @spec subscribe(atom(), integer()) -> ok | erreur
-subscribe(_Table, 0) ->
-   erreur;
-subscribe(Table, C) ->
-   case mnesia:subscribe({table, Table, simple}) of 
-       {error, {not_active_local, Table}} ->       
-         mnesia:add_table_copy(minichat, node(), ram_copies),
-         subscribe(Table, C - 1);
-      {error, _}->
-         erreur;
-      _ ->
-         ok
-   end.   
+% Obsolète
+%~ subscribe(_Table, 0) ->
+   %~ erreur;
+%~ subscribe(Table, C) ->
+   %~ case mnesia:subscribe({table, Table, simple}) of 
+       %~ {error, {not_active_local, Table}} ->
+         %~ mnesia:add_table_copy(minichat, node(), ram_copies),
+         %~ subscribe(Table, C - 1);
+      %~ {error, _}->
+         %~ erreur;
+      %~ _ ->
+         %~ ok
+   %~ end.   
    
    
 % Arrête d'écouter les modifications d'une table.
 % @spec unsubscribe(atom()) -> term()
-unsubscribe(Table) -> 
-   mnesia:unsubscribe({table, Table, simple}).
+% Obsolète
+%~ unsubscribe(Table) -> 
+   %~ mnesia:unsubscribe({table, Table, simple}).
  
  
 % Attend qu'un nouveau message arrive, function bloquante.
index c2342ca..5c8d6d8 100755 (executable)
@@ -13,6 +13,9 @@
    put_message/1,
    ban/1,
    slap/1,
+   put_troll/1,
+   mod_troll/1,
+   del_troll/1,
    erreur/1
 ]).\r
 
@@ -120,7 +123,7 @@ profile(
 
 % Renvoie les messages appropriés.
 % last_message id et cookie sont facultatifs
-wait_event(Data) ->
+wait_event([{page, "chat"} | Data]) ->
    Cookie = case lists:keysearch(cookie, 1, Data) of {value, {_, C}} -> C; _ -> inconnu end,
    Last_message_id = case lists:keysearch(last_message_id, 1, Data) of {value, {_, Id}} -> Id; _ -> 0 end,
    {value, {_, Message_count}} = lists:keysearch(message_count, 1, Data),
@@ -187,7 +190,48 @@ wait_event(Data) ->
             )
          )\r
       }}\r
-   ]}.
+   ]};
+wait_event([{page, "admin"}, {last_troll, Last_troll}]) ->
+   case euphorik_bd:trolls(Last_troll) of
+      {mod, Troll} ->
+         {struct,
+            [
+               {reply, "troll_modified"},
+               {troll_id, Troll#troll.id},
+               {content, Troll#troll.content}
+            ]
+         };
+      {add, Trolls} ->
+         {struct,
+            [
+               {reply, "troll_added"},
+               {trolls, {array, 
+                  lists:map(
+                     fun(T) ->                        
+                        {struct,
+                           [
+                              {troll_id, T#troll.id},
+                              {content, T#troll.content}
+                           ]
+                        }
+                     end,
+                     Trolls
+                  )
+               }}
+            ]
+         };         
+      {del, Troll_id} ->
+         {struct,
+            [
+               {reply, "troll_deleted"},
+               {troll_id, Troll_id}
+            ]
+         };                  
+      _ ->
+         erreur("timeout")
+   end;
+wait_event(_) ->
+   erreur("Page inconnue").
             
          
 % Un utilisateur envoie un message
@@ -243,7 +287,8 @@ ban(
    [
       {cookie, Cookie},
       {duration, Duration},
-      {user_id, User_id}
+      {user_id, User_id},
+      {reason, Reason}
    ]) ->
       % controle que l'utilisateur est un admin
       case euphorik_bd:user_by_cookie(Cookie) of
@@ -253,12 +298,13 @@ ban(
                   erreur("Il n'est pas possible de s'auto bannir");
                {ok, User2 = #user{ek_master = false}} ->
                   euphorik_bd:ban(User2#user.last_ip, Duration),
-                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s ~s est ~s pour ~s",
+                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s ~s est ~s pour ~s.~s",
                      [
                         User2#user.pseudo,
                         if User2#user.login =:= [] -> ""; true -> "(" ++ User2#user.login ++ ")" end,
                         if Duration =< 15 -> "kické"; true -> "banni" end,
-                        format_minutes(Duration)
+                        format_minutes(Duration),
+                        if Reason =/= [] -> " Raison: " ++ Reason; true -> "" end ++ "."
                      ]
                   ))),
                   json_reponse_ok();
@@ -276,19 +322,26 @@ ban(
 slap(
    [
       {cookie, Cookie},
-      {user_id, User_id}
+      {user_id, User_id},
+      {reason, Reason}
    ]) ->
       % controle que l'utilisateur est un admin
       case euphorik_bd:user_by_cookie(Cookie) of
          {ok, User1 = #user{ek_master = true}} ->
             case euphorik_bd:user_by_id(User_id) of
                {ok, User1} ->
-                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s s'auto slap (et il aime ça)", [User1#user.pseudo])));
+                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s s'auto slap~s.", 
+                     [
+                        User1#user.pseudo,
+                        if Reason =/= [] -> " Raison: " ++ Reason; true -> "" end
+                     ]
+                  )));
                {ok, User2 = #user{ek_master = false}} ->
-                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s se fait slaper par ~s",
+                  euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s se fait slaper par ~s.~s",
                      [
                         User2#user.pseudo,
-                        User1#user.pseudo
+                        User1#user.pseudo,
+                        if Reason =/= [] -> " Raison: " ++ Reason; true -> "" end ++ "."
                      ]
                   ))),
                   json_reponse_ok();
@@ -301,6 +354,73 @@ slap(
             erreur("Utilisateur inconnu ou non ek master")
       end.
       
+put_troll(
+   [
+      {cookie, Cookie},
+      {content, Content}
+   ]
+) ->
+   % controle que l'utilisateur est un admin
+   case euphorik_bd:user_by_cookie(Cookie) of
+      {ok, User = #user{ek_master = true}} ->
+         case euphorik_bd:put_troll(User#user.id, Content) of
+            max_troll_reached_per_user ->
+               erreur(lists:flatten(io_lib:format("Le nombre de troll maximum par utilisateur est atteint : ~w ", [?NB_MAX_TROLL_WAITING_BY_USER])));
+            max_troll_reached ->
+               erreur(lists:flatten(io_lib:format("Le nombre de troll maximum en attente est atteint : ~w ", [?NB_MAX_TROLL_WAITING])));
+            _Id ->
+               json_reponse_ok()
+         end;
+      _ ->
+         erreur("Seul les ekMaster peuvent proposer des trolls")
+   end.
+   
+   
+mod_troll(
+   [
+      {cookie, Cookie},
+      {troll_id, Troll_id},
+      {content, Content}
+   ]
+) ->
+   % controle que l'utilisateur est un admin
+   case euphorik_bd:user_by_cookie(Cookie) of
+      {ok, User = #user{ek_master = true}} ->
+         User_id = User#user.id,
+         case euphorik_bd:troll_by_id(Troll_id) of
+            {ok, #troll{id_user = User_id}} ->
+               euphorik_bd:mod_troll(User#user.id, Content),
+               json_reponse_ok();
+            _ ->
+               erreur("Vous ne posséder pas ce troll")
+         end;
+      _ ->
+         erreur("Seul les ekMaster peuvent proposer des trolls")
+      end.
+
+   
+del_troll(
+   [
+      {cookie, Cookie},
+      {troll_id, Troll_id}
+   ]
+) -> 
+   % controle que l'utilisateur est un admin
+   case euphorik_bd:user_by_cookie(Cookie) of
+      {ok, User = #user{ek_master = true}} ->
+         User_id = User#user.id,
+         case euphorik_bd:troll_by_id(Troll_id) of
+            {ok, #troll{id_user = User_id}} ->
+               euphorik_bd:del_troll(User#user.id),
+               json_reponse_ok();
+            _ ->
+               erreur("Vous ne posséder pas ce troll")
+         end;
+      _ ->
+         erreur("Seul les ekMaster peuvent proposer des trolls")
+   end.
+   
 
 % Construit une erreur
 erreur(Message) ->
index a7e2ae1..5c2e538 100755 (executable)
@@ -58,5 +58,11 @@ traiter_action("put_message", JSON, _) ->
 traiter_action("ban", JSON, _) ->
    euphorik_protocole:ban(JSON);
 traiter_action("slap", JSON, _) ->
-   euphorik_protocole:slap(JSON).
+   euphorik_protocole:slap(JSON);
+traiter_action("put_troll", JSON, _) ->
+   euphorik_protocole:put_troll(JSON);
+traiter_action("mod_troll", JSON, _) ->
+   euphorik_protocole:mod_troll(JSON);
+traiter_action("del_troll", JSON, _) ->
+   euphorik_protocole:del_troll(JSON).
  
\ No newline at end of file
index f1a2241..55f76cd 100755 (executable)
@@ -46,7 +46,7 @@
       conversations = [], % [{integer(), integer()}], la liste des messages correspondant au conversation ainsi que la page affichée
       ek_master = false,
       last_ip = undefined % integer(), undefined si inconnu\r
-   }). 
+   }).
 
 
 % identificateur : (ip)
@@ -68,6 +68,6 @@
       id_user,
       date_create, % erlang:now()
       date_post = undefined, % date à laquelle le troll est affiché sur la page principale. undefined initialement puis erlang:now() quand affiché
-      contenu % chaine de caractère
+      content % chaine de caractère
    }).
    
\ No newline at end of file
index 443437f..779a175 100755 (executable)
@@ -14,3 +14,9 @@
 -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). 
+
+
+% le nombre max de troll qui peuvent être en attente d'être posté (tous les utilisateurs réunis)
+-define(NB_MAX_TROLL_WAITING, 10).
+% chaque admin peut proposer 1 seul troll à la fois
+-define(NB_MAX_TROLL_WAITING_BY_USER, 1).
index 14eede6..263e789 100644 (file)
@@ -35,7 +35,8 @@ Il est déconseillé d'utiliser Microsoft Internet Explorer pour des raisons d'i
 
 
 <h3>Est-ce possible d'avoir les sources du site ?</h3>
-<p>Oui, un repository subversion accessible en lecture existe ici : svn://svn.euphorik.ch/euphorik</p>\r
+<p>Oui, un repository subversion accessible en lecture existe ici : svn://svn.euphorik.ch/euphorik</p>
+<p>Un accès web existe également ici : <a href="http://svn.euphorik.ch/index.cgi/euphorik/">http://svn.euphorik.ch/index.cgi/euphorik/</a></p>\r
 \r
 <h3>Ouais mais c'est libre au moins ?</h3>\r
 <p>Oui, euphorik.ch n'est développé qu'avec des logiciels et technologies libres et son code est proposé sous licence GPLv3.</p>
@@ -53,14 +54,14 @@ voici mon email/jabberID : {EMAIL}</p>
    <li>Présentation du document : <a href="http://www.w3.org/TR/CSS21/">CSS 2.1</a></li>
    <li>Programmation de la partie dynamique : <a href="http://fr.wikipedia.org/wiki/JavaScript">JavaScript</a></li>
    <li>Méthode de communication avec le serveur : <a href="http://en.wikipedia.org/wiki/Ajax_(programming)">AJAX</a>/<a href="http://en.wikipedia.org/wiki/Comet_(programming)">COMET</a></li>
-   <li>Bibliothèques JavaScript : <a href="http://jquery.com">jQuery</a> et <a href="http://www.lokeshdhakar.com/projects/lightbox2/">Lightbox</a></li>
+   <li>Bibliothèques JavaScript : <a href="http://jquery.com">jQuery</a> et <a href="http://leandrovieira.com/projects/jquery/lightbox/">jQuery lightBox plugin</a></li>
 </ul>
 <h4>Coté serveur</h4>
 <ul>
    <li>Langage de programmation : <a href="http://www.erlang.org">Erlang</a></li>
    <li>Serveur Web : <a href="http://yaws.hyber.org">Yaws</a></li>
    <li>Base de données : <a href="http://erlang.org/doc/apps/mnesia/index.html">Mnesia</a></li>
-   <li>OS : <a href="http://www.debian.org">Debian</a></li>
+   <li>Système d'exploitation : <a href="http://www.debian.org">Debian</a></li>
 </ul>
 <h4>Outils</h4>
 <ul>
@@ -72,7 +73,7 @@ voici mon email/jabberID : {EMAIL}</p>
 </ul>
 
 <h3>Comment est appelé le petit du gnou ?</h3>
-<p>Le gaou</p>
+<p>Le gaou.</p>
 
 
 <h2>Versions à venir</h2>