From 477f2727c98fa9ebc0e1dfb95c7e1e0adf2173df Mon Sep 17 00:00:00 2001 From: Alexey Khabulyak Date: Wed, 23 Jun 2021 14:29:10 +0300 Subject: [PATCH 1/2] PISTON-1290 added the ability to be able to skip call recording for feature calls. --- applications/crossbar/doc/accounts.md | 1 + applications/crossbar/doc/devices.md | 1 + applications/crossbar/doc/ref/accounts.md | 1 + applications/crossbar/doc/ref/devices.md | 1 + applications/crossbar/doc/ref/users.md | 1 + applications/crossbar/doc/users.md | 1 + applications/crossbar/priv/api/swagger.json | 5 +++++ .../schemas/call_recording.parameters.json | 5 +++++ core/kazoo_call/src/kapps_call.erl | 17 +++++++++++++++++ .../kazoo_endpoint/src/kz_account_recording.erl | 6 ++++-- .../src/kz_endpoint_recording.erl | 6 ++++-- 11 files changed, 41 insertions(+), 4 deletions(-) diff --git a/applications/crossbar/doc/accounts.md b/applications/crossbar/doc/accounts.md index 6fb7e8b0a65..46cf75f5564 100644 --- a/applications/crossbar/doc/accounts.md +++ b/applications/crossbar/doc/accounts.md @@ -83,6 +83,7 @@ Key | Description | Type | Default | Required | Support Level --- | ----------- | ---- | ------- | -------- | ------------- `enabled` | is recording enabled | `boolean()` | | `false` | `format` | What format to store the recording on disk | `string('mp3' | 'wav')` | | `false` | +`record_feature_code_calls` | Record calls to feature codes | `boolean()` | `true` | `false` | `record_min_sec` | The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted | `integer()` | | `false` | `record_on_answer` | Recording should start on answer | `boolean()` | | `false` | `record_on_bridge` | Recording should start on bridge | `boolean()` | | `false` | diff --git a/applications/crossbar/doc/devices.md b/applications/crossbar/doc/devices.md index ccdd579994f..6bb76b73468 100644 --- a/applications/crossbar/doc/devices.md +++ b/applications/crossbar/doc/devices.md @@ -105,6 +105,7 @@ Key | Description | Type | Default | Required | Support Level --- | ----------- | ---- | ------- | -------- | ------------- `enabled` | is recording enabled | `boolean()` | | `false` | `format` | What format to store the recording on disk | `string('mp3' | 'wav')` | | `false` | +`record_feature_code_calls` | Record calls to feature codes | `boolean()` | `true` | `false` | `record_min_sec` | The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted | `integer()` | | `false` | `record_on_answer` | Recording should start on answer | `boolean()` | | `false` | `record_on_bridge` | Recording should start on bridge | `boolean()` | | `false` | diff --git a/applications/crossbar/doc/ref/accounts.md b/applications/crossbar/doc/ref/accounts.md index 8da3db51cfb..aa65b5f7c80 100644 --- a/applications/crossbar/doc/ref/accounts.md +++ b/applications/crossbar/doc/ref/accounts.md @@ -75,6 +75,7 @@ Key | Description | Type | Default | Required | Support Level --- | ----------- | ---- | ------- | -------- | ------------- `enabled` | is recording enabled | `boolean()` | | `false` | `format` | What format to store the recording on disk | `string('mp3' | 'wav')` | | `false` | +`record_feature_code_calls` | Record calls to feature codes | `boolean()` | `true` | `false` | `record_min_sec` | The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted | `integer()` | | `false` | `record_on_answer` | Recording should start on answer | `boolean()` | | `false` | `record_on_bridge` | Recording should start on bridge | `boolean()` | | `false` | diff --git a/applications/crossbar/doc/ref/devices.md b/applications/crossbar/doc/ref/devices.md index 8d8b618b587..e30af48c0c8 100644 --- a/applications/crossbar/doc/ref/devices.md +++ b/applications/crossbar/doc/ref/devices.md @@ -102,6 +102,7 @@ Key | Description | Type | Default | Required | Support Level --- | ----------- | ---- | ------- | -------- | ------------- `enabled` | is recording enabled | `boolean()` | | `false` | `format` | What format to store the recording on disk | `string('mp3' | 'wav')` | | `false` | +`record_feature_code_calls` | Record calls to feature codes | `boolean()` | `true` | `false` | `record_min_sec` | The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted | `integer()` | | `false` | `record_on_answer` | Recording should start on answer | `boolean()` | | `false` | `record_on_bridge` | Recording should start on bridge | `boolean()` | | `false` | diff --git a/applications/crossbar/doc/ref/users.md b/applications/crossbar/doc/ref/users.md index 186e6384b91..a21a463fd07 100644 --- a/applications/crossbar/doc/ref/users.md +++ b/applications/crossbar/doc/ref/users.md @@ -86,6 +86,7 @@ Key | Description | Type | Default | Required | Support Level --- | ----------- | ---- | ------- | -------- | ------------- `enabled` | is recording enabled | `boolean()` | | `false` | `format` | What format to store the recording on disk | `string('mp3' | 'wav')` | | `false` | +`record_feature_code_calls` | Record calls to feature codes | `boolean()` | `true` | `false` | `record_min_sec` | The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted | `integer()` | | `false` | `record_on_answer` | Recording should start on answer | `boolean()` | | `false` | `record_on_bridge` | Recording should start on bridge | `boolean()` | | `false` | diff --git a/applications/crossbar/doc/users.md b/applications/crossbar/doc/users.md index 15359d600d7..27a7af9ec32 100644 --- a/applications/crossbar/doc/users.md +++ b/applications/crossbar/doc/users.md @@ -88,6 +88,7 @@ Key | Description | Type | Default | Required | Support Level --- | ----------- | ---- | ------- | -------- | ------------- `enabled` | is recording enabled | `boolean()` | | `false` | `format` | What format to store the recording on disk | `string('mp3' | 'wav')` | | `false` | +`record_feature_code_calls` | Record calls to feature codes | `boolean()` | `true` | `false` | `record_min_sec` | The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted | `integer()` | | `false` | `record_on_answer` | Recording should start on answer | `boolean()` | | `false` | `record_on_bridge` | Recording should start on bridge | `boolean()` | | `false` | diff --git a/applications/crossbar/priv/api/swagger.json b/applications/crossbar/priv/api/swagger.json index f7d200f5744..13f281ef7c3 100644 --- a/applications/crossbar/priv/api/swagger.json +++ b/applications/crossbar/priv/api/swagger.json @@ -1087,6 +1087,11 @@ ], "type": "string" }, + "record_feature_code_calls": { + "default": true, + "description": "Record calls to feature codes", + "type": "boolean" + }, "record_min_sec": { "description": "The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted", "type": "integer" diff --git a/applications/crossbar/priv/couchdb/schemas/call_recording.parameters.json b/applications/crossbar/priv/couchdb/schemas/call_recording.parameters.json index a71bf74b424..1ed1af6e13c 100644 --- a/applications/crossbar/priv/couchdb/schemas/call_recording.parameters.json +++ b/applications/crossbar/priv/couchdb/schemas/call_recording.parameters.json @@ -15,6 +15,11 @@ ], "type": "string" }, + "record_feature_code_calls": { + "default": true, + "description": "Record calls to feature codes", + "type": "boolean" + }, "record_min_sec": { "description": "The minimum length, in seconds, the recording must be to be considered successful. Otherwise it is deleted", "type": "integer" diff --git a/core/kazoo_call/src/kapps_call.erl b/core/kazoo_call/src/kapps_call.erl index 35c645cf7cd..cc098e5fa4d 100644 --- a/core/kazoo_call/src/kapps_call.erl +++ b/core/kazoo_call/src/kapps_call.erl @@ -136,6 +136,7 @@ ,mask_recording/1, mask_recording/2 ,unmask_recording/1, unmask_recording/2 ,stop_recording/1 + ,should_skip_feature_calls_recording/2 ]). -export([is_recording/1, set_is_recording/2]). @@ -1609,6 +1610,22 @@ get_recordings(Call) -> Q -> Q end. +%%------------------------------------------------------------------------------ +%% @doc Check if we should record calls to feature codes. +%% First, we check if the callee number starts with * and then check +%% if the `record_feature_code_calls' param is set. +%% If the call is a feature call and record feature code calls is false, +%% then we skip the call recording. +%% @end +%%------------------------------------------------------------------------------ +-spec should_skip_feature_calls_recording(call(), kz_term:api_object()) -> boolean(). +should_skip_feature_calls_recording(Call, Data) -> + try binary:first(request_user(Call)) == $* + andalso not kz_json:is_true(<<"record_feature_code_calls">>, Data, 'true') + catch + _:_ -> 'false' + end. + -spec inception_type(call()) -> kz_term:ne_binary(). inception_type(#kapps_call{inception='undefined'}) -> <<"onnet">>; inception_type(#kapps_call{}) -> <<"offnet">>. diff --git a/core/kazoo_endpoint/src/kz_account_recording.erl b/core/kazoo_endpoint/src/kz_account_recording.erl index 046cec94edb..c496d50f6e7 100644 --- a/core/kazoo_endpoint/src/kz_account_recording.erl +++ b/core/kazoo_endpoint/src/kz_account_recording.erl @@ -27,7 +27,8 @@ maybe_record_inbound(FromNetwork, Endpoint, Call) -> {'true', kapps_call:call()} | 'false'. maybe_record_inbound(_FromNetwork, _Endpoint, _Call, 'undefined') -> 'false'; maybe_record_inbound(FromNetwork, _Endpoint, Call, Data) -> - case kz_json:is_true(<<"enabled">>, Data) of + case kz_json:is_true(<<"enabled">>, Data) + andalso not kapps_call:should_skip_feature_calls_recording(Call, Data) of 'false' -> 'false'; 'true' -> LabeledData = kz_json:set_value(<<"origin">>, ?ACCOUNT_INBOUND_RECORDING_LABEL(FromNetwork), Data), @@ -46,7 +47,8 @@ maybe_record_outbound(ToNetwork, Endpoint, Call) -> {'true', kapps_call:call()} | 'false'. maybe_record_outbound(_ToNetwork, _Endpoint, _Call, 'undefined') -> 'false'; maybe_record_outbound(ToNetwork, _Endpoint, Call, Data) -> - case kz_json:is_true(<<"enabled">>, Data) of + case kz_json:is_true(<<"enabled">>, Data) + andalso not kapps_call:should_skip_feature_calls_recording(Call, Data) of 'false' -> 'false'; 'true' -> LabeledData = kz_json:set_value(<<"origin">>, ?ACCOUNT_OUTBOUND_RECORDING_LABEL(ToNetwork), Data), diff --git a/core/kazoo_endpoint/src/kz_endpoint_recording.erl b/core/kazoo_endpoint/src/kz_endpoint_recording.erl index 651fb776f10..20d23248920 100644 --- a/core/kazoo_endpoint/src/kz_endpoint_recording.erl +++ b/core/kazoo_endpoint/src/kz_endpoint_recording.erl @@ -532,7 +532,8 @@ maybe_record_inbound(FromNetwork, Endpoint, Call) -> {'true', {kz_json:path(), kz_json:object()}} | 'false'. maybe_record_inbound(_FromNetwork, _Endpoint, _Call, 'undefined') -> 'false'; maybe_record_inbound(FromNetwork, Endpoint, Call, Data) -> - case kz_json:is_true(<<"enabled">>, Data) of + case kz_json:is_true(<<"enabled">>, Data) + andalso not kapps_call:should_skip_feature_calls_recording(Call, Data) of 'false' -> 'false'; 'true' -> Values = [{<<"origin">>, <<"inbound from ", FromNetwork/binary, " to endpoint">>}], @@ -551,7 +552,8 @@ maybe_record_outbound(ToNetwork, Endpoint, Call) -> {'true', kapps_call:call()} | 'false'. maybe_record_outbound(_ToNetwork, _Endpoint, _Call, 'undefined') -> 'false'; maybe_record_outbound(ToNetwork, _Endpoint, Call, Data) -> - case kz_json:is_true(<<"enabled">>, Data) of + case kz_json:is_true(<<"enabled">>, Data) + andalso not kapps_call:should_skip_feature_calls_recording(Call, Data) of 'false' -> 'false'; 'true' -> LabeledData = kz_json:set_value(<<"origin">>, ?ENDPOINT_OUTBOUND_RECORDING_LABEL(ToNetwork), Data), From e2f80be431466d923f2634b9b3f577270bb4f49a Mon Sep 17 00:00:00 2001 From: Alexey Khabulyak Date: Wed, 14 Jul 2021 18:32:16 +0300 Subject: [PATCH 2/2] Small code refactoring. Split should_skip_feature_calls_recording to 2 functions --- core/kazoo_call/src/kapps_call.erl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/kazoo_call/src/kapps_call.erl b/core/kazoo_call/src/kapps_call.erl index cc098e5fa4d..0e58e7acb7c 100644 --- a/core/kazoo_call/src/kapps_call.erl +++ b/core/kazoo_call/src/kapps_call.erl @@ -1620,11 +1620,16 @@ get_recordings(Call) -> %%------------------------------------------------------------------------------ -spec should_skip_feature_calls_recording(call(), kz_term:api_object()) -> boolean(). should_skip_feature_calls_recording(Call, Data) -> - try binary:first(request_user(Call)) == $* - andalso not kz_json:is_true(<<"record_feature_code_calls">>, Data, 'true') - catch - _:_ -> 'false' - end. + is_feature_call(request_user(Call)) + andalso not should_record_feature_code_calls(Data). + +-spec is_feature_call(kz_term:ne_binary()) -> boolean(). +is_feature_call(<<"*", _/binary>>) -> 'true'; +is_feature_call(_) -> 'false'. + +-spec should_record_feature_code_calls(kz_term:api_object()) -> boolean(). +should_record_feature_code_calls(Data) -> + kz_json:is_true(<<"record_feature_code_calls">>, Data, 'true'). -spec inception_type(call()) -> kz_term:ne_binary(). inception_type(#kapps_call{inception='undefined'}) -> <<"onnet">>;