pabx 0.0.2

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZGVmZDE4ZGFhNDBmMzA5ZTUxYTRjODhmNjhjZDUyZTg2ZjZiZmExOQ==
5
+ data.tar.gz: !binary |-
6
+ Y2U0ZDcwNWQ2ZmNhMzBiY2NmZDIzODNhMDFiMGVmYmE0NmRlN2QzOQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YmIxZjRmNzMwMjVjYjJiMmNlYjJkYjZmOWZmMjM2MzBmNDEwNzJmZWNiNGU1
10
+ YTQxZDgyZjBhZDgyYjVhNzc1OWI3YTczOGUxNWZmZWU5Yzg1OWY0ZTllMDJk
11
+ YTk0NjhlMWFmMGEwYTNjYWUzYzU4ZmM0M2FiZTM5ODk1ZWM5OTA=
12
+ data.tar.gz: !binary |-
13
+ MWEyNGRjYTVjMmY4MWNmZmVhZmQ1MTM0N2IwNWU4NjIzNWY0ODQyNGFhZjA5
14
+ ODg3ZTI0NWYxNDU3ZTc5ZWZmYzZmOTcwYzIyOTcyMzNmOTc1YWQxN2RiYmE0
15
+ OTE4NzZkOTcxMGQ5YzRjYjhiZWZmZmQ3MmE2ZWY1ZjJkMzFiN2Q=
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rami.gemspec
4
+ gemspec
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,117 @@
1
+ require "pabx/version"
2
+ require "pabx/request"
3
+ require "pabx/response"
4
+
5
+ require 'net/telnet'
6
+
7
+ module Pabx
8
+ class AMI
9
+ attr_accessor :host, :port, :connected
10
+
11
+ def initialize(host,port)
12
+ self.host = host.to_s
13
+ self.port = port.to_i
14
+ self.connected = false
15
+ @session = nil
16
+ end
17
+
18
+ def connect
19
+ begin
20
+ @session = Net::Telnet::new("Host" => self.host,"Port" => self.port)
21
+ self.connected = true
22
+ rescue Exception => ex
23
+ false
24
+ end
25
+ end
26
+
27
+ def disconnect
28
+ begin
29
+ @session.close if self.connected
30
+ @session = nil
31
+ self.connected = false
32
+ true
33
+ rescue Exception => ex
34
+ puts ex
35
+ false
36
+ end
37
+ end
38
+
39
+ def login(username,password)
40
+ self.connect unless self.connected
41
+ request = Request.new("Login",{"Username" => username, "Secret" => password})
42
+ request.commands.each do |command|
43
+ @session.write(command)
44
+ end
45
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 3) do |data|
46
+ request.response_data << data
47
+ end
48
+ Response.new("Login",request.response_data)
49
+ end
50
+
51
+ def command(command)
52
+ request = Request.new("Command",{ "Command" => command })
53
+ request.commands.each do |command|
54
+ @session.write(command)
55
+ end
56
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 3) do |data|
57
+ request.response_data << data
58
+ end
59
+ Response.new("Command",request.response_data)
60
+ end
61
+
62
+ def core_show_channels
63
+ request = Request.new("CoreShowChannels")
64
+ request.commands.each do |command|
65
+ @session.write(command)
66
+ end
67
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 3) do |data|
68
+ request.response_data << data
69
+ end
70
+ Response.new("CoreShowChannels",request.response_data)
71
+ end
72
+
73
+ def meet_me_list
74
+ request = Request.new("MeetMeList")
75
+ request.commands.each do |command|
76
+ @session.write(command)
77
+ end
78
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 3) do |data|
79
+ request.response_data << data
80
+ end
81
+ Response.new("MeetMeList",request.response_data)
82
+ end
83
+
84
+ def parked_calls
85
+ request = Request.new("ParkedCalls")
86
+ request.commands.each do |command|
87
+ @session.write(command)
88
+ end
89
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 3) do |data|
90
+ request.response_data << data
91
+ end
92
+ Response.new("ParkedCalls",request.response_data)
93
+ end
94
+
95
+ def extension_state(exten,context)
96
+ request = Request.new("ExtensionState",{"Exten" => exten, "Context" => context})
97
+ request.commands.each do |command|
98
+ @session.write(command)
99
+ end
100
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 3) do |data|
101
+ request.response_data << data
102
+ end
103
+ Response.new("ExtensionState",request.response_data)
104
+ end
105
+
106
+ def originate(caller,context,callee,priority,variable=nil)
107
+ request = Request.new("Originate",{"Channel" => caller, "Context" => context, "Exten" => callee, "Priority" => priority, "Callerid" => caller, "Timeout" => "30000", "Variable" => variable })
108
+ request.commands.each do |command|
109
+ @session.write(command)
110
+ end
111
+ @session.waitfor("String" => "ActionID: "+request.action_id, "Timeout" => 40) do |data|
112
+ request.response_data << data
113
+ end
114
+ Response.new("Originate",request.response_data)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,32 @@
1
+ module Pabx
2
+ class Request
3
+ attr_accessor :action, :action_id, :parameters, :response_data
4
+
5
+ def initialize(action,parameters={})
6
+ self.action = action
7
+ self.action_id = self.generate_action_id
8
+ self.parameters = parameters
9
+ self.response_data = ""
10
+ end
11
+
12
+ 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?
16
+ end
17
+ _commands[_commands.length-1]<<"\r\n"
18
+ _commands
19
+ end
20
+
21
+ protected
22
+
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
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,114 @@
1
+ module Pabx
2
+ class Response
3
+ attr_accessor :type, :success, :action_id, :message, :data
4
+
5
+ def initialize(type,response)
6
+ self.type = type
7
+ self.success = self._parse_successfull(response)
8
+ self.action_id = self._parse_action_id(response)
9
+ self.message = self._parse_message(response)
10
+ self.data = self._parse_data(response)
11
+ end
12
+
13
+ protected
14
+
15
+ def _parse_successfull(response)
16
+ response.include?("Response: Success")
17
+ end
18
+
19
+ def _parse_action_id(response)
20
+ _action_id = self._parse(response,"ActionID:")
21
+ end
22
+
23
+ def _parse_message(response)
24
+ _message = self._parse(response,"Message:")
25
+ end
26
+
27
+ def _parse(response,field)
28
+ _value = nil
29
+ response.each_line do |line|
30
+ if line.start_with?(field)
31
+ _value = line[line.rindex(":")+1..line.size].strip
32
+ end
33
+ end
34
+ _value
35
+ end
36
+
37
+ def _parse_data(response)
38
+ case self.type
39
+ when "CoreShowChannels"
40
+ self._parse_data_core_show_channels(response)
41
+ when "ParkedCalls"
42
+ self._parse_data_parked_calls(response)
43
+ when "Originate"
44
+ self._parse_originate(response)
45
+ when "MeetMeList"
46
+ self._parse_meet_me_list(response)
47
+ when "ExtensionState"
48
+ self._parse_extension_state(response)
49
+ end
50
+ end
51
+
52
+ def _parse_meet_me_list(response)
53
+ self._parse_objects(response,:rooms,"Event: MeetmeList")
54
+ end
55
+
56
+ def _parse_originate(response)
57
+ self._parse_objects(response,:dial,"Event: Dial")
58
+ end
59
+
60
+ def _parse_data_parked_calls(response)
61
+ self._parse_objects(response,:calls,"Event: ParkedCall")
62
+ end
63
+
64
+ def _parse_data_core_show_channels(response)
65
+ self._parse_objects(response,:channels,"Event: CoreShowChannel","Event: CoreShowChannelsComplete")
66
+ end
67
+
68
+ def _parse_extension_state(response)
69
+ _data = self._parse_objects(response,:hints,"Response:")
70
+ self._convert_status(_data)
71
+ end
72
+
73
+ def _convert_status(_data)
74
+ _data[:hints].each do |hint|
75
+ case hint["Status"]
76
+ when "-1"
77
+ hint["DescriptiveStatus"] = "Extension not found"
78
+ when "0"
79
+ hint["DescriptiveStatus"] = "Idle"
80
+ when "1"
81
+ hint["DescriptiveStatus"] = "In Use"
82
+ when "2"
83
+ hint["DescriptiveStatus"] = "Busy"
84
+ when "4"
85
+ hint["DescriptiveStatus"] = "Unavailable"
86
+ when "8"
87
+ hint["DescriptiveStatus"] = "Ringing"
88
+ when "16"
89
+ hint["DescriptiveStatus"] = "On Hold"
90
+ end
91
+ end
92
+ _data
93
+ end
94
+
95
+ def _parse_objects(response,symbol_name,search_for,stop_with=nil)
96
+ _data = { symbol_name => [] }
97
+ parsing = false
98
+ object = nil
99
+ response.each_line do |line|
100
+ if line.strip.empty? or (!stop_with.nil? and line.start_with?(stop_with))
101
+ parsing = false
102
+ elsif line.start_with?(search_for)
103
+ _data[symbol_name] << object unless object.nil?
104
+ object = {}
105
+ parsing = true
106
+ elsif parsing
107
+ object[line.split(':')[0].strip]=line.split(':')[1].strip unless line.split(':')[1].nil?
108
+ end
109
+ end
110
+ _data[symbol_name] << object unless object.nil?
111
+ _data
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,3 @@
1
+ module Rami
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "pabx/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pabx"
7
+ s.license = 'MIT'
8
+ s.version = Rami::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Elias Hasnat"]
11
+ s.email = ["android.hasnat@gmail.com"]
12
+ s.homepage = "http://github.com/claymodel/telephony/pabx"
13
+ s.summary = %q{IMS SoftSwitch Manager - Ruby}
14
+ s.description = %q{Add support to your ruby or rails projects to IMS SoftSwitch Manager}
15
+
16
+ s.rubyforge_project = "pabx"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency 'rspec'
25
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ describe Pabx do
4
+
5
+ def mock_request(stubs={})
6
+ (@mock_request ||= mock_model(Pabx::Request).as_null_object).tap do |request|
7
+ request.stub(stubs) unless stubs.empty?
8
+ end
9
+ end
10
+
11
+ before :each do
12
+ @session = Pabx::AMI.new("127.0.0.1",5038)
13
+ end
14
+
15
+ after :each do
16
+ @session.disconnect
17
+ end
18
+
19
+ describe ".new" do
20
+ it "initialize session with host" do
21
+ @session.host.should eq("127.0.0.1")
22
+ end
23
+
24
+ it "initialize session with host" do
25
+ @session.port.should eq(5038)
26
+ end
27
+
28
+ it "should start the session as disconnected" do
29
+ @session.connected.should_not be_true
30
+ end
31
+ end
32
+
33
+ describe ".connect" do
34
+ it "should return true if everything is ok" do
35
+ @session.connect.should be_true
36
+ end
37
+
38
+ it "should return false if everything if something went wrong" do
39
+ @session.port = 666
40
+ @session.connect.should_not be_true
41
+ @session.port = 5038
42
+ end
43
+
44
+ it "should change state to session as connected" do
45
+ @session.connect
46
+ @session.connected.should be_true
47
+ end
48
+ end
49
+
50
+ describe ".disconnect" do
51
+ it "should return true if everything is ok" do
52
+ @session.disconnect.should be_true
53
+ end
54
+
55
+ it "should change state to session as disconnected" do
56
+ @session.disconnect
57
+ @session.connected.should_not be_true
58
+ end
59
+ end
60
+
61
+ describe ".login" do
62
+ it "should return a response object" do
63
+ @session.login("mark","mysecret").should be_kind_of(Pabx::Response)
64
+ end
65
+
66
+ it "should return a response with type Login" do
67
+ @session.login("mark","mysecret").type.should eq("Login")
68
+ end
69
+
70
+ describe "if everything is ok" do
71
+ it "should return a successfull response" do
72
+ @session.login("mark","mysecret").success.should be_true
73
+ end
74
+
75
+ it "should fill the ActionID" do
76
+ @session.login("mark","mysecret").action_id.should_not be_nil
77
+ end
78
+
79
+ it "should fill the Message" do
80
+ @session.login("mark","mysecret").message.should_not be_nil
81
+ end
82
+ end
83
+
84
+ describe "if credentials are wrong" do
85
+ it "should not return a successfull response" do
86
+ @session.login("mark","wrong").success.should be_false
87
+ end
88
+ end
89
+ end
90
+
91
+ describe ".core_show_channels" do
92
+ it "should return a response object" do
93
+ @session.login("mark","mysecret")
94
+ @session.core_show_channels.should be_kind_of(Pabx::Response)
95
+ end
96
+
97
+ it "should contain additional data about channels" do
98
+ @session.login("mark","mysecret")
99
+ @session.core_show_channels.data[:channels].should_not be_nil
100
+ end
101
+ end
102
+
103
+ describe ".parked_calls" do
104
+ it "should return a response object" do
105
+ @session.login("mark","mysecret")
106
+ @session.parked_calls.should be_kind_of(Pabx::Response)
107
+ end
108
+
109
+ it "should contain additional data about parked calls" do
110
+ @session.login("mark","mysecret")
111
+ @session.parked_calls.data[:calls].should_not be_nil
112
+ end
113
+ end
114
+
115
+ describe ".originate" do
116
+ it "should return a response object" do
117
+ @session.login("mark","mysecret")
118
+ @session.originate("SIP/9100","OUTGOING","123456","1","queue=SIP/1000&SIP/1001").should be_kind_of(RubyAsterisk::Response)
119
+ end
120
+ end
121
+
122
+ describe ".command" do
123
+ it "should return a response object" do
124
+ @session.login("mark","mysecret")
125
+ @session.command("meetme list").should be_kind_of(Pabx::Response)
126
+ end
127
+ end
128
+
129
+ describe ".meet_me_list" do
130
+ it "should return a response object" do
131
+ @session.login("mark","mysecret")
132
+ @session.meet_me_list.should be_kind_of(Pabx::Response)
133
+ end
134
+ end
135
+
136
+ describe ".extension_state" do
137
+ it "should return a response object" do
138
+ @session.login("mark","mysecret")
139
+ @session.extension_state("9100","HINT").should be_kind_of(Pabx::Response)
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ describe Pabx::Request do
4
+
5
+ describe "of type Originate" do
6
+ it "should set a Variable option if set" do
7
+ request = Pabx::Request.new("Originate",{"Channel" => "1234", "Context" => "test", "Exten" => "1", "Priority" => "1", "Callerid" => "1234", "Timeout" => "30000", "Variable" => "var1=15" })
8
+ request.commands.include?("Variable: var1=15\r\n").should_not be_nil
9
+ end
10
+
11
+ it "should not set a Variable option if not set" do
12
+ request = Pabx::Request.new("Originate",{"Channel" => "1234", "Context" => "test", "Exten" => "1", "Priority" => "1", "Callerid" => "1234", "Timeout" => "30000", "Variable" => nil })
13
+ request.commands.include?("Variable: var=15").should==false
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,157 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ describe Pabx::Response do
4
+
5
+ def empty_core_show_channels_response
6
+ "Event: CoreShowChannelsComplete
7
+ EventList: Complete
8
+ ListItems: 1
9
+ ActionID: 839"
10
+ end
11
+
12
+ def core_show_channels_response
13
+ "Event: CoreShowChannel
14
+ ActionID: 839
15
+ Channel: SIP/195.62.226.4-00000025
16
+ UniqueID: 1335448133.61
17
+ Context: incoming
18
+ Extension: s
19
+ Priority: 1
20
+ ChannelState: 6
21
+ ChannelStateDesc: Up
22
+ Application: Parked Call
23
+ ApplicationData:
24
+ CallerIDnum: 123456
25
+ CallerIDname:
26
+ ConnectedLineNum:
27
+ ConnectedLineName:
28
+ Duration: 00:00:05
29
+ AccountCode:
30
+ BridgedChannel:
31
+ BridgedUniqueID:
32
+
33
+ Event: CoreShowChannelsComplete
34
+ EventList: Complete
35
+ ListItems: 1
36
+ ActionID: 839"
37
+ end
38
+
39
+ def parked_calls_response
40
+ "Event: ParkedCall
41
+ Parkinglot: default
42
+ Exten: 701
43
+ Channel: SIP/195.62.226.2-00000026
44
+ From: SIP/195.62.226.2-00000026
45
+ Timeout: 3
46
+ CallerIDNum: 123456
47
+ CallerIDName:
48
+ ConnectedLineNum:
49
+ ConnectedLineName:
50
+ ActionID: 899"
51
+ end
52
+
53
+ def originate_response
54
+ "Event: Dial
55
+ Privilege: call,all
56
+ SubEvent: End
57
+ Channel: SIP/9100-0000002b
58
+ UniqueID: 1335457364.68
59
+ DialStatus: CHANUNAVAIL"
60
+ end
61
+
62
+ def meet_me_list_response
63
+ "Event: MeetmeList
64
+ ActionID: 921
65
+ Conference: 1234
66
+ UserNumber: 1
67
+ CallerIDNum: 123456
68
+ CallerIDName: <no name>
69
+ ConnectedLineNum: <unknown>
70
+ ConnectedLineName: <no name>
71
+ Channel: SIP/195.62.226.18-0000000e
72
+ Admin: No
73
+ Role: Talk and listen
74
+ MarkedUser: No
75
+ Muted: No
76
+ Talking: Not monitored"
77
+ end
78
+
79
+ def extension_state_response
80
+ "Response: Success
81
+ ActionID: 180
82
+ Message: Extension Status
83
+ Exten: 9100
84
+ Context: HINT
85
+ Hint: SIP/9100
86
+ Status: 0"
87
+ end
88
+
89
+ describe ".new" do
90
+
91
+ describe "receiving a Core Show Channels request" do
92
+ it "should parse correctly data coming from Soft Switch about channels" do
93
+ @response = Pabx::Response.new("CoreShowChannels",core_show_channels_response)
94
+ @response.data[:channels].should_not be_empty
95
+ end
96
+
97
+ it "should correctly fill the fields" do
98
+ @response = Pabx::Response.new("CoreShowChannels",core_show_channels_response)
99
+ @response.data[:channels][0]["CallerIDnum"].should eq("123456")
100
+ end
101
+
102
+ it "should have no channels if answer is empty" do
103
+ @response = Pabx::Response.new("CoreShowChannels",empty_core_show_channels_response)
104
+ @response.data[:channels].count.should eq(0)
105
+ end
106
+ end
107
+
108
+ describe "receiving a Parked Calls request" do
109
+ it "should parse correctly data coming from Asterisk about calls" do
110
+ @response = Pabx::Response.new("ParkedCalls",parked_calls_response)
111
+ @response.data[:calls].should_not be_empty
112
+ end
113
+
114
+ it "should correctly fill the fields" do
115
+ @response = Pabx::Response.new("ParkedCalls",parked_calls_response)
116
+ @response.data[:calls][0]["Exten"].should eq("701")
117
+ end
118
+ end
119
+
120
+ describe "receiving a Originate request" do
121
+ it "should parse correctly data coming from Asterisk about the call" do
122
+ @response = Pabx::Response.new("Originate",originate_response)
123
+ @response.data[:dial].should_not be_empty
124
+ end
125
+
126
+ it "should correctly fill the fields" do
127
+ @response = Pabx::Response.new("Originate",originate_response)
128
+ @response.data[:dial][0]["UniqueID"].should eq("1335457364.68")
129
+ end
130
+ end
131
+
132
+ describe "receiving a MeetMeList request" do
133
+ it "should parse correctly data coming from Asterisk about the conference room" do
134
+ @response = Pabx::Response.new("MeetMeList",meet_me_list_response)
135
+ @response.data[:rooms].should_not be_empty
136
+ end
137
+
138
+ it "should correctly fill the fields" do
139
+ @response = Pabx::Response.new("MeetMeList",meet_me_list_response)
140
+ @response.data[:rooms][0]["Conference"].should eq("1234")
141
+ end
142
+ end
143
+
144
+ describe "receiving a ExtensionState request" do
145
+ it "should parse correctly data coming from Asterisk about the state of the extension" do
146
+ @response = Pabx::Response.new("ExtensionState",extension_state_response)
147
+ @response.data[:hints].should_not be_empty
148
+ end
149
+
150
+ it "should correctly fill the fields" do
151
+ @response = Pabx::Response.new("ExtensionState",extension_state_response)
152
+ @response.data[:hints][0]["Status"].should eq("0")
153
+ @response.data[:hints][0]["DescriptiveStatus"].should eq("Idle")
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ require 'pabx'
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pabx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Elias Hasnat
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Add support to your ruby or rails projects to IMS SoftSwitch Manager
42
+ email:
43
+ - android.hasnat@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .rspec
49
+ - Gemfile
50
+ - Rakefile
51
+ - lib/pabx.rb
52
+ - lib/pabx/request.rb
53
+ - lib/pabx/response.rb
54
+ - lib/pabx/version.rb
55
+ - pabx.gemspec
56
+ - spec/pabx/pabx_spec.rb
57
+ - spec/pabx/request_spec.rb
58
+ - spec/pabx/response_spec.rb
59
+ - spec/spec_helper.rb
60
+ homepage: http://github.com/claymodel/telephony/pabx
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project: pabx
80
+ rubygems_version: 2.0.7
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: IMS SoftSwitch Manager - Ruby
84
+ test_files:
85
+ - spec/pabx/pabx_spec.rb
86
+ - spec/pabx/request_spec.rb
87
+ - spec/pabx/response_spec.rb
88
+ - spec/spec_helper.rb
89
+ has_rdoc: