ruby-asterisk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,32 +1,31 @@
1
1
  module RubyAsterisk
2
+ ##
3
+ #
4
+ # Class responsible of building commands structure
5
+ #
2
6
  class Request
3
7
  attr_accessor :action, :action_id, :parameters, :response_data
4
8
 
5
- def initialize(action,parameters={})
9
+ def initialize(action, parameters = {})
6
10
  self.action = action
7
- self.action_id = self.generate_action_id
11
+ self.action_id = Request.generate_action_id
8
12
  self.parameters = parameters
9
- self.response_data = ""
13
+ self.response_data = ''
10
14
  end
11
15
 
12
16
  def commands
13
- _commands=["Action: "+self.action+"\r\n","ActionID: "+self.action_id+"\r\n"]
14
- self.parameters.each do |key,value|
15
- _commands<<key+": "+value+"\r\n" unless value.nil?
17
+ _commands = ["Action: #{self.action}\r\n", "ActionID: #{self.action_id}\r\n"]
18
+ self.parameters.each do |key, value|
19
+ _commands<<"#{key.to_s}: #{value.to_s}\r\n" unless value.nil?
16
20
  end
17
- _commands[_commands.length-1]<<"\r\n"
21
+ _commands[_commands.length - 1] << "\r\n"
18
22
  _commands
19
- end
23
+ end
20
24
 
21
25
  protected
22
26
 
23
- def generate_action_id
24
- if RUBY_VERSION.start_with?("1.9")
25
- Random.rand(999).to_s
26
- else
27
- rand(999).to_s
28
- end
27
+ def self.generate_action_id
28
+ Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond).to_s(36)
29
29
  end
30
-
31
30
  end
32
31
  end
@@ -1,33 +1,38 @@
1
+ require 'ruby-asterisk/response_parser'
2
+
1
3
  module RubyAsterisk
4
+ ##
5
+ #
6
+ # Class for response coming from Asterisk
7
+ #
2
8
  class Response
3
- attr_accessor :type, :success, :action_id, :message, :data, :raw_response
9
+ attr_accessor :type, :action_id, :message, :data, :raw_response
4
10
 
5
11
  def initialize(type,response)
6
12
  self.raw_response = response
7
13
  self.type = type
8
- self.success = self._parse_successfull(response)
9
- self.action_id = self._parse_action_id(response)
10
- self.message = self._parse_message(response)
11
- self.data = self._parse_data(response)
14
+ self.action_id = self._parse_action_id
15
+ self.message = self._parse_message
16
+ self.data = self._parse_response
12
17
  end
13
18
 
14
- protected
15
-
16
- def _parse_successfull(response)
17
- response.include?("Response: Success")
19
+ def success
20
+ self.raw_response.include?("Response: Success")
18
21
  end
19
22
 
20
- def _parse_action_id(response)
21
- self._parse(response,"ActionID:")
23
+ protected
24
+
25
+ def _parse_action_id
26
+ self._parse("ActionID:")
22
27
  end
23
28
 
24
- def _parse_message(response)
25
- self._parse(response,"Message:")
29
+ def _parse_message
30
+ self._parse("Message:")
26
31
  end
27
32
 
28
- def _parse(response,field)
33
+ def _parse(field)
29
34
  _value = nil
30
- response.each_line do |line|
35
+ self.raw_response.each_line do |line|
31
36
  if line.start_with?(field)
32
37
  _value = line[line.rindex(":")+1..line.size].strip
33
38
  end
@@ -35,128 +40,9 @@ module RubyAsterisk
35
40
  _value
36
41
  end
37
42
 
