Send !-commands to AMQP for other programs
authorMatt Mullins <mmullins@mmlx.us>
Tue, 22 Jan 2013 04:00:16 +0000 (20:00 -0800)
committerMatt Mullins <mmullins@mmlx.us>
Tue, 22 Jan 2013 04:00:16 +0000 (20:00 -0800)
irc/irc_amqp_listener.erl
irc/irc_command.erl
irc/irc_conn.erl

index a5accc7..ceca5aa 100644 (file)
@@ -4,10 +4,13 @@
 -behavior(gen_server).
 -vsn(2).
 
+-define(EXCHANGE, <<"irc">>).
+
 -export([
           start_link/2,
           encode_routing_key/1,
-          decode_routing_key/1
+          decode_routing_key/1,
+          send_message/3
         ]).
 
 -export([
@@ -44,6 +47,22 @@ handle_info(
     irc_conn:send_command(ConnectionPid, Command),
     {noreply, State}.
 
+%% @doc Sends a message with the given routing key and body to the proper
+%% exchange
+send_message(RoutingKey, ReplyTo, Body) ->
+    BinKey = list_to_binary(RoutingKey),
+    BinReplyKey = list_to_binary(ReplyTo),
+    BinBody = list_to_binary(Body),
+    {ok, Channel} = amqp_bot_connection:open_channel(),
+    amqp_channel:call(Channel, #'basic.publish'{ routing_key = BinKey,
+                                                 exchange = ?EXCHANGE },
+                               #amqp_msg{ payload = BinBody,
+                                          props = #'P_basic' {
+                                              reply_to = BinReplyKey
+                                          }
+                                        }),
+    amqp_channel:close(Channel).
+
 %% @doc Encode an IRC-domain string as an AMQP-compatible routing key -- that
 %% is, in the set [A-Za-z0-9}.  We encode them as follows:
 %%   * lower-case letters are unchanged.
index 87463eb..4f37cc7 100644 (file)
@@ -22,9 +22,30 @@ do_privmsg_command(Text, From) ->
                                       middles = [From],
                                       trailing = Response},
             irc_conn:send_command(self(), NewCommand);
-        _ -> ok
+        _ ->
+            Source = extract_source(From),
+            {Command, SpaceThenBody} = lists:splitwith(
+                    fun(X) -> X /= $  end,
+                    Text),
+            Body = case SpaceThenBody of
+                [] -> [];
+                [_|T] -> T
+            end,
+
+            irc_conn:send_amqp_command(self(), Command, Body, Source)
     end.
 
+%% Extracts the logical source of the message from the string received from the
+%% IRC server's PRIVMSG commands.
+%%
+%% This is used to determine what to PRIVMSG to send a reply.
+%%
+%% Example:
+%%   "mokomull!mmullins@mmlx.us" -> "mokomull"
+%%   "#tamulug" -> "#tamulug"
+extract_source(From) ->
+    hd(string:tokens(From, "!")).
+
 random_choice([SplitChar | ChoicesText]) ->
     Choices = string:tokens(ChoicesText, [SplitChar]),
     Count = length(Choices),
index 3628fc1..3d4ba62 100644 (file)
@@ -6,7 +6,8 @@
 
 -export([
           start_link/3,
-          send_command/2
+          send_command/2,
+          send_amqp_command/4
         ]).
 
 -export([
@@ -37,6 +38,9 @@ start_link(Instance, Supervisor, TableId) ->
 send_command(Pid, Command) ->
     gen_server:cast(Pid, {send_command, Command}).
 
+send_amqp_command(Pid, Command, Body, Source) ->
+       gen_server:cast(Pid, {send_amqp_command, Command, Body, Source}).
+
 init({Instance, Supervisor, TableId}) ->
     ets:insert(TableId, {irc_conn_pid, self()}), % record the connection PID in the table
 
@@ -87,6 +91,16 @@ handle_cast({send_command, Command}, State) ->
                 ),
     {noreply, State};
 
+handle_cast({send_amqp_command, Command, Body, Source}, State) ->
+       #irc_state{ instance = Instance } = State,
+       InstanceKey = irc_amqp_listener:encode_routing_key(atom_to_list(Instance)),
+       SourceKey = irc_amqp_listener:encode_routing_key(Source),
+       CommandKey = irc_amqp_listener:encode_routing_key(Command),
+       Key = InstanceKey ++ ".command." ++ CommandKey,
+       ReplyKey = InstanceKey ++ ".output." ++ SourceKey,
+       irc_amqp_listener:send_message(Key, ReplyKey, Body),
+       {noreply, State};
+
 handle_cast(create_object_sup, State) ->
     #irc_state{ instance = Instance,
                 supervisor = Supervisor,