font-family: sans-serif;\r
font-size: 12px;
color: #EEEEEE;\r
- text-align: center; /* uniquement pour IE */\r
+ /*text-align: center;*/ /* uniquement pour IE */\r
background-color: #DFDFDF;\r
background-image: url(../../img/css1/fond.png)\r
}\r
left: 300px;
font-size: 11px;
background-color: #000000;
- text-align: left;
}
#menu div {
cursor: pointer;
position: relative;
font-size: 12px;
background-color: #000000;
- text-align : left;
padding: 30px 10px 15px 10px;
}
border-style: none;\r
}\r
\r
-div#info {\r
+div#info {
+ text-align: center;\r
width:100%;\r
position: fixed;\r
left: 0px;\r
#page.minichat {
padding: 25px 0px 15px 0px;
- text-align: center
}
#page.minichat img {
margin-left: 1px
}
+#page.minichat #trollCourant {
+ border-top: 1px solid;
+ border-bottom: 1px solid;
+ border-color: #253f18;
+ background-color: #0c2003;
+ margin-top: 4px;
+ margin-bottom: 8px;
+ padding : 1px 0px 1px 10px
+}
+
+#page.minichat #trollCourant .troll {
+ font-style: italic;
+ color: #FFFF88
+}
+
#page.minichat .titreSmiles:hover {
background-color: #2d8800;
}
#page.minichat form {
- text-align: left;
margin-bottom: 15px;
padding-left: 10px;
}
border-left-width: 5px;
border-left-style: solid;
border-color: transparent;
- text-align: left;
padding-right: 5px;
padding-left: 4px;
cursor: pointer;
}
#page.minichat #conversations .titre {
+ text-align: center;
padding-right: 8px;
background-color: #4b4215
}
\r
=== v1.0 ===
-* Est-ce que client.dernierMessageErreur est vraiment utile ??\r
+* Est-ce que client.dernierMessageErreur est vraiment utile ??
+* Problème des images dans les trolls
+* Finir l'édition (mémoriser le contenu) des trolls
+* marquer <aucun login> lors de l'affichage des login dans le chat pour les personnes n'en ayant pas\r
[80%] Un statut "EK" avec plein de privilège à la con. (avoir une petite étoile à coté de son nick ou le nick d'une certaine couleur)\r
* Une page "admin" avec :\r
* Trolls : La liste des trolls proposés. L'admin peut éditer ses propres trolls.\r
L'ordre des conversation est le même que celui des données de l'utilisateur.\r
Le format de la date n'est pas formel.\r
{\r
- "reply" : "new_messages",\r
+ "reply" : "new_message",\r
"conversations" : [\r
{\r
"last_page" : true | false,\r
{
$("span", troll).css("display", "none")
$(troll).append(
- '<form><p><input class="content" type="text" size="50" maxlength="500" value="' + $(".content", troll).html() + '"></input><span class="modifier">modifier</span><span class="annuler">annuler</span></p></form>'
+ '<form><p><input class="content" type="text" size="50" maxlength="500" value="' +
+ $(".contentPasFormate", troll).html() +
+ '"></input><span class="modifier">modifier</span><span class="annuler">annuler</span></p></form>'
)
var virerLeFormulaire = function()
{
$("form", troll).remove()
- $("span", troll).css("display", "inline")
+ $('span', troll).css("display", "inline")
}
$("span.modifier", troll).click(
function()
thisTrolls.dernierTroll = data["trolls"][data["trolls"].length - 1]["troll_id"]
break
case "troll_modified" :
- $("#trolls #troll" + data["troll_id"] + " .content").html(data["content"])
+ $("#trolls #troll" + data["troll_id"] + " .content").html(thisTrolls.formateur.traitementComplet(data["content"], $("#trolls #troll" + data["troll_id"] + " .author").html()))
+ $("#trolls #troll" + data["troll_id"] + " .contentPasFormat").html(data["content"])
break
case "troll_deleted" :
$("#trolls #troll"+data["troll_id"]).remove()
PageMinichat.prototype.contenu = function()
{
return '\
+<div id="trollCourant">Troll de la semaine : <span class="troll"></span></div>\
<form method="post" action="">\
<p>\
<input class="captcha" name="captcha" type="text" size="8" maxlength="8"></input>\
this.conversations = new Array() // les conversations, la première représente la conversation principale
this.nouvelleConversation(0)
+ this.trollIdCourant = 0
+
this.pageEvent = new PageEvent("chat", this.util)
}
var mess = {
"message_count" : conf.nbMessageAffiche,
"main_page" : this.client.pagePrincipale,
- "conversations" : this.getJSONConversations()
+ "conversations" : this.getJSONConversations(),
+ "troll_id" : this.trollIdCourant
}
- if (this.client.cookie != null) mess["cookie"] = this.client.cookie;
+ if (this.client.cookie != null) mess["cookie"] = this.client.cookie
mess["last_message_id"] = this.conversations[0].idDernierMessageAffiche
return mess
function() { return thisMessages.getJSONrafraichirMessages() },
function(data)
{
- if (vider)
- {
- thisMessages.viderMessages()
- vider = false
- }
-
- // ajoute les messages reçus à leur conversation respective
- for (var numConv = 0; numConv < data["conversations"].length; numConv++)
- {
- if (! thisMessages.ajouterMessages(data["conversations"][numConv], numConv))
+ if (vider)
+ {
+ thisMessages.viderMessages()
+ vider = false
+ }
+
+ // en fonction du message
+ switch(data["reply"])
+ {
+ case "new_troll" :
+ thisMessages.trollIdCourant = data["troll_id"]
+ $("#trollCourant .troll").html(thisMessages.formateur.traitementComplet(data["content"]))
+ break
+
+ case "new_messages" :
+ // ajoute les messages reçus à leur conversation respective
+ for (var numConv = 0; numConv < data["conversations"].length; numConv++)
{
- thisMessages.util.messageDialogue("La conversation {" + thisMessages.client.conversations[numConv -1].root.toString(36) + "} n'existe pas")
- thisMessages.client.supprimerConversation(numConv - 1)
+ if (! thisMessages.ajouterMessages(data["conversations"][numConv], numConv))
+ {
+ thisMessages.util.messageDialogue("La conversation {" + thisMessages.client.conversations[numConv -1].root.toString(36) + "} n'existe pas")
+ thisMessages.client.supprimerConversation(numConv - 1)
+ }
}
- }
+ break
+ }
}
)
}
% trolls :
trolls/0,
trolls/1,
+ trolls_attente/1,
put_troll/2,
mod_troll/2,
del_troll/1,
troll_by_id/1,
+ current_troll/0,
+ elire_troll/0,
% versions :
update_version/1,
% utiles :
resultat_transaction/1\r
-]).\r
+]).
+
+-import(qlc, [e/1, e/2, q/1, cursor/1]).\r
\r
-include("../include/euphorik_bd.hrl").
-include("../include/euphorik_defines.hrl").\r
% Renvoie tous les users.
users() ->
resultat_transaction(mnesia:transaction(fun() ->
- qlc:e(qlc:q([E || E <- mnesia:table(user)]))
+ e(q([E || E <- mnesia:table(user)]))
end)).
user_by_cookie(Cookie) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([E || E <- mnesia:table(user), E#user.cookie =:= Cookie])) of
+ case e(q([E || E <- mnesia:table(user), E#user.cookie =:= Cookie])) of
[User] -> {ok, User};
_ -> erreur
end
user_by_id(ID) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([E || E <- mnesia:table(user), E#user.id =:= ID])) of
+ case e(q([E || E <- mnesia:table(user), E#user.id =:= ID])) of
[User] -> {ok, User};
_ -> erreur
end
user_by_login(Login) ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
- Users = qlc:e(qlc:q([E || E <- mnesia:table(user), E#user.login =:= Login])),\r
+ Users = e(q([E || E <- mnesia:table(user), E#user.login =:= Login])),\r
case Users of\r
[User] -> {ok, User};\r
_ -> erreur\r
toggle_ek_master(User_id) ->
resultat_transaction(mnesia:transaction(
fun() ->
- Users = qlc:e(qlc:q([E || E <- mnesia:table(user), E#user.id =:= User_id])),
+ Users = e(q([E || E <- mnesia:table(user), E#user.id =:= User_id])),
case Users of
[User] ->
mnesia:write(User#user{ek_master = not User#user.ek_master});
user_by_login_password(Login, Password) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([E || E <- mnesia:table(user), E#user.login =:= Login, E#user.password =:= Password])) of
+ case e(q([E || E <- mnesia:table(user), E#user.login =:= Login, E#user.password =:= Password])) of
[User | _] -> {ok, User};
_ -> erreur
end
user_by_mess(Id) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([U || U <- mnesia:table(user), M <- mnesia:table(minichat), M#minichat.id =:= Id, M#minichat.auteur_id =:= U#user.id])) of
+ case e(q([U || U <- mnesia:table(user), M <- mnesia:table(minichat), M#minichat.id =:= Id, M#minichat.auteur_id =:= U#user.id])) of
[User | _] -> {ok, User};
_ -> erreur
end
nouveau_message(Mess, Auteur_id, Repond_A) ->
% regarde si les id 'Repond_A' existent
F = fun() ->
- Nb_id_trouve = length(qlc:e(qlc:q([E#minichat.id || E <- mnesia:table(minichat), lists:member(E#minichat.id, Repond_A)]))),
+ Nb_id_trouve = length(e(q([E#minichat.id || E <- mnesia:table(minichat), lists:member(E#minichat.id, Repond_A)]))),
% est-ce que l'auteur existe ?
- Auteur = case qlc:e(qlc:q([E || E <- mnesia:table(user), E#user.id =:= Auteur_id])) of
+ Auteur = case e(q([E || E <- mnesia:table(user), E#user.id =:= Auteur_id])) of
[A] -> A;
_ -> throw("L'auteur du message est introuvable")
end,
% Renvoie N messages se trouvant sur la page P
messages(N, P) ->
F = fun() ->
- C = qlc:cursor(qlc:q([E || E <- qlc:keysort(2, mnesia:table(minichat), [{order, descending}])])),
+ C = cursor(q([E || E <- qlc:keysort(2, mnesia:table(minichat), [{order, descending}])])),
if P > 1 -> qlc:next_answers(C, N * (P - 1));
true -> ok
end,
message_by_id(Id) ->
case resultat_transaction(mnesia:transaction(
fun() ->
- qlc:e(qlc:q([E || E <- qlc:keysort(2, mnesia:table(minichat), [{order, ascending}]), Id =:= E#minichat.id]))
+ e(q([E || E <- qlc:keysort(2, mnesia:table(minichat), [{order, ascending}]), Id =:= E#minichat.id]))
end
)) of
[M] -> {ok, M};
resultat_transaction(mnesia:transaction(
fun() ->
% TODO : optimisations ? serait-ce du O(n) ?
- Query = qlc:q([E || E <- qlc:keysort(2, mnesia:table(minichat), [{order, ascending}]), lists:any(fun(Id) -> Id =:= E#minichat.id end, Ids)]),
- qlc:e(Query)
+ Query = q([E || E <- qlc:keysort(2, mnesia:table(minichat), [{order, ascending}]), lists:any(fun(Id) -> Id =:= E#minichat.id end, Ids)]),
+ e(Query)
end
)).
% TODO : ya pas plus simple ?
message_existe(Id) ->
resultat_transaction(mnesia:transaction(fun() ->
- length(qlc:e(qlc:q([E#minichat.id || E <- mnesia:table(minichat), E#minichat.id =:= Id]))) =:= 1
+ length(e(q([E#minichat.id || E <- mnesia:table(minichat), E#minichat.id =:= Id]))) =:= 1
end)).
% Renvoie les reponses (utilisé normalement uniquement pendant le debug).
reponses() ->
F = fun() ->
- qlc:e(qlc:q([E || E <- mnesia:table(reponse_minichat)]))
+ e(q([E || E <- mnesia:table(reponse_minichat)]))
end,
resultat_transaction(mnesia:transaction(F)).
repond_a(M_id) ->
resultat_transaction(mnesia:transaction(
fun() ->
- qlc:e(qlc:q(
+ e(q(
[M || E <- mnesia:table(reponse_minichat),
M <- mnesia:table(minichat),
E#reponse_minichat.repondant =:= M_id,
est_une_reponse_a_user(Id_user, Id_mess) ->
case mnesia:transaction(
fun() ->
- qlc:e(qlc:q([
+ e(q([
M#minichat.auteur_id || M <- mnesia:table(minichat), R <- mnesia:table(reponse_minichat),
M#minichat.auteur_id =:= Id_user, M#minichat.id =:= R#reponse_minichat.cible, R#reponse_minichat.repondant =:= Id_mess
]), [{unique_all, true}])
a_repondu_a_message(Id_user, Id_mess) ->
case mnesia:transaction(
fun() ->
- qlc:e(qlc:q([
+ e(q([
M#minichat.auteur_id || M <- mnesia:table(minichat), R <- mnesia:table(reponse_minichat),
R#reponse_minichat.cible =:= Id_mess, R#reponse_minichat.repondant =:= M#minichat.id, M#minichat.auteur_id =:= Id_user
]), [{unique_all, true}])
possede_message(Id_user, Id_mess) ->
case mnesia:transaction(
fun() ->
- qlc:e(qlc:q([E#minichat.auteur_id || E <- mnesia:table(minichat), E#minichat.id =:= Id_mess]))
+ e(q([E#minichat.auteur_id || E <- mnesia:table(minichat), E#minichat.id =:= Id_mess]))
end
) of
{atomic, [Id_user | []]} -> true;
ip_table() ->
resultat_transaction(mnesia:transaction(
fun() ->
- qlc:e(qlc:q([IP || IP <- mnesia:table(ip_table)]))
+ e(q([IP || IP <- mnesia:table(ip_table)]))
end
)).
est_banni(User_id) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([
+ case e(q([
{IP#ip_table.ban, IP#ip_table.ban_duration} ||
U <- mnesia:table(user),
U#user.id =:= User_id,
can_register(IP) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([I || I <- mnesia:table(ip_table), I#ip_table.ip =:= IP])) of
+ case e(q([I || I <- mnesia:table(ip_table), I#ip_table.ip =:= IP])) of
[] ->
mnesia:write(#ip_table{ip = IP, date_last_try_register = now()}),
true;
trolls() ->
resultat_transaction(mnesia:transaction(
fun() ->
- qlc:e(qlc:q([T || T <- qlc:keysort(2, mnesia:table(troll))]))
+ e(q([T || T <- qlc:keysort(2, mnesia:table(troll))]))
end
)).
+
+% Renvoie les trolls manquants posté après Last_id.
+trolls(Last_id) ->
+ resultat_transaction(mnesia:transaction(
+ e(q([T || T <- qlc:keysort(2, mnesia:table(troll)), T#troll.id > Last_id, T#troll.date_post =:= undefined]))
+ )).
+
+
% 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 :
% ou {add, [Trolls]}
% ou {del, Troll_id}
% ou timeout
-trolls(Last_id) ->
+trolls_attente(Last_id) ->
case mnesia:subscribe({table, troll, detailed}) of
{error, E} = E ->
E;
_ ->
- case resultat_transaction(mnesia:transaction(
+ R = case resultat_transaction(mnesia:transaction(
fun() ->
- qlc:e(qlc:q([T || T <- qlc:keysort(2, mnesia:table(troll)), T#troll.id > Last_id, T#troll.date_post =:= undefined]))
+ e(q([T || T <- qlc:keysort(2, 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,
+ mnesia:unsubscribe({table, troll, detailed}),
+ R
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
+ % cas où un troll est choisit comme courant
+ {mnesia_table_event, {write, troll, Troll, [Old_troll | _], _}} when Old_troll#troll.date_post =:= undefined, Troll#troll.date_post =/= undefined ->
+ {del, Troll#troll.id};
{mnesia_table_event, {write, troll, Troll, [_Old_troll | _], _}} ->
{mod, Troll};
{mnesia_table_event, {write, troll, Troll, [], _}} ->
resultat_transaction(mnesia:transaction(
fun() ->
% control le nombre de troll déjà posté
- Nb_troll_poste_par_user = length(qlc:e(qlc:q(
+ Nb_troll_poste_par_user = length(e(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(
+ Nb_troll_poste_total = length(e(q(
[
E#troll.id || E <- mnesia:table(troll),
E#troll.date_post =:= undefined
troll_by_id(Troll_id) ->
resultat_transaction(mnesia:transaction(
fun() ->
- case qlc:e(qlc:q([T || T <- mnesia:table(troll), T#troll.id =:= Troll_id])) of
+ case e(q([T || T <- mnesia:table(troll), T#troll.id =:= Troll_id])) of
[T] -> {ok, T};
_ ->
erreur
end
)).
+
+% Renvoie le troll actuel qui se trouve sur la page principale.
+% Renvois aucun si pas de troll courant.
+current_troll() ->
+ resultat_transaction(mnesia:transaction(
+ fun() ->
+ % TODO : ya pas moyen de désigner le champs plutot qu'avec un nombre pour le tri ?
+ C = cursor(q([T || T <- qlc:keysort(5, mnesia:table(troll), [{order, descending}]), T#troll.date_post =/= undefined])),
+ R = case qlc:next_answers(C, 1) of
+ [T] -> T;
+ _ -> aucun
+ end,
+ qlc:delete_cursor(C),
+ R
+ end
+ )).
+
+
+% Elit un troll au hasard parmis les trolls en attente (leur date_post =:= undefined)
+% met à jour sa date de post.
+% renvoie plus_de_trolls si il n'y a aucun troll en attente.
+elire_troll() ->
+ {A1,A2,A3} = now(),
+ random:seed(A1, A2, A3),
+ mnesia:transaction(
+ fun() ->
+ case e(q([T || T <- mnesia:table(troll), T#troll.date_post =:= undefined])) of
+ [] ->
+ plus_de_trolls;
+ Trolls ->
+ Troll = lists:nth(random:uniform(length(Trolls)), Trolls),
+ Troll2 = Troll#troll{date_post = now()},
+ mnesia:write(Troll2)
+ end
+ end
+ ).
+
+
update_version(1) ->
mnesia:transform_table(
--- /dev/null
+% Module tournant en background s'occupant periodiquement de certaines tâches.\r
+% Auteur : G.Burri\r
+% Date : 05.11.2007\r
+\r
+-module(euphorik_deamon).
+-export([start/1]).
+
+-include("../include/euphorik_defines.hrl").\r
+
+
+% Démarre le démon
+start(A) ->\r
+ loop(A).
+
+\r
+loop(A) ->
+ euphorik_bd:elire_troll(),\r
+ timer:sleep(1000),\r
+ loop(A).
+\r
+
+
% Chaque conversation est un tuple {[{Message, Parents}], Plus} où
% Message est le message de type #minichat et Parents une liste d'Id.
% Plus est un bool. Si Plus vaut true alors il y a encore des messages.
-% Si il n'y a pas de nouveaux message alors la fonction est bloquante et attend un nouveau message.
+% Si il n'y a pas de nouveaux message alors vide est renvoyé.
% @spec conversations([{integer(), integer(), integer()}], integer(), integer(), integer()) -> [Conversation()]
conversations(Racines, N, D, P) ->
- % écoute des nouveaux messages
- case mnesia:subscribe({table, minichat, simple}) of
- {error, E} = E ->
- E;
- _ ->
- % demande des conversations
- Conversations = conversations_detailees(Racines, N, D, P),
- % si les conversations sont vides alors on attend un nouveau message
- Vide = not any(
- fun(C) ->
- case C of
- {[], _} -> false;
- {_, [], _, _} -> false;
- _ -> true
- end
- end,
- Conversations
- ),
- Conversations_mises_en_forme = mise_en_forme_conversations(
- if Vide ->
- attend_nouveau_message(),
- conversations_detailees(Racines, N, D, P);
- true ->
- Conversations
+ Conversations = conversations_detailees(Racines, N, D, P),
+ % si les conversations sont vides alors on attend un nouveau message
+ Vide = not any(
+ fun(C) ->
+ case C of
+ {[], _} -> false;
+ {_, [], _, _} -> false;
+ _ -> true
end
- ),
- mnesia:unsubscribe({table, minichat, simple}),
- Conversations_mises_en_forme
- end.
+ end,
+ Conversations
+ ),
+ if Vide ->
+ vide;
+ true ->
+ mise_en_forme_conversations(Conversations)
+ end.
% Ecoute les événements de modification d'une table.
% Attend qu'un nouveau message arrive, function bloquante.
% Renvoie le nouveau message.
+% Obsolète
% @spec attend_nouveau_message() -> #minichat | timeout
-attend_nouveau_message() ->
- receive % attente d'un post
- {mnesia_table_event, {write, Message, _}} ->
- Message;
- %file:close(F);
+%~ attend_nouveau_message() ->
+ %~ receive % attente d'un post
+ %~ {mnesia_table_event, {write, Message, _}} ->
+ %~ Message;
+ %~ %file:close(F);
%~ {tcp_closed, _} ->
%~ mnesia:unsubscribe({table, minichat, simple});
- _ ->
- attend_nouveau_message()
+ %~ _ ->
+ %~ attend_nouveau_message()
% 60 minutes de timeout (le cas ou il n'y a que des consultations et jamais de post)
% Après 60 minutes de connexion, le client doit donc reétablir une connexion
% TODO : pour être mieux : quand le socket se ferme alors un message devrait être envoyé et débloquer ce receive (demande en cours sur la mailing list de yaws)
- after 1000 * 60 * 60 ->
- timeout
- end.
+ %~ after 1000 * 60 * 60 ->
+ %~ timeout
+ %~ end.
% Mise en forme des conversations pour l'utilisateur du module.
euphorik_bd:update_date_derniere_connexion(User#user.id),
json_reponse_login_ok(User);
loginUser(_, _) ->
- % ajoute un délais d'attente (TODO : un autre moyen plus élégant ?)
- receive after 1000 ->
- erreur("Erreur login")
- end.
+ % ajoute un délais d'attente
+ timer:sleep(1000),
+ erreur("Erreur login").
\r
% Renvoie un string() représentant un cookie en base 36. Il y a 10^32 possibillités.\r
% Renvoie les messages appropriés.
% last_message id et cookie sont facultatifs
wait_event([{page, "chat"} | Data]) ->
+ % traitement des inputs
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),
Main_page = case lists:keysearch(main_page, 1, Data) of {value, {_, P}} -> P; _ -> 1 end,
+ Troll_id = case lists:keysearch(troll_id, 1, Data) of {value, {_, T}} -> T; _ -> 0 end,
{value, {_, {array, Conversations_json}}} = lists:keysearch(conversations, 1, Data),
- Conversations = lists:map(
+ Racines_conversations = lists:map(
fun({struct, [{root, Racine}, {page, Page} | Reste]}) ->
Last_mess_conv = case Reste of [{last_message_id, L}] -> L; _ -> 0 end,
{Racine, Page, Last_mess_conv}
User = case euphorik_bd:user_by_cookie(Cookie) of\r
{ok, U} -> U;\r
_ -> inconnu\r
- end,\r
- {struct, [\r
- {reply, "new_message"},\r
- {conversations, {array,
- % accrochez-vous ca va siouxer ;)
- lists:map(
- fun({Conv, Plus}) ->
- {struct, [
- {last_page, not Plus},
- {messages, {array,
- lists:map(
- fun({Mess, Repond_a}) ->
- Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id,
- A_repondu_a_message = User =/= inconnu andalso euphorik_bd:a_repondu_a_message(User#user.id, Mess#minichat.id),
- Est_une_reponse_a_user = User =/= inconnu andalso euphorik_bd:est_une_reponse_a_user(User#user.id, Mess#minichat.id),
- {ok, User_mess } = euphorik_bd:user_by_id(Mess#minichat.auteur_id),
- {struct, [
- {id, Mess#minichat.id},
- {user_id, User_mess#user.id},
- {date, format_date(Mess#minichat.date)},
- {system, Mess#minichat.auteur_id =:= 0},
- {owner, Est_proprietaire},
- {answered, A_repondu_a_message},
- {is_a_reply, Est_une_reponse_a_user},
- {nick, Mess#minichat.pseudo},
- {login, User_mess#user.login},
- {content, Mess#minichat.contenu},
- {answer_to, {array, lists:map(
- fun(Id_mess) ->
- {ok, M} = euphorik_bd:message_by_id(Id_mess),
- {ok, User_reponse} = euphorik_bd:user_by_mess(M#minichat.id),
- {struct, [{id, M#minichat.id}, {nick, M#minichat.pseudo}, {login, User_reponse#user.login}]}
- end,
- Repond_a
- )}},
- {ek_master, User_mess#user.ek_master}
- ]}
- end,
- Conv
- )
- }}
- ]}
- end,
- euphorik_minichat_conversation:conversations(
- Conversations,
- Message_count,
- Last_message_id,
- Main_page
- )
- )\r
- }}\r
- ]};
+ end,
+ case {mnesia:subscribe({table, minichat, detailed}), mnesia:subscribe({table, troll, detailed})} of
+ {{error, E}, _} -> E;
+ {_, {error, E}} -> E;
+ _ ->
+ % attente d'événements
+ R = wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id),
+ mnesia:unsubscribe({table, minichat, detailed}),
+ mnesia:unsubscribe({table, troll, detailed}),
+ R
+ end;
wait_event([{page, "admin"}, {last_troll, Last_troll}]) ->
- case euphorik_bd:trolls(Last_troll) of
+ case euphorik_bd:trolls_attente(Last_troll) of
{mod, Troll} ->
{struct,
[
end;
wait_event(_) ->
erreur("Page inconnue").
-
+
+
+wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id) ->
+ % est-ce qu'il y a des nouveaux messages ?
+ case euphorik_minichat_conversation:conversations(Racines_conversations, Message_count, Last_message_id, Main_page) of
+ vide ->
+ % est-ce que le troll est à jour ?
+ case euphorik_bd:current_troll() of
+ Current when is_record(Current, troll), Current#troll.id =/= Troll_id ->
+ {struct, [
+ {reply, "new_troll"},
+ {troll_id, Current#troll.id},
+ {content, Current#troll.content}
+ ]};
+ _ ->
+ wait_event_bd_page_chat(),
+ % TODO : l'appel est-il bien tail-recursive ?
+ wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id)
+ end;
+ Conversations ->
+ % accrochez-vous ca va siouxer ;)
+ {struct, [
+ {reply, "new_messages"},
+ {conversations, {array,
+ lists:map(
+ fun({Conv, Plus}) ->
+ {struct, [
+ {last_page, not Plus},
+ {messages, {array,
+ lists:map(
+ fun({Mess, Repond_a}) ->
+ Est_proprietaire = User =/= inconnu andalso User#user.id =:= Mess#minichat.auteur_id,
+ A_repondu_a_message = User =/= inconnu andalso euphorik_bd:a_repondu_a_message(User#user.id, Mess#minichat.id),
+ Est_une_reponse_a_user = User =/= inconnu andalso euphorik_bd:est_une_reponse_a_user(User#user.id, Mess#minichat.id),
+ {ok, User_mess } = euphorik_bd:user_by_id(Mess#minichat.auteur_id),
+ {struct, [
+ {id, Mess#minichat.id},
+ {user_id, User_mess#user.id},
+ {date, format_date(Mess#minichat.date)},
+ {system, Mess#minichat.auteur_id =:= 0},
+ {owner, Est_proprietaire},
+ {answered, A_repondu_a_message},
+ {is_a_reply, Est_une_reponse_a_user},
+ {nick, Mess#minichat.pseudo},
+ {login, User_mess#user.login},
+ {content, Mess#minichat.contenu},
+ {answer_to, {array, lists:map(
+ fun(Id_mess) ->
+ {ok, M} = euphorik_bd:message_by_id(Id_mess),
+ {ok, User_reponse} = euphorik_bd:user_by_mess(M#minichat.id),
+ {struct, [{id, M#minichat.id}, {nick, M#minichat.pseudo}, {login, User_reponse#user.login}]}
+ end,
+ Repond_a
+ )}},
+ {ek_master, User_mess#user.ek_master}
+ ]}
+ end,
+ Conv
+ )
+ }}
+ ]}
+ end,
+ Conversations
+ )
+ }}
+ ]}
+ end.
+
+
+% Attend un événement lié à la page 'chat'.
+wait_event_bd_page_chat() ->
+ receive % attente d'un post
+ {mnesia_table_event, {write, minichat, _Message, [], _}} ->
+ ok;
+ {mnesia_table_event, {write, troll, Troll, [Old_troll | _], _}} when Troll#troll.date_post =/= undefined, Old_troll#troll.date_post == undefined ->
+ ok;
+ _ ->
+ wait_event_bd_page_chat()
+ % 60 minutes de timeout (le cas ou il n'y a que des consultations et jamais de post)
+ % Après 60 minutes de connexion, le client doit donc reétablir une connexion
+ % TODO : pour être mieux : quand le socket se ferme alors un message devrait être envoyé et débloquer ce receive (demande en cours sur la mailing list de yaws)
+ after 1000 * 60 * 60 ->
+ timeout
+ end.
+
% Un utilisateur envoie un message
put_message(