ADD FIX#50 : numérotation des erreurs et préparation à leur traduction (coté serveur
[euphorik.git] / modules / erl / euphorik_protocole.erl
index dbad874..82a4fce 100755 (executable)
@@ -25,7 +25,6 @@
 -export([\r
    register/2,\r
    login/2,\r
-   logout/1,\r
    profile/1,\r
    wait_event/1,\r
    put_message/1,\r
 \r
 \r
 % Une utilisateur s'enregistre avec un tuple {Login, Password}.\r
-register([{login, Login}, {password, Password}], IP) ->\r
+register([{login, Login}, {password, Password}, {profile, Profile_json}], IP) ->\r
    Can_register = euphorik_bd:can_register(IP),\r
    if Can_register ->\r
          case euphorik_bd:user_by_login(Login) of\r
             {ok, _} ->\r
-               erreur("Login déjà existant");\r
+               erreur(10);\r
             _ ->\r
-               User = euphorik_bd:nouveau_user(Login, Password, generer_cookie()),\r
+               User = euphorik_bd:nouveau_user(Login, Password, generer_cookie(), profile_from_json(Profile_json)),\r
                euphorik_bd:update_ip(User#user.id, IP),\r
                json_reponse_login_ok(User)\r
          end;\r
@@ -58,10 +57,11 @@ register([{login, Login}, {password, Password}], IP) ->
          erreur_register_flood()\r
    end;\r
 % Enregistrement sans {Login, Password}\r
-register([], IP) ->   \r
+register([{profile, Profile_json}], IP) ->   \r
    Can_register = euphorik_bd:can_register(IP),\r
    if Can_register ->\r
-         User = euphorik_bd:nouveau_user("<nick>", generer_cookie()),\r
+         Profile = profile_from_json(Profile_json),\r
+         User = euphorik_bd:nouveau_user(generer_cookie(), Profile#profile{pseudo = "<nick>"}),\r
          euphorik_bd:update_ip(User#user.id, IP),\r
          json_reponse_login_ok(User);\r
       true ->\r
@@ -69,7 +69,7 @@ register([], IP) ->
    end.\r
    \r
 erreur_register_flood() ->\r
-   erreur("Trop de register (flood)").\r
+   erreur(20).\r
    \r
 \r
 % Un utilisateur se logge (avec un couple {login, mot de passe})\r
@@ -79,7 +79,7 @@ login([{login, Login}, {password, Password}], IP) ->
          loginUser(User, IP);\r
       _ -> \r
          timer:sleep(?TEMPS_ATTENTE_ERREUR_LOGIN),\r
-         erreur("Couple login/pass introuvable")\r
+         erreur(30)\r
    end;\r
 % Un utilisateur se logge (avec un cookie)\r
 login([{cookie, Cookie}], IP) ->\r
@@ -88,9 +88,11 @@ login([{cookie, Cookie}], IP) ->
          loginUser(User, IP);\r
       _ ->\r
          timer:sleep(?TEMPS_ATTENTE_ERREUR_LOGIN),\r
-         erreur("Authentification impossible par cookie")\r
+         erreur(40)\r
    end.\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
@@ -104,26 +106,44 @@ generer_cookie() ->
    erlang:integer_to_list(random:uniform(math:pow(10, 32)), 36).\r
 \r
 \r
-% Un utilisateur se délogge.\r
-logout(_) ->\r
-   do_nothing.\r
-\r
-\r
 % Modification du profile.\r
 profile(\r
    [\r
       {cookie, Cookie},\r
       {login, Login},\r
       {password, Password},\r
-      {nick, Pseudo},\r
-      {email, Email},\r
-      {css, Css},\r
-      {nick_format, Nick_format_str},\r
-      {view_times, View_times},\r
-      {view_tooltips, View_tooltips},\r
-      {conversations, {array, Conversations_json}},\r
-      {ostentatious_master, Ostentatious_master}\r
+      {profile, Profile_json}\r
    ]\r
+) ->\r
+   case profile_from_json(Profile_json) of\r
+      {erreur, E} -> E;\r
+      Profile ->\r
+         case euphorik_bd:set_profile(Cookie, Login, Password, Profile) of\r
+            ok ->\r
+               json_reponse_ok();\r
+            login_deja_pris ->\r
+               erreur(10);\r
+            _ ->\r
+               erreur(50)\r
+         end\r
+   end.\r
+\r
+\r
+% Construit un #user à partir des données JSON\r
+profile_from_json(\r
+   {struct,\r
+      [\r
+         {nick, Pseudo},\r
+         {email, Email},\r
+         {css, Css},\r
+         {chat_order, Chat_order_str},\r
+         {nick_format, Nick_format_str},\r
+         {view_times, View_times},\r
+         {view_tooltips, View_tooltips},\r
+         {conversations, {array, Conversations_json}},\r
+         {ostentatious_master, Ostentatious_master_str}\r
+      ]\r
+   }\r
 ) ->\r
    % décomposition de la strucure JSON\r
    Conversations = lists:foldr(\r
@@ -139,29 +159,39 @@ profile(
       [],\r
       Conversations_json\r
    ),\r
-   %  TODO : pas très beau, mieux vaut construire un #user\r
-   case euphorik_bd:set_profile(\r
-         Cookie,\r
-         Login,\r
-         Password,\r
-         Pseudo,\r
-         Email,\r
-         Css,\r
-         list_to_atom(Nick_format_str),\r
-         View_times,\r
-         View_tooltips,\r
-         Conversations,\r
-         list_to_atom(Ostentatious_master)) of\r
-      ok ->\r
-         json_reponse_ok();\r
-      login_deja_pris ->\r
-         erreur("Login déjà pris");\r
-      _ ->\r
-         erreur("Impossible de mettre à jour le profile")\r
+   % vérification des données JSON\r
+   Chat_order = list_to_atom(Chat_order_str),\r
+   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
+         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
+               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
+                     {erreur, Ostentatious_master_str ++ " n'est pas une valeur acceptée pour 'ostentatious_master'"};\r
+                  true ->\r
+                     #profile{\r
+                        pseudo = Pseudo,\r
+                        email = Email,\r
+                        css = Css,\r
+                        chat_order = Chat_order,\r
+                        nick_format = Nick_format,\r
+                        view_times = View_times,\r
+                        view_tooltips = View_tooltips,\r
+                        conversations = Conversations,\r
+                        ostentatious_master = Ostentatious_master\r
+                     }\r
+               end\r
+         end      \r
    end.\r
 \r
 \r
-% Renvoie les messages appropriés.\r
+% Attend un événement pour la page "Chat"\r
 % last_message id et cookie sont facultatifs\r
 wait_event([{page, "chat"} | Data]) ->\r
    % traitement des inputs\r
@@ -192,6 +222,7 @@ wait_event([{page, "chat"} | Data]) ->
          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
       banned_ips_refresh ->\r
@@ -215,12 +246,12 @@ wait_event([{page, "admin"}, {last_troll, Last_troll}]) ->
                {trolls, {array, \r
                   lists:map(\r
                      fun(T) ->                        \r
-                        {ok, User} = euphorik_bd:user_by_id(T#troll.id_user),\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, User#user.pseudo},\r
+                              {author, Profile#profile.pseudo},\r
                               {author_id, User#user.id}\r
                            ]\r
                         }\r
@@ -238,12 +269,13 @@ wait_event([{page, "admin"}, {last_troll, Last_troll}]) ->
             ]\r
          };                  \r
       _ ->\r
-         erreur("timeout")\r
+         erreur(60)\r
    end;\r
 wait_event(_) ->\r
-   erreur("Page inconnue").\r
+   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
@@ -269,7 +301,7 @@ wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id
                         fun({Racine, {Conv, Plus}}) ->\r
                            {struct, [\r
                               {last_page, not Plus},\r
-                              {first, \r
+                              {first, % le premier message de la conversation\r
                                  if Racine =:= undefined orelse Conv =:= [] ->\r
                                        null;\r
                                     true ->\r
@@ -281,7 +313,7 @@ wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id
                                              null\r
                                        end\r
                                  end\r
-                              }, % le premier message de la conversation, peut correspondre\r
+                              },\r
                               {messages, {array,\r
                                  lists:map(\r
                                     fun({Mess, Repond_a}) ->\r
@@ -394,23 +426,23 @@ put_message(
       {ok, User} ->\r
          case euphorik_bd:est_banni(User#user.id) of\r
             {true, Temps_restant} ->\r
-               erreur("Vous êtes banni pour encore " ++ format_minutes(Temps_restant));\r
+               erreur(80, format_minutes(Temps_restant));\r
             _ ->\r
                Strip_content = string:strip(Content),\r
                if Strip_content =:= [] ->\r
-                     erreur("Message vide");\r
+                     erreur(90);\r
                   true ->\r
                      % attention : non-atomique (update_pseudo+nouveau_message)\r
                      euphorik_bd:update_pseudo_user(User#user.id, Nick),\r
                      case euphorik_bd:nouveau_message(Strip_content, User#user.id, Answer_to) of\r
-                        {erreur, R} -> erreur("Impossible d'ajouter un nouveau message. Raison : " ++ R);\r
+                        {erreur, R} -> erreur(100, R);\r
                         _ ->\r
                            json_reponse_ok()\r
                      end\r
                end\r
          end;\r
    _ ->\r
-      erreur("Utilisateur inconnu")\r
+      erreur(110)\r
    end.\r
 \r
 \r
@@ -427,12 +459,12 @@ ban(
          {ok, User1 = #user{ek_master = true}} ->\r
             case euphorik_bd:user_by_id(User_id) of\r
                {ok, User1} ->\r
-                  erreur("Il n'est pas possible de s'auto bannir");\r
-               {ok, User2 = #user{ek_master = false}} ->\r
+                  erreur(120);\r
+               {ok, #user{ek_master = false, profile = Profile2} = User2} ->\r
                   euphorik_bd:ban(User2#user.last_ip, Duration),\r
                   euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("''~s~s'' est ~s pour ~s.~s",\r
                      [\r
-                        User2#user.pseudo,\r
+                        Profile2#profile.pseudo,\r
                         if User2#user.login =:= [] -> ""; true -> " (" ++ User2#user.login ++ ")" end,\r
                         if Duration =< 15 -> "kické"; true -> "banni" end,\r
                         format_minutes(Duration),\r
@@ -441,12 +473,12 @@ ban(
                   ))),\r
                   json_reponse_ok();\r
                {ok, _} ->\r
-                  erreur("L'utilisateur est lui même un ekMaster");\r
+                  erreur(130);\r
                _ ->\r
-                  erreur("Utilisateur à bannir inconnu")\r
+                  erreur(140)\r
             end;\r
          _ ->\r
-            erreur("Utilisateur inconnu ou non ek master")\r
+            erreur(150)\r
       end.\r
       \r
 \r
@@ -459,32 +491,32 @@ slap(
    ]) ->\r
       % controle que l'utilisateur est un admin\r
       case euphorik_bd:user_by_cookie(Cookie) of\r
-         {ok, User1 = #user{ek_master = true}} ->\r
+         {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
                      [\r
-                        User1#user.pseudo,\r
+                        Profile1#profile.pseudo,\r
                         if Reason =/= [] -> " - Raison: " ++ Reason; true -> "" end\r
                      ]\r
                   ))),\r
                   json_reponse_ok();\r
-               {ok, User2 = #user{ek_master = false}} ->\r
+               {ok, #user{ek_master = false, profile = Profile2}} ->\r
                   euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s se fait slaper par ~s.~s",\r
                      [\r
-                        User2#user.pseudo,\r
-                        User1#user.pseudo,\r
+                        Profile2#profile.pseudo,\r
+                        Profile1#profile.pseudo,\r
                         if Reason =/= [] -> " - Raison: " ++ Reason; true -> "" end ++ "."\r
                      ]\r
                   ))),\r
                   json_reponse_ok();\r
                {ok, _} ->\r
-                  erreur("L'utilisateur est lui même un ekMaster");\r
+                  erreur(130);\r
                _ ->\r
-                  erreur("Utilisateur à slaper inconnu")\r
+                  erreur(160)\r
             end;\r
          _ ->\r
-            erreur("Utilisateur inconnu ou non ek master")\r
+            erreur(170)\r
       end.\r
       \r
  \r
@@ -499,14 +531,14 @@ put_troll(
       {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(lists:flatten(io_lib:format("Le nombre de troll maximum par utilisateur est atteint : ~w ", [?NB_MAX_TROLL_WAITING_BY_USER])));\r
+               erreur(180, ?NB_MAX_TROLL_WAITING_BY_USER);\r
             max_troll_reached ->\r
-               erreur(lists:flatten(io_lib:format("Le nombre de troll maximum en attente est atteint : ~w ", [?NB_MAX_TROLL_WAITING])));\r
+               erreur(190, ?NB_MAX_TROLL_WAITING);\r
             _Id ->\r
                json_reponse_ok()\r
          end;\r
       _ ->\r
-         erreur("Seul les ekMaster peuvent proposer des trolls")\r
+         erreur(200)\r
    end.\r
    \r
    \r
@@ -526,10 +558,10 @@ mod_troll(
                euphorik_bd:mod_troll(Troll_id, Content),\r
                json_reponse_ok();\r
             _ ->\r
-               erreur("Vous ne posséder pas ce troll")\r
+               erreur(210)\r
          end;\r
       _ ->\r
-         erreur("Seul les ekMaster peuvent proposer des trolls")\r
+         erreur(220)\r
       end.\r
 \r
    \r
@@ -548,10 +580,10 @@ del_troll(
                euphorik_bd:del_troll(Troll_id),\r
                json_reponse_ok();\r
             _ ->\r
-               erreur("Vous ne posséder pas ce troll")\r
+               erreur(210)\r
          end;\r
       _ ->\r
-         erreur("Seul les ekMaster peuvent proposer des trolls")\r
+         erreur(220)\r
    end.\r
    \r
    \r
@@ -566,7 +598,7 @@ unban_ip(
          euphorik_bd:deban(euphorik_common:unserialize_ip(IP)),\r
          json_reponse_ok();\r
       _ ->\r
-         erreur("Seul les ekMaster peuvent connaitre la liste des ips bannies")\r
+         erreur(230)\r
    end.\r
    \r
    \r
@@ -606,16 +638,25 @@ list_banned_ips(
             ]\r
          };\r
       _ ->\r
-         erreur("Seul les ekMaster peuvent connaitre la liste des ips bannies")\r
+         erreur(230)\r
    end.\r
 \r
 \r
 % Construit une erreur\r
-erreur(Message) ->\r
+erreur(Num, Args) ->\r
+   erreur_json(Num, lists:flatten(io_lib:format(euphorik_bd:get_texte(Num), Args))).\r
+   \r
+   \r
+erreur(Num) ->\r
+   erreur_json(Num, euphorik_bd:get_texte(Num)).\r
+   \r
+   \r
+erreur_json(Num, Mess) ->\r
    {\r
       struct, [\r
          {reply, "error"},\r
-         {error_message, Message}\r
+         {no, Num},\r
+         {error_message, Mess}\r
       ]\r
    }.\r
    \r
@@ -661,28 +702,33 @@ json_reponse_ok() ->
    {struct, [{reply, "ok"}]}.\r
    \r
    \r
-json_reponse_login_ok(User) ->\r
+json_reponse_login_ok(#user{profile = Profile} = User) ->\r
    {\r
       struct, [\r
          {reply, "login"},\r
          {status, if (User#user.password =/= []) and (User#user.login =/= []) -> "auth_registered"; true -> "auth_not_registered" end},\r
          {cookie, User#user.cookie},\r
          {id, User#user.id},\r
-         {nick, User#user.pseudo},\r
          {login, User#user.login},\r
-         {email, User#user.email},\r
-         {css, User#user.css},\r
-         {nick_format, atom_to_list(User#user.nick_format)},\r
-         {view_times, User#user.view_times},\r
-         {view_tooltips, User#user.view_tooltips},\r
-         {conversations, {array, lists:map(\r
-            fun({Racine, Reduit}) ->\r
-               {struct, [{root, Racine}, {minimized, Reduit}]}\r
-            end,\r
-            User#user.conversations\r
-         )}},\r
          {ek_master, User#user.ek_master},\r
-         {ostentatious_master, atom_to_list(User#user.ostentatious_master)}\r
+         {profile, {struct,\r
+            [\r
+               {nick, Profile#profile.pseudo},\r
+               {email, Profile#profile.email},\r
+               {css, Profile#profile.css},\r
+               {chat_order, atom_to_list(Profile#profile.chat_order)},\r
+               {nick_format, atom_to_list(Profile#profile.nick_format)},\r
+               {view_times, Profile#profile.view_times},\r
+               {view_tooltips, Profile#profile.view_tooltips},\r
+               {conversations, {array, lists:map(\r
+                  fun({Racine, Reduit}) ->\r
+                     {struct, [{root, Racine}, {minimized, Reduit}]}\r
+                  end,\r
+                  Profile#profile.conversations\r
+               )}},\r
+               {ostentatious_master, atom_to_list(Profile#profile.ostentatious_master)}\r
+            ]\r
+         }}\r
       ]\r
    }.\r
    \r
@@ -694,7 +740,7 @@ json_message(Mess, Repond_a, User) ->
    Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id,\r
    A_repondu_a_message = User =/= inconnu andalso euphorik_bd:a_repondu_a_message(User#user.id, Mess#minichat.id),\r
    Est_une_reponse_a_user = User =/= inconnu andalso euphorik_bd:est_une_reponse_a_user(User#user.id, Mess#minichat.id),\r
-   {ok, User_mess } = euphorik_bd:user_by_id(Mess#minichat.auteur_id),\r
+   {ok,  #user{profile = Profile_mess} = User_mess } = euphorik_bd:user_by_id(Mess#minichat.auteur_id),\r
    {struct, [\r
       {id, Mess#minichat.id},\r
       {user_id, User_mess#user.id},\r
@@ -716,5 +762,5 @@ json_message(Mess, Repond_a, User) ->
          Repond_a\r
       )}},\r
       {ek_master, User_mess#user.ek_master},\r
-      {ostentatious_master, atom_to_list(User_mess#user.ostentatious_master)}\r
+      {ostentatious_master, atom_to_list(Profile_mess#profile.ostentatious_master)}\r
    ]}.\r