Skip to content

Commit

Permalink
WHISTLE-947: support subscriptions for parking extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
k-anderson committed Feb 14, 2012
1 parent 3086627 commit d1a78dd
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 16 deletions.
23 changes: 21 additions & 2 deletions whistle_apps/apps/callflow/src/cf_util.erl
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,27 @@ presence_mwi_update(_, _, _, _) ->
ok.

-spec presence_parking_slot/4 :: (ne_binary(), {ne_binary(), ne_binary()}, {ne_binary(), ne_binary()}, wh_json:json_object()) -> ok.
presence_parking_slot(_, _, _, _) ->
ok.
presence_parking_slot(<<"message-summary">>, _, _, _) ->
ok;
presence_parking_slot(_, {_, FromRealm}, {ToUser, ToRealm}, _) ->
case whapps_util:get_account_by_realm(FromRealm) of
{ok, AccountDb} ->
AccountId = wh_util:format_account_id(AccountDb, raw),
lookup_callflow(ToUser, AccountId),
case wh_cache:fetch({cf_flow, ToUser, AccountDb}) of
{error, not_found} -> ok;
{ok, Flow} ->
case wh_json:get_value([<<"flow">>, <<"module">>], Flow) of
<<"park">> ->
SlotNumber = wh_json:get_ne_value(<<"capture_group">>, Flow, ToUser),
cf_park:update_presence(SlotNumber, <<ToUser/binary, "@", ToRealm/binary>>, AccountDb);
_Else -> ok
end
end;
_E ->
?LOG("failed to find the account for realm ~s: ~p", [FromRealm, _E]),
ok
end.

%%--------------------------------------------------------------------
%% @private
Expand Down
49 changes: 35 additions & 14 deletions whistle_apps/apps/callflow/src/module/cf_park.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,30 @@
-include("../callflow.hrl").

-export([handle/2]).
-export([update_presence/3]).

-define(MOD_CONFIG_CAT, <<(?CF_CONFIG_CAT)/binary, ".park">>).

-define(DB_DOC_NAME, whapps_config:get(?MOD_CONFIG_CAT, <<"db_doc_name">>, <<"parked_calls">>)).
-define(DEFAULT_RINGBACK_TM, whapps_config:get_integer(?MOD_CONFIG_CAT, <<"default_ringback_time">>, 120000)).

