Fixed enough to join/send/receive/topic in groupchats
This commit is contained in:
parent
ce4c11f5fe
commit
e2a85ef9ad
|
@ -84,7 +84,7 @@ socket_type() ->
|
||||||
%% {stop, StopReason}
|
%% {stop, StopReason}
|
||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
init([{SockMod, Socket}, Opts]) ->
|
init([{SockMod, Socket}, Opts]) ->
|
||||||
iconv:start(),
|
%iconv:start(),
|
||||||
Access = case lists:keysearch(access, 1, Opts) of
|
Access = case lists:keysearch(access, 1, Opts) of
|
||||||
{value, {_, A}} -> A;
|
{value, {_, A}} -> A;
|
||||||
_ -> all
|
_ -> all
|
||||||
|
@ -134,7 +134,8 @@ init([{SockMod, Socket}, Opts]) ->
|
||||||
}}.
|
}}.
|
||||||
|
|
||||||
handle_info({tcp, _Socket, Line}, StateName, StateData) ->
|
handle_info({tcp, _Socket, Line}, StateName, StateData) ->
|
||||||
DecodedLine = iconv:convert(StateData#state.encoding, "utf-8", Line),
|
%DecodedLine = iconv:convert(StateData#state.encoding, "utf-8", Line),
|
||||||
|
DecodedLine = Line,
|
||||||
Parsed = parse_line(DecodedLine),
|
Parsed = parse_line(DecodedLine),
|
||||||
?MODULE:StateName({line, Parsed}, StateData);
|
?MODULE:StateName({line, Parsed}, StateData);
|
||||||
handle_info({tcp_closed, _}, _StateName, StateData) ->
|
handle_info({tcp_closed, _}, _StateName, StateData) ->
|
||||||
|
@ -163,8 +164,8 @@ terminate(_Reason, _StateName, #state{socket = Socket, sockmod = SockMod,
|
||||||
none ->
|
none ->
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
Packet = {xmlelement, "presence",
|
Packet = {xmlel, <<"presence">>,
|
||||||
[{"type", "unavailable"}], []},
|
[{<<"type">>, <<"unavailable">>}], []},
|
||||||
FromJID = user_jid(State),
|
FromJID = user_jid(State),
|
||||||
?DICT:map(fun(ChannelJID, _ChannelData) ->
|
?DICT:map(fun(ChannelJID, _ChannelData) ->
|
||||||
ejabberd_router:route(FromJID, ChannelJID, Packet)
|
ejabberd_router:route(FromJID, ChannelJID, Packet)
|
||||||
|
@ -186,8 +187,10 @@ wait_for_nick({line, #line{command = "NICK", params = Params}}, State) ->
|
||||||
Nick = hd(Params),
|
Nick = hd(Params),
|
||||||
Pass = State#state.pass,
|
Pass = State#state.pass,
|
||||||
Server = State#state.host,
|
Server = State#state.host,
|
||||||
|
?DEBUG("user=~p server=~p", [Nick, Server]),
|
||||||
|
|
||||||
JID = jlib:make_jid(Nick, Server, "irc"),
|
JID = jlib:make_jid(list_to_binary(Nick), Server, <<"irc">>),
|
||||||
|
?DEBUG("JID=~p", [JID]),
|
||||||
case JID of
|
case JID of
|
||||||
error ->
|
error ->
|
||||||
?DEBUG("invalid nick '~p'", [Nick]),
|
?DEBUG("invalid nick '~p'", [Nick]),
|
||||||
|
@ -200,7 +203,7 @@ wait_for_nick({line, #line{command = "NICK", params = Params}}, State) ->
|
||||||
send_reply('ERR_NICKCOLLISION', [Nick, "Nickname collision"], State),
|
send_reply('ERR_NICKCOLLISION', [Nick, "Nickname collision"], State),
|
||||||
{next_state, wait_for_nick, State};
|
{next_state, wait_for_nick, State};
|
||||||
allow ->
|
allow ->
|
||||||
case ejabberd_auth:check_password(Nick, Server, Pass) of
|
case ejabberd_auth:check_password(list_to_binary(Nick), Server, list_to_binary(Pass)) of
|
||||||
false ->
|
false ->
|
||||||
?DEBUG("auth failed for '~p'", [Nick]),
|
?DEBUG("auth failed for '~p'", [Nick]),
|
||||||
send_reply('ERR_NICKCOLLISION', [Nick, "Authentication failed"], State),
|
send_reply('ERR_NICKCOLLISION', [Nick, "Authentication failed"], State),
|
||||||
|
@ -209,15 +212,15 @@ wait_for_nick({line, #line{command = "NICK", params = Params}}, State) ->
|
||||||
?DEBUG("good nickname '~p'", [Nick]),
|
?DEBUG("good nickname '~p'", [Nick]),
|
||||||
SID = {now(), self()},
|
SID = {now(), self()},
|
||||||
ejabberd_sm:open_session(
|
ejabberd_sm:open_session(
|
||||||
SID, Nick, Server, "irc", peerip(gen_tcp, State#state.socket)),
|
SID, list_to_binary(Nick), Server, <<"irc">>, peerip(gen_tcp, State#state.socket)),
|
||||||
ejabberd_sm:set_presence(SID, Nick, Server, "irc",
|
ejabberd_sm:set_presence(SID, list_to_binary(Nick), Server, <<"irc">>,
|
||||||
3, "undefined",
|
3, "undefined",
|
||||||
[{'ip', peerip(gen_tcp, State#state.socket)}, {'conn','c2s'}, {'state',"+"}]),
|
[{'ip', peerip(gen_tcp, State#state.socket)}, {'conn','c2s'}, {'state',"+"}]),
|
||||||
send_text_command("", "001", [Nick, "IRC interface of ejabberd server "++Server], State),
|
send_text_command("", "001", [Nick, "IRC interface of ejabberd server "++Server], State),
|
||||||
send_reply('RPL_MOTDSTART', [Nick, "- "++Server++" Message of the day - "], State),
|
send_reply('RPL_MOTDSTART', [Nick, "- "++binary_to_list(Server)++" Message of the day - "], State),
|
||||||
send_reply('RPL_MOTD', [Nick, "- This is the IRC interface of the ejabberd server "++Server++"."], State),
|
send_reply('RPL_MOTD', [Nick, "- This is the IRC interface of the ejabberd server "++binary_to_list(Server)++"."], State),
|
||||||
send_reply('RPL_MOTD', [Nick, "- Your full JID is "++Nick++"@"++Server++"/irc."], State),
|
send_reply('RPL_MOTD', [Nick, "- Your full JID is "++Nick++"@"++binary_to_list(Server)++"/irc."], State),
|
||||||
send_reply('RPL_MOTD', [Nick, "- Channel #whatever corresponds to MUC room whatever@"++State#state.muc_host++"."], State),
|
send_reply('RPL_MOTD', [Nick, "- Channel #whatever corresponds to MUC room whatever@"++binary_to_list(State#state.muc_host)++"."], State),
|
||||||
send_reply('RPL_MOTD', [Nick, "- This IRC interface is quite immature. You will probably find bugs."], State),
|
send_reply('RPL_MOTD', [Nick, "- This IRC interface is quite immature. You will probably find bugs."], State),
|
||||||
send_reply('RPL_MOTD', [Nick, "- Have a good time!"], State),
|
send_reply('RPL_MOTD', [Nick, "- Have a good time!"], State),
|
||||||
send_reply('RPL_ENDOFMOTD', [Nick, "End of /MOTD command"], State),
|
send_reply('RPL_ENDOFMOTD', [Nick, "End of /MOTD command"], State),
|
||||||
|
@ -244,6 +247,7 @@ wait_for_cmd({line, #line{command = "USER", params = [_Username, _Hostname, _Ser
|
||||||
%% Yeah, like we care.
|
%% Yeah, like we care.
|
||||||
{next_state, wait_for_cmd, State};
|
{next_state, wait_for_cmd, State};
|
||||||
wait_for_cmd({line, #line{command = "JOIN", params = Params}}, State) ->
|
wait_for_cmd({line, #line{command = "JOIN", params = Params}}, State) ->
|
||||||
|
?DEBUG("received JOIN ~p", [Params]),
|
||||||
{ChannelsString, KeysString} =
|
{ChannelsString, KeysString} =
|
||||||
case Params of
|
case Params of
|
||||||
[C, K] ->
|
[C, K] ->
|
||||||
|
@ -253,7 +257,9 @@ wait_for_cmd({line, #line{command = "JOIN", params = Params}}, State) ->
|
||||||
end,
|
end,
|
||||||
Channels = string:tokens(ChannelsString, ","),
|
Channels = string:tokens(ChannelsString, ","),
|
||||||
Keys = string:tokens(KeysString, ","),
|
Keys = string:tokens(KeysString, ","),
|
||||||
|
?DEBUG("joining channels ~p", [Channels]),
|
||||||
NewState = join_channels(Channels, Keys, State),
|
NewState = join_channels(Channels, Keys, State),
|
||||||
|
?DEBUG("joined channels ~p", [Channels]),
|
||||||
{next_state, wait_for_cmd, NewState};
|
{next_state, wait_for_cmd, NewState};
|
||||||
|
|
||||||
%% USERHOST command
|
%% USERHOST command
|
||||||
|
@ -294,18 +300,18 @@ wait_for_cmd({line, #line{command = "PRIVMSG", params = [To, Text]}}, State) ->
|
||||||
fun(Rcpt) ->
|
fun(Rcpt) ->
|
||||||
case Rcpt of
|
case Rcpt of
|
||||||
[$# | Roomname] ->
|
[$# | Roomname] ->
|
||||||
Packet = {xmlelement, "message",
|
Packet = {xmlel, <<"message">>,
|
||||||
[{"type", "groupchat"}],
|
[{<<"type">>, <<"groupchat">>}],
|
||||||
[{xmlelement, "body", [],
|
[{xmlel, <<"body">>, [],
|
||||||
filter_cdata(translate_action(Text))}]},
|
filter_cdata(translate_action(Text))}]},
|
||||||
ToJID = channel_to_jid(Roomname, State),
|
ToJID = channel_to_jid(Roomname, State),
|
||||||
ejabberd_router:route(FromJID, ToJID, Packet);
|
ejabberd_router:route(FromJID, ToJID, Packet);
|
||||||
_ ->
|
_ ->
|
||||||
case string:tokens(Rcpt, "#") of
|
case string:tokens(Rcpt, "#") of
|
||||||
[Nick, Channel] ->
|
[Nick, Channel] ->
|
||||||
Packet = {xmlelement, "message",
|
Packet = {xmlel, <<"message">>,
|
||||||
[{"type", "chat"}],
|
[{<<"type">>, <<"chat">>}],
|
||||||
[{xmlelement, "body", [],
|
[{xmlel, <<"body">>, [],
|
||||||
filter_cdata(translate_action(Text))}]},
|
filter_cdata(translate_action(Text))}]},
|
||||||
ToJID = channel_nick_to_jid(Nick, Channel, State),
|
ToJID = channel_nick_to_jid(Nick, Channel, State),
|
||||||
ejabberd_router:route(FromJID, ToJID, Packet);
|
ejabberd_router:route(FromJID, ToJID, Packet);
|
||||||
|
@ -357,9 +363,9 @@ wait_for_cmd({line, #line{command = "TOPIC", params = Params}}, State) ->
|
||||||
end;
|
end;
|
||||||
[Channel, NewTopic] ->
|
[Channel, NewTopic] ->
|
||||||
Packet =
|
Packet =
|
||||||
{xmlelement, "message",
|
{xmlel, <<"message">>,
|
||||||
[{"type", "groupchat"}],
|
[{<<"type">>, <<"groupchat">>}],
|
||||||
[{xmlelement, "subject", [], filter_cdata(NewTopic)}]},
|
[{xmlel, <<"subject">>, [], filter_cdata(NewTopic)}]},
|
||||||
FromJID = user_jid(State),
|
FromJID = user_jid(State),
|
||||||
ToJID = channel_to_jid(Channel, State),
|
ToJID = channel_to_jid(Channel, State),
|
||||||
ejabberd_router:route(FromJID, ToJID, Packet)
|
ejabberd_router:route(FromJID, ToJID, Packet)
|
||||||
|
@ -411,10 +417,11 @@ wait_for_cmd({line, #line{command = Unknown, params = Params} = Line}, State) ->
|
||||||
Unknown ++ "/" ++ integer_to_list(length(Params))], State),
|
Unknown ++ "/" ++ integer_to_list(length(Params))], State),
|
||||||
{next_state, wait_for_cmd, State};
|
{next_state, wait_for_cmd, State};
|
||||||
|
|
||||||
wait_for_cmd({route, From, _To, {xmlelement, "presence", Attrs, Els} = El}, State) ->
|
wait_for_cmd({route, From, _To, {xmlel, <<"presence">>, Attrs, Els} = El}, State) ->
|
||||||
|
?DEBUG("Received a Presence ~p ~p ~p", [From, _To, El]),
|
||||||
Type = xml:get_attr_s("type", Attrs),
|
Type = xml:get_attr_s("type", Attrs),
|
||||||
FromRoom = jlib:jid_remove_resource(From),
|
FromRoom = jlib:jid_remove_resource(From),
|
||||||
FromNick = From#jid.resource,
|
FromNick = binary_to_list(From#jid.resource),
|
||||||
|
|
||||||
Channel = jid_to_channel(From, State),
|
Channel = jid_to_channel(From, State),
|
||||||
MyNick = State#state.nick,
|
MyNick = State#state.nick,
|
||||||
|
@ -422,24 +429,29 @@ wait_for_cmd({route, From, _To, {xmlelement, "presence", Attrs, Els} = El}, Stat
|
||||||
|
|
||||||
Joining = ?DICT:find(FromRoom, State#state.joining),
|
Joining = ?DICT:find(FromRoom, State#state.joining),
|
||||||
Joined = ?DICT:find(FromRoom, State#state.joined),
|
Joined = ?DICT:find(FromRoom, State#state.joined),
|
||||||
|
?DEBUG("JoinState ~p ~p ~p", [Joining, Joined, Type]),
|
||||||
case {Joining, Joined, Type} of
|
case {Joining, Joined, Type} of
|
||||||
{{ok, BufferedNicks}, _, ""} ->
|
{{ok, BufferedNicks}, _, <<"">>} ->
|
||||||
|
?DEBUG("BufferedNicks ~p", [BufferedNicks]),
|
||||||
case BufferedNicks of
|
case BufferedNicks of
|
||||||
[] ->
|
[] ->
|
||||||
%% If this is the first presence, tell the
|
%% If this is the first presence, tell the
|
||||||
%% client that it's joining.
|
%% client that it's joining.
|
||||||
send_command(make_irc_sender(MyNick, FromRoom, State),
|
?DEBUG("Sending Command ~p ~p", [IRCSender, Channel]),
|
||||||
"JOIN", [Channel], State);
|
send_command(IRCSender, "JOIN", [Channel], State),
|
||||||
|
?DEBUG("Command Sent", []);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
?DEBUG("Getting NewRole", []),
|
||||||
NewRole = case find_el("x", ?NS_MUC_USER, Els) of
|
NewRole = case find_el("x", ?NS_MUC_USER, Els) of
|
||||||
nothing ->
|
nothing ->
|
||||||
"";
|
"";
|
||||||
XMucEl ->
|
XMucEl ->
|
||||||
xml:get_path_s(XMucEl, [{elem, "item"}, {attr, "role"}])
|
xml:get_path_s(XMucEl, [{elem, "item"}, {attr, "role"}])
|
||||||
end,
|
end,
|
||||||
|
?DEBUG("NewRole ~p", [NewRole]),
|
||||||
NewBufferedNicks = [{FromNick, NewRole} | BufferedNicks],
|
NewBufferedNicks = [{FromNick, NewRole} | BufferedNicks],
|
||||||
?DEBUG("~s is present in ~s. we now have ~p.",
|
?DEBUG("~s is present in ~s. we now have ~p.",
|
||||||
[FromNick, Channel, NewBufferedNicks]),
|
[FromNick, Channel, NewBufferedNicks]),
|
||||||
|
@ -479,14 +491,14 @@ wait_for_cmd({route, From, _To, {xmlelement, "presence", Attrs, Els} = El}, Stat
|
||||||
State#state{joining = NewJoining}
|
State#state{joining = NewJoining}
|
||||||
end,
|
end,
|
||||||
{next_state, wait_for_cmd, NewState};
|
{next_state, wait_for_cmd, NewState};
|
||||||
{{ok, _BufferedNicks}, _, "error"} ->
|
{{ok, _BufferedNicks}, _, <<"error">>} ->
|
||||||
NewState =
|
NewState =
|
||||||
case FromNick of
|
case FromNick of
|
||||||
MyNick ->
|
MyNick ->
|
||||||
%% we couldn't join the room
|
%% we couldn't join the room
|
||||||
{ReplyCode, ErrorDescription} =
|
{ReplyCode, ErrorDescription} =
|
||||||
case xml:get_subtag(El, "error") of
|
case xml:get_subtag(El, "error") of
|
||||||
{xmlelement, _, _, _} = ErrorEl ->
|
{xmlel, _, _, _} = ErrorEl ->
|
||||||
{ErrorName, ErrorText} = parse_error(ErrorEl),
|
{ErrorName, ErrorText} = parse_error(ErrorEl),
|
||||||
{case ErrorName of
|
{case ErrorName of
|
||||||
"forbidden" -> 'ERR_INVITEONLYCHAN';
|
"forbidden" -> 'ERR_INVITEONLYCHAN';
|
||||||
|
@ -511,7 +523,7 @@ wait_for_cmd({route, From, _To, {xmlelement, "presence", Attrs, Els} = El}, Stat
|
||||||
end,
|
end,
|
||||||
{next_state, wait_for_cmd, NewState};
|
{next_state, wait_for_cmd, NewState};
|
||||||
%% Presence in a channel we have already joined
|
%% Presence in a channel we have already joined
|
||||||
{_, {ok, _}, ""} ->
|
{_, {ok, _}, <<"">>} ->
|
||||||
%% Someone enters
|
%% Someone enters
|
||||||
send_command(IRCSender, "JOIN", [Channel], State),
|
send_command(IRCSender, "JOIN", [Channel], State),
|
||||||
{next_state, wait_for_cmd, State};
|
{next_state, wait_for_cmd, State};
|
||||||
|
@ -524,29 +536,37 @@ wait_for_cmd({route, From, _To, {xmlelement, "presence", Attrs, Els} = El}, Stat
|
||||||
{next_state, wait_for_cmd, State}
|
{next_state, wait_for_cmd, State}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
wait_for_cmd({route, From, _To, {xmlelement, "message", Attrs, Els} = El}, State) ->
|
wait_for_cmd({route, From, _To, {xmlel, <<"message">>, Attrs, Els} = El}, State) ->
|
||||||
Type = xml:get_attr_s("type", Attrs),
|
?DEBUG("Got a Message! ~p ~p ~p", [From, _To, El]),
|
||||||
|
Type = xml:get_attr_s(<<"type">>, Attrs),
|
||||||
case Type of
|
case Type of
|
||||||
"groupchat" ->
|
<<"groupchat">> ->
|
||||||
|
?DEBUG("It's a groupchat", []),
|
||||||
ChannelJID = jlib:jid_remove_resource(From),
|
ChannelJID = jlib:jid_remove_resource(From),
|
||||||
case ?DICT:find(ChannelJID, State#state.joined) of
|
case ?DICT:find(ChannelJID, State#state.joined) of
|
||||||
{ok, #channel{} = ChannelData} ->
|
{ok, #channel{} = ChannelData} ->
|
||||||
FromChannel = jid_to_channel(From, State),
|
FromChannel = jid_to_channel(From, State),
|
||||||
FromNick = From#jid.resource,
|
FromNick = binary_to_list(From#jid.resource),
|
||||||
Subject = xml:get_path_s(El, [{elem, "subject"}, cdata]),
|
Subject = xml:get_path_s(El, [{elem, <<"subject">>}, cdata]),
|
||||||
Body = xml:get_path_s(El, [{elem, "body"}, cdata]),
|
Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]),
|
||||||
XDelay = lists:any(fun({xmlelement, "x", XAttrs, _}) ->
|
?DEBUG("Message Data ~p ~p", [Subject, Body]),
|
||||||
xml:get_attr_s("xmlns", XAttrs) == ?NS_DELAY;
|
XDelay = lists:any(fun({xmlel, <<"x">>, XAttrs, _}) ->
|
||||||
|
xml:get_attr_s(<<"xmlns">>, XAttrs) == ?NS_DELAY;
|
||||||
(_) ->
|
(_) ->
|
||||||
false
|
false
|
||||||
end, Els),
|
end, Els),
|
||||||
|
?DEBUG("XDelay ~p", [XDelay]),
|
||||||
if
|
if
|
||||||
Subject /= "" ->
|
Subject /= <<"">> ->
|
||||||
|
?DEBUG("Cleaning Subject!", []),
|
||||||
CleanSubject = lists:map(fun($\n) ->
|
CleanSubject = lists:map(fun($\n) ->
|
||||||
$\ ;
|
$\ ;
|
||||||
(C) -> C
|
(C) -> C
|
||||||
end, Subject),
|
end, binary_to_list(Subject)),
|
||||||
send_text_command(make_irc_sender(From, State),
|
?DEBUG("CleanSubject ~p", [CleanSubject]),
|
||||||
|
IRCSender = make_irc_sender(From, State),
|
||||||
|
?DEBUG("IRCSender ~p", [IRCSender]),
|
||||||
|
send_text_command(IRCSender,
|
||||||
"TOPIC", [FromChannel, CleanSubject], State),
|
"TOPIC", [FromChannel, CleanSubject], State),
|
||||||
NewChannelData = ChannelData#channel{topic = CleanSubject},
|
NewChannelData = ChannelData#channel{topic = CleanSubject},
|
||||||
NewState = State#state{joined = ?DICT:store(jlib:jid_remove_resource(From), NewChannelData, State#state.joined)},
|
NewState = State#state{joined = ?DICT:store(jlib:jid_remove_resource(From), NewChannelData, State#state.joined)},
|
||||||
|
@ -554,9 +574,11 @@ wait_for_cmd({route, From, _To, {xmlelement, "message", Attrs, Els} = El}, State
|
||||||
not XDelay, FromNick == State#state.nick ->
|
not XDelay, FromNick == State#state.nick ->
|
||||||
%% there is no message echo in IRC.
|
%% there is no message echo in IRC.
|
||||||
%% we let the backlog through, though.
|
%% we let the backlog through, though.
|
||||||
|
?DEBUG("Don't care about it", []),
|
||||||
{next_state, wait_for_cmd, State};
|
{next_state, wait_for_cmd, State};
|
||||||
true ->
|
true ->
|
||||||
BodyLines = string:tokens(Body, "\n"),
|
?DEBUG("Send it to someone!", []),
|
||||||
|
BodyLines = string:tokens(binary_to_list(Body), "\n"),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Line) ->
|
fun(Line) ->
|
||||||
Line1 =
|
Line1 =
|
||||||
|
@ -576,7 +598,7 @@ wait_for_cmd({route, From, _To, {xmlelement, "message", Attrs, Els} = El}, State
|
||||||
[jlib:jid_to_string(ChannelJID)]),
|
[jlib:jid_to_string(ChannelJID)]),
|
||||||
{next_state, wait_for_cmd, State}
|
{next_state, wait_for_cmd, State}
|
||||||
end;
|
end;
|
||||||
"error" ->
|
<<"error">> ->
|
||||||
MucHost = State#state.muc_host,
|
MucHost = State#state.muc_host,
|
||||||
ErrorFrom =
|
ErrorFrom =
|
||||||
case From of
|
case From of
|
||||||
|
@ -595,7 +617,7 @@ wait_for_cmd({route, From, _To, {xmlelement, "message", Attrs, Els} = El}, State
|
||||||
%% I think this should cover all possible combinations of
|
%% I think this should cover all possible combinations of
|
||||||
%% XMPP and non-XMPP error messages...
|
%% XMPP and non-XMPP error messages...
|
||||||
ErrorText =
|
ErrorText =
|
||||||
error_to_string(xml:get_subtag(El, "error")),
|
error_to_string(xml:get_subtag(El, <<"error">>)),
|
||||||
send_text_command("", "NOTICE", [State#state.nick,
|
send_text_command("", "NOTICE", [State#state.nick,
|
||||||
"Message to "++ErrorFrom++" bounced: "++
|
"Message to "++ErrorFrom++" bounced: "++
|
||||||
ErrorText], State),
|
ErrorText], State),
|
||||||
|
@ -604,8 +626,8 @@ wait_for_cmd({route, From, _To, {xmlelement, "message", Attrs, Els} = El}, State
|
||||||
ChannelJID = jlib:jid_remove_resource(From),
|
ChannelJID = jlib:jid_remove_resource(From),
|
||||||
case ?DICT:find(ChannelJID, State#state.joined) of
|
case ?DICT:find(ChannelJID, State#state.joined) of
|
||||||
{ok, #channel{}} ->
|
{ok, #channel{}} ->
|
||||||
FromNick = From#jid.lresource++jid_to_channel(From, State),
|
FromNick = binary_to_list(From#jid.lresource)++jid_to_channel(From, State),
|
||||||
Body = xml:get_path_s(El, [{elem, "body"}, cdata]),
|
Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]),
|
||||||
BodyLines = string:tokens(Body, "\n"),
|
BodyLines = string:tokens(Body, "\n"),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Line) ->
|
fun(Line) ->
|
||||||
|
@ -636,30 +658,36 @@ join_channels(Channels, [], State) ->
|
||||||
join_channels([Channel | Channels], [Key | Keys],
|
join_channels([Channel | Channels], [Key | Keys],
|
||||||
#state{nick = Nick} = State) ->
|
#state{nick = Nick} = State) ->
|
||||||
Packet =
|
Packet =
|
||||||
{xmlelement, "presence", [],
|
{xmlel, <<"presence">>, [],
|
||||||
[{xmlelement, "x", [{"xmlns", ?NS_MUC}],
|
[{xmlel, <<"x">>, [{<<"xmlns">>, ?NS_MUC}],
|
||||||
case Key of
|
case Key of
|
||||||
none ->
|
none ->
|
||||||
[];
|
[];
|
||||||
_ ->
|
_ ->
|
||||||
[{xmlelement, "password", [], filter_cdata(Key)}]
|
[{xmlel, <<"password">>, [], filter_cdata(Key)}]
|
||||||
end}]},
|
end}]},
|
||||||
|
?DEBUG("joining channel nick=~p channel=~p state=~p", [Nick, Channel, State]),
|
||||||
From = user_jid(State),
|
From = user_jid(State),
|
||||||
|
?DEBUG("1 ~p", [From]),
|
||||||
To = channel_nick_to_jid(Nick, Channel, State),
|
To = channel_nick_to_jid(Nick, Channel, State),
|
||||||
|
?DEBUG("2 ~p", [To]),
|
||||||
Room = jlib:jid_remove_resource(To),
|
Room = jlib:jid_remove_resource(To),
|
||||||
|
?DEBUG("3 ~p", [Room]),
|
||||||
ejabberd_router:route(From, To, Packet),
|
ejabberd_router:route(From, To, Packet),
|
||||||
|
?DEBUG("4", []),
|
||||||
NewState = State#state{joining = ?DICT:store(Room, [], State#state.joining)},
|
NewState = State#state{joining = ?DICT:store(Room, [], State#state.joining)},
|
||||||
|
?DEBUG("5 ~p", [NewState]),
|
||||||
join_channels(Channels, Keys, NewState).
|
join_channels(Channels, Keys, NewState).
|
||||||
|
|
||||||
part_channels([], State, _Message) ->
|
part_channels([], State, _Message) ->
|
||||||
State;
|
State;
|
||||||
part_channels([Channel | Channels], State, Message) ->
|
part_channels([Channel | Channels], State, Message) ->
|
||||||
Packet =
|
Packet =
|
||||||
{xmlelement, "presence",
|
{xmlel, <<"presence">>,
|
||||||
[{"type", "unavailable"}],
|
[{<<"type">>, <<"unavailable">>}],
|
||||||
case Message of
|
case Message of
|
||||||
nothing -> [];
|
nothing -> [];
|
||||||
_ -> [{xmlelement, "status", [],
|
_ -> [{xmlel, <<"status">>, [],
|
||||||
[{xmlcdata, Message}]}]
|
[{xmlcdata, Message}]}]
|
||||||
end},
|
end},
|
||||||
From = user_jid(State),
|
From = user_jid(State),
|
||||||
|
@ -704,7 +732,8 @@ upcase([C|String]) ->
|
||||||
send_line(Line, #state{sockmod = SockMod, socket = Socket, encoding = Encoding}) ->
|
send_line(Line, #state{sockmod = SockMod, socket = Socket, encoding = Encoding}) ->
|
||||||
?DEBUG("sending ~s", [Line]),
|
?DEBUG("sending ~s", [Line]),
|
||||||
gen_tcp = SockMod,
|
gen_tcp = SockMod,
|
||||||
EncodedLine = iconv:convert("utf-8", Encoding, Line),
|
%EncodedLine = iconv:convert("utf-8", Encoding, Line),
|
||||||
|
EncodedLine = Line,
|
||||||
ok = gen_tcp:send(Socket, [EncodedLine, 13, 10]).
|
ok = gen_tcp:send(Socket, [EncodedLine, 13, 10]).
|
||||||
|
|
||||||
send_command(Sender, Command, Params, State) ->
|
send_command(Sender, Command, Params, State) ->
|
||||||
|
@ -716,9 +745,10 @@ send_text_command(Sender, Command, Params, State) ->
|
||||||
send_command(Sender, Command, Params, State, true).
|
send_command(Sender, Command, Params, State, true).
|
||||||
|
|
||||||
send_command(Sender, Command, Params, State, AlwaysQuote) ->
|
send_command(Sender, Command, Params, State, AlwaysQuote) ->
|
||||||
|
?DEBUG("SendCommand ~p ~p ~p", [Sender, Command, Params]),
|
||||||
Prefix = case Sender of
|
Prefix = case Sender of
|
||||||
"" ->
|
"" ->
|
||||||
[$: | State#state.host];
|
[$: | binary_to_list(State#state.host)];
|
||||||
_ ->
|
_ ->
|
||||||
[$: | Sender]
|
[$: | Sender]
|
||||||
end,
|
end,
|
||||||
|
@ -784,7 +814,7 @@ make_param_string([Param | Params], AlwaysQuote) ->
|
||||||
" " ++ Param ++ make_param_string(Params, AlwaysQuote)
|
" " ++ Param ++ make_param_string(Params, AlwaysQuote)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
find_el(Name, NS, [{xmlelement, N, Attrs, _} = El|Els]) ->
|
find_el(Name, NS, [{xmlel, N, Attrs, _} = El|Els]) ->
|
||||||
XMLNS = xml:get_attr_s("xmlns", Attrs),
|
XMLNS = xml:get_attr_s("xmlns", Attrs),
|
||||||
case {Name, NS} of
|
case {Name, NS} of
|
||||||
{N, XMLNS} ->
|
{N, XMLNS} ->
|
||||||
|
@ -801,7 +831,7 @@ channel_to_jid(Channel, #state{muc_host = MucHost,
|
||||||
channels_to_jids = ChannelsToJids}) ->
|
channels_to_jids = ChannelsToJids}) ->
|
||||||
case ?DICT:find(Channel, ChannelsToJids) of
|
case ?DICT:find(Channel, ChannelsToJids) of
|
||||||
{ok, RoomJID} -> RoomJID;
|
{ok, RoomJID} -> RoomJID;
|
||||||
_ -> jlib:make_jid(Channel, MucHost, "")
|
_ -> jlib:make_jid(list_to_binary(Channel), MucHost, <<"">>)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
channel_nick_to_jid(Nick, [$#|Channel], State) ->
|
channel_nick_to_jid(Nick, [$#|Channel], State) ->
|
||||||
|
@ -809,28 +839,28 @@ channel_nick_to_jid(Nick, [$#|Channel], State) ->
|
||||||
channel_nick_to_jid(Nick, Channel, #state{muc_host = MucHost,
|
channel_nick_to_jid(Nick, Channel, #state{muc_host = MucHost,
|
||||||
channels_to_jids = ChannelsToJids}) ->
|
channels_to_jids = ChannelsToJids}) ->
|
||||||
case ?DICT:find(Channel, ChannelsToJids) of
|
case ?DICT:find(Channel, ChannelsToJids) of
|
||||||
{ok, RoomJID} -> jlib:jid_replace_resource(RoomJID, Nick);
|
{ok, RoomJID} -> jlib:jid_replace_resource(RoomJID, list_to_binary(Nick));
|
||||||
_ -> jlib:make_jid(Channel, MucHost, Nick)
|
_ -> jlib:make_jid(list_to_binary(Channel), MucHost, list_to_binary(Nick))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
jid_to_channel(#jid{user = Room} = RoomJID,
|
jid_to_channel(#jid{user = Room} = RoomJID,
|
||||||
#state{jids_to_channels = JidsToChannels}) ->
|
#state{jids_to_channels = JidsToChannels}) ->
|
||||||
case ?DICT:find(jlib:jid_remove_resource(RoomJID), JidsToChannels) of
|
case ?DICT:find(jlib:jid_remove_resource(RoomJID), JidsToChannels) of
|
||||||
{ok, Channel} -> [$#|Channel];
|
{ok, Channel} -> [$#|binary_to_list(Channel)];
|
||||||
_ -> [$#|Room]
|
_ -> [$#|binary_to_list(Room)]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
make_irc_sender(Nick, #jid{luser = Room} = RoomJID,
|
make_irc_sender(Nick, #jid{luser = Room} = RoomJID,
|
||||||
#state{jids_to_channels = JidsToChannels}) ->
|
#state{jids_to_channels = JidsToChannels}) ->
|
||||||
case ?DICT:find(jlib:jid_remove_resource(RoomJID), JidsToChannels) of
|
case ?DICT:find(jlib:jid_remove_resource(RoomJID), JidsToChannels) of
|
||||||
{ok, Channel} -> Nick++"!"++Nick++"@"++Channel;
|
{ok, Channel} -> Nick++"!"++Nick++"@"++binary_to_list(Channel);
|
||||||
_ -> Nick++"!"++Nick++"@"++Room
|
_ -> Nick++"!"++Nick++"@"++binary_to_list(Room)
|
||||||
end.
|
end.
|
||||||
make_irc_sender(#jid{lresource = Nick} = JID, State) ->
|
make_irc_sender(#jid{lresource = Nick} = JID, State) ->
|
||||||
make_irc_sender(Nick, JID, State).
|
make_irc_sender(binary_to_list(Nick), JID, State).
|
||||||
|
|
||||||
user_jid(#state{nick = Nick, host = Host}) ->
|
user_jid(#state{nick = Nick, host = Host}) ->
|
||||||
jlib:make_jid(Nick, Host, "irc").
|
jlib:make_jid(list_to_binary(Nick), Host, <<"irc">>).
|
||||||
|
|
||||||
filter_cdata(Msg) ->
|
filter_cdata(Msg) ->
|
||||||
[{xmlcdata, filter_message(Msg)}].
|
[{xmlcdata, filter_message(Msg)}].
|
||||||
|
@ -857,25 +887,25 @@ translate_action(Msg) ->
|
||||||
Msg
|
Msg
|
||||||
end.
|
end.
|
||||||
|
|
||||||
parse_error({xmlelement, "error", _ErrorAttrs, ErrorEls} = ErrorEl) ->
|
parse_error({xmlel, "error", _ErrorAttrs, ErrorEls} = ErrorEl) ->
|
||||||
ErrorTextEl = xml:get_subtag(ErrorEl, "text"),
|
ErrorTextEl = xml:get_subtag(ErrorEl, "text"),
|
||||||
ErrorName =
|
ErrorName =
|
||||||
case ErrorEls -- [ErrorTextEl] of
|
case ErrorEls -- [ErrorTextEl] of
|
||||||
[{xmlelement, ErrorReason, _, _}] ->
|
[{xmlel, ErrorReason, _, _}] ->
|
||||||
ErrorReason;
|
ErrorReason;
|
||||||
_ ->
|
_ ->
|
||||||
"unknown error"
|
"unknown error"
|
||||||
end,
|
end,
|
||||||
ErrorText =
|
ErrorText =
|
||||||
case ErrorTextEl of
|
case ErrorTextEl of
|
||||||
{xmlelement, _, _, _} ->
|
{xmlel, _, _, _} ->
|
||||||
xml:get_tag_cdata(ErrorTextEl);
|
xml:get_tag_cdata(ErrorTextEl);
|
||||||
_ ->
|
_ ->
|
||||||
nothing
|
nothing
|
||||||
end,
|
end,
|
||||||
{ErrorName, ErrorText}.
|
{ErrorName, ErrorText}.
|
||||||
|
|
||||||
error_to_string({xmlelement, "error", _ErrorAttrs, _ErrorEls} = ErrorEl) ->
|
error_to_string({xmlel, "error", _ErrorAttrs, _ErrorEls} = ErrorEl) ->
|
||||||
case parse_error(ErrorEl) of
|
case parse_error(ErrorEl) of
|
||||||
{ErrorName, ErrorText} when is_list(ErrorText) ->
|
{ErrorName, ErrorText} when is_list(ErrorText) ->
|
||||||
ErrorName ++ ": " ++ ErrorText;
|
ErrorName ++ ": " ++ ErrorText;
|
||||||
|
|
Loading…
Reference in New Issue