38
- def _parse_data(response)
39
- case self.type
40
- when "CoreShowChannels"
41
- self._parse_data_core_show_channels(response)
42
- when "ParkedCalls"
43
- self._parse_data_parked_calls(response)
44
- when "Originate"
45
- self._parse_originate(response)
46
- when "MeetMeList"
47
- self._parse_meet_me_list(response)
48
- when "Status"
49
- self._parse_status(response)
50
- when "ExtensionState"
51
- self._parse_extension_state(response)
52
- when "SKINNYdevices"
53
- self._parse_skinny_devices(response)
54
- when "SKINNYlines"
55
- self._parse_skinny_lines(response)
56
- when "Command"
57
- response
58
- when "QueuePause"
59
- self._parse_queue_pause(response)
60
- when "Pong"
61
- self._parse_pong(response)
62
- when "Events"
63
- self._parse_event_mask(response)
64
- when "SIPpeers"
65
- self._parse_sip_peers(response)
66
- end
67
-
68
- end
69
-
70
- def _parse_sip_peers(response)
71
- self._parse_objects(response, :peers, "Event: PeerEntry")
72
- end
73
-
74
- def _parse_meet_me_list(response)
75
- self._parse_objects(response,:rooms,"Event: MeetmeList")
76
- end
77
-
78
- def _parse_originate(response)
79
- self._parse_objects(response,:dial,"Event: Dial")
80
- end
81
-
82
- def _parse_data_parked_calls(response)
83
- self._parse_objects(response,:calls,"Event: ParkedCall")
84
- end
85
-
86
- def _parse_data_core_show_channels(response)
87
- self._parse_objects(response,:channels,"Event: CoreShowChannel","Event: CoreShowChannelsComplete")
43
+ def _parse_response
44
+ ResponseParser.parse(self.raw_response, self.type)
88
45
  end
89
46
 
90
- def _parse_extension_state(response)
91
- _data = self._parse_objects(response,:hints,"Response:")
92
- self._convert_status(_data)
93
- end
94
-
95
- def _parse_skinny_devices(response)
96
- self._parse_objects(response,:skinnydevs,"Event: DeviceEntry")
97
- end
98
-
99
- def _parse_skinny_lines(response)
100
- self._parse_objects(response,:skinnylines,"Event: LineEntry")
101
- end
102
-
103
- def _parse_queue_pause(response)
104
- _data = self._parse_objects(response,:queue_pause,"Response:")
105
- end
106
-
107
- def _parse_pong(response)
108
- _data = self._parse_objects(response,:pong, "Response:")
109
- end
110
-
111
- def _parse_event_mask(response)
112
- _data = self._parse_objects(response, :event_mask, "Ping:")
113
- end
114
-
115
- def _parse_status(response)
116
- self._parse_objects(response, :status, "Event: Status")
117
- end
118
-
119
- def _convert_status(_data)
120
- _data[:hints].each do |hint|
121
- case hint["Status"]
122
- when "-1"
123
- hint["DescriptiveStatus"] = "Extension not found"
124
- when "0"
125
- hint["DescriptiveStatus"] = "Idle"
126
- when "1"
127
- hint["DescriptiveStatus"] = "In Use"
128
- when "2"
129
- hint["DescriptiveStatus"] = "Busy"
130
- when "4"
131
- hint["DescriptiveStatus"] = "Unavailable"
132
- when "8"
133
- hint["DescriptiveStatus"] = "Ringing"
134
- when "16"
135
- hint["DescriptiveStatus"] = "On Hold"
136
- end
137
- end
138
- _data
139
- end
140
-
141
- def _parse_objects(response,symbol_name,search_for,stop_with=nil)
142
- _data = { symbol_name => [] }
143
- parsing = false
144
- object = nil
145
- response.each_line do |line|
146
- line.strip!
147
- if line.strip.empty? or (!stop_with.nil? and line.start_with?(stop_with))
148
- parsing = false
149
- elsif line.start_with?(search_for)
150
- _data[symbol_name] << object unless object.nil?
151
- object = {}
152
- parsing = true
153
- elsif parsing
154
- tokens = line.split(':', 2)
155
- object[tokens[0].strip]=tokens[1].strip unless tokens[1].nil?
156
- end
157
- end
158
- _data[symbol_name] << object unless object.nil?
159
- _data
160
- end
161
47
  end
162
48
  end
