⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_irc_connection.erl

📁 ejabberd-0.7.5 分布式Jabber服务器
💻 ERL
📖 第 1 页 / 共 3 页
字号:
%%%----------------------------------------------------------------------%%% File    : mod_irc_connection.erl%%% Author  : Alexey Shchepin <alexey@sevcom.net>%%% Purpose : %%% Created : 15 Feb 2003 by Alexey Shchepin <alexey@sevcom.net>%%% Id      : $Id: mod_irc_connection.erl,v 1.20 2004/08/02 22:17:05 aleksey Exp $%%%-----------------------------------------------------------------------module(mod_irc_connection).-author('alexey@sevcom.net').-vsn('$Revision: 1.20 $ ').-behaviour(gen_fsm).%% External exports-export([start/5, receiver/2, route_chan/4, route_nick/3]).%% gen_fsm callbacks-export([init/1,	 open_socket/2,	 wait_for_registration/2,	 stream_established/2,	 handle_event/3,	 handle_sync_event/4,	 handle_info/3,	 terminate/3,	 code_change/4]).-include("ejabberd.hrl").-include("jlib.hrl").-define(SETS, gb_sets).-record(state, {socket, encoding, receiver, queue,		user, myname, server, nick,		channels = dict:new(),		inbuf = "", outbuf = ""}).%-define(DBGFSM, true).-ifdef(DBGFSM).-define(FSMOPTS, [{debug, [trace]}]).-else.-define(FSMOPTS, []).-endif.%%%----------------------------------------------------------------------%%% API%%%----------------------------------------------------------------------start(From, Host, Server, Username, Encoding) ->    gen_fsm:start(?MODULE, [From, Host, Server, Username, Encoding], ?FSMOPTS).%%%----------------------------------------------------------------------%%% Callback functions from gen_fsm%%%----------------------------------------------------------------------%%----------------------------------------------------------------------%% Func: init/1%% Returns: {ok, StateName, StateData}          |%%          {ok, StateName, StateData, Timeout} |%%          ignore                              |%%          {stop, StopReason}                   %%----------------------------------------------------------------------init([From, Host, Server, Username, Encoding]) ->    gen_fsm:send_event(self(), init),    {ok, open_socket, #state{queue = queue:new(),			     encoding = Encoding,			     user = From,			     nick = Username,			     myname = Host,			     server = Server}}.%%----------------------------------------------------------------------%% Func: StateName/2%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------open_socket(init, StateData) ->    Addr = StateData#state.server,    Port = 6667,    ?DEBUG("connecting to ~s:~p~n", [Addr, Port]),    case gen_tcp:connect(Addr, Port, [binary, {packet, 0}]) of	{ok, Socket} ->	    NewStateData = StateData#state{socket = Socket},	    send_text(NewStateData,		      io_lib:format("NICK ~s\r\n", [StateData#state.nick])),	    send_text(NewStateData,		      io_lib:format(			"USER ~s ~s ~s :~s\r\n",			[StateData#state.nick,			 StateData#state.nick,			 StateData#state.myname,			 StateData#state.nick])),	    send_text(NewStateData,		      io_lib:format("CODEPAGE ~s\r\n", [StateData#state.encoding])),	    {next_state, wait_for_registration,	     NewStateData};	{error, Reason} ->	    ?DEBUG("connect return ~p~n", [Reason]),	    Text = case Reason of		       timeout -> "Server Connect Timeout";		       _ -> "Server Connect Failed"		   end,	    bounce_messages(Text),	    {stop, normal, StateData}    end.wait_for_registration(closed, StateData) ->    {stop, normal, StateData}.stream_established({xmlstreamend, Name}, StateData) ->    {stop, normal, StateData};stream_established(timeout, StateData) ->    {stop, normal, StateData};stream_established(closed, StateData) ->    {stop, normal, StateData}.%%----------------------------------------------------------------------%% Func: StateName/3%% 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}                    %%----------------------------------------------------------------------%state_name(Event, From, StateData) ->%    Reply = ok,%    {reply, Reply, state_name, StateData}.%%----------------------------------------------------------------------%% Func: handle_event/3%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------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(Event, From, StateName, StateData) ->    Reply = ok,    {reply, Reply, StateName, StateData}.code_change(OldVsn, StateName, StateData, Extra) ->    {ok, StateName, StateData}.-define(SEND(S),	if	    StateName == stream_established ->		send_text(StateData, S),		StateData;	    true ->		StateData#state{outbuf = StateData#state.outbuf ++ S}	end).%%----------------------------------------------------------------------%% Func: handle_info/3%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------handle_info({route_chan, Channel, Resource,	     {xmlelement, "presence", Attrs, Els}},	    StateName, StateData) ->    NewStateData =	case xml:get_attr_s("type", Attrs) of	    "unavailable" ->		S1 = ?SEND(io_lib:format("PART #~s\r\n", [Channel])),		S1#state{channels =			 dict:erase(Channel, S1#state.channels)};	    "subscribe" -> StateData;	    "subscribed" -> StateData;	    "unsubscribe" -> StateData;	    "unsubscribed" -> StateData;	    "error" -> stop;	    _ ->		Nick = case Resource of			   "" ->			       StateData#state.nick;			   _ ->			       Resource		       end,		S1 = ?SEND(io_lib:format("NICK ~s\r\n"					 "JOIN #~s\r\n",					 [Nick, Channel])),		case dict:is_key(Channel, S1#state.channels) of		    true ->			S1#state{nick = Nick};		    _ ->			S1#state{nick = Nick,				 channels =				 dict:store(Channel, ?SETS:new(),					    S1#state.channels)}		end	end,    if	NewStateData == stop ->	    {stop, normal, StateData};	true ->	    case length(dict:fetch_keys(NewStateData#state.channels)) of		0 ->		    {stop, normal, NewStateData};		_ ->		    {next_state, StateName, NewStateData}	    end    end;handle_info({route_chan, Channel, Resource,	     {xmlelement, "message", Attrs, Els} = El},	    StateName, StateData) ->    NewStateData =	case xml:get_attr_s("type", Attrs) of	    "groupchat" ->		case xml:get_path_s(El, [{elem, "subject"}, cdata]) of		    "" ->			ejabberd_router:route(			  jlib:make_jid(			    lists:concat(			      [Channel, "%", StateData#state.server]),			    StateData#state.myname, StateData#state.nick),			  StateData#state.user, El),			Body = xml:get_path_s(El, [{elem, "body"}, cdata]),			case Body of			    "/quote " ++ Rest ->				?SEND(Rest ++ "\r\n");			    _ ->				Body1 =				    case Body of					[$/, $m, $e, $  | Rest] ->					    "\001ACTION " ++ Rest ++ "\001";					_ ->					    Body				    end,				Strings = string:tokens(Body1, "\n"),				Res = lists:concat(					lists:map(					  fun(S) ->						  io_lib:format(						    "PRIVMSG #~s :~s\r\n",						    [Channel, S])					  end, Strings)),				?SEND(Res)			end;		    Subject ->			Strings = string:tokens(Subject, "\n"),			Res = lists:concat(				lists:map(				  fun(S) ->					  io_lib:format("TOPIC #~s :~s\r\n",							[Channel, S])				  end, Strings)),			?SEND(Res)		end;	    "chat" ->		Body = xml:get_path_s(El, [{elem, "body"}, cdata]),		case Body of		    "/quote " ++ Rest ->			?SEND(Rest ++ "\r\n");		    _ ->			Body1 = case Body of				    [$/, $m, $e, $  | Rest] ->					"\001ACTION " ++ Rest ++ "\001";				    _ ->					Body				end,			Strings = string:tokens(Body1, "\n"),			Res = lists:concat(				lists:map(				  fun(S) ->					  io_lib:format("PRIVMSG ~s :~s\r\n",							[Resource, 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_chan, Channel, Resource,	     {xmlelement, "iq", Attrs, Els} = El},	    StateName, StateData) ->    From = StateData#state.user,    To = jlib:make_jid(lists:concat([Channel, "%", StateData#state.server]),		       StateData#state.myname, StateData#state.nick),    case jlib:iq_query_info(El) of	#iq{xmlns = ?NS_MUC_ADMIN} = IQ ->	    iq_admin(StateData, Channel, From, To, IQ);	#iq{xmlns = ?NS_VERSION} ->	    Res = io_lib:format("PRIVMSG ~s :\001VERSION\001\r\n",				[Resource]),	    ?SEND(Res),	    Err = jlib:make_error_reply(		    El, ?ERR_FEATURE_NOT_IMPLEMENTED),	    ejabberd_router:route(To, From, Err);	#iq{xmlns = ?NS_TIME} ->	    Res = io_lib:format("PRIVMSG ~s :\001TIME\001\r\n",				[Resource]),	    ?SEND(Res),	    Err = jlib:make_error_reply(		    El, ?ERR_FEATURE_NOT_IMPLEMENTED),	    ejabberd_router:route(To, From, Err);	#iq{} ->	    Err = jlib:make_error_reply(		    El, ?ERR_FEATURE_NOT_IMPLEMENTED),	    ejabberd_router:route(To, From, Err);	_ ->	    ok    end,    {next_state, StateName, StateData};handle_info({route_chan, Channel, Resource, Packet}, StateName, StateData) ->    {next_state, StateName, StateData};handle_info({route_nick, Nick,	     {xmlelement, "message", Attrs, Els} = El},	    StateName, StateData) ->    NewStateData =	case xml:get_attr_s("type", Attrs) of	    "chat" ->		Body = xml:get_path_s(El, [{elem, "body"}, cdata]),		case Body of		    "/quote " ++ Rest ->			?SEND(Rest ++ "\r\n");		    _ ->			Body1 = case Body of				    [$/, $m, $e, $  | Rest] ->					"\001ACTION " ++ Rest ++ "\001";				    _ ->					Body				end,			Strings = string:tokens(Body1, "\n"),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -