📄 mod_muc_room.erl
字号:
ejabberd_router:route( jlib:jid_replace_resource( StateData#state.jid, ToNick), From, Err); ToJID -> {ok, #user{nick = FromNick}} = ?DICT:find(jlib:jid_tolower(From), StateData#state.users), ejabberd_router:route( jlib:jid_replace_resource( StateData#state.jid, FromNick), ToJID, Packet) end end; _ -> ErrText = "Only occupants are allowed to send messages to the conference", Err = jlib:make_error_reply( Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route( jlib:jid_replace_resource( StateData#state.jid, ToNick), From, Err) end, {next_state, normal_state, StateData} end;normal_state({route, From, ToNick, {xmlelement, "iq", Attrs, _Els} = Packet}, StateData) -> Lang = xml:get_attr_s("xml:lang", Attrs), case {(StateData#state.config)#config.allow_query_users, is_user_online(From, StateData)} of {true, true} -> case find_jid_by_nick(ToNick, StateData) of false -> case jlib:iq_query_info(Packet) of reply -> ok; _ -> ErrText = "Recipient is not in the conference room", Err = jlib:make_error_reply( Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), ejabberd_router:route( jlib:jid_replace_resource( StateData#state.jid, ToNick), From, Err) end; ToJID -> {ok, #user{nick = FromNick}} = ?DICT:find(jlib:jid_tolower(From), StateData#state.users), ejabberd_router:route( jlib:jid_replace_resource(StateData#state.jid, FromNick), ToJID, Packet) end; {_, false} -> case jlib:iq_query_info(Packet) of reply -> ok; _ -> ErrText = "Only occupants are allowed to send queries to the conference", Err = jlib:make_error_reply( Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), ejabberd_router:route( jlib:jid_replace_resource(StateData#state.jid, ToNick), From, Err) end; _ -> case jlib:iq_query_info(Packet) of reply -> ok; _ -> ErrText = "Queries to the conference members are not allowed in this room", Err = jlib:make_error_reply( Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)), ejabberd_router:route( jlib:jid_replace_resource(StateData#state.jid, ToNick), From, Err) end end, {next_state, normal_state, StateData};normal_state(Event, StateData) -> io:format("MUC: unknown event ~p~n", [Event]), {next_state, normal_state, StateData}.%%----------------------------------------------------------------------%% Func: handle_event/3%% Returns: {next_state, NextStateName, NextStateData} |%% {next_state, NextStateName, NextStateData, Timeout} |%% {stop, Reason, NewStateData} %%----------------------------------------------------------------------handle_event({service_message, Msg}, _StateName, StateData) -> MessagePkt = {xmlelement, "message", [{"type", "groupchat"}], [{xmlelement, "body", [], [{xmlcdata, Msg}]}]}, lists:foreach( fun({_LJID, Info}) -> ejabberd_router:route( StateData#state.jid, Info#user.jid, MessagePkt) end, ?DICT:to_list(StateData#state.users)), NSD = add_message_to_history("", MessagePkt, StateData), {next_state, normal_state, NSD};handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}.%%----------------------------------------------------------------------%% Func: handle_sync_event/4%% Returns: {next_state, NextStateName, NextStateData} |%% {next_state, NextStateName, NextStateData, Timeout} |%% {reply, Reply, NextStateName, NextStateData} |%% {reply, Reply, NextStateName, NextStateData, Timeout} |%% {stop, Reason, NewStateData} |%% {stop, Reason, Reply, NewStateData} %%----------------------------------------------------------------------handle_sync_event({get_disco_item, JID, Lang}, _From, StateName, StateData) -> FAffiliation = get_affiliation(JID, StateData), FRole = get_role(JID, StateData), Tail = case ((StateData#state.config)#config.public_list == true) orelse (FRole /= none) orelse (FAffiliation == admin) orelse (FAffiliation == owner) of true -> Desc = case (StateData#state.config)#config.public of true -> ""; _ -> translate:translate(Lang, "private, ") end, Len = length(?DICT:to_list(StateData#state.users)), " (" ++ Desc ++ integer_to_list(Len) ++ ")"; _ -> "" end, Reply = case ((StateData#state.config)#config.public == true) orelse (FRole /= none) orelse (FAffiliation == admin) orelse (FAffiliation == owner) of true -> {item, get_title(StateData) ++ Tail}; _ -> false end, {reply, Reply, StateName, StateData};handle_sync_event(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData}.code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}.%%----------------------------------------------------------------------%% Func: handle_info/3%% Returns: {next_state, NextStateName, NextStateData} |%% {next_state, NextStateName, NextStateData, Timeout} |%% {stop, Reason, NewStateData} %%----------------------------------------------------------------------handle_info(_Info, StateName, StateData) -> {next_state, StateName, StateData}.%%----------------------------------------------------------------------%% Func: terminate/3%% Purpose: Shutdown the fsm%% Returns: any%%----------------------------------------------------------------------terminate(_Reason, _StateName, StateData) -> mod_muc:room_destroyed(StateData#state.room), ok.%%%----------------------------------------------------------------------%%% Internal functions%%%----------------------------------------------------------------------route(Pid, From, ToNick, Packet) -> gen_fsm:send_event(Pid, {route, From, ToNick, Packet}).is_user_online(JID, StateData) -> LJID = jlib:jid_tolower(JID), ?DICT:is_key(LJID, StateData#state.users).role_to_list(Role) -> case Role of moderator -> "moderator"; participant -> "participant"; visitor -> "visitor"; none -> "none" end.affiliation_to_list(Affiliation) -> case Affiliation of owner -> "owner"; admin -> "admin"; member -> "member"; outcast -> "outcast"; none -> "none" end.list_to_role(Role) -> case Role of "moderator" -> moderator; "participant" -> participant; "visitor" -> visitor; "none" -> none end.list_to_affiliation(Affiliation) -> case Affiliation of "owner" -> owner; "admin" -> admin; "member" -> member; "outcast" -> outcast; "none" -> none end.set_affiliation(JID, Affiliation, StateData) -> LJID = jlib:jid_remove_resource(jlib:jid_tolower(JID)), Affiliations = case Affiliation of none -> ?DICT:erase(LJID, StateData#state.affiliations); _ -> ?DICT:store(LJID, Affiliation, StateData#state.affiliations) end, StateData#state{affiliations = Affiliations}.get_affiliation(JID, StateData) -> {_AccessRoute, _AccessCreate, AccessAdmin} = StateData#state.access, case acl:match_rule(AccessAdmin, JID) of allow -> owner; _ -> LJID = jlib:jid_remove_resource(jlib:jid_tolower(JID)), case ?DICT:find(LJID, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; _ -> none end end.set_role(JID, Role, StateData) -> LJID = jlib:jid_tolower(JID), LJIDs = case LJID of {U, S, ""} -> ?DICT:fold( fun(J, _, Js) -> case J of {U, S, _} -> [J | Js]; _ -> Js end end, [], StateData#state.users); _ -> case ?DICT:is_key(LJID, StateData#state.users) of true -> [LJID]; _ -> [] end end, Users = case Role of none -> lists:foldl(fun(J, Us) -> ?DICT:erase(J, Us) end, StateData#state.users, LJIDs); _ -> lists:foldl(fun(J, Us) -> {ok, User} = ?DICT:find(J, Us), ?DICT:store(J, User#user{role = Role}, Us) end, StateData#state.users, LJIDs) end, StateData#state{users = Users}.get_role(JID, StateData) -> LJID = jlib:jid_tolower(JID), case ?DICT:find(LJID, StateData#state.users) of {ok, #user{role = Role}} -> Role; _ -> none end.get_default_role(Affiliation, StateData) -> case Affiliation of owner -> moderator; admin -> moderator; member -> participant; outcast -> none; none -> case (StateData#state.config)#config.members_only of true -> none; _ -> case (StateData#state.config)#config.members_by_default of true -> participant; _ -> visitor end end end.add_online_user(JID, Nick, Role, StateData) -> LJID = jlib:jid_tolower(JID), Users = ?DICT:store(LJID, #user{jid = JID, nick = Nick, role = Role}, StateData#state.users), StateData#state{users = Users}.remove_online_user(JID, StateData) -> LJID = jlib:jid_tolower(JID), Users = ?DICT:erase(LJID, StateData#state.users), StateData#state{users = Users}.filter_presence({xmlelement, "presence", Attrs, Els}) -> FEls = lists:filter( fun(El) -> case El of {xmlcdata, _} -> false; {xmlelement, Name1, _Attrs1, _Els1} -> XMLNS = xml:get_attr_s("xmlns", Attrs), case {Name1, XMLNS} of {"show", ""} -> true; {"status", ""} -> true; _ -> false end end end, Els), {xmlelement, "presence", Attrs, FEls}.add_user_presence(JID, Presence, StateData) -> LJID = jlib:jid_tolower(JID), FPresence = filter_presence(Presence), Users = ?DICT:update( LJID, fun(#user{} = User) -> User#user{last_presence = FPresence} end, StateData#state.users), StateData#state{users = Users}.add_user_presence_un(JID, Presence, StateData) -> LJID = jlib:jid_tolower(JID), FPresence = filter_presence(Presence), Users = ?DICT:update( LJID, fun(#user{} = User) -> User#user{last_presence = FPresence, role = none} end, StateData#state.users), StateData#state{users = Users}.is_nick_exists(Nick, StateData) -> ?DICT:fold(fun(_, #user{nick = N}, B) -> B orelse (N == Nick) end, false, StateData#state.users).find_jid_by_nick(Nick, StateData) -> ?DICT:fold(fun(_, #user{jid = JID, nick = N}, R) -> case Nick of N -> JID; _ -> R end end, false, StateData#state.users).is_nick_change(JID, Nick, StateData) -> LJID = jlib:jid_tolower(JID), case Nick of "" -> false; _ -> {ok, #user{nick = OldNick}} = ?DICT:find(LJID, StateData#state.users), Nick /= OldNick end.add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) -> Lang = xml:get_attr_s("xml:lang", Attrs), case {is_nick_exists(Nick, StateData), mod_muc:can_use_nick(From, Nick)} of {true, _} -> ErrText = "Nickname is already in use by another occupant", Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), ejabberd_router:route( % TODO: s/Nick/""/ jlib:jid_replace_resource(StateData#state.jid, Nick), From, Err), StateData; {_, false} -> ErrText = "Nickname is registered by another person", Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), ejabberd_router:route( % TODO: s/Nick/""/ jlib:jid_replace_resource(StateData#state.jid, Nick), From, Err), StateData; _ -> Affiliation = get_affiliation(From, StateData), Role = get_default_role(Affiliation, StateData), case Role of none -> Err = jlib:make_error_reply( Packet, case Affiliation of outcast -> ErrText = "You have been banned from this room", ?ERRT_FORBIDDEN(Lang, ErrText); _ -> ErrText = "Membership required to enter this room", ?ERRT_REGISTRATION_REQUIRED(Lang, ErrText) end), ejabberd_router:route( % TODO: s/Nick/""/ jlib:jid_replace_resource(StateData#state.jid, Nick), From, Err), StateData; _ -> case check_password(Affiliation, Els, StateData) of true -> NewState = add_user_presence( From, Packet,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -