ruby-asterisk 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53c6e14b4aa50cd5f5e4742021d1b806c58ee640
4
- data.tar.gz: 21d66e82b5e2755110f83c6fcecd235560cd992b
3
+ metadata.gz: 95239d89540f2e3507f0b72b8f7e42af3c76f781
4
+ data.tar.gz: b3d95a77ba65f358d3504d008e5b41d3035399e5
5
5
  SHA512:
6
- metadata.gz: be06cc29301f21aafa7a9d9d72cdfff8cca8cd1822fa447096e60f3db791f3d3bc6cdae8eb3bf8c506d63c077cb8f433ffb55cc01d3856c5f296e81ce6f47ba4
7
- data.tar.gz: ecca78c7fa306058acc211ff90d6d330b0009f3219d3315fd2123190491e678b12103a6e3d3f510edf388a6782efc41f41a3309b1ae4556a8cadd69e51e62ec6
6
+ metadata.gz: 4fdcf0145516e61659670bce72dd974925b076321180c115fa2d65fd55033faf08d9656d667c6934afbf51238ba42ac535a26a5208c20c79a2a3f17476e74ebf
7
+ data.tar.gz: 424f729d2eea0516b353f412d7fc4ee6830caf2b847d2931dd4bf78388ea52c4fb38f63ad28b7c73a91fec5975ca04917f3dbe31d1782a40f4ca0e0fe3389e10
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ coverage/*
6
+ .cane
7
+ *_high_water_mark
data/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Emiliano Della Casa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # RUBY-ASTERISK
2
2
 
3
3
  [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/emilianodellacasa/ruby-asterisk)
4
+ [![Donate via Zerocracy](https://www.0crat.com/contrib-badge/CE8UGB6NP.svg)](https://www.0crat.com/contrib/CE8UGB6NP)
5
+ [![Managed by Zerocracy](https://www.0crat.com/badge/CE8UGB6NP.svg)](https://www.0crat.com/p/CE8UGB6NP)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/2861728929db934eb376/maintainability)](https://codeclimate.com/github/emilianodellacasa/ruby-asterisk/maintainability)
4
7
 
5
8
  This gem add support to your Ruby or RubyOnRails projects to Asterisk Manager Interface
6
9
 
@@ -65,7 +68,7 @@ To get a list of all parked calls on your Asterisk PBX, use the following comman
65
68
  To start a new call use the following command
66
69
 
67
70
  ```ruby
68
- @ami.originate("SIP/9100","OUTGOING","123456","1","var1=12,var2=99") # CALLER, CONTEXT, CALLEE, PRIORITY, VARIABLE
71
+ @ami.originate("SIP/9100","OUTGOING","123456","1","var1=12,var2=99") # CHANNEL, CONTEXT, CALLEE, PRIORITY, VARIABLES
69
72
  ```
70
73
 
71
74
 
@@ -92,6 +95,15 @@ To get the state of an extension use the following command
92
95
  ```ruby
93
96
  @ami.extension_state(@exten,@context)
94
97
  ```
98
+
99
+ ### DEVICE STATE LIST
100
+
101
+ To get list of states of devices
102
+
103
+ ```ruby
104
+ @ami.device_state_list(@exten,@context)
105
+ ```
106
+
95
107
  ### SKINNY DEVICES AND LINES
96
108
 
97
109
  To get list of skinny devices
@@ -138,6 +150,14 @@ To get a list of sip peers (equivalent to "sip show peers" call on the asterisk
138
150
  @ami.sip_peers
139
151
  ```
140
152
 
153
+ ### SIP SHOW PEER
154
+
155
+ To get info of a peer (equivalent to "sip show peer" call on the asterisk server).
156
+
157
+ ```ruby
158
+ @ami.sip_show_peer(peer)
159
+ ```
160
+
141
161
  ### STATUS
142
162
 
143
163
  To get a status of a single channel or for all channels
@@ -145,6 +165,62 @@ To get a status of a single channel or for all channels
145
165
  @ami.status
146
166
  ```
147
167
 
168
+ ### ATXFER
169
+
170
+ Attendand transfer
171
+
172
+ ```ruby
173
+ @ami.atxfer(channel, exten, context, priority = '1')
174
+ ```
175
+
176
+ ### WAIT EVENT
177
+
178
+ Wait for an event to occur. Timeout in seconds to wait for events, -1 means forever
179
+
180
+ ```ruby
181
+ wait_event(timeout=-1)
182
+ ```
183
+
184
+ ### MONITOR
185
+
186
+ Monitor a channel
187
+
188
+ ```ruby
189
+ monitor(channel,mix=false,file=nil,format='wav')
190
+ ```
191
+
192
+ ### STOP MONITOR
193
+
194
+ Stop monitoring a channel
195
+
196
+ ```ruby
197
+ stop_monitor(channel)
198
+ ```
199
+
200
+ ### PAUSE MONITOR
201
+
202
+ Pause monitoring of a channel
203
+
204
+ ```ruby
205
+ pause_monitor(channel)
206
+ ```
207
+
208
+ ### UNPAUSE MONITOR
209
+
210
+ Unpause monitoring of a channel
211
+
212
+ ```ruby
213
+ unpause_monitor(channel)
214
+ ```
215
+
216
+ ### CHANGE MONITOR
217
+
218
+ Change monitoring filename of a channel
219
+
220
+ ```ruby
221
+ change_monitor(channel,file)
222
+ ```
223
+
148
224
  ### THE RESPONSE OBJECT
149
225
 
150
226
  The response object contains all information about all data received from Asterisk. Here follows a list of all object's properties:
@@ -158,6 +234,12 @@ The response object contains all information about all data received from Asteri
158
234
 
159
235
  The data property contains all additional information obtained from Asterisk, like for example the list of active channels after a "core show channels" command.
160
236
 
237
+ ## Todo List
238
+
239
+ - Adding initialization parameters for Telnet options like Output_log, Waittime, Dump_log, timeout;
240
+ - Adding test cases for better code coverage;
241
+ - Refactoring of ruby-asterisk.rb, adding method_missing for the purpose of supporting as much AMI commands as possible
242
+
161
243
  ## Development
162
244
 
163
245
  Questions or problems? Please post them on the [issue tracker](https://github.com/emilianodellacasa/ruby-asterisk/issues). You can contribute changes by forking the project and submitting a pull request. You can ensure the tests passing by running `bundle` and `rake`.
data/Rakefile CHANGED
@@ -5,4 +5,8 @@ require 'rspec'
5
5
  require 'rspec/core/rake_task'
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
+ require 'quality/rake/task'
9
+
10
+ Quality::Rake::Task.new
11
+
8
12
  task default: :spec
@@ -1,23 +1,28 @@
1
- require "ruby-asterisk/version"
2
- require "ruby-asterisk/request"
3
- require "ruby-asterisk/response"
4
-
1
+ require 'ruby-asterisk/version'
2
+ require 'ruby-asterisk/request'
3
+ require 'ruby-asterisk/response'
5
4
  require 'net/telnet'
6
5
 
7
6
  module RubyAsterisk
7
+ ##
8
+ #
9
+ # Ruby-asterisk main classes
10
+ #
8
11
  class AMI
9
- attr_accessor :host, :port, :connected
12
+ attr_accessor :host, :port, :connected, :timeout, :wait_time
10
13
 
11
- def initialize(host,port)
14
+ def initialize(host, port)
12
15
  self.host = host.to_s
13
16
  self.port = port.to_i
14
17
  self.connected = false
18
+ @timeout = 5
19
+ @wait_time = 0.1
15
20
  @session = nil
16
21
  end
17
22
 
18
23
  def connect
19
24
  begin
20
- @session = Net::Telnet::new("Host" => self.host,"Port" => self.port)
25
+ @session = Net::Telnet::new('Host' => self.host, 'Port' => self.port, 'Timeout' => 10)
21
26
  self.connected = true
22
27
  rescue Exception => ex
23
28
  false
@@ -27,7 +32,6 @@ module RubyAsterisk
27
32
  def disconnect
28
33
  begin
29
34
  @session.close if self.connected
30
- @session = nil
31
35
  self.connected = false
32
36
  true
33
37
  rescue Exception => ex
@@ -36,113 +40,184 @@ module RubyAsterisk
36
40
  end
37
41
  end
38
42
 
39
- def login(username,password)
43
+ def login(username, password)
40
44
  self.connect unless self.connected
41
- execute "Login", {"Username" => username, "Secret" => password, "Event" => "On"}
45
+ execute 'Login', {'Username' => username, 'Secret' => password, 'Event' => 'On'}
46
+ end
47
+
48
+ def logoff
49
+ execute 'Logoff'
42
50
  end
43
51
 
44
52
  def command(command)
45
- execute "Command", {"Command" => command}
53
+ execute 'Command', {'Command' => command}
46
54
  end
47
55
 
48
56
  def core_show_channels
49
- execute "CoreShowChannels"
57
+ execute 'CoreShowChannels'
50
58
  end
51
59
 
52
60
  def meet_me_list
53
- execute "MeetMeList"
61
+ execute 'MeetMeList'
62
+ end
63
+
64
+ def confbridges
65
+ execute 'ConfbridgeListRooms'
66
+ end
67
+
68
+ def confbridge(conference)
69
+ execute 'ConfbridgeList', {'Conference' => conference}
70
+ end
71
+
72
+ def confbridge_mute(conference, channel)
73
+ execute 'ConfbridgeMute', {'Conference' => conference, 'Channel' => channel}
74
+ end
75
+
76
+ def confbridge_unmute(conference, channel)
77
+ execute 'ConfbridgeUnmute', {'Conference' => conference, 'Channel' => channel}
78
+ end
79
+
80
+ def confbridge_kick(conference, channel)
81
+ execute 'ConfbridgeKick', {'Conference' => conference, 'Channel' => channel}
54
82
  end
55
83
 
56
84
  def parked_calls
57
- execute "ParkedCalls"
85
+ execute 'ParkedCalls'
58
86
  end
59
87
 
60
- def extension_state(exten, context, action_id=nil)
61
- execute "ExtensionState", {"Exten" => exten, "Context" => context, "ActionID" => action_id}
88
+ def extension_state(exten, context, action_id = nil)
89
+ execute 'ExtensionState', {'Exten' => exten, 'Context' => context, 'ActionID' => action_id}
90
+ end
91
+
92
+ def device_state_list
93
+ execute 'DeviceStateList'
62
94
  end
63
95
 
64
96
  def skinny_devices
65
- execute "SKINNYdevices"
97
+ execute 'SKINNYdevices'
66
98
  end
67
-
99
+
68
100
  def skinny_lines
69
- execute "SKINNYlines"
101
+ execute 'SKINNYlines'
102
+ end
103
+
104
+ def status(channel = nil, action_id = nil)
105
+ execute 'Status', {'Channel' => channel, 'ActionID' => action_id}
70
106
  end
71
107
 
72
- def status(channel=nil,action_id=nil)
73
- execute "Status", {"Channel" => channel, "ActionID" => action_id}
108
+ def originate(channel, context, callee, priority, variable = nil, caller_id = nil, timeout = 30000)
109
+ @timeout = [@timeout, timeout/1000].max
110
+ execute 'Originate', {'Channel' => channel, 'Context' => context, 'Exten' => callee, 'Priority' => priority, 'CallerID' => caller_id || channel, 'Timeout' => timeout.to_s, 'Variable' => variable }
74
111
  end
75
112
 
76
- def originate(caller,context,callee,priority,variable=nil)
77
- execute "Originate", {"Channel" => caller, "Context" => context, "Exten" => callee, "Priority" => priority, "Callerid" => caller, "Timeout" => "30000", "Variable" => variable }
113
+ def originate_app(caller, app, data, async)
114
+ execute 'Originate', {'Channel' => caller, 'Application' => app, 'Data' => data, 'Timeout' => '30000', 'Async' => async }
78
115
  end
79
116
 
80
117
  def channels
81
- execute "Command", { "Command" => "show channels" }
118
+ execute 'Command', { 'Command' => 'show channels' }
82
119
  end
83
120
 
84
- def redirect(caller,context,callee,priority,variable=nil)
85
- execute "Redirect", {"Channel" => caller, "Context" => context, "Exten" => callee, "Priority" => priority, "Callerid" => caller, "Timeout" => "30000", "Variable" => variable}
121
+ def redirect(channel, context, callee, priority, variable=nil, caller_id = nil, timeout = 30000)
122
+ @timeout = [@timeout, timeout/1000].max
123
+ execute 'Redirect', {'Channel' => channel, 'Context' => context, 'Exten' => callee, 'Priority' => priority, 'CallerID' => caller_id || channel, 'Timeout' => timeout.to_s, 'Variable' => variable}
86
124
  end
87
125
 
88
126
  def queues
89
- execute "Queues", {}
127
+ execute 'Queues', {}
90
128
  end
91
129
 
92
- def queue_add(queue, exten, penalty=2, paused=false, member_name)
93
- execute "QueueAdd", {"Queue" => queue, "Interface" => exten, "Penalty" => penalty, "Paused" => paused, "MemberName" => member_name}
130
+ def queue_add(queue, exten, penalty = 2, paused = false, member_name = '')
131
+ execute 'QueueAdd', {'Queue' => queue, 'Interface' => exten, 'Penalty' => penalty, 'Paused' => paused, 'MemberName' => member_name}
94
132
  end
95
133
 
96
- def queue_pause(queue, exten)
97
- execute "QueuePause", {"Interface" => exten, "Paused" => paused}
134
+ def queue_pause(exten, paused)
135
+ execute 'QueuePause', {'Interface' => exten, 'Paused' => paused}
98
136
  end
99
137
 
100
138
  def queue_remove(queue, exten)
101
- execute "QueueRemove", {"Queue" => queue, "Interface" => exten}
139
+ execute 'QueueRemove', {'Queue' => queue, 'Interface' => exten}
102
140
  end
103
141
 
104
142
  def queue_status
105
- execute "QueueStatus"
143
+ execute 'QueueStatus'
106
144
  end
107
145
 
108
146
  def queue_summary(queue)
109
- execute "QueueSummary", {"Queue" => queue}
147
+ execute 'QueueSummary', {'Queue' => queue}
110
148
  end
111
149
 
112
- def mailbox_status(exten, context="default")
113
- execute "MailboxStatus", {"Mailbox" => "#{exten}@#{context}"}
150
+ def mailbox_status(exten, context='default')
151
+ execute 'MailboxStatus', {'Mailbox' => "#{exten}@#{context}"}
114
152
  end
115
153
 
116
- def mailbox_count(exten, context="default")
117
- execute "MailboxCount", {"Mailbox" => "#{exten}@#{context}"}
154
+ def mailbox_count(exten, context='default')
155
+ execute 'MailboxCount', {'Mailbox' => "#{exten}@#{context}"}
118
156
  end
119
157
 
120
158
  def queue_pause(interface,paused,queue,reason='none')
121
- execute "QueuePause", {"Interface" => interface, "Paused" => paused, "Queue" => queue, "Reason" => reason}
159
+ execute 'QueuePause', {'Interface' => interface, 'Paused' => paused, 'Queue' => queue, 'Reason' => reason}
122
160
  end
123
161
 
124
162
  def ping
125
- execute "Ping"
163
+ execute 'Ping'
126
164
  end
127
165
 
128
- def event_mask(event_mask="off")
129
- execute "Events", {"EventMask" => event_mask}
166
+ def event_mask(event_mask='off')
167
+ execute 'Events', {'EventMask' => event_mask}
130
168
  end
131
169
 
132
170
  def sip_peers
133
- execute "SIPpeers"
171
+ execute 'SIPpeers'
172
+ end
173
+
174
+ def sip_show_peer(peer)
175
+ execute 'SIPshowpeer', {'Peer' => peer}
176
+ end
177
+
178
+ def hangup(channel)
179
+ execute 'Hangup', {'Channel' => channel}
180
+ end
181
+
182
+ def atxfer(channel, exten, context, priority = '1')
183
+ execute 'Atxfer', {'Channel' => channel, 'Exten' => exten.to_s, 'Context' => context, 'Priority' => priority}
184
+ end
185
+
186
+ def wait_event(timeout=-1)
187
+ @timeout = [@timeout, timeout].max
188
+ execute 'WaitEvent', {'Timeout' => timeout}
189
+ end
190
+
191
+ def monitor(channel,mix=false,file=nil,format='wav')
192
+ execute 'Monitor', {'Channel' => channel, 'File' => file, 'Mix' => mix}
193
+ end
194
+
195
+ def stop_monitor(channel)
196
+ execute 'StopMonitor', {'Channel' => channel}
197
+ end
198
+
199
+ def pause_monitor(channel)
200
+ execute 'PauseMonitor', {'Channel' => channel}
201
+ end
202
+
203
+ def unpause_monitor(channel)
204
+ execute 'UnpauseMonitor', {'Channel' => channel}
205
+ end
206
+
207
+ def change_monitor(channel,file)
208
+ execute 'ChangeMonitor', {'Channel' => channel, 'File' => file}
134
209
  end
135
210
 
136
211
  private
137
- def execute(command, options={})
212
+ def execute(command, options = {})
138
213
  request = Request.new(command, options)
139
214
  request.commands.each do |command|
140
215
  @session.write(command)
141
216
  end
142
- @session.waitfor("Match" => /ActionID: #{request.action_id}.*?\n\n/m, "Timeout" => 10) do |data|
143
- request.response_data << data
217
+ @session.waitfor('Match' => /ActionID: #{request.action_id}.*?\n\n/m, "Timeout" => @timeout, "Waittime" => @wait_time) do |data|
218
+ request.response_data << data.to_s
144
219
  end
145
- Response.new(command,request.response_data)
220
+ Response.new(command, request.response_data)
146
221
  end
147
222
  end
148
223
  end
@@ -0,0 +1,98 @@
1
+ ##
2
+ #
3
+ # File containing parsing constants
4
+ #
5
+ module RubyAsterisk
6
+ DESCRIPTIVE_STATUS = {
7
+ '-1' => 'Extension not found',
8
+ '0' => 'Idle',
9
+ '1' => 'In Use',
10
+ '2' => 'Busy',
11
+ '3' => 'Unavailable',
12
+ '4' => 'Ringing',
13
+ '5' => 'On Hold'
14
+ }
15
+
16
+ PARSE_DATA = {
17
+ 'CoreShowChannels' => {
18
+ :symbol => :channels,
19
+ :search_for => 'Event: CoreShowChannel',
20
+ :stop_with => 'Event: CoreShowChannelsComplete'
21
+ },
22
+ 'ParkedCalls' => {
23
+ :symbol => :calls,
24
+ :search_for => 'Event: ParkedCall',
25
+ :stop_with => nil
26
+ },
27
+ 'Originate' => {
28
+ :symbol => :dial,
29
+ :search_for => 'Event: Dial',
30
+ :stop_with => nil
31
+ },
32
+ 'MeetMeList' => {
33
+ :symbol => :rooms,
34
+ :search_for => 'Event: MeetmeList',
35
+ :stop_with => nil
36
+ },
37
+ 'ConfbridgeListRooms' => {
38
+ :symbol => :rooms,
39
+ :search_for => 'Event: ConfbridgeListRooms',
40
+ :stop_with => nil
41
+ },
42
+ 'ConfbridgeList' => {
43
+ :symbol => :channels,
44
+ :search_for => 'Event: ConfbridgeList',
45
+ :stop_with => nil
46
+ },
47
+ 'Status' => {
48
+ :symbol => :status,
49
+ :search_for => 'Event: Status',
50
+ :stop_with => nil
51
+ },
52
+ 'ExtensionState' => {
53
+ :symbol => :hints,
54
+ :search_for => 'Response: Success',
55
+ :stop_with => nil
56
+ },
57
+ 'DeviceStateList' => {
58
+ :symbol => :hints,
59
+ :search_for => 'Response: Success',
60
+ :stop_with => nil
61
+ },
62
+ 'SKINNYdevices' => {
63
+ :symbol => :skinnydevs,
64
+ :search_for => 'Event: DeviceEntry',
65
+ :stop_with => nil
66
+ },
67
+ 'SKINNYlines' => {
68
+ :symbol => :skinnylines,
69
+ :search_for => 'Event: LineEntry',
70
+ :stop_with => nil
71
+ },
72
+ 'QueuePause' => {
73
+ :symbol => :queue_pause,
74
+ :search_for => 'Response:',
75
+ :stop_with => nil
76
+ },
77
+ 'Pong' => {
78
+ :symbol => :pong,
79
+ :search_for => 'Response:',
80
+ :stop_with => nil
81
+ },
82
+ 'Events' => {
83
+ :symbol => :event_mask,
84
+ :search_for => 'Ping:',
85
+ :stop_with => nil
86
+ },
87
+ 'SIPpeers' => {
88
+ :symbol => :peers,
89
+ :search_for => 'Event: PeerEntry',
90
+ :stop_with => nil
91
+ },
92
+ 'SIPshowpeer' => {
93
+ :symbol => :hints,
94
+ :search_for => 'Response: Success',
95
+ :stop_with => nil
96
+ },
97
+ }
98
+ end