Guest User

OpenACD Restful Call Control

a guest
May 1st, 2012
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 9.78 KB | None | 0 0
  1. %Module
  2. -module(open_rcc_server).
  3.  
  4. %Behaviour
  5. -behaviour(gen_server).
  6.  
  7. %Start Function
  8. -export([start_link/1]).
  9.  
  10. %Gen_Server API
  11. -export([
  12.     init/1,
  13.     handle_call/3,
  14.     handle_cast/2,
  15.     handle_info/2,
  16.     terminate/2,
  17.     code_change/3
  18. ]).
  19.  
  20. %% mochi
  21. -export([start/1,
  22.          stop/0]).
  23.  
  24. %OpenACD
  25. -include_lib("OpenACD/include/log.hrl").
  26. -include_lib("OpenACD/include/call.hrl").
  27. -include_lib("OpenACD/include/agent.hrl").
  28.  
  29.  
  30. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  31. %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Gen_Server Stuff %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  32. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  33.  
  34.  
  35. -record(state, {} ). %Empty for now.
  36.  
  37. start_link(Port) ->
  38.     {foo, '[email protected]'} ! {api, log, "info [open_rcc_server:start_link/0] Starting open_rcc_server..."},
  39.     gen_server:start_link({local, open_rcc_server}, open_rcc_server, [Port], []).
  40.  
  41. init([Port]) ->
  42.     {foo, '[email protected]'} ! {api, log, "info [open_rcc_server:init/1] Starting mochi..."},
  43.     start(Port),
  44.     NewState = #state{},
  45.     {ok, NewState}.
  46.  
  47. handle_call(_Msg, _From, State) ->
  48.     {reply, ok, State}.
  49.  
  50. handle_cast(_MSG, State) ->
  51.     {noreply, State}.
  52.  
  53. handle_info(_Msg, State) ->
  54.     NewState = State,
  55.     {noreply, NewState}.
  56.  
  57. terminate(_,_) ->
  58.     ok.
  59.  
  60. code_change(_, _, State) ->
  61.     {ok, State}.
  62.  
  63. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  64. %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Mochi-Web Stuff %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  65. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  66.  
  67.  
  68. start(Port) ->
  69.     mochiweb_http:start([{port, Port},
  70.                          {loop, fun(Req) ->
  71.                             Path = Req:get(path),
  72.                             Resource = case string:str(Path, "?") of
  73.                                 0 -> Path;
  74.                                 N -> string:substr(Path, 1, length(Path) - (N + 1))
  75.                             end,
  76.                             handle_request(Resource, Req)
  77.                         end}]).
  78.  
  79. stop() ->
  80.     mochiweb_http:stop().
  81.  
  82. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  83. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% REST API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  84. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  85.  
  86.  
  87. handle_request("/agents", Req) ->
  88.     Data = cpx:get_agents(),
  89.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Data])))});
  90.  
  91. handle_request("/clients", Req) ->
  92.     Data = call_queue_config:get_clients(),
  93.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Data])))});
  94.  
  95. handle_request("/queues", Req) ->
  96.     Data = call_queue_config:get_queues(),
  97.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Data])))});
  98.  
  99. handle_request("/ringtest/" ++ Agent, Req) ->
  100.     AgentPid = cpx:get_agent(Agent),
  101.     AgentRec = agent:dump_state(AgentPid),
  102.     Callrec = #call{id = "unused", source = self(), callerid= {"Echo test", "0000000"}},
  103.    
  104.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p~p~p", [AgentPid, AgentRec, Callrec])))}),
  105.  
  106.     Data = freeswitch_media_manager:ring_agent_echo(AgentPid, AgentRec, Callrec, 60000),
  107.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Data])))});
  108.     %Data = freeswitch_dialer:start(Node, Number, Exten, Skills, Client, Vars),
  109.  
  110. %freeswitch_media_manager:make_outbound_call("DCF", cpx:get_agent("742"), agent:dump_state(cpx:get_agent("742")#agent.login)
  111.  
  112. handle_request("/init_outbound/" ++ Rest, Req) ->
  113.     Apid = cpx:get_agent(Rest),
  114.     AgentRec = agent:dump_state(cpx:get_agent(Rest)), % TODO - avoid
  115.     Reply = case AgentRec#agent.state of
  116.         Agentstate when Agentstate =:= released; Agentstate =:= idle ->
  117.             try list_to_existing_atom("freeswitch") of
  118.                 freeswitch ->
  119.                     case whereis(freeswitch_media_manager) of
  120.                         P when is_pid(P) ->
  121.                             case freeswitch_media_manager:make_outbound_call("DCF", Apid, AgentRec#agent.login) of
  122.                                 {ok, Pid} ->
  123.                                     Call = gen_media:get_call(Pid),
  124.                                     agent:set_state(Apid, precall, Call),
  125.                                     {200, [], mochijson2:encode({struct, [{success, true}]}), Call};
  126.                                 {error, Reason} ->
  127.                                     {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, list_to_binary(io_lib:format("Initializing outbound call failed (~p)", [Reason]))}, {<<"errcode">>, <<"UNKNOWN_ERROR">>}]})}
  128.                             end;
  129.                          _ ->
  130.                             {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"freeswitch is not available">>}, {<<"errcode">>, <<"MEDIA_NOEXISTS">>}]})}
  131.                     end;
  132.                 % TODO - more outbound types go here :)
  133.                 _ ->
  134.                     {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"Unknown call type">>}, {<<"errcode">>, <<"MEDIA_NOEXISTS">>}]})}
  135.             catch
  136.                 _:_ ->
  137.                     {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"Unknown call type">>}, {<<"errcode">>, <<"MEDIA_NOEXISTS">>}]})}
  138.             end;
  139.         _ ->
  140.             {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"Agent must be released or idle">>}, {<<"errcode">>, <<"INVALID_STATE_CHANGE">>}]})}
  141.     end,
  142.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Reply])))});
  143.  
  144. handle_request("/dial" ++ _Rest, Req) ->
  145.     QueryStringData = Req:parse_qs(),
  146.     Agent = proplists:get_value("agent", QueryStringData, "undefined"),
  147.     Number = proplists:get_value("number", QueryStringData, "undefined"),
  148.     {true, Pid} = agent_manager:query_agent(Agent),
  149.     ?NOTICE("1) ~p~p", [Agent, Number]),
  150.     AgentRec = agent:dump_state(Pid),
  151.     ?NOTICE("2) ~p", [AgentRec]),
  152.     try
  153.        
  154.         Reply =
  155.             case AgentRec#agent.state of
  156.                 precall ->
  157.                     #agent{statedata = Call} = AgentRec,
  158.                     ?NOTICE("3) ~p", [Call]),
  159.                     case Call#call.direction of
  160.                         outbound ->
  161.                             case gen_media:call(Call#call.source, {dial, Number}) of
  162.                                 ok ->
  163.                                     {reply, {200, [], mochijson2:encode({struct, [{success, true}]})}};
  164.                                 {error, Error} ->
  165.                                     ?NOTICE("Outbound call error ~p", [Error]),
  166.                                     {reply, {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, list_to_binary(lists:flatten(io_lib:format("~p, Check your phone configuration", [Error])))}, {<<"errcode">>, <<"UNKNOWN_ERROR">>}]})}}
  167.                             end;
  168.                         _ ->
  169.                             {reply, {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"This is not an outbound call">>}, {<<"errcode">>, <<"INVALID_STATE_CHANGE">>}]})}}
  170.                     end;
  171.                 _ ->
  172.                     {reply, {200, [], mochijson2:encode({struct, [{success, false}, {<<"message">>, <<"Agent is not in pre-call">>}, {<<"errcode">>, <<"INVALID_STATE_CHANGE">>}]})}}
  173.             end,
  174.         Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Reply])))})
  175.     catch
  176.         What:Why ->
  177.             cpxlog:error(now(), ?MODULE, ?LINE, self(), "//////////////////////////////////////////////////////////////////////////////\n
  178.                                                         //////////////////////////////////////////////////////////////////////////////\n
  179.                                                         What:~p\n
  180.                                                         Why:~p\n
  181.                                                         //////////////////////////////////////////////////////////////////////////////\n
  182.                                                         //////////////////////////////////////////////////////////////////////////////\n", [What, Why])
  183.     end;
  184.  
  185. handle_request("/spy" ++ _Rest, Req) ->
  186.    
  187.     QueryStringData = Req:parse_qs(),
  188.     Spy = proplists:get_value("spy", QueryStringData, "undefined"),
  189.     Agent = proplists:get_value("agent", QueryStringData, "undefined"),
  190.  
  191.     SpyPid = case agent_manager:query_agent(Spy) of
  192.         {true, Spid} -> Spid;
  193.         false -> self()
  194.     end,
  195.     Response  = case agent_manager:query_agent(Agent) of
  196.         {true, Apid} ->
  197.             case agent_channel:get_media(Apid) of
  198.                 CallRec when is_record(CallRec, call) ->
  199.                     case gen_media:spy(CallRec#call.source, SpyPid, agent:dump_state(cpx:get_agent(Apid))) of
  200.                         ok ->
  201.                             {struct, [{success, true}]};
  202.                         invalid ->
  203.                             {struct, [{success, false}, {<<"message">>, <<"invalid action">>}, {<<"errcode">>, <<"MEDIA_ACTION_UNSUPPORTED">>}]};
  204.                         {error, Err} ->
  205.                             {struct, [{success, false}, {<<"message">>, list_to_binary(io_lib:format("Error:  ~p", [Err]))}, {<<"errcode">>, <<"UNKNOWN_ERROR">>}]}
  206.                     end;
  207.                 _ ->
  208.                     {struct, [{success, false}, {<<"message">>, <<"agent not oncall">>}, {<<"errcode">>, <<"INVALID_STATE or NYI">>}]}
  209.             end;
  210.         false ->
  211.             {struct, [{success, false}, {<<"message">>, <<"no such agent">>}, {<<"errcode">>, <<"AGENT_NOEXISTS">>}]}
  212.     end,
  213.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Response])))});
  214.    
  215. handle_request("/hangup", Req) ->
  216.     Data = agent_tcp_client:hangup(self()),
  217.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Data])))});
  218.  
  219. handle_request("/transfer", Req) ->
  220.     QueryStringData = Req:parse_qs(),
  221.     FromAgent = proplists:get_value("from", QueryStringData, "undefined"),
  222.     ToAgent = proplists:get_value("to", QueryStringData, "undefined"),
  223.    
  224.     {true, From} = agent_manager:query_agent(FromAgent),
  225.     {true, To} = agent_manager:query_agent(ToAgent),
  226.    
  227.     Response = agent_channel:agent_transfer(From, To),
  228.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(lists:flatten(io_lib:format("~p", [Response])))});
  229.  
  230. handle_request(Path, Req) ->
  231.     Get = Req:parse_qs(),
  232.     Post = Req:parse_post(),
  233.     User_agent = Req:get_header_value("user-agent"),
  234.     %erlang:display({get, Get}),
  235.     %erlang:display({post, Post}),
  236.     %erlang:display({user_agent, User_agent}),
  237.     %erlang:display({path, Path}),
  238.     Req:respond({200, [{"Content-Type", "text/html"}], list_to_binary(Path)}).
Advertisement
Add Comment
Please, Sign In to add comment