0

I wanna add a possibility to ejabberd-2.1.12 to be invisible in MUC via presence "invisible" (I know that in 3.x.x versions of ejabberd this will be deprecated, - I'll do that for site via http-bind).

so the task is: send non-directed presence "invisible" and in every room user connected change it's StateData.

so I modified ejabberd_c2s.erl and when user changes his non-directed presence, he sends to mod_muc_room.erl notification

function mod_muc_room.erl :

room_state() ->
 receive
    Msg ->  (any data about user, presence),
 room_state()
end.

so room knows that user changed his presence and it should change it's own StateData, but how can I get this value, modify and inject(replace) it to this room?

DeMiRioN
  • 3
  • 1

1 Answers1

0

mod_muc_room uses the gen_fsm behaviour. You can tell since this line is near the top of the file:

-behaviour(gen_fsm).

To receive and handle a message sent to a gen_fsm process you wouldn't use receive directly, but rather add a new clause to the handle_info function.

For example, there is a clause that handles the {process_user_presence, From} message. It starts with:

handle_info({process_user_presence, From}, normal_state = _StateName, StateData) ->

and eventually ends up in something like:

{next_state, normal_state, StateData1}

where StateData1 is a modified form of StateData. This is how you modify the state of the room.

legoscia
  • 39,593
  • 22
  • 116
  • 167
  • Thank you, legoscia, for your answer, but I registered new process with name of each room in mod_muc_room.erl and knew that name of process is unique just like name of room: global:register_name(Room, spawn(fun() -> room_state() end)) in ejabberd_c2s.erl I send for example such data: Pid_receiver=global:whereis_name("example_room_name"), Pid_receiver!{User_name, invisible} and got {User_name, invisible} in mod_muc_room.erl How and where should I send data from ejabberd_c2s.erl to mod_muc_room.erl {user_invisible, User_name} if I use handle_info like you sayed? – DeMiRioN May 02 '13 at 15:31
  • Not sure what the best way to do that is, but `mod_muc` calls `mnesia:dirty_read(muc_online_room, {Room, Host})`, which should return a list of one record `[R]`, from which you can get the pid with `Pid = R#muc_online_room.pid`. Then you can send the message with `Pid ! {User_name, invisible}` and handle it in `handle_info`. (Example from [here](https://github.com/processone/ejabberd/blob/v2.1.12/src/mod_muc/mod_muc.erl#L545-L581)) – legoscia May 03 '13 at 14:52
  • thanks, legoscia, it's too bad but I use mysql and there isn't realized this, so I'll try to make something like this: every room after start in gen_fsm:start_link/3 returns {ok, Pid} and this Pid for room I'll save/update by name of room to mysql-database and will know where I have to send data. And I've got one question: legoscia, StateData in ejabberd_c2s.erl is different from StateData in mod_muc_room.erl, do you think that I send {User_name, invisible} to PID and in handle_info({process_user_presence, From}, normal_state = _StateName, StateData) get current StateData of that room? – DeMiRioN May 03 '13 at 16:29
  • legoscia, I did all I described and sent to pid gen_fsm data and there I printed results: handle_info({user_invisible, From}, normal_state = _StateName, StateData) -> file:write_file("/home/demirion/myfile", io_lib:fwrite("user invisible: StateData =~p\n,", [StateData]),[append]), {next_state, normal_state, StateData}; StateData has real current StateData of connected room with all another users connected, - thanks, my problem solved! I haven't 15 reputation yet so I can't vote your answer but I will! ;) – DeMiRioN May 05 '13 at 20:47