| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package SignalWire::Agents::Relay::Call; |
|
2
|
4
|
|
|
4
|
|
146227
|
use strict; |
|
|
4
|
|
|
|
|
82
|
|
|
|
4
|
|
|
|
|
197
|
|
|
3
|
4
|
|
|
4
|
|
24
|
use warnings; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
326
|
|
|
4
|
4
|
|
|
4
|
|
706
|
use Moo; |
|
|
4
|
|
|
|
|
10760
|
|
|
|
4
|
|
|
|
|
34
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
4
|
|
|
4
|
|
4957
|
use SignalWire::Agents::Relay::Action; |
|
|
4
|
|
|
|
|
35
|
|
|
|
4
|
|
|
|
|
278
|
|
|
7
|
4
|
|
|
4
|
|
714
|
use SignalWire::Agents::Relay::Constants qw(CALL_TERMINAL_STATES ACTION_TERMINAL_STATES); |
|
|
4
|
|
|
|
|
52
|
|
|
|
4
|
|
|
|
|
11448
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
has 'call_id' => ( is => 'ro', required => 1 ); |
|
10
|
|
|
|
|
|
|
has 'node_id' => ( is => 'rw', default => sub { '' } ); |
|
11
|
|
|
|
|
|
|
has 'tag' => ( is => 'ro', default => sub { '' } ); |
|
12
|
|
|
|
|
|
|
has 'state' => ( is => 'rw', default => sub { 'created' } ); |
|
13
|
|
|
|
|
|
|
has 'device' => ( is => 'rw', default => sub { {} } ); |
|
14
|
|
|
|
|
|
|
has 'end_reason' => ( is => 'rw', default => sub { '' } ); |
|
15
|
|
|
|
|
|
|
has 'peer' => ( is => 'rw', default => sub { {} } ); |
|
16
|
|
|
|
|
|
|
has 'context' => ( is => 'rw', default => sub { '' } ); |
|
17
|
|
|
|
|
|
|
has 'dial_winner' => ( is => 'rw', default => sub { 0 } ); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has '_client' => ( is => 'rw', default => sub { undef } ); |
|
20
|
|
|
|
|
|
|
has '_actions' => ( is => 'rw', default => sub { {} } ); # control_id => Action |
|
21
|
|
|
|
|
|
|
has '_on_event' => ( is => 'rw', default => sub { [] } ); # event callbacks |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# Helper to generate a UUID-like control_id |
|
24
|
|
|
|
|
|
|
sub _generate_uuid { |
|
25
|
0
|
|
|
0
|
|
0
|
my @hex = map { sprintf('%02x', int(rand(256))) } 1..16; |
|
|
0
|
|
|
|
|
0
|
|
|
26
|
0
|
|
|
|
|
0
|
$hex[6] = sprintf('%02x', (hex($hex[6]) & 0x0f) | 0x40); |
|
27
|
0
|
|
|
|
|
0
|
$hex[8] = sprintf('%02x', (hex($hex[8]) & 0x3f) | 0x80); |
|
28
|
0
|
|
|
|
|
0
|
return join('-', |
|
29
|
|
|
|
|
|
|
join('', @hex[0..3]), |
|
30
|
|
|
|
|
|
|
join('', @hex[4..5]), |
|
31
|
|
|
|
|
|
|
join('', @hex[6..7]), |
|
32
|
|
|
|
|
|
|
join('', @hex[8..9]), |
|
33
|
|
|
|
|
|
|
join('', @hex[10..15]), |
|
34
|
|
|
|
|
|
|
); |
|
35
|
|
|
|
|
|
|
} |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _base_params { |
|
38
|
0
|
|
|
0
|
|
0
|
my ($self) = @_; |
|
39
|
|
|
|
|
|
|
return ( |
|
40
|
0
|
|
|
|
|
0
|
node_id => $self->node_id, |
|
41
|
|
|
|
|
|
|
call_id => $self->call_id, |
|
42
|
|
|
|
|
|
|
); |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub _execute { |
|
46
|
0
|
|
|
0
|
|
0
|
my ($self, $method, %extra) = @_; |
|
47
|
0
|
|
|
|
|
0
|
my $client = $self->_client; |
|
48
|
0
|
0
|
|
|
|
0
|
die "No client attached to call" unless $client; |
|
49
|
0
|
|
|
|
|
0
|
my %params = ($self->_base_params, %extra); |
|
50
|
0
|
|
|
|
|
0
|
return $client->execute($method, \%params); |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Start an action-based method: creates the Action, registers it, executes the RPC |
|
54
|
|
|
|
|
|
|
sub _start_action { |
|
55
|
0
|
|
|
0
|
|
0
|
my ($self, $method, $action_class, %extra) = @_; |
|
56
|
0
|
|
|
|
|
0
|
my $control_id = _generate_uuid(); |
|
57
|
0
|
|
|
|
|
0
|
my %params = ($self->_base_params, control_id => $control_id, %extra); |
|
58
|
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
0
|
my $action = $action_class->new( |
|
60
|
|
|
|
|
|
|
control_id => $control_id, |
|
61
|
|
|
|
|
|
|
call_id => $self->call_id, |
|
62
|
|
|
|
|
|
|
node_id => $self->node_id, |
|
63
|
|
|
|
|
|
|
_client => $self->_client, |
|
64
|
|
|
|
|
|
|
); |
|
65
|
0
|
|
|
|
|
0
|
$self->_actions->{$control_id} = $action; |
|
66
|
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
0
|
my $client = $self->_client; |
|
68
|
0
|
0
|
|
|
|
0
|
if ($client) { |
|
69
|
0
|
|
|
|
|
0
|
my $result = $client->execute($method, \%params); |
|
70
|
|
|
|
|
|
|
# If call is gone (404/410), resolve action immediately |
|
71
|
0
|
0
|
0
|
|
|
0
|
if (ref $result eq 'HASH' && $result->{code} && $result->{code} =~ /^(404|410)$/) { |
|
|
|
|
0
|
|
|
|
|
|
72
|
0
|
|
|
|
|
0
|
$action->_resolve(undef); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
0
|
|
|
|
|
0
|
return $action; |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# --- Event dispatch --- |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub dispatch_event { |
|
82
|
15
|
|
|
15
|
0
|
81
|
my ($self, $event) = @_; |
|
83
|
15
|
|
50
|
|
|
76
|
my $event_type = $event->event_type // ''; |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# Update call state from state events |
|
86
|
15
|
50
|
|
|
|
45
|
if ($event_type eq 'calling.call.state') { |
|
|
|
0
|
|
|
|
|
|
|
87
|
15
|
|
50
|
|
|
50
|
my $new_state = $event->call_state // ''; |
|
88
|
15
|
|
|
|
|
60
|
$self->state($new_state); |
|
89
|
15
|
100
|
66
|
|
|
120
|
$self->end_reason($event->end_reason) if $event->can('end_reason') && $event->end_reason; |
|
90
|
15
|
50
|
33
|
|
|
102
|
$self->peer($event->peer) if $event->can('peer') && ref $event->peer eq 'HASH' && %{$event->peer}; |
|
|
15
|
|
33
|
|
|
55
|
|
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# If call ended, resolve all pending actions |
|
93
|
15
|
100
|
|
|
|
46
|
if (CALL_TERMINAL_STATES->{$new_state}) { |
|
94
|
5
|
|
|
|
|
20
|
$self->_resolve_all_actions; |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
elsif ($event_type eq 'calling.call.connect') { |
|
98
|
0
|
0
|
|
|
|
0
|
$self->peer($event->peer) if $event->can('peer'); |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Route to action by control_id |
|
102
|
15
|
50
|
|
|
|
56
|
my $control_id = $event->can('control_id') ? $event->control_id : ''; |
|
103
|
15
|
0
|
33
|
|
|
58
|
if ($control_id && exists $self->_actions->{$control_id}) { |
|
104
|
0
|
|
|
|
|
0
|
my $action = $self->_actions->{$control_id}; |
|
105
|
0
|
|
|
|
|
0
|
$action->_handle_event($event); |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# Check if action reached terminal state |
|
108
|
0
|
|
0
|
|
|
0
|
my $terminal = ACTION_TERMINAL_STATES->{$event_type} // {}; |
|
109
|
0
|
0
|
0
|
|
|
0
|
my $action_state = $event->can('state') ? ($event->state // '') : ''; |
|
110
|
0
|
0
|
|
|
|
0
|
if ($terminal->{$action_state}) { |
|
111
|
0
|
|
|
|
|
0
|
$action->_resolve($event); |
|
112
|
0
|
|
|
|
|
0
|
delete $self->_actions->{$control_id}; |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# Fire registered event callbacks |
|
117
|
15
|
|
|
|
|
48
|
for my $cb (@{$self->_on_event}) { |
|
|
15
|
|
|
|
|
78
|
|
|
118
|
4
|
|
|
|
|
9
|
eval { $cb->($self, $event) }; |
|
|
4
|
|
|
|
|
11
|
|
|
119
|
4
|
50
|
|
|
|
24
|
warn "Call event callback error: $@" if $@; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Register an event listener |
|
124
|
|
|
|
|
|
|
sub on { |
|
125
|
4
|
|
|
4
|
0
|
70
|
my ($self, $cb) = @_; |
|
126
|
4
|
|
|
|
|
7
|
push @{$self->_on_event}, $cb; |
|
|
4
|
|
|
|
|
16
|
|
|
127
|
4
|
|
|
|
|
10
|
return $self; |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# Resolve all pending actions (e.g., on call ended or call-gone) |
|
131
|
|
|
|
|
|
|
sub _resolve_all_actions { |
|
132
|
5
|
|
|
5
|
|
14
|
my ($self) = @_; |
|
133
|
5
|
|
|
|
|
12
|
for my $action (values %{$self->_actions}) { |
|
|
5
|
|
|
|
|
23
|
|
|
134
|
2
|
50
|
|
|
|
34
|
$action->_resolve(undef) unless $action->completed; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
5
|
|
|
|
|
25
|
$self->_actions({}); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# --- Simple fire-and-response methods --- |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub answer { |
|
142
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
143
|
0
|
|
|
|
|
|
return $self->_execute('calling.answer', %opts); |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub hangup { |
|
147
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
148
|
0
|
|
|
|
|
|
return $self->_execute('calling.end', %opts); |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub pass { |
|
152
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
153
|
0
|
|
|
|
|
|
return $self->_execute('calling.pass'); |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub connect { |
|
157
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
158
|
0
|
|
|
|
|
|
return $self->_execute('calling.connect', %opts); |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub disconnect { |
|
162
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
163
|
0
|
|
|
|
|
|
return $self->_execute('calling.disconnect'); |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub hold { |
|
167
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
168
|
0
|
|
|
|
|
|
return $self->_execute('calling.hold'); |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub unhold { |
|
172
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
173
|
0
|
|
|
|
|
|
return $self->_execute('calling.unhold'); |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub denoise { |
|
177
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
178
|
0
|
|
|
|
|
|
return $self->_execute('calling.denoise'); |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub denoise_stop { |
|
182
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
183
|
0
|
|
|
|
|
|
return $self->_execute('calling.denoise.stop'); |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub transfer { |
|
187
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
188
|
0
|
|
|
|
|
|
return $self->_execute('calling.transfer', %opts); |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub join_conference { |
|
192
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
193
|
0
|
|
|
|
|
|
return $self->_execute('calling.join_conference', %opts); |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub leave_conference { |
|
197
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
198
|
0
|
|
|
|
|
|
return $self->_execute('calling.leave_conference', %opts); |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub echo { |
|
202
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
203
|
0
|
|
|
|
|
|
return $self->_execute('calling.echo', %opts); |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub bind_digit { |
|
207
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
208
|
0
|
|
|
|
|
|
return $self->_execute('calling.bind_digit', %opts); |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub clear_digit_bindings { |
|
212
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
213
|
0
|
|
|
|
|
|
return $self->_execute('calling.clear_digit_bindings', %opts); |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub live_transcribe { |
|
217
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
218
|
0
|
|
|
|
|
|
return $self->_execute('calling.live_transcribe', %opts); |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub live_translate { |
|
222
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
223
|
0
|
|
|
|
|
|
return $self->_execute('calling.live_translate', %opts); |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub join_room { |
|
227
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
228
|
0
|
|
|
|
|
|
return $self->_execute('calling.join_room', %opts); |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub leave_room { |
|
232
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
233
|
0
|
|
|
|
|
|
return $self->_execute('calling.leave_room'); |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub amazon_bedrock { |
|
237
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
238
|
0
|
|
|
|
|
|
return $self->_execute('calling.amazon_bedrock', %opts); |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub ai_message { |
|
242
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
243
|
0
|
|
|
|
|
|
return $self->_execute('calling.ai_message', %opts); |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub ai_hold { |
|
247
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
248
|
0
|
|
|
|
|
|
return $self->_execute('calling.ai_hold', %opts); |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub ai_unhold { |
|
252
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
253
|
0
|
|
|
|
|
|
return $self->_execute('calling.ai_unhold', %opts); |
|
254
|
|
|
|
|
|
|
} |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub user_event { |
|
257
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
258
|
0
|
|
|
|
|
|
return $self->_execute('calling.user_event', %opts); |
|
259
|
|
|
|
|
|
|
} |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub queue_enter { |
|
262
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
263
|
0
|
|
|
|
|
|
return $self->_execute('calling.queue.enter', %opts); |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
sub queue_leave { |
|
267
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
268
|
0
|
|
|
|
|
|
return $self->_execute('calling.queue.leave', %opts); |
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub refer { |
|
272
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
273
|
0
|
|
|
|
|
|
return $self->_execute('calling.refer', %opts); |
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub send_digits { |
|
277
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
278
|
0
|
|
|
|
|
|
return $self->_execute('calling.send_digits', %opts); |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# --- Action-based methods (control_id tracking) --- |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub play { |
|
284
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
285
|
0
|
|
|
|
|
|
return $self->_start_action('calling.play', 'SignalWire::Agents::Relay::Action::Play', %opts); |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub record { |
|
289
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
290
|
0
|
|
|
|
|
|
return $self->_start_action('calling.record', 'SignalWire::Agents::Relay::Action::Record', %opts); |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub detect { |
|
294
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
295
|
0
|
|
|
|
|
|
return $self->_start_action('calling.detect', 'SignalWire::Agents::Relay::Action::Detect', %opts); |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
sub collect { |
|
299
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
300
|
0
|
|
|
|
|
|
return $self->_start_action('calling.collect', 'SignalWire::Agents::Relay::Action::Collect', %opts); |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
sub play_and_collect { |
|
304
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
305
|
0
|
|
|
|
|
|
return $self->_start_action('calling.play_and_collect', 'SignalWire::Agents::Relay::Action::Collect', %opts); |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub send_fax { |
|
309
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
310
|
0
|
|
|
|
|
|
my $action = $self->_start_action('calling.send_fax', 'SignalWire::Agents::Relay::Action::Fax', %opts); |
|
311
|
0
|
|
|
|
|
|
return $action; |
|
312
|
|
|
|
|
|
|
} |
|
313
|
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
sub receive_fax { |
|
315
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
316
|
0
|
|
|
|
|
|
my $control_id = _generate_uuid(); |
|
317
|
0
|
|
|
|
|
|
my %params = ($self->_base_params, control_id => $control_id, %opts); |
|
318
|
|
|
|
|
|
|
|
|
319
|
0
|
|
|
|
|
|
my $action = SignalWire::Agents::Relay::Action::Fax->new( |
|
320
|
|
|
|
|
|
|
control_id => $control_id, |
|
321
|
|
|
|
|
|
|
call_id => $self->call_id, |
|
322
|
|
|
|
|
|
|
node_id => $self->node_id, |
|
323
|
|
|
|
|
|
|
_client => $self->_client, |
|
324
|
|
|
|
|
|
|
_fax_type => 'receive', |
|
325
|
|
|
|
|
|
|
); |
|
326
|
0
|
|
|
|
|
|
$self->_actions->{$control_id} = $action; |
|
327
|
|
|
|
|
|
|
|
|
328
|
0
|
|
|
|
|
|
my $client = $self->_client; |
|
329
|
0
|
0
|
|
|
|
|
if ($client) { |
|
330
|
0
|
|
|
|
|
|
my $result = $client->execute('calling.receive_fax', \%params); |
|
331
|
0
|
0
|
0
|
|
|
|
if (ref $result eq 'HASH' && $result->{code} && $result->{code} =~ /^(404|410)$/) { |
|
|
|
|
0
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
$action->_resolve(undef); |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
} |
|
335
|
|
|
|
|
|
|
|
|
336
|
0
|
|
|
|
|
|
return $action; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub tap { |
|
340
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
341
|
0
|
|
|
|
|
|
return $self->_start_action('calling.tap', 'SignalWire::Agents::Relay::Action::Tap', %opts); |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub stream { |
|
345
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
346
|
0
|
|
|
|
|
|
return $self->_start_action('calling.stream', 'SignalWire::Agents::Relay::Action::Stream', %opts); |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub pay { |
|
350
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
351
|
0
|
|
|
|
|
|
return $self->_start_action('calling.pay', 'SignalWire::Agents::Relay::Action::Pay', %opts); |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub transcribe { |
|
355
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
356
|
0
|
|
|
|
|
|
return $self->_start_action('calling.transcribe', 'SignalWire::Agents::Relay::Action::Transcribe', %opts); |
|
357
|
|
|
|
|
|
|
} |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub ai { |
|
360
|
0
|
|
|
0
|
0
|
|
my ($self, %opts) = @_; |
|
361
|
0
|
|
|
|
|
|
return $self->_start_action('calling.ai', 'SignalWire::Agents::Relay::Action::AI', %opts); |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
1; |