%%--------------------------------------------------------------------
%% @public
%% @doc
%% Entry point for this module sends an arbitrary response back to the
%% call originator.
%% @end
%%--------------------------------------------------------------------
-spec update_presence/3 :: (ne_binary(), ne_binary(), ne_binary()) -> ok.
update_presence(SlotNumber, PresenceId, AccountDb) ->
AccountId = wh_util:format_account_id(AccountDb, raw),
ParkedCalls = get_parked_calls(#cf_call{account_db=AccountDb, account_id=AccountId}),
{State, CallId} = case wh_json:get_value([<<"slots">>, SlotNumber, <<"Call-ID">>], ParkedCalls) of
undefined -> {<<"terminated">>, undefined};
Else -> {<<"early">>, Else}
end,
cf_call_command:presence(State, PresenceId, CallId).

%%--------------------------------------------------------------------
%% @public
%% @doc
Expand All @@ -39,7 +57,7 @@ handle(Data, #cf_call{channel_vars=CCVs}=Call) ->
<<"retrieve">> ->
?LOG("action is to retrieve a parked call"),
case retrieve(SlotNumber, ParkedCalls, Call) of
false ->
false ->
cf_call_command:b_answer(Call),
cf_call_command:b_prompt(<<"park-no_caller">>, Call),
cf_exe:continue(Call);
Expand Down Expand Up @@ -95,7 +113,7 @@ retrieve(SlotNumber, ParkedCalls, #cf_call{to_user=ToUser, to_realm=ToRealm}=Cal
?LOG("They hungup? play back nobody here message", []),
false;
Slot ->
ParkedCall = wh_json:get_ne_value(<<"Call-ID">>, Slot),
ParkedCall = wh_json:get_ne_value(<<"Call-ID">>, Slot),
case get_switch_hostname(ParkedCall, Call) of
undefined ->
?LOG("the parked caller node is undefined"),
Expand Down Expand Up @@ -172,10 +190,11 @@ park_call(SlotNumber, ParkedCalls, ReferredTo, Call) ->
ok;
%% blind transfer and allowed to update the provided slot number
{_, {ok, _}} ->
ParkedCallId = wh_json:get_value(<<"Call-ID">>, Slot),
PresenceId = wh_json:get_value(<<"Presence-ID">>, Slot),
?LOG("update presence-id '~s' with state: early", [PresenceId]),
cf_call_command:presence(<<"early">>, PresenceId, Call),
wait_for_pickup(SlotNumber, wh_json:get_value(<<"Ringback-ID">>, Slot), Call),
cf_call_command:presence(<<"early">>, PresenceId, ParkedCallId),
wait_for_pickup(SlotNumber, wh_json:get_value(<<"Ringback-ID">>, Slot), Call),
ok
end.

Expand Down Expand Up @@ -296,16 +315,16 @@ update_call_id(Replaces, ParkedCalls, #cf_call{account_db=Db, channel_vars=CCVs
,fun(J) -> wh_json:set_value(<<"Node">>, CallerHost, J) end
,fun(J) -> wh_json:set_value(<<"CID-Number">>, CIDNum, J) end
,fun(J) -> wh_json:set_value(<<"CID-Name">>, CIDName, J) end
,fun(J) ->
,fun(J) ->
Referred = wh_json:get_value(<<"Referred-By">>, CCVs),
ReOptions = [{capture, [1], binary}],
case catch(re:run(Referred, <<".*sip:(.*)@.*">>, ReOptions)) of
{match, [Match]} ->
{match, [Match]} ->
case get_endpoint_id(Match, Call) of
undefined -> wh_json:delete_key(<<"Ringback-ID">>, J);
RingbackId -> wh_json:set_value(<<"Ringback-ID">>, RingbackId, J)
end;
_ ->
_ ->
wh_json:delete_key(<<"Ringback-ID">>, J)
end
end
Expand All @@ -315,9 +334,10 @@ update_call_id(Replaces, ParkedCalls, #cf_call{account_db=Db, channel_vars=CCVs
case couch_mgr:save_doc(Db, JObj) of
{ok, _} ->
publish_usurp_control(Call),
ParkedCallId = wh_json:get_value(<<"Call-ID">>, Slot),
PresenceId = wh_json:get_value(<<"Presence-ID">>, Slot),
?LOG("update presence-id '~s' with state: early", [PresenceId]),
cf_call_command:presence(<<"early">>, PresenceId, Call),
cf_call_command:presence(<<"early">>, PresenceId, ParkedCallId),
{ok, SlotNumber, UpdatedSlot};
{error, conflict} ->
update_call_id(Replaces, get_parked_calls(Call), Call)
Expand Down Expand Up @@ -385,11 +405,12 @@ cleanup_slot(SlotNumber, ParkedCall, #cf_call{account_db=Db}=Call) ->
case couch_mgr:open_doc(Db, ?DB_DOC_NAME) of
{ok, JObj} ->
case wh_json:get_value([<<"slots">>, SlotNumber, <<"Call-ID">>], JObj) of
ParkedCall ->
ParkedCall ->
?LOG("clean up matched the call id in the slot, terminating presence"),
ParkedCallId = wh_json:get_value([<<"slots">>, SlotNumber, <<"Call-ID">>], JObj),
PresenceId = wh_json:get_value([<<"slots">>, SlotNumber, <<"Presence-ID">>], JObj),
?LOG("update presence-id '~s' with state: terminated", [PresenceId]),
cf_call_command:presence(<<"terminated">>, PresenceId, Call),
cf_call_command:presence(<<"terminated">>, PresenceId, ParkedCallId),
case couch_mgr:save_doc(Db, wh_json:delete_key([<<"slots">>, SlotNumber], JObj)) of
{ok, _} -> true;
{error, conflict} -> cleanup_slot(SlotNumber, ParkedCall, Call);
Expand Down Expand Up @@ -454,7 +475,7 @@ get_node_ip(Node) ->
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Kill any other cf_exe or ecallmgr_call_control processes that are
%% Kill any other cf_exe or ecallmgr_call_control processes that are
%% hanging around waiting for the parked call on hold to hit the
%% timeout.
%% @end
Expand Down Expand Up @@ -490,7 +511,7 @@ get_endpoint_id(Username, #cf_call{account_db=Db}) ->
case couch_mgr:get_results(Db, <<"cf_attributes/sip_credentials">>, ViewOptions) of
{ok, [Device]} -> wh_json:get_value(<<"id">>, Device);
_ -> undefined
end.
end.

%%--------------------------------------------------------------------
%% @private
Expand All @@ -508,7 +529,7 @@ ringback_parker(EndpointId, SlotNumber, TmpCID, #cf_call{cid_name=OriginalName,
Update = [{<<"Caller-ID-Name">>, TmpCID}
,{<<"Callee-ID-Name">>, TmpCID}
],
CleanUpFun = fun(_) ->
CleanUpFun = fun(_) ->
cleanup_slot(SlotNumber, cf_exe:callid(Call), Call),
Restore = [{<<"Caller-ID-Name">>, OriginalName}
,{<<"Callee-ID-Name">>, OriginalName}
Expand All @@ -517,7 +538,7 @@ ringback_parker(EndpointId, SlotNumber, TmpCID, #cf_call{cid_name=OriginalName,
end,
cf_call_command:bridge(Endpoints, <<"20">>, Call#cf_call{channel_vars=wh_json:set_values(Update, CCVs)}),
case cf_call_command:wait_for_bridge(30000, CleanUpFun, Call) of
{ok, _} ->
{ok, _} ->
?LOG("completed successful bridge to the ringback device"),
answered;
_Else ->
Expand Down

0 comments on commit d1a78dd

Please sign in to comment.