summaryrefslogtreecommitdiff
path: root/src/mod_irc/mod_irc_connection.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_irc/mod_irc_connection.erl')
-rw-r--r--src/mod_irc/mod_irc_connection.erl242
1 files changed, 171 insertions, 71 deletions
diff --git a/src/mod_irc/mod_irc_connection.erl b/src/mod_irc/mod_irc_connection.erl
index 869b2e86..d503d17a 100644
--- a/src/mod_irc/mod_irc_connection.erl
+++ b/src/mod_irc/mod_irc_connection.erl
@@ -115,7 +115,7 @@ open_socket(init, StateData) ->
wait_for_registration(closed, StateData) ->
{stop, normal, StateData}.
-stream_established({xmlstreamend, Name}, StateData) ->
+stream_established({xmlstreamend, _Name}, StateData) ->
{stop, normal, StateData};
stream_established(timeout, StateData) ->
@@ -145,7 +145,7 @@ stream_established(closed, StateData) ->
%% {next_state, NextStateName, NextStateData, Timeout} |
%% {stop, Reason, NewStateData}
%%----------------------------------------------------------------------
-handle_event(Event, StateName, StateData) ->
+handle_event(_Event, StateName, StateData) ->
{next_state, StateName, StateData}.
%%----------------------------------------------------------------------
@@ -157,11 +157,11 @@ handle_event(Event, StateName, StateData) ->
%% {stop, Reason, NewStateData} |
%% {stop, Reason, Reply, NewStateData}
%%----------------------------------------------------------------------
-handle_sync_event(Event, From, StateName, StateData) ->
+handle_sync_event(_Event, _From, StateName, StateData) ->
Reply = ok,
{reply, Reply, StateName, StateData}.
-code_change(OldVsn, StateName, StateData, Extra) ->
+code_change(_OldVsn, StateName, StateData, _Extra) ->
{ok, StateName, StateData}.
-define(SEND(S),
@@ -243,15 +243,36 @@ handle_info({route_chan, Channel, Resource,
case Body of
"/quote " ++ Rest ->
?SEND(Rest ++ "\r\n");
+ "/msg " ++ Rest ->
+ ?SEND("PRIVMSG " ++ Rest ++ "\r\n");
+ "/me " ++ Rest ->
+ Strings = string:tokens(Rest, "\n"),
+ Res = lists:concat(
+ lists:map(
+ fun(S) ->
+ io_lib:format(
+ "PRIVMSG #~s :\001ACTION ~s\001\r\n",
+ [Channel, S])
+ end, Strings)),
+ ?SEND(Res);
+ "/ctcp " ++ Rest ->
+ Words = string:tokens(Rest, " "),
+ case Words of
+ [CtcpDest | _] ->
+ CtcpCmd =
+ toupper(
+ string:substr(
+ Rest,
+ string:str(Rest, " ") + 1)),
+ Res = io_lib:format(
+ "PRIVMSG ~s :\001~s\001\r\n",
+ [CtcpDest, CtcpCmd]),
+ ?SEND(Res);
+ _ ->
+ ok
+ end;
_ ->
- Body1 =
- case Body of
- [$/, $m, $e, $ | Rest] ->
- "\001ACTION " ++ Rest ++ "\001";
- _ ->
- Body
- end,
- Strings = string:tokens(Body1, "\n"),
+ Strings = string:tokens(Body, "\n"),
Res = lists:concat(
lists:map(
fun(S) ->
@@ -271,19 +292,40 @@ handle_info({route_chan, Channel, Resource,
end, Strings)),
?SEND(Res)
end;
- "chat" ->
+ Type when Type == "chat"; Type == ""; Type == "normal" ->
Body = xml:get_path_s(El, [{elem, "body"}, cdata]),
case Body of
"/quote " ++ Rest ->
?SEND(Rest ++ "\r\n");
+ "/msg " ++ Rest ->
+ ?SEND("PRIVMSG " ++ Rest ++ "\r\n");
+ "/me " ++ Rest ->
+ Strings = string:tokens(Rest, "\n"),
+ Res = lists:concat(
+ lists:map(
+ fun(S) ->
+ io_lib:format(
+ "PRIVMSG ~s :\001ACTION ~s\001\r\n",
+ [Resource, S])
+ end, Strings)),
+ ?SEND(Res);
+ "/ctcp " ++ Rest ->
+ Words = string:tokens(Rest, " "),
+ case Words of
+ [CtcpDest | _ ] ->
+ CtcpCmd =
+ toupper(
+ string:substr(
+ Rest, string:str(Rest, " ") + 1)),
+ Res = io_lib:format(
+ "PRIVMSG ~s :~s\r\n",
+ [CtcpDest, "\001" ++ CtcpCmd ++ "\001"]),
+ ?SEND(Res);
+ _ ->
+ ok
+ end;
_ ->
- Body1 = case Body of
- [$/, $m, $e, $ | Rest] ->
- "\001ACTION " ++ Rest ++ "\001";
- _ ->
- Body
- end,
- Strings = string:tokens(Body1, "\n"),
+ Strings = string:tokens(Body, "\n"),
Res = lists:concat(
lists:map(
fun(S) ->
@@ -358,14 +400,32 @@ handle_info({route_nick, Nick,
case Body of
"/quote " ++ Rest ->
?SEND(Rest ++ "\r\n");
+ "/msg " ++ Rest ->
+ ?SEND("PRIVMSG " ++ Rest ++ "\r\n");
+ "/me " ++ Rest ->
+ Strings = string:tokens(Rest, "\n"),
+ Res = lists:concat(
+ lists:map(
+ fun(S) ->
+ io_lib:format(
+ "PRIVMSG ~s :\001ACTION ~s\001\r\n",
+ [Nick, S])
+ end, Strings)),
+ ?SEND(Res);
+ "/ctcp " ++ Rest ->
+ Words = string:tokens(Rest, " "),
+ case Words of
+ [CtcpDest | _ ] ->
+ CtcpCmd = toupper(string:substr(Rest, string:str(Rest, " ")+1 )),
+ Res = io_lib:format(
+ "PRIVMSG ~s :~s\r\n",
+ [CtcpDest, "\001" ++ CtcpCmd ++ "\001"]),
+ ?SEND(Res);
+ _ ->
+ ok
+ end;
_ ->
- Body1 = case Body of
- [$/, $m, $e, $ | Rest] ->
- "\001ACTION " ++ Rest ++ "\001";
- _ ->
- Body
- end,
- Strings = string:tokens(Body1, "\n"),
+ Strings = string:tokens(Body, "\n"),
Res = lists:concat(
lists:map(
fun(S) ->
@@ -403,6 +463,9 @@ handle_info({ircstring, [$: | String]}, StateName, StateData) ->
[_, "332", Nick, [$# | Chan] | _] ->
process_channel_topic(StateData, Chan, String),
StateData;
+ [_, "333", Nick, [$# | Chan] | _] ->
+ process_channel_topic_who(StateData, Chan, String),
+ StateData;
[_, "318", _, Nick | _] ->
process_endofwhois(StateData, String, Nick),
StateData;
@@ -451,7 +514,7 @@ handle_info({ircstring, [$: | String]}, StateName, StateData) ->
"member", "participant"),
StateData;
[From, "KICK", [$# | Chan], Nick | _] ->
- process_kick(StateData, Chan, From, Nick),
+ process_kick(StateData, Chan, From, Nick, String),
StateData;
[From, "NICK", Nick | _] ->
process_nick(StateData, From, Nick);
@@ -626,16 +689,43 @@ process_channel_list_user(StateData, Chan, User) ->
process_channel_topic(StateData, Chan, String) ->
- FromUser = "someone",
{ok, Msg, _} = regexp:sub(String, ".*332[^:]*:", ""),
Msg1 = filter_message(Msg),
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.host, FromUser),
+ StateData#state.host, ""),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
- [{xmlelement, "subject", [], [{xmlcdata, Msg1}]}]}).
+ [{xmlelement, "subject", [], [{xmlcdata, Msg1}]},
+ {xmlelement, "body", [], [{xmlcdata, "Topic for #" ++ Chan ++ ": " ++ Msg1}]}
+ ]}).
+
+process_channel_topic_who(StateData, Chan, String) ->
+ Words = string:tokens(String, " "),
+ Msg1 = case Words of
+ [_, "333", _, _Chan, Whoset , Timeset] ->
+ case string:to_integer(Timeset) of
+ {Unixtimeset, Rest} ->
+ "Topic for #" ++ Chan ++ " set by " ++ Whoset ++
+ " at " ++ unixtime2string(Unixtimeset);
+ _->
+ "Topic for #" ++ Chan ++ " set by " ++ Whoset
+ end;
+ [_, "333", _, _Chan, Whoset | _] ->
+ "Topic for #" ++ Chan ++ " set by " ++ Whoset;
+ _ ->
+ String
+ end,
+ Msg2 = filter_message(Msg1),
+
+ ejabberd_router:route(
+ jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
+ StateData#state.host, ""),
+ StateData#state.user,
+ {xmlelement, "message", [{"type", "groupchat"}],
+ [{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
+
process_endofwhois(StateData, String, Nick) ->
@@ -708,7 +798,7 @@ process_channotice(StateData, Chan, From, String) ->
[1, $A, $C, $T, $I, $O, $N, $ | Rest] ->
"/me " ++ Rest;
_ ->
- Msg
+ "/me NOTICE: " ++ Msg
end,
Msg2 = filter_message(Msg1),
ejabberd_router:route(
@@ -716,7 +806,7 @@ process_channotice(StateData, Chan, From, String) ->
StateData#state.host, FromUser),
StateData#state.user,
{xmlelement, "message", [{"type", "groupchat"}],
- [{xmlelement, "body", [], [{xmlcdata, "NOTICE: " ++ Msg2}]}]}).
+ [{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
@@ -746,7 +836,7 @@ process_notice(StateData, Nick, From, String) ->
[1, $A, $C, $T, $I, $O, $N, $ | Rest] ->
"/me " ++ Rest;
_ ->
- Msg
+ "/me NOTICE: " ++ Msg
end,
Msg2 = filter_message(Msg1),
ejabberd_router:route(
@@ -754,7 +844,7 @@ process_notice(StateData, Nick, From, String) ->
StateData#state.host, ""),
StateData#state.user,
{xmlelement, "message", [{"type", "chat"}],
- [{xmlelement, "body", [], [{xmlcdata, "NOTICE: " ++ Msg2}]}]}).
+ [{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}).
process_version(StateData, Nick, From) ->
@@ -776,7 +866,7 @@ process_userinfo(StateData, Nick, From) ->
send_text(
StateData,
io_lib:format("NOTICE ~s :\001USERINFO "
- "This user uses xmpp:~s"
+ "xmpp:~s"
"\001\r\n",
[FromUser,
jlib:jid_to_string(StateData#state.user)])).
@@ -798,21 +888,12 @@ process_topic(StateData, Chan, From, String) ->
process_part(StateData, Chan, From, String) ->
[FromUser | FromIdent] = string:tokens(From, "!"),
- {ok, Msg, _} = regexp:sub(String, ".*PART[^:]*", ""),
+ {ok, Msg, _} = regexp:sub(String, ".*PART[^:]*:", ""),
Msg1 = filter_message(Msg),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, FromUser),
StateData#state.user,
- {xmlelement, "message", [{"type", "groupchat"}],
- [{xmlelement, "body", [],
- [{xmlcdata, "/me has part: " ++
- Msg1 ++ "(" ++ FromIdent ++ ")" }]}]}),
-
- ejabberd_router:route(
- jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.host, FromUser),
- StateData#state.user,
{xmlelement, "presence", [{"type", "unavailable"}],
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
[{xmlelement, "item",
@@ -820,7 +901,7 @@ process_part(StateData, Chan, From, String) ->
{"role", "none"}],
[]}]},
{xmlelement, "status", [],
- [{xmlcdata, Msg1 ++ "(" ++ FromIdent ++ ")"}]}]
+ [{xmlcdata, Msg1 ++ " (" ++ FromIdent ++ ")"}]}]
}),
case catch dict:update(Chan,
fun(Ps) ->
@@ -843,16 +924,6 @@ process_quit(StateData, From, String) ->
fun(Chan, Ps) ->
case ?SETS:is_member(FromUser, Ps) of
true ->
- ejabberd_router:route(
- jlib:make_jid(
- lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.host, FromUser),
- StateData#state.user,
- {xmlelement, "message", [{"type", "groupchat"}],
- [{xmlelement, "body", [],
- [{xmlcdata, "/me has quit: " ++
- Msg1 ++ "(" ++ FromIdent ++ ")" }]}]}),
-
ejabberd_router:route(
jlib:make_jid(
lists:concat([Chan, "%", StateData#state.server]),
@@ -865,7 +936,7 @@ process_quit(StateData, From, String) ->
{"role", "none"}],
[]}]},
{xmlelement, "status", [],
- [{xmlcdata, Msg1 ++ "(" ++ FromIdent ++ ")"}]}
+ [{xmlcdata, Msg1 ++ " (" ++ FromIdent ++ ")"}]}
]}),
remove_element(FromUser, Ps);
_ ->
@@ -890,16 +961,6 @@ process_join(StateData, Channel, From, String) ->
[]}]},
{xmlelement, "status", [],
[{xmlcdata, FromIdent}]}]}),
- {ok, Msg, _} = regexp:sub(String, ".*JOIN[^:]*:", ""),
- Msg1 = filter_message(Msg),
- ejabberd_router:route(
- jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
- StateData#state.host, FromUser),
- StateData#state.user,
- {xmlelement, "message", [{"type", "groupchat"}],
- [{xmlelement, "body", [],
- [{xmlcdata, "/me has joined " ++
- Msg1 ++ "(" ++ FromIdent ++ ")" }]}]}),
case catch dict:update(Chan,
fun(Ps) ->
@@ -926,8 +987,15 @@ process_mode_o(StateData, Chan, From, Nick, Affiliation, Role) ->
{"role", Role}],
[]}]}]}).
-process_kick(StateData, Chan, From, Nick) ->
- %Msg = lists:last(string:tokens(String, ":")),
+process_kick(StateData, Chan, From, Nick, String) ->
+ Msg = lists:last(string:tokens(String, ":")),
+ Msg2 = Nick ++ " kicked by " ++ From ++ " (" ++ filter_message(Msg) ++ ")",
+ ejabberd_router:route(
+ jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
+ StateData#state.host, ""),
+ StateData#state.user,
+ {xmlelement, "message", [{"type", "groupchat"}],
+ [{xmlelement, "body", [], [{xmlcdata, Msg2}]}]}),
ejabberd_router:route(
jlib:make_jid(lists:concat([Chan, "%", StateData#state.server]),
StateData#state.host, Nick),
@@ -1086,4 +1154,36 @@ filter_message(Msg) ->
false;
true -> true
end
- end, Msg).
+ end, filter_mirc_colors(Msg)).
+
+filter_mirc_colors(Msg) ->
+ case regexp:gsub(Msg, "(\\003[0-9]+)(,[0-9]+)?", "") of
+ {ok, Msg2, _} ->
+ Msg2;
+ _ ->
+ Msg
+ end.
+
+unixtime2string(Unixtime) ->
+ Secs = Unixtime + calendar:datetime_to_gregorian_seconds(
+ {{1970, 1, 1}, {0,0,0}}),
+ case calendar:universal_time_to_local_time(
+ calendar:gregorian_seconds_to_datetime(Secs)) of
+ {{Year, Month, Day}, {Hour, Minute, Second}} ->
+ lists:flatten(
+ io_lib:format("~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",
+ [Year, Month, Day, Hour, Minute, Second]));
+ _->
+ "0000-00-00 00:00:00"
+ end.
+
+toupper([C | Cs]) ->
+ if
+ C >= $a, C =< $z ->
+ [C - 32 | toupper(Cs)];
+ true ->
+ [C | toupper(Cs)]
+ end;
+toupper([]) ->
+ [].
+