📄 mod_irc_connection.erl
字号:
Res = lists:concat( lists:map( fun(S) -> io_lib:format("PRIVMSG ~s :~s\r\n", [Nick, S]) end, Strings)), ?SEND(Res) end; "error" -> stop; _ -> StateData end, if NewStateData == stop -> {stop, normal, StateData}; true -> {next_state, StateName, NewStateData} end;handle_info({route_nick, Nick, Packet}, StateName, StateData) -> {next_state, StateName, StateData};handle_info({ircstring, [$P, $I, $N, $G, $ | ID]}, StateName, StateData) -> send_text(StateData, "PONG " ++ ID ++ "\r\n"), {next_state, StateName, StateData};handle_info({ircstring, [$: | String]}, StateName, StateData) -> Words = string:tokens(String, " "), NewStateData = case Words of [_, "353" | Items] -> process_channel_list(StateData, Items); [_, "332", Nick, [$# | Chan] | _] -> process_channel_topic(StateData, Chan, String), StateData; [From, "PRIVMSG", [$# | Chan] | _] -> process_chanprivmsg(StateData, Chan, From, String), StateData; [From, "NOTICE", [$# | Chan] | _] -> process_channotice(StateData, Chan, From, String), StateData; [From, "PRIVMSG", Nick, ":\001VERSION\001" | _] -> process_version(StateData, Nick, From), StateData; [From, "PRIVMSG", Nick | _] -> process_privmsg(StateData, Nick, From, String), StateData; [From, "NOTICE", Nick | _] -> process_notice(StateData, Nick, From, String), StateData; [From, "TOPIC", [$# | Chan] | _] -> process_topic(StateData, Chan, From, String), StateData; [From, "PART", [$# | Chan] | _] -> process_part(StateData, Chan, From, String); [From, "QUIT" | _] -> process_quit(StateData, From, String); [From, "JOIN", Chan | _] -> process_join(StateData, Chan, From, String); [From, "MODE", [$# | Chan], "+o", Nick | _] -> process_mode_o(StateData, Chan, From, Nick, "admin", "moderator"), StateData; [From, "MODE", [$# | Chan], "-o", Nick | _] -> process_mode_o(StateData, Chan, From, Nick, "member", "participant"), StateData; [From, "KICK", [$# | Chan], Nick | _] -> process_kick(StateData, Chan, From, Nick), StateData; [From, "NICK", Nick | _] -> process_nick(StateData, From, Nick); _ -> ?DEBUG("unknown irc command '~s'~n", [String]), StateData end, NewStateData1 = case StateData#state.outbuf of "" -> NewStateData; Data -> send_text(NewStateData, Data), NewStateData#state{outbuf = ""} end, {next_state, stream_established, NewStateData1};handle_info({ircstring, [$E, $R, $R, $O, $R | _] = String}, StateName, StateData) -> process_error(StateData, String), {next_state, StateName, StateData};handle_info({ircstring, String}, StateName, StateData) -> ?DEBUG("unknown irc command '~s'~n", [String]), {next_state, StateName, StateData};handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), {next_state, StateName, StateData};handle_info({tcp, Socket, Data}, StateName, StateData) -> Buf = StateData#state.inbuf ++ binary_to_list(Data), {ok, Strings} = regexp:split([C || C <- Buf, C /= $\r], "\n"), ?DEBUG("strings=~p~n", [Strings]), NewBuf = process_lines(StateData#state.encoding, Strings), {next_state, StateName, StateData#state{inbuf = NewBuf}};handle_info({tcp_closed, Socket}, StateName, StateData) -> gen_fsm:send_event(self(), closed), {next_state, StateName, StateData};handle_info({tcp_error, Socket, Reason}, StateName, StateData) -> gen_fsm:send_event(self(), closed), {next_state, StateName, StateData}.%%----------------------------------------------------------------------%% Func: terminate/3%% Purpose: Shutdown the fsm%% Returns: any%%----------------------------------------------------------------------terminate(Reason, StateName, StateData) -> mod_irc:closed_conection(StateData#state.user, StateData#state.server), bounce_messages("Server Connect Failed"), lists:foreach( fun(Chan) -> ejabberd_router:route( jlib:make_jid( lists:concat([Chan, "%", StateData#state.server]), StateData#state.myname, StateData#state.nick), StateData#state.user, {xmlelement, "presence", [{"type", "error"}], [{xmlelement, "error", [{"code", "502"}], [{xmlcdata, "Server Connect Failed"}]}]}) end, dict:fetch_keys(StateData#state.channels)), case StateData#state.socket of undefined -> ok; Socket -> gen_tcp:close(Socket) end, ok.%%%----------------------------------------------------------------------%%% Internal functions%%%----------------------------------------------------------------------receiver(Socket, C2SPid) -> XMLStreamPid = xml_stream:start(C2SPid), receiver(Socket, C2SPid, XMLStreamPid).receiver(Socket, C2SPid, XMLStreamPid) -> case gen_tcp:recv(Socket, 0) of {ok, Text} -> xml_stream:send_text(XMLStreamPid, Text), receiver(Socket, C2SPid, XMLStreamPid); {error, Reason} -> exit(XMLStreamPid, closed), gen_fsm:send_event(C2SPid, closed), ok end.send_text(#state{socket = Socket, encoding = Encoding}, Text) -> CText = iconv:convert("utf-8", Encoding, lists:flatten(Text)), %?DEBUG("IRC OUTu: ~s~nIRC OUTk: ~s~n", [Text, CText]), gen_tcp:send(Socket, CText).%send_queue(Socket, Q) ->% case queue:out(Q) of% {{value, El}, Q1} ->% send_element(Socket, El),% send_queue(Socket, Q1);% {empty, Q1} ->% ok% end.bounce_messages(Reason) -> receive {send_element, El} -> {xmlelement, Name, Attrs, SubTags} = El, case xml:get_attr_s("type", Attrs) of "error" -> ok; _ -> Err = jlib:make_error_reply(El, "502", Reason), From = jlib:string_to_jid(xml:get_attr_s("from", Attrs)), To = jlib:string_to_jid(xml:get_attr_s("to", Attrs)), ejabberd_router:route(To, From, Err) end, bounce_messages(Reason) after 0 -> ok end.route_chan(Pid, Channel, Resource, Packet) -> Pid ! {route_chan, Channel, Resource, Packet}.route_nick(Pid, Nick, Packet) -> Pid ! {route_nick, Nick, Packet}.process_lines(Encoding, [S]) -> S;process_lines(Encoding, [S | Ss]) -> self() ! {ircstring, iconv:convert(Encoding, "utf-8", S)}, process_lines(Encoding, Ss).process_channel_list(StateData, Items) -> process_channel_list_find_chan(StateData, Items).process_channel_list_find_chan(StateData, []) -> StateData;process_channel_list_find_chan(StateData, [[$# | Chan] | Items]) -> process_channel_list_users(StateData, Chan, Items);process_channel_list_find_chan(StateData, [_ | Items]) -> process_channel_list_find_chan(StateData, Items).process_channel_list_users(StateData, Chan, []) -> StateData;process_channel_list_users(StateData, Chan, [User | Items]) -> NewStateData = process_channel_list_user(StateData, Chan, User), process_channel_list_users(NewStateData, Chan, Items).process_channel_list_user(StateData, Chan, User) -> User1 = case User of [$: | U1] -> U1; _ -> User end, {User2, Affiliation, Role} = case User1 of [$@ | U2] -> {U2, "admin", "moderator"}; [$+ | U2] -> {U2, "member", "participant"}; _ -> {User1, "member", "participant"} end, ejabberd_router:route( jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), StateData#state.myname, User2), StateData#state.user, {xmlelement, "presence", [], [{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}], [{xmlelement, "item", [{"affiliation", Affiliation}, {"role", Role}], []}]}]}), case catch dict:update(Chan, fun(Ps) -> ?SETS:add_element(User2, Ps) end, StateData#state.channels) of {'EXIT', _} -> StateData; NS -> StateData#state{channels = NS} end.process_channel_topic(StateData, Chan, String) -> FromUser = "someone", {ok, Msg, _} = regexp:sub(String, ".*332[^:]*:", ""), Msg1 = lists:filter( fun(C) -> if (C < 32) and (C /= 9) and (C /= 10) and (C /= 13) -> false; true -> true end end, Msg), ejabberd_router:route( jlib:make_jid( lists:concat([Chan, "%", StateData#state.server]), StateData#state.myname, FromUser), StateData#state.user, {xmlelement, "message", [{"type", "groupchat"}], [{xmlelement, "subject", [], [{xmlcdata, Msg1}]}]}).process_chanprivmsg(StateData, Chan, From, String) -> [FromUser | _] = string:tokens(From, "!"), {ok, Msg, _} = regexp:sub(String, ".*PRIVMSG[^:]*:", ""), Msg1 = case Msg of [1, $A, $C, $T, $I, $O, $N, $ | Rest] -> "/me " ++ Rest; _ -> Msg end, Msg2 = lists:filter( fun(C) -> if (C < 32) and (C /= 9) and (C /= 10) and (C /= 13) -> false; true -> true end end, Msg1), ejabberd_router:route( jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), StateData#state.myname, FromUser), StateData#state.user, {xmlelement, "message", [{"type", "groupchat"}], [{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).process_channotice(StateData, Chan, From, String) -> [FromUser | _] = string:tokens(From, "!"), {ok, Msg, _} = regexp:sub(String, ".*NOTICE[^:]*:", ""), Msg1 = case Msg of [1, $A, $C, $T, $I, $O, $N, $ | Rest] -> "/me " ++ Rest; _ -> Msg end, Msg2 = lists:filter( fun(C) -> if (C < 32) and (C /= 9) and (C /= 10) and (C /= 13) -> false; true -> true end end, Msg1), ejabberd_router:route( jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]), StateData#state.myname, FromUser), StateData#state.user, {xmlelement, "message", [{"type", "groupchat"}], [{xmlelement, "body", [], [{xmlcdata, "NOTICE: " ++ Msg2}]}]}).process_privmsg(StateData, Nick, From, String) -> [FromUser | _] = string:tokens(From, "!"), {ok, Msg, _} = regexp:sub(String, ".*PRIVMSG[^:]*:", ""), Msg1 = case Msg of [1, $A, $C, $T, $I, $O, $N, $ | Rest] -> "/me " ++ Rest; _ -> Msg end, Msg2 = lists:filter( fun(C) -> if (C < 32) and (C /= 9) and (C /= 10) and (C /= 13) -> false; true -> true end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -