X-Git-Url: http://git.euphorik.ch/?p=euphorik.git;a=blobdiff_plain;f=modules%2Ferl%2Feuphorik_bd.erl;h=4fecb737d8f19afd2da9d276746cb902e0229e15;hp=921bac5e67b796b55e2b4de9e0e2f07c4764b19f;hb=e290f3af3f37ca377712b02460da8b3c4ce02d3d;hpb=bd9caeefe3cfc9b4194c31052b0ddd4da26f604c diff --git a/modules/erl/euphorik_bd.erl b/modules/erl/euphorik_bd.erl index 921bac5..4fecb73 100755 --- a/modules/erl/euphorik_bd.erl +++ b/modules/erl/euphorik_bd.erl @@ -24,6 +24,10 @@ -module(euphorik_bd). -export([ + % texte : + get_texte/1, + get_texte/2, + % users : nouveau_user/2, nouveau_user/4, @@ -42,7 +46,6 @@ % messages : nouveau_message/3, nouveau_message_sys/1, - nouveau_message_sys/2, messages/1, messages/2, messages/3, @@ -74,7 +77,6 @@ troll_by_id/1, current_troll/0, elire_troll/0, - message_id_associe/1, % utiles : resultat_transaction/1 @@ -85,6 +87,20 @@ -include_lib("stdlib/include/qlc.hrl"). +get_texte(Id) -> + get_texte(Id, fr). + + +% TODO : généraliser la langue +get_texte(Id, _Lang = fr) -> + resultat_transaction(mnesia:transaction(fun() -> + case mnesia:read({texte, Id}) of + [#texte{fr = Texte}] -> Texte; + _ -> "Message " ++ integer_to_list(Id) ++ " unknown" + end + end)). + + % Ajoute un nouveau user et le renvoie nouveau_user(Cookie, Profile) -> F = fun() -> @@ -258,11 +274,17 @@ user_by_mess(Id) -> % retourne soit l'id du message soit {erreur, }. nouveau_message(Mess, Auteur_id, Repond_A_ids) -> % regarde si les id 'Repond_A' existent - F = fun() -> - Repond_a = e( - q([M || M <- mnesia:table(minichat), lists:member(M#minichat.id, Repond_A_ids)]), - [{tmpdir, ?KEY_SORT_TEMP_DIR}] - ), + F = fun() -> + Repond_a = lists:foldr( + fun(Repond_a_id, Acc) -> + case mnesia:read({minichat, Repond_a_id}) of + [M] -> [M | Acc]; + _ -> Acc % le message n'est pas trouvé + end + end, + [], + Repond_A_ids + ), Racine_id = case Repond_a of [] -> undefined; [M | _] -> @@ -274,47 +296,48 @@ nouveau_message(Mess, Auteur_id, Repond_A_ids) -> _ -> {erreur, "Les messages ne font pas partie de la même conversation"} end - end, - case Racine_id of - {erreur, E} -> {erreur, E}; - _ -> - % est-ce que l'auteur existe ? - case e(q([E || E <- mnesia:table(user), E#user.id =:= Auteur_id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of - [#user{profile = Profile} = Auteur] -> - if length(Repond_a) =/= length(Repond_A_ids) -> - {erreur, "Un ou plusieurs messages introuvable"}; - true -> + end, + if length(Repond_a) =/= length(Repond_A_ids) -> + {erreur, "Un ou plusieurs messages introuvable"}; + true -> + case Racine_id of + {erreur, E} -> {erreur, E}; + _ -> + % est-ce que l'auteur existe ? + case mnesia:wread({user, Auteur_id}) of + [#user{profile = Profile} = Auteur] -> % comparaison entre la date du dernier poste et maintenant (gestion du flood) - Delta = euphorik_common:delta_date_ms(Auteur#user.date_derniere_connexion, now()), + Now = now(), + Delta = euphorik_common:delta_date_ms(Auteur#user.date_derniere_connexion, Now), Nouvel_indice_flood = Auteur#user.indice_flood + if Delta =< ?DUREE_SPAM -> 2; true -> -1 end, Auteur_maj = Auteur#user{ indice_flood = if Nouvel_indice_flood > ?INDICE_SPAM_MAX -> ?INDICE_SPAM_MAX; Nouvel_indice_flood < 0 -> 0; true -> Nouvel_indice_flood end, - date_derniere_connexion = now() + date_derniere_connexion = Now }, % 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("''" ++ 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."); - Auteur#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM -> - {erreur, "Bloqué pour cause de flood"}; - true -> - mnesia:write(Auteur_maj), - Id = nouvel_id(minichat), - inserer_reponses(Id, Repond_A_ids), - mnesia:write(#minichat{ - id = Id, - auteur_id = Auteur#user.id, - date = now(), - pseudo = Profile#profile.pseudo, - contenu = Mess, - racine_id = if Racine_id =:= undefined -> Id; true -> Racine_id end - }), - Id - end - end; - _ -> - {erreur, "L'auteur du message est introuvable"} - end + mnesia:write(Auteur#user{indice_flood = Auteur_maj#user.indice_flood}), + 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."); + Auteur#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM -> + {erreur, "Bloqué pour cause de flood"}; + true -> + mnesia:write(Auteur_maj), + Id = nouvel_id(minichat), + inserer_reponses(Id, Repond_A_ids), + mnesia:write(#minichat{ + id = Id, + auteur_id = Auteur#user.id, + date = Now, + pseudo = Profile#profile.pseudo, + contenu = Mess, + racine_id = if Racine_id =:= undefined -> Id; true -> Racine_id end + }), + Id + end; + _ -> + {erreur, "L'auteur du message est introuvable"} + end + end end end, resultat_transaction(mnesia:transaction(F)). @@ -330,16 +353,11 @@ inserer_reponses(_, []) -> % Permet de créer un message système. % Renvoie l'id du message système nouveau_message_sys(Mess) -> - nouveau_message_sys(Mess, undefined). - - -% Création d'un message système lié à un troll. -nouveau_message_sys(Mess, Troll_id) -> {ok, #user{profile = Profile}} = user_by_id(0), resultat_transaction(mnesia:transaction( fun() -> Id = nouvel_id(minichat), - mnesia:write(#minichat{id = Id, auteur_id = 0, date = now(), pseudo = Profile#profile.pseudo, contenu = Mess, troll_id = Troll_id, racine_id = Id}), + mnesia:write(#minichat{id = Id, auteur_id = 0, date = now(), pseudo = Profile#profile.pseudo, contenu = Mess, racine_id = Id}), Id end )). @@ -350,26 +368,29 @@ messages(N) -> messages(N, 1). -% Renvoie N messages se trouvant sur la page P +% Renvoie N messages se trouvant sur la page P +% TODO FIXME : fonction en O(N * P) ! messages(N, P) -> - F = fun() -> - C = cursor( - qlc:keysort( - #minichat.id, - q([E#minichat{contenu = contenu_message(E)} || E <- mnesia:table(minichat)]), - [{order, descending}] - ), - [{tmpdir, ?KEY_SORT_TEMP_DIR}] - ), - if P > 1 -> qlc:next_answers(C, N * (P - 1)); - true -> ok - end, - R = qlc:next_answers(C, N), - qlc:delete_cursor(C), - R + F = fun() -> + % % #minichat{contenu = contenu_message(E)} + get_tuples_avant(minichat, reculer(minichat, mnesia:last(minichat), N * (P - 1)), N) end, - lists:reverse(resultat_transaction(mnesia:transaction(F))). - + resultat_transaction(mnesia:transaction(F)). + +get_tuples_avant(Table, Id, N) -> + get_tuples_avant(Table, Id, N, []). +get_tuples_avant(_, '$end_of_table', _, Tuples) -> Tuples; +get_tuples_avant(_, _, 0, Tuples) -> + Tuples; +get_tuples_avant(Table, Id, N, Tuples) -> + [T] = mnesia:read({Table, Id}), + get_tuples_avant(Table, mnesia:prev(Table, Id), N - 1, [T | Tuples]). + +reculer(_, '$end_of_table' = Fin, _) -> Fin; +reculer(_, Id, 0) -> Id; +reculer(Table, Id, N) -> + reculer(Table, mnesia:prev(Table, Id), N - 1). + % Renvoie les messages manquants pour la page P en sachant qu'il y a N message % par page et que le dernier message que l'on possède est Id @@ -390,9 +411,9 @@ message_by_id(Id) -> % Renvoie le contenu d'un message donnée en fonction du troll associé, à utiliser à l'intérieur d'une transaction. -% TODO : Cette fonction pourrait être remplacé par un "outer-join", est-ce possible avec qlc ? +% TODO : Cette fonction pourrait être remplacée par un "outer-join", est-ce possible avec qlc ? contenu_message(E) -> - case mnesia:read({troll, E#minichat.troll_id}) of + case mnesia:index_read(troll, E#minichat.id, #troll.id_minichat) of [] -> E#minichat.contenu; [T] -> E#minichat.contenu ++ T#troll.content end. @@ -634,7 +655,7 @@ can_register(IP) -> if T#ip_table.nb_try_register =:= ?NB_MAX_FLOOD_REGISTER, Delta < ?TEMPS_BAN_FLOOD_REGISTER -> false; true -> - mnesia:write(#ip_table{ + mnesia:write(T#ip_table{ ip = IP, date_last_try_register = now(), nb_try_register = T#ip_table.nb_try_register + if Delta < ?TEMPS_FLOOD_REGISTER -> 1; T#ip_table.nb_try_register > 0 -> -1; true -> 0 end @@ -774,26 +795,13 @@ elire_troll() -> plus_de_trolls; Trolls -> Troll = lists:nth(random:uniform(length(Trolls)), Trolls), - Troll2 = Troll#troll{date_post = now()}, - mnesia:write(Troll2), - nouveau_message_sys("Troll de la semaine : ", Troll2#troll.id) + Id_message = nouveau_message_sys("Troll de la semaine : "), + Troll2 = Troll#troll{date_post = now(), id_minichat = Id_message}, + mnesia:write(Troll2) end end ). - -% Renvoie l'id du message associé au troll dont l'id est donnée. -% Renvoie undefined si il n'y en a pas. -message_id_associe(Troll_id) -> - resultat_transaction(mnesia:transaction( - fun() -> - case e(q([M#minichat.id || M <- mnesia:table(minichat), M#minichat.troll_id =:= Troll_id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of - [Id] -> Id; - _ -> undefined - end - end - )). - % Renvoie le résultat d'une transaction (en décomposant le tuple fournit) resultat_transaction({_, T}) ->