pabx 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: