1 | package goagi |
||
2 | |||
3 | import ( |
||
4 | "fmt" |
||
5 | ) |
||
6 | |||
7 | // Command sends command as string to the AGI and returns response valus with |
||
8 | // text response |
||
9 | func (agi *AGI) Command(cmd string) (Response, error) { |
||
10 | return agi.execute(cmd + "\n") |
||
11 | } |
||
12 | |||
13 | // Answer executes AGI command "ANSWER" |
||
14 | // Answers channel if not already in answer state. |
||
15 | func (agi *AGI) Answer() (Response, error) { |
||
16 | return agi.execute("ANSWER\n") |
||
17 | } |
||
18 | |||
19 | // AsyncAGIBreak Interrupts Async AGI |
||
20 | // Interrupts expected flow of Async AGI commands and returns control |
||
21 | // to previous source (typically, the PBX dialplan). |
||
22 | func (agi *AGI) AsyncAGIBreak() (Response, error) { |
||
23 | return agi.execute("ASYNCAGI BREAK\n") |
||
24 | } |
||
25 | |||
26 | /* |
||
27 | ChannelStatus returns status of the connected channel. |
||
28 | |||
29 | If no channel name is given (empty line) then returns the status of the current channel. |
||
30 | |||
31 | Return values: |
||
32 | |||
33 | 0 - Channel is down and available. |
||
34 | |||
35 | 1 - Channel is down, but reserved. |
||
36 | |||
37 | 2 - Channel is off hook. |
||
38 | |||
39 | 3 - Digits (or equivalent) have been dialed. |
||
40 | |||
41 | 4 - Line is ringing. |
||
42 | |||
43 | 5 - Remote end is ringing. |
||
44 | |||
45 | 6 - Line is up. |
||
46 | |||
47 | 7 - Line is busy. |
||
48 | */ |
||
49 | func (agi *AGI) ChannelStatus(channel string) (Response, error) { |
||
50 | cmd := fmt.Sprintf("CHANNEL STATUS %s\n", channel) |
||
51 | return agi.execute(cmd) |
||
52 | } |
||
53 | |||
54 | /* |
||
55 | ControlStreamFile sends audio file on channel and allows the listener to control the stream. |
||
56 | Send the given file, allowing playback to be controlled by the given digits, if any. |
||
57 | Use double quotes for the digits if you wish none to be permitted. If offsetms |
||
58 | is provided then the audio will seek to offsetms before play starts. |
||
59 | |||
60 | Example: |
||
61 | |||
62 | agi.ControlStreamFile("prompt_en", "19", "3000", "#", "0", "#", "1600") |
||
63 | agi.ControlStreamFile("prompt_en", "") |
||
64 | agi.ControlStreamFile("prompt_en", "19", "", "", "", "#", "1600") |
||
65 | |||
66 | */ |
||
67 | func (agi *AGI) ControlStreamFile(filename, digits string, args ...string) (Response, error) { |
||
68 | cmd := fmt.Sprintf("CONTROL STREAM FILE %s %q", filename, digits) |
||
69 | |||
70 | if len(args) > 5 { |
||
71 | return nil, ErrAGI.Msg("Too many arguments. Unknown args: %v", args[5:]) |
||
72 | } |
||
73 | |||
74 | for _, v := range args { |
||
75 | cmd = fmt.Sprintf("%s %q", cmd, v) |
||
76 | } |
||
77 | |||
78 | cmd = fmt.Sprintf("%s\n", cmd) |
||
79 | return agi.execute(cmd) |
||
80 | } |
||
81 | |||
82 | // DatabaseDel deletes an entry in the Asterisk database for a given family and key. |
||
83 | // Returns status and error if fails. |
||
84 | func (agi *AGI) DatabaseDel(family, key string) (Response, error) { |
||
85 | cmd := fmt.Sprintf("DATABASE DEL %s %s\n", family, key) |
||
86 | return agi.execute(cmd) |
||
87 | } |
||
88 | |||
89 | // DatabaseDelTree deletes a family or specific keytree within a family in the Asterisk database. |
||
90 | func (agi *AGI) DatabaseDelTree(family, keytree string) (Response, error) { |
||
91 | cmd := fmt.Sprintf("DATABASE DELTREE %s %s\n", family, keytree) |
||
92 | return agi.execute(cmd) |
||
93 | } |
||
94 | |||
95 | // DatabaseGet Retrieves an entry in the Asterisk database for a given family and key. |
||
96 | // Returns value as string or error if failed or value not set |
||
97 | // Response.Value() for result |
||
98 | func (agi *AGI) DatabaseGet(family, key string) (Response, error) { |
||
99 | cmd := fmt.Sprintf("DATABASE GET %s %s\n", family, key) |
||
100 | return agi.execute(cmd) |
||
101 | } |
||
102 | |||
103 | // DatabasePut adds or updates an entry in the Asterisk database for |
||
104 | // a given family, key, and value. |
||
105 | func (agi *AGI) DatabasePut(family, key, val string) (Response, error) { |
||
106 | cmd := fmt.Sprintf("DATABASE PUT %s %s %s\n", family, key, val) |
||
107 | return agi.execute(cmd) |
||
108 | } |
||
109 | |||
110 | // Exec executes application with given options. |
||
111 | func (agi *AGI) Exec(app, opts string) (Response, error) { |
||
112 | cmd := fmt.Sprintf("EXEC %s %q\n", app, opts) |
||
113 | return agi.execute(cmd) |
||
114 | } |
||
115 | |||
116 | /* |
||
117 | GetData Stream the given file, and receive DTMF data. |
||
118 | Note: when timeout is 0 then Asterisk will use 6 secods. |
||
119 | Note: Asterisk has strange way to handle get data response. |
||
120 | Contrary to other responses, where result has numeric value, |
||
121 | here asterisk puts DTMF to sent by user to result and this value |
||
122 | may contain "#" and "*". |
||
123 | |||
124 | To get DTMF sent by user use Response.Data() |
||
125 | |||
126 | Response.Value() will contain "timeout" if user has not terminated |
||
127 | input with "#" |
||
128 | */ |
||
129 | func (agi *AGI) GetData(file string, timeout, maxdigit int) (Response, error) { |
||
130 | cmd := fmt.Sprintf("GET DATA %s %d %d\n", file, timeout, maxdigit) |
||
131 | resp, err := agi.execute(cmd) |
||
132 | if err != nil { |
||
133 | return nil, err |
||
134 | } |
||
135 | // special get data result treatment |
||
136 | if resp.Result() == -1 || resp.Code() != codeSucc { |
||
137 | return resp, nil |
||
138 | } |
||
139 | |||
140 | r := resp.(*responseSuccess) |
||
141 | r.result = 0 |
||
142 | r.data = scanResultStrFromRaw(r.raw) |
||
143 | return r, nil |
||
144 | } |
||
145 | |||
146 | // GetFullVariable evaluates a channel expression |
||
147 | func (agi *AGI) GetFullVariable(name, channel string) (Response, error) { |
||
148 | cmd := "GET FULL VARIABLE" |
||
149 | if channel == "" { |
||
150 | cmd = fmt.Sprintf("%s %s\n", cmd, name) |
||
151 | } else { |
||
152 | cmd = fmt.Sprintf("%s %s %s\n", cmd, name, channel) |
||
153 | } |
||
154 | return agi.execute(cmd) |
||
155 | } |
||
156 | |||
157 | // GetOption Stream file, prompt for DTMF, with timeout. |
||
158 | // Behaves similar to STREAM FILE but used with a timeout option. |
||
159 | // Returns digit pressed, offset and error |
||
160 | func (agi *AGI) GetOption(filename, digits string, timeout int32) (Response, error) { |
||
161 | cmd := fmt.Sprintf("GET OPTION %s %q %d\n", filename, digits, timeout) |
||
162 | return agi.execute(cmd) |
||
163 | } |
||
164 | |||
165 | // GetVariable Gets a channel variable. |
||
166 | func (agi *AGI) GetVariable(name string) (Response, error) { |
||
167 | cmd := fmt.Sprintf("GET VARIABLE %s\n", name) |
||
168 | return agi.execute(cmd) |
||
169 | } |
||
170 | |||
171 | // Hangs up the specified channel. If no channel name is given, hangs up the current channel |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
172 | func (agi *AGI) Hangup(channel ...string) (Response, error) { |
||
173 | cmd := "HANGUP" |
||
174 | |||
175 | if len(channel) > 0 { |
||
176 | cmd = fmt.Sprintf("%s %s\n", cmd, channel[0]) |
||
177 | } else { |
||
178 | cmd = fmt.Sprintf("%s\n", cmd) |
||
179 | } |
||
180 | return agi.execute(cmd) |
||
181 | } |
||
182 | |||
183 | /* |
||
184 | ReceiveChar Receives one character from channels supporting it. |
||
185 | Most channels do not support the reception of text. Returns the decimal value of |
||
186 | the character if one is received, or 0 if the channel does not support text reception. |
||
187 | |||
188 | timeout - The maximum time to wait for input in milliseconds, or 0 for infinite. |
||
189 | |||
190 | Returns result -1 on error or char byte |
||
191 | */ |
||
192 | func (agi *AGI) ReceiveChar(timeout int) (Response, error) { |
||
193 | cmd := fmt.Sprintf("RECEIVE CHAR %d\n", timeout) |
||
194 | return agi.execute(cmd) |
||
195 | } |
||
196 | |||
197 | /* |
||
198 | ReceiveText Receives text from channels supporting it. |
||
199 | |||
200 | timeout - The timeout to be the maximum time to wait for input in milliseconds, or 0 for infinite. |
||
201 | */ |
||
202 | func (agi *AGI) ReceiveText(timeout int) (Response, error) { |
||
203 | cmd := fmt.Sprintf("RECEIVE TEXT %d\n", timeout) |
||
204 | return agi.execute(cmd) |
||
205 | } |
||
206 | |||
207 | /* |
||
208 | RecordFile Record to a file until a given dtmf digit in the sequence is received. |
||
209 | The format will specify what kind of file will be recorded. The timeout is the |
||
210 | maximum record time in milliseconds, or -1 for no timeout. |
||
211 | |||
212 | offset samples is optional, and, if provided, will seek to the offset without |
||
213 | exceeding the end of the file. |
||
214 | |||
215 | beep causes Asterisk to play a beep to the channel that is about to be recorded. |
||
216 | |||
217 | silence is the number of seconds of silence allowed before the function returns |
||
218 | despite the lack of dtmf digits or reaching timeout. |
||
219 | |||
220 | silence is the number of seconds of silence that are permitted before the |
||
221 | recording is terminated, regardless of the escape_digits or timeout arguments |
||
222 | |||
223 | If interupted by DTMF, digits will be available in Response.Data() |
||
224 | */ |
||
225 | func (agi *AGI) RecordFile(file, format, escDigits string, |
||
226 | timeout, offset int, beep bool, silence int) (Response, error) { |
||
227 | |||
228 | cmd := "RECORD FILE" |
||
229 | cmd = fmt.Sprintf("%s %s %s %q %d", cmd, file, format, escDigits, timeout) |
||
230 | if offset > 0 { |
||
231 | cmd = fmt.Sprintf("%s %d", cmd, offset) |
||
232 | } |
||
233 | if beep { |
||
234 | cmd = fmt.Sprintf("%s BEEP", cmd) |
||
235 | } |
||
236 | if silence > 0 { |
||
237 | cmd = fmt.Sprintf("%s s=%d", cmd, silence) |
||
238 | } |
||
239 | cmd = fmt.Sprintf("%s\n", cmd) |
||
240 | |||
241 | resp, err := agi.execute(cmd) |
||
242 | if err != nil { |
||
243 | return nil, err |
||
244 | } |
||
245 | |||
246 | if resp.Value() != "dtmf" { |
||
247 | return resp, nil |
||
248 | } |
||
249 | |||
250 | r := resp.(*responseSuccess) |
||
251 | r.result = 1 |
||
252 | r.data = scanResultStrFromRaw(r.raw) |
||
253 | |||
254 | return r, nil |
||
255 | } |
||
256 | |||
257 | // SayAlpha says a given character string, returning early if any of the given |
||
258 | // DTMF digits are received on the channel. |
||
259 | func (agi *AGI) SayAlpha(number, escDigits string) (Response, error) { |
||
260 | cmd := fmt.Sprintf("SAY ALPHA %s %q\n", number, escDigits) |
||
261 | return agi.execute(cmd) |
||
262 | } |
||
263 | |||
264 | // SayDate say a given date, returning early if any of the given DTMF digits |
||
265 | // are received on the channel |
||
266 | func (agi *AGI) SayDate(date, escDigits string) (Response, error) { |
||
267 | cmd := fmt.Sprintf("SAY DATE %s %q\n", date, escDigits) |
||
268 | return agi.execute(cmd) |
||
269 | } |
||
270 | |||
271 | // SayDatetime say a given time, returning early if any of the given DTMF |
||
272 | // digits are received on the channel |
||
273 | func (agi *AGI) SayDatetime(time, escDigits, format, timezone string) (Response, error) { |
||
274 | cmd := fmt.Sprintf("SAY DATETIME %s %q %q %q\n", time, escDigits, format, timezone) |
||
275 | return agi.execute(cmd) |
||
276 | } |
||
277 | |||
278 | // SayDigits say a given digit string, returning early if any of the given |
||
279 | // DTMF digits are received on the channel |
||
280 | func (agi *AGI) SayDigits(number, escDigits string) (Response, error) { |
||
281 | cmd := fmt.Sprintf("SAY DIGITS %s %q\n", number, escDigits) |
||
282 | return agi.execute(cmd) |
||
283 | } |
||
284 | |||
285 | // SayNumber say a given digit string, returning early if any of the given |
||
286 | // DTMF digits are received on the channel |
||
287 | func (agi *AGI) SayNumber(number, escDigits string) (Response, error) { |
||
288 | cmd := fmt.Sprintf("SAY NUMBER %s %q\n", number, escDigits) |
||
289 | return agi.execute(cmd) |
||
290 | } |
||
291 | |||
292 | // SayPhonetic say a given character string with phonetics, returning early |
||
293 | // if any of the given DTMF digits are received on the channel |
||
294 | func (agi *AGI) SayPhonetic(str, escDigits string) (Response, error) { |
||
295 | cmd := fmt.Sprintf("SAY PHONETIC %s %q\n", str, escDigits) |
||
296 | return agi.execute(cmd) |
||
297 | } |
||
298 | |||
299 | // SayTime say a given time, returning early if any of the given DTMF digits |
||
300 | // are received on the channel |
||
301 | func (agi *AGI) SayTime(time, escDigits string) (Response, error) { |
||
302 | cmd := fmt.Sprintf("SAY TIME %s %q\n", time, escDigits) |
||
303 | return agi.execute(cmd) |
||
304 | } |
||
305 | |||
306 | // SendImage Sends the given image on a channel. Most channels do not support |
||
307 | // the transmission of images. |
||
308 | func (agi *AGI) SendImage(image string) (Response, error) { |
||
309 | cmd := fmt.Sprintf("SEND IMAGE %q\n", image) |
||
310 | return agi.execute(cmd) |
||
311 | } |
||
312 | |||
313 | // SendText Sends the given text on a channel. Most channels do not support |
||
314 | // the transmission of text. |
||
315 | func (agi *AGI) SendText(text string) (Response, error) { |
||
316 | cmd := fmt.Sprintf("SEND TEXT %q\n", text) |
||
317 | return agi.execute(cmd) |
||
318 | } |
||
319 | |||
320 | // SetAutoHangup Cause the channel to automatically hangup at time seconds in the future. |
||
321 | // Setting to 0 will cause the autohangup feature to be disabled on this channel. |
||
322 | func (agi *AGI) SetAutoHangup(seconds int) (Response, error) { |
||
323 | cmd := fmt.Sprintf("SET AUTOHANGUP %d\n", seconds) |
||
324 | return agi.execute(cmd) |
||
325 | } |
||
326 | |||
327 | // SetCallerid Changes the callerid of the current channel. |
||
328 | func (agi *AGI) SetCallerid(clid string) (Response, error) { |
||
329 | cmd := fmt.Sprintf("SET CALLERID %q\n", clid) |
||
330 | return agi.execute(cmd) |
||
331 | } |
||
332 | |||
333 | // SetContext Sets the context for continuation upon exiting the application. |
||
334 | func (agi *AGI) SetContext(ctx string) (Response, error) { |
||
335 | cmd := fmt.Sprintf("SET CONTEXT %s\n", ctx) |
||
336 | return agi.execute(cmd) |
||
337 | } |
||
338 | |||
339 | // SetExtension Changes the extension for continuation upon exiting the application. |
||
340 | func (agi *AGI) SetExtension(ext string) (Response, error) { |
||
341 | cmd := fmt.Sprintf("SET EXTENSION %s\n", ext) |
||
342 | return agi.execute(cmd) |
||
343 | } |
||
344 | |||
345 | // SetMusic Enables/Disables the music on hold generator. If class is not specified, |
||
346 | // then the default music on hold class will be used. |
||
347 | func (agi *AGI) SetMusic(enable bool, class string) (Response, error) { |
||
348 | cmd := "SET MUSIC" |
||
349 | |||
350 | if enable { |
||
351 | cmd = fmt.Sprintf("%s on", cmd) |
||
352 | } else { |
||
353 | cmd = fmt.Sprintf("%s off", cmd) |
||
354 | } |
||
355 | |||
356 | cmd = fmt.Sprintf("%s %q\n", cmd, class) |
||
357 | return agi.execute(cmd) |
||
358 | } |
||
359 | |||
360 | // SetPriority Changes the priority for continuation upon exiting the application. |
||
361 | // The priority must be a valid priority or label. |
||
362 | func (agi *AGI) SetPriority(priority string) (Response, error) { |
||
363 | cmd := fmt.Sprintf("SET PRIORITY %s\n", priority) |
||
364 | return agi.execute(cmd) |
||
365 | } |
||
366 | |||
367 | // SetVariable Sets a variable to the current channel. |
||
368 | func (agi *AGI) SetVariable(name, value string) (Response, error) { |
||
369 | cmd := fmt.Sprintf("SET VARIABLE %s %q\n", name, value) |
||
370 | return agi.execute(cmd) |
||
371 | } |
||
372 | |||
373 | // StreamFile Send the given file, allowing playback to be interrupted by the given |
||
374 | // digits, if any. |
||
375 | func (agi *AGI) StreamFile(file, escDigits string, offset int) (Response, error) { |
||
376 | cmd := fmt.Sprintf("STREAM FILE %s %q %d\n", file, escDigits, offset) |
||
377 | return agi.execute(cmd) |
||
378 | } |
||
379 | |||
380 | // TDDMode Enable/Disable TDD transmission/reception on a channel. |
||
381 | // Modes: on, off, mate, tdd |
||
382 | func (agi *AGI) TDDMode(mode string) (Response, error) { |
||
383 | cmd := "TDD MODE" |
||
384 | switch mode { |
||
385 | case "on", "off", "mate", "tdd": |
||
386 | cmd = fmt.Sprintf("%s %s\n", cmd, mode) |
||
387 | default: |
||
388 | cmd = fmt.Sprintf("%s off\n", cmd) |
||
389 | } |
||
390 | return agi.execute(cmd) |
||
391 | } |
||
392 | |||
393 | // Verbose Sends message to the console via verbose message system. |
||
394 | // level is the verbose level (1-4) |
||
395 | func (agi *AGI) Verbose(msg string, level ...int) (Response, error) { |
||
396 | cmd := fmt.Sprintf("VERBOSE %q", msg) |
||
397 | lvl := 1 |
||
398 | if level != nil { |
||
399 | if level[0] > 0 && level[0] < 5 { |
||
400 | lvl = level[0] |
||
401 | } |
||
402 | } |
||
403 | cmd = fmt.Sprintf("%s %d\n", cmd, lvl) |
||
404 | return agi.execute(cmd) |
||
405 | } |
||
406 | |||
407 | /* |
||
408 | WaitForDigit Waits up to timeout *milliseconds* for channel to receive a DTMF digit. |
||
409 | Use -1 for the timeout value if you desire the call to block indefinitely. |
||
410 | |||
411 | Return digit pressed as string or error |
||
412 | */ |
||
413 | func (agi *AGI) WaitForDigit(timeout int) (Response, error) { |
||
414 | cmd := fmt.Sprintf("WAIT FOR DIGIT %d\n", timeout) |
||
415 | return agi.execute(cmd) |
||
416 | } |
||
417 |