File Coverage

blib/lib/SignalWire/Agents/Relay/Event.pm
Criterion Covered Total %
statement 84 84 100.0
branch 2 2 100.0
condition 1 2 50.0
subroutine 26 26 100.0
pod 0 1 0.0
total 113 115 98.2


line stmt bran cond sub pod time code
1             package SignalWire::Agents::Relay::Event;
2 5     5   339379 use strict;
  5         13  
  5         318  
3 5     5   28 use warnings;
  5         9  
  5         328  
4 5     5   983 use Moo;
  5         12595  
  5         31  
5              
6             # Base event class -- all relay events inherit from this.
7             has 'event_type' => ( is => 'ro', default => sub { '' } );
8             has 'timestamp' => ( is => 'ro', default => sub { 0 } );
9             has 'params' => ( is => 'ro', default => sub { {} } );
10              
11             # --- Subclasses for each event type ---
12              
13             # Call state change: created, ringing, answered, ending, ended
14             package SignalWire::Agents::Relay::Event::CallState;
15 5     5   4454 use Moo;
  5         25  
  5         22  
16             extends 'SignalWire::Agents::Relay::Event';
17             has 'call_id' => ( is => 'ro', default => sub { '' } );
18             has 'node_id' => ( is => 'ro', default => sub { '' } );
19             has 'tag' => ( is => 'ro', default => sub { '' } );
20             has 'call_state' => ( is => 'ro', default => sub { '' } );
21             has 'device' => ( is => 'ro', default => sub { {} } );
22             has 'end_reason' => ( is => 'ro', default => sub { '' } );
23             has 'peer' => ( is => 'ro', default => sub { {} } );
24              
25             # Inbound call offer
26             package SignalWire::Agents::Relay::Event::CallReceive;
27 5     5   2740 use Moo;
  5         10  
  5         22  
28             extends 'SignalWire::Agents::Relay::Event';
29             has 'call_id' => ( is => 'ro', default => sub { '' } );
30             has 'node_id' => ( is => 'ro', default => sub { '' } );
31             has 'tag' => ( is => 'ro', default => sub { '' } );
32             has 'call_state' => ( is => 'ro', default => sub { '' } );
33             has 'device' => ( is => 'ro', default => sub { {} } );
34             has 'context' => ( is => 'ro', default => sub { '' } );
35              
36             # Dial completion
37             package SignalWire::Agents::Relay::Event::CallDial;
38 5     5   2512 use Moo;
  5         10  
  5         22  
39             extends 'SignalWire::Agents::Relay::Event';
40             has 'tag' => ( is => 'ro', default => sub { '' } );
41             has 'node_id' => ( is => 'ro', default => sub { '' } );
42             has 'dial_state' => ( is => 'ro', default => sub { '' } );
43             has 'call' => ( is => 'ro', default => sub { {} } );
44              
45             # Connect state
46             package SignalWire::Agents::Relay::Event::CallConnect;
47 5     5   2557 use Moo;
  5         9  
  5         31  
48             extends 'SignalWire::Agents::Relay::Event';
49             has 'call_id' => ( is => 'ro', default => sub { '' } );
50             has 'node_id' => ( is => 'ro', default => sub { '' } );
51             has 'connect_state' => ( is => 'ro', default => sub { '' } );
52             has 'peer' => ( is => 'ro', default => sub { {} } );
53              
54             # Disconnect state
55             package SignalWire::Agents::Relay::Event::CallDisconnect;
56 5     5   2370 use Moo;
  5         11  
  5         30  
57             extends 'SignalWire::Agents::Relay::Event';
58             has 'call_id' => ( is => 'ro', default => sub { '' } );
59             has 'node_id' => ( is => 'ro', default => sub { '' } );
60              
61             # Play state
62             package SignalWire::Agents::Relay::Event::CallPlay;
63 5     5   2189 use Moo;
  5         10  
  5         32  