@@ -0,0 +1,42 @@
1
+ require 'ruby-asterisk/parsing_constants'
2
+
3
+ module RubyAsterisk
4
+ ##
5
+ #
6
+ # Class for parsing response coming from Asterisk
7
+ #
8
+ class ResponseParser
9
+
10
+ def self.parse(raw_response, type)
11
+ if PARSE_DATA.include?(type)
12
+ self._parse_objects(raw_response, PARSE_DATA[type])
13
+ else
14
+ raw_response
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ def self._add_status(exten_array)
21
+ exten_array.each do |hint|
22
+ hint["DescriptiveStatus"] = DESCRIPTIVE_STATUS[hint["Status"]]
23
+ end
24
+ exten_array
25
+ end
26
+
27
+ def self._parse_objects(response, parse_params)
28
+ object_array = []
29
+ object_regex = Regexp.new(/#{parse_params[:search_for]}\n(.*?)\n\n/m)
30
+ response.scan(object_regex) do |match|
31
+ object = {}
32
+ match[0].split(/\n/).each do |line|
33
+ tokens = line.split(':', 2)
34
+ object[tokens[0].strip]=tokens[1].strip unless tokens[1].nil?
35
+ end
36
+ object_array << object unless object.empty?
37
+ end
38
+ object_array = _add_status(object_array) if parse_params[:symbol].eql?(:hints)
39
+ { parse_params[:symbol] => object_array }
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module Rami
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -7,10 +7,11 @@ Gem::Specification.new do |s|
7
7
  s.version = Rami::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Emiliano Della Casa"]
10
- s.email = ["e.dellacasa@engim.eu"]
10
+ s.email = ["emiliano.dellacasa@gmail.com"]
11
11
  s.homepage = "http://github.com/emilianodellacasa/ruby-asterisk"
12
12
  s.summary = %q{Asterisk Manager Interface in Ruby}
13
13
  s.description = %q{Add support to your ruby or rails projects to Asterisk Manager Interface (AMI)}
14
+ s.licenses = ['MIT']
14
15
 
15
16
  s.rubyforge_project = "ruby-asterisk"
16
17
 
@@ -19,6 +20,8 @@ Gem::Specification.new do |s|
19
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
21
  s.require_paths = ["lib"]
21
22
 
22
- s.add_development_dependency "rake"
23
- s.add_development_dependency 'rspec'
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency 'rspec'
25
+ s.add_development_dependency 'simplecov'
26
+ s.add_development_dependency 'quality'
24
27
  end
@@ -8,7 +8,7 @@ describe RubyAsterisk::Request do
8
8
  request.commands.include?("Variable: var1=15\r\n").should_not be_nil
9
9
  end
10
10
 
11
- it "should not set a Variable option if not set" do
11
+ it "should not set a Variable option if not set" do
12
12
  request = RubyAsterisk::Request.new("Originate",{"Channel" => "1234", "Context" => "test", "Exten" => "1", "Priority" => "1", "Callerid" => "1234", "Timeout" => "30000", "Variable" => nil })
13
13
  request.commands.include?("Variable: var=15").should==false
14
14
  end
@@ -5,130 +5,130 @@ describe RubyAsterisk::Response do
5
5
  def sip_peers_response
6
6
  "Response: Success
7
7
  Message: Peer status list will follow
8
-
8
+
9
9
  Event: PeerEntry
10
10
  Channeltype: SIP
11
11
  ObjectName: 9915057
12
- IPport: 5060"
12
+ IPport: 5060\n\n"
13
+ end
14
+
15
+ def empty_core_show_channels_response
16
+ "Event: CoreShowChannelsComplete
17
+ EventList: Complete
18
+ ListItems: 1
19
+ ActionID: 839\n\n"
13
20
  end
14
21
 
15
- def empty_core_show_channels_response
16
- "Event: CoreShowChannelsComplete
17
- EventList: Complete
22
+ def core_show_channels_response
23
+ "Event: CoreShowChannel
24
+ ActionID: 839
25
+ Channel: SIP/195.62.226.4-00000025
26
+ UniqueID: 1335448133.61
27
+ Context: incoming
28
+ Extension: s
29
+ Priority: 1
30
+ ChannelState: 6
31
+ ChannelStateDesc: Up
32
+ Application: Parked Call
33
+ ApplicationData:
34
+ CallerIDnum: 123456
35
+ CallerIDname:
36
+ ConnectedLineNum:
37
+ ConnectedLineName:
38
+ Duration: 00:00:05
39
+ AccountCode:
40
+ BridgedChannel:
41
+ BridgedUniqueID:
42
+
43
+ Event: CoreShowChannelsComplete
44
+ EventList: Complete
18
45
  ListItems: 1
19
- ActionID: 839"
20
- end
21
-
22
- def core_show_channels_response
23
- "Event: CoreShowChannel
24
- ActionID: 839
25
- Channel: SIP/195.62.226.4-00000025
26
- UniqueID: 1335448133.61
27
- Context: incoming
28
- Extension: s
29
- Priority: 1
30
- ChannelState: 6
31
- ChannelStateDesc: Up
32
- Application: Parked Call
33
- ApplicationData:
34
- CallerIDnum: 123456
35
- CallerIDname:
36
- ConnectedLineNum:
37
- ConnectedLineName:
38
- Duration: 00:00:05
39
- AccountCode:
40
- BridgedChannel:
41
- BridgedUniqueID:
42
-
43
- Event: CoreShowChannelsComplete
44
- EventList: Complete
45
- ListItems: 1
46
- ActionID: 839"
47
- end
48
-
49
- def parked_calls_response
50
- "Event: ParkedCall
51
- Parkinglot: default
52
- Exten: 701
53
- Channel: SIP/195.62.226.2-00000026
54
- From: SIP/195.62.226.2-00000026
55
- Timeout: 3
56
- CallerIDNum: 123456
57
- CallerIDName:
58
- ConnectedLineNum:
59
- ConnectedLineName:
60
- ActionID: 899"
61
- end
62
-
63
- def originate_response
64
- "Event: Dial
65
- Privilege: call,all
66
- SubEvent: End
67
- Channel: SIP/9100-0000002b
68
- UniqueID: 1335457364.68
69
- DialStatus: CHANUNAVAIL"
70
- end
71
-
72
- def meet_me_list_response
73
- "Event: MeetmeList
74
- ActionID: 921
75
- Conference: 1234
76
- UserNumber: 1
77
- CallerIDNum: 123456
78
- CallerIDName: <no name>
79
- ConnectedLineNum: <unknown>
80
- ConnectedLineName: <no name>
81
- Channel: SIP/195.62.226.18-0000000e
82
- Admin: No
83
- Role: Talk and listen
84
- MarkedUser: No
85
- Muted: No
86
- Talking: Not monitored"
87
- end
88
-
89
- def extension_state_response
90
- "Response: Success
91
- ActionID: 180
92
- Message: Extension Status
93
- Exten: 9100
94
- Context: HINT
95
- Hint: SIP/9100
96
- Status: 0"
97
- end
98
-
99
- describe ".new" do
100
-
101
- describe "receiving a Core Show Channels request" do
102
- it "should parse correctly data coming from Asterisk about channels" do
103
- @response = RubyAsterisk::Response.new("CoreShowChannels",core_show_channels_response)
104
- @response.data[:channels].should_not be_empty
105
- end
106
-
107
- it "should correctly fill the fields" do
46
+ ActionID: 839\n\n"
47
+ end
48
+
49
+ def parked_calls_response
50
+ "Event: ParkedCall
51
+ Parkinglot: default
52
+ Exten: 701
53
+ Channel: SIP/195.62.226.2-00000026
54
+ From: SIP/195.62.226.2-00000026
55
+ Timeout: 3
56
+ CallerIDNum: 123456
57
+ CallerIDName:
58
+ ConnectedLineNum:
59
+ ConnectedLineName:
60
+ ActionID: 899\n\n"
61
+ end
62
+
63
+ def originate_response
64
+ "Event: Dial
65
+ Privilege: call,all
66
+ SubEvent: End
67
+ Channel: SIP/9100-0000002b
68
+ UniqueID: 1335457364.68
69
+ DialStatus: CHANUNAVAIL\n\n"
70
+ end
71
+
72
+ def meet_me_list_response
73
+ "Event: MeetmeList
74
+ ActionID: 921
75
+ Conference: 1234
76
+ UserNumber: 1
77
+ CallerIDNum: 123456
78
+ CallerIDName: <no name>
79
+ ConnectedLineNum: <unknown>
80
+ ConnectedLineName: <no name>
81
+ Channel: SIP/195.62.226.18-0000000e
82
+ Admin: No
83
+ Role: Talk and listen
84
+ MarkedUser: No
85
+ Muted: No
86
+ Talking: Not monitored\n\n"
87
+ end
88
+
89
+ def extension_state_response
90
+ "Response: Success
91
+ ActionID: 180
92
+ Message: Extension Status
93
+ Exten: 9100
94
+ Context: HINT
95
+ Hint: SIP/9100
96
+ Status: 0\n\n"
97
+ end
98
+
99
+ describe ".new" do
100
+
101
+ describe "receiving a Core Show Channels request" do
102
+ it "should parse correctly data coming from Asterisk about channels" do
103
+ @response = RubyAsterisk::Response.new("CoreShowChannels",core_show_channels_response)
104
+ @response.data[:channels].should_not be_empty
105
+ end
106
+
107
+ it "should correctly fill the fields" do
108
108
  @response = RubyAsterisk::Response.new("CoreShowChannels",core_show_channels_response)
109
109
  @response.data[:channels][0]["CallerIDnum"].should eq("123456")
110
110
  end
111
111
 
112
- it "should have no channels if answer is empty" do
113
- @response = RubyAsterisk::Response.new("CoreShowChannels",empty_core_show_channels_response)
114
- @response.data[:channels].count.should eq(0)
115
- end
116
- end
117
-
118
- describe "receiving a Parked Calls request" do
119
- it "should parse correctly data coming from Asterisk about calls" do
120
- @response = RubyAsterisk::Response.new("ParkedCalls",parked_calls_response)
121
- @response.data[:calls].should_not be_empty
122
- end
123
-
124
- it "should correctly fill the fields" do
125
- @response = RubyAsterisk::Response.new("ParkedCalls",parked_calls_response)
126
- @response.data[:calls][0]["Exten"].should eq("701")
127
- end
128
- end
129
-
130
- describe "receiving a Originate request" do
131
- it "should parse correctly data coming from Asterisk about the call" do
112
+ it "should have no channels if answer is empty" do
113
+ @response = RubyAsterisk::Response.new("CoreShowChannels",empty_core_show_channels_response)
114
+ @response.data[:channels].count.should eq(0)
115
+ end
116
+ end
117
+
118
+ describe "receiving a Parked Calls request" do
119
+ it "should parse correctly data coming from Asterisk about calls" do
120
+ @response = RubyAsterisk::Response.new("ParkedCalls",parked_calls_response)
121
+ @response.data[:calls].should_not be_empty
122
+ end
123
+
124
+ it "should correctly fill the fields" do
125
+ @response = RubyAsterisk::Response.new("ParkedCalls",parked_calls_response)
126
+ @response.data[:calls][0]["Exten"].should eq("701")
127
+ end
128
+ end
129
+
130
+ describe "receiving a Originate request" do
131
+ it "should parse correctly data coming from Asterisk about the call" do
132
132
  @response = RubyAsterisk::Response.new("Originate",originate_response)
133
133
  @response.data[:dial].should_not be_empty
134
134
  end
@@ -143,8 +143,8 @@ describe RubyAsterisk::Response do
143
143
  @response.raw_response.should eq(originate_response)
144
144
  end
145
145
  end
146
-
147
- describe "receiving a MeetMeList request" do
146
+
147
+ describe "receiving a MeetMeList request" do
148
148
  it "should parse correctly data coming from Asterisk about the conference room" do
149
149
  @response = RubyAsterisk::Response.new("MeetMeList",meet_me_list_response)
150
150
  @response.data[:rooms].should_not be_empty
@@ -156,7 +156,7 @@ describe RubyAsterisk::Response do
156
156
  end
157
157
  end
158
158
 
159
- describe "receiving a ExtensionState request" do
159
+ describe "receiving a ExtensionState request" do
160
160
  it "should parse correctly data coming from Asterisk about the state of the extension" do
161
161
  @response = RubyAsterisk::Response.new("ExtensionState",extension_state_response)
162
162
  @response.data[:hints].should_not be_empty
@@ -165,17 +165,17 @@ describe RubyAsterisk::Response do
165
165
  it "should correctly fill the fields" do
166
166
  @response = RubyAsterisk::Response.new("ExtensionState",extension_state_response)
167
167
  @response.data[:hints][0]["Status"].should eq("0")
168
- @response.data[:hints][0]["DescriptiveStatus"].should eq("Idle")
168
+ @response.data[:hints][0]["DescriptiveStatus"].should eq("Idle")
169
169
  end
170
170
  end
171
- end
171
+ end
172
172
 
173
173
  describe "receiving a SIPPeers request" do
174
174
  it "should parse correctly data coming from Asterisk abous sip peers" do
175
175
  @response = RubyAsterisk::Response.new("SIPpeers",sip_peers_response)
176
176
  @response.data[:peers].should_not be_empty
177
177
  end
178
-
178
+
179
179
  it "should correctly fill the fields" do
180
180
  @response = RubyAsterisk::Response.new("SIPpeers",sip_peers_response)
181
181
  @response.data[:peers][0]["ObjectName"].should eq("9915057")