summaryrefslogtreecommitdiff
path: root/misc/freeswitch/scripts/dialplan/ivr.lua
blob: 6b230dc3dcc5ebc264b105865b8dea34e0c23de6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
-- Gemeinschaft 5 module: ivr class
-- (c) AMOOMA GmbH 2013
-- 

module(...,package.seeall)

Ivr = {}

-- create ivr ivr ;)
function Ivr.new(self, arg)
  arg = arg or {}
  ivr = arg.ivr or {}
  setmetatable(ivr, self);
  self.__index = self;
  self.class = 'ivr';
  self.log = arg.log;
  self.caller = arg.caller;
  self.dtmf_threshold = arg.dtmf_threshold or 500;

  return ivr;
end


function Ivr.ivr_break(self)
  return self.exit or not self.caller:ready();
end


function Ivr.ivr_phrase(self, phrase, keys, timeout, ivr_repeat, phrase_data)
  ivr_repeat = ivr_repeat or 3;
  timeout = timeout or 30;
  self.digit = '';
  self.exit = false;

  self.break_keys = {};
  local query_keys = {};

  for index=1, #keys do
    if type(keys[index]) == 'table' then
      if tostring(keys[index].key) ~= '' then
        table.insert(query_keys, keys[index].key);
      end
      self.break_keys[keys[index].key] = keys[index];
    else
      if tostring(keys[index]) ~= '' then
        table.insert(query_keys, keys[index]);
      end
      self.break_keys[keys[index]] = true;
    end
  end

  global_callback:callback('dtmf', 'ivr_ivr_phrase', self.ivr_phrase_dtmf, self);
  local continue = true;
  for index=0, ivr_repeat do
    continue = self:ivr_break() or self.caller.session:sayPhrase(phrase, phrase_data or table.concat(query_keys, ':'));
    continue = self:ivr_break() or self.caller:sleep(timeout * 1000);

    if self:ivr_break() then
      break;
    end
  end

  global_callback:callback_unset('dtmf', 'ivr_ivr_phrase');

  if type(self.break_keys[self.digit]) == 'table' then
    return self.digit, self.break_keys[self.digit];
  end

  return self.digit;
end


function Ivr.ivr_phrase_dtmf(self, dtmf)
  if self.break_keys[dtmf.digit] then
    self.digit = dtmf.digit;
    self.exit = true;
    return false;
  end
end


function Ivr.read_phrase(self, phrase, phrase_data, max_keys, min_keys, timeout, key_terminator)
  self.max_keys = max_keys or 64;
  self.min_keys = min_keys or 1;
  self.key_terminator = key_terminator or '#';
  self.digits = '';
  self.exit = false;
  timeout = timeout or 30;

  global_callback:callback('dtmf', 'ivr_read_phrase', self.read_phrase_dtmf, self);
  local continue = self:ivr_break() or self.caller.session:sayPhrase(phrase, phrase_data or key_terminator or '');
  continue = self:ivr_break() or self.caller:sleep(timeout * 1000);
  global_callback:callback_unset('dtmf', 'ivr_read_phrase');

  return self.digits;
end


function Ivr.read_phrase_dtmf(self, dtmf)
  if dtmf.duration < self.dtmf_threshold then
    return nil;
  end

  if self.key_terminator == dtmf.digit then
    self.exit = true;
    return false;
  end

  self.digits = self.digits .. dtmf.digit;
end


function Ivr.check_pin(self, phrase_enter, phrase_incorrect, pin, pin_timeout, pin_repeat, key_terminator)
  if not pin then
    return nil;
  end

  self.exit = false;
  pin_timeout = pin_timeout or 30;
  pin_repeat = pin_repeat or 3;
  key_terminator = key_terminator or '#';

  local digits = '';
  for i = 1, pin_repeat do
    if digits == pin then
      self.caller:send_display('PIN: OK');
      break;
    elseif digits ~= "" then
      self.caller:send_display('PIN: wrong');
      self.caller.session:sayPhrase(phrase_incorrect, '');
    elseif self:ivr_break() then
      break;
    end
    self.caller:send_display('Enter PIN');
    digits = ivr:read_phrase(phrase_enter, nil, 0, pin:len() + 1, pin_timeout, key_terminator);
  end

  if digits ~= pin then
    self.caller:send_display('PIN: wrong');
    self.caller.session:sayPhrase(phrase_incorrect, '');
    return false
  end
  self.caller:send_display('PIN: OK');

  return true;
end


function Ivr.record(self, file_name, beep, phrase_record, phrase_too_short, record_length_max, record_length_min, record_repeat, silence_level, silence_lenght_abort)
  local duration = nil;
  for index=1, record_repeat do
    if (duration and duration >= record_length_min) or not self.caller:ready() then
      break;
    elseif duration then
      self.caller:send_display('Recording too short');
      if phrase_too_short then
        self.caller.session:sayPhrase(phrase_too_short);
      end
    end
    if phrase_record then
      self.caller.session:sayPhrase(phrase_record);
    end
    if beep then
      self.caller:playback(beep);
    end
    self.caller:send_display('Recording...');
    local result = self.caller.session:recordFile(file_name, record_length_max, silence_level, silence_lenght_abort);
    duration = self.caller:to_i('record_seconds');
  end

  return duration or 0;
end