64             extends 'SignalWire::Agents::Relay::Event';
65             has 'call_id' => ( is => 'ro', default => sub { '' } );
66             has 'node_id' => ( is => 'ro', default => sub { '' } );
67             has 'control_id' => ( is => 'ro', default => sub { '' } );
68             has 'state' => ( is => 'ro', default => sub { '' } );
69              
70             # Record state
71             package SignalWire::Agents::Relay::Event::CallRecord;
72 5     5   2353 use Moo;
  5         10  
  5         19  
73             extends 'SignalWire::Agents::Relay::Event';
74             has 'call_id' => ( is => 'ro', default => sub { '' } );
75             has 'node_id' => ( is => 'ro', default => sub { '' } );
76             has 'control_id' => ( is => 'ro', default => sub { '' } );
77             has 'state' => ( is => 'ro', default => sub { '' } );
78             has 'url' => ( is => 'ro', default => sub { '' } );
79             has 'duration' => ( is => 'ro', default => sub { 0 } );
80             has 'size' => ( is => 'ro', default => sub { 0 } );
81             has 'record' => ( is => 'ro', default => sub { {} } );
82              
83             # Collect result
84             package SignalWire::Agents::Relay::Event::CallCollect;
85 5     5   2802 use Moo;
  5         9  
  5         21  
86             extends 'SignalWire::Agents::Relay::Event';
87             has 'call_id' => ( is => 'ro', default => sub { '' } );
88             has 'node_id' => ( is => 'ro', default => sub { '' } );
89             has 'control_id' => ( is => 'ro', default => sub { '' } );
90             has 'result' => ( is => 'ro', default => sub { {} } );
91              
92             # Detect result
93             package SignalWire::Agents::Relay::Event::CallDetect;
94 5     5   2401 use Moo;
  5         12  
  5         22  
95             extends 'SignalWire::Agents::Relay::Event';
96             has 'call_id' => ( is => 'ro', default => sub { '' } );
97             has 'node_id' => ( is => 'ro', default => sub { '' } );
98             has 'control_id' => ( is => 'ro', default => sub { '' } );
99             has 'detect' => ( is => 'ro', default => sub { {} } );
100              
101             # Fax state (send_fax / receive_fax)
102             package SignalWire::Agents::Relay::Event::CallFax;
103 5     5   2411 use Moo;
  5         9  
  5         19  
104             extends 'SignalWire::Agents::Relay::Event';
105             has 'call_id' => ( is => 'ro', default => sub { '' } );
106             has 'node_id' => ( is => 'ro', default => sub { '' } );
107             has 'control_id' => ( is => 'ro', default => sub { '' } );
108             has 'fax' => ( is => 'ro', default => sub { {} } );
109              
110             # Tap state
111             package SignalWire::Agents::Relay::Event::CallTap;
112 5     5   2364 use Moo;
  5         10  
  5         25  
113             extends 'SignalWire::Agents::Relay::Event';
114             has 'call_id' => ( is => 'ro', default => sub { '' } );
115             has 'node_id' => ( is => 'ro', default => sub { '' } );
116             has 'control_id' => ( is => 'ro', default => sub { '' } );
117             has 'state' => ( is => 'ro', default => sub { '' } );
118             has 'tap' => ( is => 'ro', default => sub { {} } );
119              
120             # Stream state
121             package SignalWire::Agents::Relay::Event::CallStream;
122 5     5   2544 use Moo;
  5         19  
  5         22  
123             extends 'SignalWire::Agents::Relay::Event';
124             has 'call_id' => ( is => 'ro', default => sub { '' } );
125             has 'node_id' => ( is => 'ro', default => sub { '' } );
126             has 'control_id' => ( is => 'ro', default => sub { '' } );
127             has 'state' => ( is => 'ro', default => sub { '' } );
128              
129             # Transcribe state
130             package SignalWire::Agents::Relay::Event::CallTranscribe;
131 5     5   2528 use Moo;
  5         37  
  5         24  
132             extends 'SignalWire::Agents::Relay::Event';
133             has 'call_id' => ( is => 'ro', default => sub { '' } );
134             has 'node_id' => ( is => 'ro', default => sub { '' } );
135             has 'control_id' => ( is => 'ro', default => sub { '' } );
136             has 'state' => ( is => 'ro', default => sub { '' } );
137              
138             # Pay state
139             package SignalWire::Agents::Relay::Event::CallPay;
140 5     5   2318 use Moo;
  5         22  
  5         23  
