Skip to content

Commit

Permalink
Merge pull request #311 from 2600hz/KAZOO-1658
Browse files Browse the repository at this point in the history
Kazoo 1658
  • Loading branch information
k-anderson committed Apr 26, 2014
2 parents 143d9d2 + 2599965 commit ea7cdeb
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 70 deletions.
24 changes: 19 additions & 5 deletions applications/pivot/src/pivot_call.erl
Expand Up @@ -206,18 +206,26 @@ handle_cast({'gen_listener', {'created_queue', Q}}, #state{call=Call}=State) ->
%% TODO: Block on waiting for controller queue
{'noreply', State#state{call=whapps_call:set_controller_queue(Q, Call)}};

handle_cast({'stop', Call}, #state{cdr_uri='undefined'}=State) ->
handle_cast({'stop', _Call}, #state{cdr_uri='undefined'}=State) ->
lager:debug("no cdr callback, server going down"),
_ = whapps_call_command:hangup(Call),
{'stop', 'normal', State};

handle_cast({'cdr', JObj}, #state{cdr_uri=Url}=State) when Url =/= 'undefined'->
handle_cast({'cdr', _JObj}, #state{cdr_uri='undefined'
,call=Call
}=State) ->
lager:debug("recv cdr for call, no cdr uri though"),
erlang:send_after(3000, self(), {'stop', Call}),
{'noreply', State};
handle_cast({'cdr', JObj}, #state{cdr_uri=Url
,call=Call
}=State) ->
JObj1 = wh_json:delete_key(<<"Custom-Channel-Vars">>, JObj),
Body = wh_json:to_querystring(wh_api:remove_defaults(JObj1)),
Headers = [{"Content-Type", "application/x-www-form-urlencoded"}],
_R = ibrowse:send_req(wh_util:to_list(Url), Headers, 'post', Body),
lager:debug("cdr callback resp from server: ~p", [_R]),
{'stop', 'normal', State};
erlang:send_after(3000, self(), {'stop', Call}),
{'noreply', State};

handle_cast({'add_event_handler', {Pid, _Ref}}, #state{response_event_handlers=Pids}=State) ->
lager:debug("adding event handler ~p", [Pid]),
Expand All @@ -242,6 +250,9 @@ handle_cast(_Req, State) ->
%% {'stop', Reason, State}
%% @end
%%--------------------------------------------------------------------
handle_info({'stop', _Call}, State) ->
{'stop', 'normal', State};

handle_info({'ibrowse_async_headers', ReqId, "200", Hdrs}
,#state{request_id=ReqId}=State) ->
RespHeaders = normalize_resp_headers(Hdrs),
Expand Down Expand Up @@ -343,8 +354,11 @@ handle_event(_JObj, #state{response_pid=Pid
%% @spec terminate(Reason, State) -> void()
%% @end
%%--------------------------------------------------------------------
terminate(_Reason, #state{call=Call}) ->
terminate(_Reason, #state{call=Call
,response_pid=Pid
}) ->
_ = whapps_call_command:hangup(Call),
exit(Pid, 'kill'),
lager:info("pivot call terminating: ~p", [_Reason]).

%%--------------------------------------------------------------------
Expand Down
22 changes: 11 additions & 11 deletions core/kazoo_translator-1.0.0/src/convertors/kzt_twiml.erl
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2012-2013, 2600Hz
%%% @copyright (C) 2012-2014, 2600Hz
%%% @doc
%%%
%%% @end
Expand All @@ -22,6 +22,7 @@
,get_engine/1
,get_voice/1
,exec_gather_els/3
,action_url/1
]).

parse_cmds(XMLString) ->
Expand Down Expand Up @@ -207,7 +208,7 @@ set_variable(Call, Attrs) ->
,Call
)}.

-spec set_variables(whapps_call:call(), list()) -> whapps_call:call().
-spec set_variables(whapps_call:call(), xml_els()) -> whapps_call:call().
set_variables(Call, Els) when is_list(Els) ->
lists:foldl(fun(#xmlElement{name='Variable'
,attributes=Attrs
Expand All @@ -216,7 +217,7 @@ set_variables(Call, Els) when is_list(Els) ->
(_, C) -> C
end, Call, Els).

-spec say(whapps_call:call(), list(), xml_attribs()) ->
-spec say(whapps_call:call(), xml_els() | xml_texts(), xml_attribs()) ->
{'ok', whapps_call:call()} |
{'error', _, whapps_call:call()}.
say(Call, XmlText, Attrs) ->
Expand All @@ -238,12 +239,12 @@ say(Call, XmlText, Attrs) ->
N when N > 0 -> kzt_receiver:say_loop(Call, SayMe, Voice, Lang, Terminators, Engine, N)
end.

-spec play(whapps_call:call(), list(), xml_attribs()) ->
-spec play(whapps_call:call(), xml_els() | xml_texts(), xml_attribs()) ->
{'ok', whapps_call:call()} |
{'error', _, whapps_call:call()}.
play(Call, XmlText, Attrs) ->
whapps_call_command:answer(Call),
PlayMe = kzt_util:xml_text_to_binary(XmlText),
PlayMe = kz_xml:texts_to_binary(XmlText),
lager:info("PLAY '~s'", [PlayMe]),

Props = kzt_util:xml_attributes_to_proplist(Attrs),
Expand All @@ -254,7 +255,7 @@ play(Call, XmlText, Attrs) ->
N when N > 0 -> kzt_receiver:play_loop(Call, PlayMe, Terminators, N)
end.

-spec redirect(whapps_call:call(), list(), xml_attribs()) ->
-spec redirect(whapps_call:call(), xml_els() | xml_texts(), xml_attribs()) ->
{'request', whapps_call:call()}.
redirect(Call, XmlText, Attrs) ->
whapps_call_command:answer(Call),
Expand All @@ -263,7 +264,7 @@ redirect(Call, XmlText, Attrs) ->

CurrentUri = kzt_util:get_voice_uri(Call),

RedirectUri = kzt_util:xml_text_to_binary(XmlText),
RedirectUri = kz_xml:texts_to_binary(XmlText),

Call1 = case kzt_util:xml_elements(XmlText) of
[] -> Call;
Expand All @@ -278,7 +279,7 @@ redirect(Call, XmlText, Attrs) ->
],
{'request', lists:foldl(fun({F, V}, C) -> F(V, C) end, Call1, Setters)}.

-spec exec_gather_els(pid(), whapps_call:call(), list()) -> 'ok'.
-spec exec_gather_els(pid(), whapps_call:call(), xml_els()) -> 'ok'.
exec_gather_els(_Parent, _Call, []) ->
lager:info("finished gather sub elements");
exec_gather_els(Parent, Call, [SubAction|SubActions]) ->
Expand All @@ -290,15 +291,15 @@ exec_gather_els(Parent, Call, [SubAction|SubActions]) ->
{'ok', Call1} -> exec_gather_els(Parent, Call1, SubActions)
end.

-spec exec_gather_els(whapps_call:call(), list()) ->
-spec exec_gather_els(whapps_call:call(), xml_els()) ->
{'ok', whapps_call:call()}.
exec_gather_els(Call, SubActions) ->
{_Pid, _Ref}=PidRef =
spawn_monitor(?MODULE, 'exec_gather_els', [self(), Call, SubActions]),
lager:debug("started to exec gather els: ~p(~p)", [_Pid, _Ref]),
{'ok', kzt_util:set_gather_pidref(PidRef, Call)}.

-spec gather(whapps_call:call(), list(), xml_attribs()) ->
-spec gather(whapps_call:call(), xml_els(), xml_attribs()) ->
kzt_receiver:collect_dtmfs_return().
gather(Call, [], Attrs) -> gather(Call, Attrs);
gather(Call, SubActions, Attrs) ->
Expand Down Expand Up @@ -330,7 +331,6 @@ gather(Call, FinishKey, Timeout, Props, N) ->
{'ok', 'timeout', C} -> gather_finished(C, Props);
{'ok', 'dtmf_finish', C} -> gather_finished(C, Props);
{'ok', C} -> gather_finished(C, Props);
{'error', _E, _C}=ERR -> ERR;
{'stop', _C}=STOP -> STOP
end.

Expand Down
41 changes: 26 additions & 15 deletions core/kazoo_translator-1.0.0/src/convertors/kzt_twiml_dial.erl
@@ -1,5 +1,5 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2013, 2600Hz
%%% @copyright (C) 2013-2014, 2600Hz
%%% @doc
%%% Handle the emulation of the Dial verb
%%% @end
Expand All @@ -12,12 +12,12 @@

-include("../kzt.hrl").

-spec exec(whapps_call:call(), xml_els(), xml_els()) ->
-spec exec(whapps_call:call(), xml_els() | xml_texts(), xml_attribs()) ->
{'ok' | 'stop', whapps_call:call()}.
exec(Call, [#xmlText{type='text'}|_]=DialMeTxts, Attrs) ->
whapps_call_command:answer(Call),

case wnm_util:to_e164(cleanup_dial_me(kzt_util:xml_text_to_binary(DialMeTxts))) of
case wnm_util:to_e164(cleanup_dial_me(kz_xml:texts_to_binary(DialMeTxts))) of
<<>> ->
lager:debug("no text to dial, using only xml elements"),
exec(Call, kzt_util:xml_elements(DialMeTxts), Attrs);
Expand Down Expand Up @@ -65,7 +65,7 @@ exec(Call, [#xmlElement{name='Conference'

lager:debug("waited for offnet, maybe ending dial"),

maybe_end_dial(Call1),
maybe_end_dial(Call1, DialProps),
{'stop', Call1};

exec(Call, [#xmlElement{name='Queue'
Expand Down Expand Up @@ -109,8 +109,9 @@ exec(Call, [#xmlElement{}|_]=Endpoints, Attrs) ->

{'ok', Call2} = kzt_receiver:wait_for_offnet(
kzt_util:update_call_status(?STATUS_RINGING, Call1)
,Props
),
maybe_end_dial(Call2)
maybe_end_dial(Call2, Props)
end.

dial_me(Call, Attrs, DialMe) ->
Expand All @@ -132,8 +133,9 @@ dial_me(Call, Attrs, DialMe) ->

{'ok', Call2} = kzt_receiver:wait_for_offnet(
kzt_util:update_call_status(?STATUS_RINGING, Call1)
,Props
),
maybe_end_dial(Call2).
maybe_end_dial(Call2, Props).

send_bridge_command(EPs, Timeout, Strategy, IgnoreEarlyMedia, Call) ->
B = [{<<"Application-Name">>, <<"bridge">>}
Expand All @@ -158,17 +160,26 @@ setup_call_for_dial(Call, Props) ->
,Setters
).

-spec maybe_end_dial(whapps_call:call()) ->
-spec maybe_end_dial(whapps_call:call(), wh_proplist()) ->
{'ok' | 'stop', whapps_call:call()}.
maybe_end_dial(Call) ->
case kzt_util:get_call_status(Call) of
?STATUS_COMPLETED -> {'stop', Call};
_Status ->
lager:debug("a-leg status after bridge: ~s", [_Status]),
{'ok', Call} % will progress to next TwiML element
end.
maybe_end_dial(Call, Props) ->
maybe_end_dial(Call, Props, kzt_twiml:action_url(Props)).

maybe_end_dial(Call, _Props, 'undefined') ->
lager:debug("a-leg status after bridge: ~s", [kzt_util:get_call_status(Call)]),
{'ok', Call}; % will progress to next TwiML element
maybe_end_dial(Call, Props, ActionUrl) ->
CurrentUri = kzt_util:get_voice_uri(Call),
NewUri = kzt_util:resolve_uri(CurrentUri, ActionUrl),
lager:debug("sending req to ~s: ~s", [ActionUrl, NewUri]),
Method = kzt_util:http_method(Props),

Setters = [{fun kzt_util:set_voice_uri_method/2, Method}
,{fun kzt_util:set_voice_uri/2, NewUri}
],
{'request', lists:foldl(fun({F, V}, C) -> F(V, C) end, Call, Setters)}.

-spec cleanup_dial_me(ne_binary()) -> ne_binary().
-spec cleanup_dial_me(binary()) -> binary().
cleanup_dial_me(Txt) -> << <<C>> || <<C>> <= Txt, is_numeric_or_plus(C)>>.

-spec is_numeric_or_plus(pos_integer()) -> boolean().
Expand Down
42 changes: 21 additions & 21 deletions core/kazoo_translator-1.0.0/src/kzt_receiver.erl
Expand Up @@ -10,7 +10,7 @@

-include("kzt.hrl").

-export([wait_for_offnet/1
-export([wait_for_offnet/1, wait_for_offnet/2
,wait_for_noop/2
,wait_for_hangup/1
,wait_for_conference/1
Expand All @@ -24,6 +24,7 @@

-record(dial_req, {call :: whapps_call:call()
,hangup_dtmf :: api_binary()
,collect_dtmf = 'false' :: boolean()
,record_call :: boolean()
,call_timeout :: integer()
,call_time_limit :: integer()
Expand Down Expand Up @@ -82,9 +83,6 @@ collect_dtmfs(Call, FinishKey, Timeout, N, OnFirstFun, Collected) ->
end;
{'other', OtherJObj} ->
lager:debug("other message: ~p", [OtherJObj]),
collect_dtmfs(Call, FinishKey, collect_decr_timeout(Call, Timeout, Start), N, OnFirstFun, Collected);
_Msg ->
lager:debug("unhandled message: ~p", [_Msg]),
collect_dtmfs(Call, FinishKey, collect_decr_timeout(Call, Timeout, Start), N, OnFirstFun, Collected)
end.

Expand Down Expand Up @@ -151,13 +149,15 @@ say_loop(Call, SayMe, Voice, Lang, Terminators, Engine, N) ->
{'error', _, _}=ERR -> ERR
end.

-spec play_loop(whapps_call:call(), ne_binary(), wh_timeout()) ->
-spec play_loop(whapps_call:call(), binary(), wh_timeout()) ->
{'ok', whapps_call:call()} |
{'error', _, whapps_call:call()}.
-spec play_loop(whapps_call:call(), ne_binary(), list() | 'undefined', wh_timeout()) ->
-spec play_loop(whapps_call:call(), binary(), list() | 'undefined', wh_timeout()) ->
{'ok', whapps_call:call()} |
{'error', _, whapps_call:call()}.
play_loop(Call, PlayMe, N) -> play_loop(Call, PlayMe, 'undefined', N).

play_loop(Call, <<>>, _, _) -> {'error', Call};
play_loop(Call, _, _, 0) -> {'ok', Call};
play_loop(Call, PlayMe, Terminators, N) ->
NoopId = whapps_call_command:play(PlayMe, Terminators, Call),
Expand Down Expand Up @@ -266,16 +266,22 @@ process_noop_event(Call, NoopId, JObj) ->

-spec wait_for_offnet(whapps_call:call()) -> {'ok', whapps_call:call()}.
wait_for_offnet(Call) ->
wait_for_offnet(Call, []).

wait_for_offnet(Call, DialProps) ->
HangupDTMF = kzt_util:get_hangup_dtmf(Call),
RecordCall = kzt_util:get_record_call(Call),

CollectDTMF = props:get_is_true('collect_dtmf', DialProps, 'false'),

CallTimeLimit = kzt_util:get_call_time_limit(Call) * 1000,
CallTimeout = kzt_util:get_call_timeout(Call) * 1000,

lager:debug("tl: ~p t: ~p", [kzt_util:get_call_time_limit(Call), kzt_util:get_call_timeout(Call)]),

wait_for_offnet_events(#dial_req{call=Call
wait_for_offnet_events(#dial_req{call=kzt_util:clear_digits_collected(Call)
,hangup_dtmf=HangupDTMF
,collect_dtmf=CollectDTMF
,record_call=RecordCall
,call_timeout=CallTimeout
,call_time_limit=CallTimeLimit
Expand Down Expand Up @@ -336,14 +342,12 @@ wait_for_offnet_events(#dial_req{call_timeout=CallTimeout

case whapps_call_command:receive_event(RecvTimeout) of
{'ok', JObj} -> process_offnet_event(OffnetReq, JObj);
{'error', 'timeout'} -> handle_offnet_timeout(OffnetReq);
_O ->
lager:debug("recv offnet other: ~p", [_O]),
wait_for_offnet_events(OffnetReq)
{'error', 'timeout'} -> handle_offnet_timeout(OffnetReq)
end.

process_offnet_event(#dial_req{call=Call
,hangup_dtmf=HangupDTMF
,collect_dtmf=CollectDTMF
,call_b_leg=CallBLeg
}=OffnetReq
,JObj) ->
Expand All @@ -357,14 +361,16 @@ process_offnet_event(#dial_req{call=Call
{'ok', kzt_util:update_call_status(call_status(RespMsg), Call)};
{{<<"call_event">>, <<"DTMF">>}, CallId} ->
case (DTMF = wh_json:get_value(<<"DTMF-Digit">>, JObj)) =:= HangupDTMF of
'false' ->
lager:info("caller pressed dtmf tone '~s', adding to collection", [DTMF]),

'false' when CollectDTMF ->
lager:info("collecting dtmf ~s", [DTMF]),
wait_for_offnet_events(
update_offnet_timers(
OffnetReq#dial_req{
call=kzt_util:add_digit_collected(DTMF, Call)
}));
'false' ->
lager:info("caller pressed dtmf tone but we're not collecting it"),
wait_for_offnet_events(update_offnet_timers(OffnetReq));
'true' ->
lager:info("recv'd hangup DTMF '~s'", [HangupDTMF]),
whapps_call_command:hangup(Call)
Expand Down Expand Up @@ -475,10 +481,7 @@ wait_for_conference_events(#dial_req{call_timeout=CallTimeout

case whapps_call_command:receive_event(RecvTimeout) of
{'ok', JObj} -> process_conference_event(OffnetReq, JObj);
{'error', 'timeout'} -> handle_conference_timeout(OffnetReq);
_O ->
lager:debug("recv offnet other: ~p", [_O]),
wait_for_conference_events(OffnetReq)
{'error', 'timeout'} -> handle_conference_timeout(OffnetReq)
end.

process_conference_event(#dial_req{call=Call
Expand Down Expand Up @@ -587,9 +590,6 @@ recording_meta(Call, MediaName) ->
),
couch_mgr:save_doc(AcctDb, MediaDoc).

recording_name(ALeg) ->
DateTime = wh_util:pretty_print_datetime(calendar:universal_time()),
iolist_to_binary([DateTime, "_", ALeg, ".mp3"]).
recording_name(ALeg, BLeg) ->
DateTime = wh_util:pretty_print_datetime(calendar:universal_time()),
iolist_to_binary([DateTime, "_", ALeg, "_to_", BLeg, ".mp3"]).
Expand Down

0 comments on commit ea7cdeb

Please sign in to comment.