141             extends 'SignalWire::Agents::Relay::Event';
142             has 'call_id' => ( is => 'ro', default => sub { '' } );
143             has 'node_id' => ( is => 'ro', default => sub { '' } );
144             has 'control_id' => ( is => 'ro', default => sub { '' } );
145             has 'state' => ( is => 'ro', default => sub { '' } );
146             has 'result' => ( is => 'ro', default => sub { {} } );
147              
148             # Send digits event
149             package SignalWire::Agents::Relay::Event::CallSendDigits;
150 5     5   2302 use Moo;
  5         20  
  5         19  
151             extends 'SignalWire::Agents::Relay::Event';
152             has 'call_id' => ( is => 'ro', default => sub { '' } );
153             has 'node_id' => ( is => 'ro', default => sub { '' } );
154             has 'control_id' => ( is => 'ro', default => sub { '' } );
155             has 'state' => ( is => 'ro', default => sub { '' } );
156              
157             # SIP REFER event
158             package SignalWire::Agents::Relay::Event::CallRefer;
159 5     5   2485 use Moo;
  5         11  
  5         21  
160             extends 'SignalWire::Agents::Relay::Event';
161             has 'call_id' => ( is => 'ro', default => sub { '' } );
162             has 'node_id' => ( is => 'ro', default => sub { '' } );
163             has 'refer_state' => ( is => 'ro', default => sub { '' } );
164              
165             # Conference event
166             package SignalWire::Agents::Relay::Event::Conference;
167 5     5   4106 use Moo;
  5         83  
  5         25  
168             extends 'SignalWire::Agents::Relay::Event';
169             has 'call_id' => ( is => 'ro', default => sub { '' } );
170             has 'node_id' => ( is => 'ro', default => sub { '' } );
171             has 'conference_id' => ( is => 'ro', default => sub { '' } );
172              
173             # AI event
174             package SignalWire::Agents::Relay::Event::CallAI;
175 5     5   2241 use Moo;
  5         13  
  5         17  
176             extends 'SignalWire::Agents::Relay::Event';
177             has 'call_id' => ( is => 'ro', default => sub { '' } );
178             has 'node_id' => ( is => 'ro', default => sub { '' } );
179             has 'control_id' => ( is => 'ro', default => sub { '' } );
180              
181             # Inbound message
182             package SignalWire::Agents::Relay::Event::MessageReceive;
183 5     5   2300 use Moo;
  5         11  
  5         50  
184             extends 'SignalWire::Agents::Relay::Event';
185             has 'message_id' => ( is => 'ro', default => sub { '' } );
186             has 'context' => ( is => 'ro', default => sub { '' } );
187             has 'direction' => ( is => 'ro', default => sub { 'inbound' } );
188             has 'from_number' => ( is => 'ro', default => sub { '' } );
189             has 'to_number' => ( is => 'ro', default => sub { '' } );
190             has 'body' => ( is => 'ro', default => sub { '' } );
191             has 'media' => ( is => 'ro', default => sub { [] } );
192             has 'segments' => ( is => 'ro', default => sub { 0 } );
193             has 'message_state' => ( is => 'ro', default => sub { 'received' } );
194             has 'tags' => ( is => 'ro', default => sub { [] } );
195              
196             # Outbound message state change
197             package SignalWire::Agents::Relay::Event::MessageState;
198 5     5   2958 use Moo;
  5         11  
  5         21  
199             extends 'SignalWire::Agents::Relay::Event';
200             has 'message_id' => ( is => 'ro', default => sub { '' } );
201             has 'context' => ( is => 'ro', default => sub { '' } );
202             has 'direction' => ( is => 'ro', default => sub { 'outbound' } );
203             has 'from_number' => ( is => 'ro', default => sub { '' } );
204             has 'to_number' => ( is => 'ro', default => sub { '' } );
205             has 'body' => ( is => 'ro', default => sub { '' } );
206             has 'media' => ( is => 'ro', default => sub { [] } );
207             has 'segments' => ( is => 'ro', default => sub { 0 } );
208             has 'message_state' => ( is => 'ro', default => sub { '' } );
209             has 'reason' => ( is => 'ro', default => sub { '' } );
210             has 'tags' => ( is => 'ro', default => sub { [] } );
211              
212             # Authorization state
213             package SignalWire::Agents::Relay::Event::AuthorizationState;
214 5     5   3003 use Moo;
  5         12  
  5         22  
215             extends 'SignalWire::Agents::Relay::Event';
216             has 'authorization_state' => ( is => 'ro', default => sub { '' } );
217              
218             # Server disconnect
219             package SignalWire::Agents::Relay::Event::Disconnect;
220 5     5   2164 use Moo;
  5         30  
  5         20  
221             extends 'SignalWire::Agents::Relay::Event';
222             has 'restart' => ( is => 'ro', default => sub { 0 } );
223              
224             # --- Factory method ---
225             package SignalWire::Agents::Relay::Event;
226              
227             # Map event_type string to class name
228             my %EVENT_CLASS_MAP = (
229             'calling.call.state' => 'SignalWire::Agents::Relay::Event::CallState',
230             'calling.call.receive' => 'SignalWire::Agents::Relay::Event::CallReceive',
231             'calling.call.dial' => 'SignalWire::Agents::Relay::Event::CallDial',
232             'calling.call.connect' => 'SignalWire::Agents::Relay::Event::CallConnect',
233             'calling.call.disconnect' => 'SignalWire::Agents::Relay::Event::CallDisconnect',
234             'calling.call.play' => 'SignalWire::Agents::Relay::Event::CallPlay',
235             'calling.call.record' => 'SignalWire::Agents::Relay::Event::CallRecord',
236             'calling.call.collect' => 'SignalWire::Agents::Relay::Event::CallCollect',
237             'calling.call.detect' => 'SignalWire::Agents::Relay::Event::CallDetect',
238             'calling.call.fax' => 'SignalWire::Agents::Relay::Event::CallFax',
239             'calling.call.tap' => 'SignalWire::Agents::Relay::Event::CallTap',
240             'calling.call.stream' => 'SignalWire::Agents::Relay::Event::CallStream',
241             'calling.call.transcribe' => 'SignalWire::Agents::Relay::Event::CallTranscribe',
242             'calling.call.pay' => 'SignalWire::Agents::Relay::Event::CallPay',
243             'calling.call.send_digits' => 'SignalWire::Agents::Relay::Event::CallSendDigits',
244             'calling.call.refer' => 'SignalWire::Agents::Relay::Event::CallRefer',
245             'calling.conference' => 'SignalWire::Agents::Relay::Event::Conference',
246             'calling.call.ai' => 'SignalWire::Agents::Relay::Event::CallAI',
247             'messaging.receive' => 'SignalWire::Agents::Relay::Event::MessageReceive',
248             'messaging.state' => 'SignalWire::Agents::Relay::Event::MessageState',
249             'signalwire.authorization.state' => 'SignalWire::Agents::Relay::Event::AuthorizationState',
250             'signalwire.disconnect' => 'SignalWire::Agents::Relay::Event::Disconnect',
251             );
252              
253             sub parse_event {
254 103     103 0 342612 my ($class_or_self, $event_type, $params) = @_;
255 103   50     380 $params //= {};
256              
257 103         266 my $event_class = $EVENT_CLASS_MAP{$event_type};
258 103 100       286 unless ($event_class) {
259             # Return base event for unknown types
260 2         13 return SignalWire::Agents::Relay::Event->new(
261             event_type => $event_type,
262             params => $params,
263             );
264             }
265              
266             # Build constructor args from event params
267 101         385 my %args = (
268             event_type => $event_type,
269             params => $params,
270             );
271              
272             # Copy known fields from params into top-level attributes
273 101         318 for my $key (keys %$params) {
274             # Moo will silently ignore unknown attrs, so we just pass everything
275 166         315 $args{$key} = $params->{$key};
276             }
277              
278 101         3029 return $event_class->new(%args);
279             }
280              
281             1;