freeswitcher 0.4.10 → 0.5.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.
@@ -17,7 +17,8 @@ module FSR
17
17
  def run(api_method = :api)
18
18
  orig_command = "%s %s" % [api_method, raw]
19
19
  Log.debug "saying #{orig_command}"
20
- @fs_socket.say(orig_command)
20
+ resp = @fs_socket.say(orig_command)
21
+ resp["body"].match(%r{^error/}) ? nil : resp["body"]
21
22
  end
22
23
 
23
24
  # This method builds the API command to send to the freeswitch event socket
@@ -0,0 +1,14 @@
1
+ module FSR
2
+ module App
3
+ module FileMethods
4
+ def test_files *files
5
+ files.each do |file|
6
+ next unless file =~ /^\//
7
+ next if File.open(file){|io| io.stat.file? }
8
+ raise(ArgumentError, "No such file - #{file}")
9
+ end
10
+ true
11
+ end
12
+ end
13
+ end
14
+ end
@@ -18,6 +18,7 @@ module FSR
18
18
  @subscribed_events = []
19
19
  @subscribed_sub_events = []
20
20
  @hooks = {}
21
+ @output_format = args[:output_format] || "json"
21
22
  end
22
23
 
23
24
  # post_init is called upon each "new" socket connection.
@@ -63,7 +64,21 @@ module FSR
63
64
  # param content content from standard Header and Content protocol
64
65
  def receive_request(header, content)
65
66
  hash_header = headers_2_hash(header)
66
- hash_content = headers_2_hash(content)
67
+ case hash_header[:content_type]
68
+ when "command/reply"
69
+ return handle_reply(header, content)
70
+ when "text/event-plain"
71
+ hash_content = headers_2_hash(content)
72
+ when "text/event-json"
73
+ require "json"
74
+ hash_content = JSON.parse(content)
75
+ when "auth/request"
76
+ return
77
+ else
78
+ FSR::Log.warn "Unhandled request (#{header}, #{content})"
79
+ return
80
+ end
81
+ hash_content ||= {}
67
82
  event = HeaderAndContentResponse.new({:headers => hash_header, :content => hash_content})
68
83
  event_name = event.content[:event_name].to_s.strip
69
84
  unless event_name.empty?
@@ -109,9 +124,9 @@ module FSR
109
124
  @subscribed_events << event
110
125
  @subscribed_sub_events += sub_events
111
126
  if custom = @subscribed_events.delete(:CUSTOM)
112
- say "event plain #{@subscribed_events.join(" ")} CUSTOM #{@subscribed_sub_events.join(" ")}"
127
+ say "event #{@output_format} #{@subscribed_events.join(" ")} CUSTOM #{@subscribed_sub_events.join(" ")}"
113
128
  else
114
- say "event plain #{@subscribed_events.join(" ")}"
129
+ say "event #{@output_format} #{@subscribed_events.join(" ")}"
115
130
  end
116
131
  end
117
132
 
@@ -129,6 +144,15 @@ module FSR
129
144
  def on_event(event)
130
145
  event
131
146
  end
147
+
148
+ # handle_reply is the callback method when a command_reply is received
149
+ #
150
+ # param header The header of the data
151
+ # param content The content of the data
152
+ # return [header, content]
153
+ def handle_reply(header, content)
154
+ [header, content]
155
+ end
132
156
 
133
157
  # add_event_hook adds an Event to listen for. When that Event is triggered, it will call the defined block
134
158
  #
data/lib/fsr/model.rb ADDED
@@ -0,0 +1,11 @@
1
+ module FSR
2
+ module Model
3
+ def to_hash
4
+ Hash[fields.map { |f| [f,self.send(f.to_sym)] }]
5
+ end
6
+
7
+ def inspect
8
+ "<##{self.object_id} #{self.class} - #{self.to_hash}>"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "../model"
2
+ module FSR
3
+ module Model
4
+ class Agent
5
+ attr_reader :fields, :extension, :full_name
6
+ include FSR::Model
7
+
8
+ def initialize(headers, *data)
9
+ @fields = headers
10
+ @fields.each_with_index do |h,i|
11
+ (class << self; self; end).send(:define_method,h.to_sym) { data[i] }
12
+ end
13
+
14
+ @extension, @full_name = name.split("-", 2)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,47 +1,12 @@
1
1
  module FSR
2
2
  module Model
3
3
  class Call
4
- attr_reader :created, :created_epoch, :function, :caller_id_name, :caller_id_number,
5
- :caller_destination, :caller_channel_name, :caller_uuid, :callee_id_name,
6
- :callee_id_number, :callee_destination, :callee_channel_name, :callee_uuid
7
- def initialize(created,
8
- created_epoch,
9
- function,
10
- caller_cid_name,
11
- caller_cid_num,
12
- caller_dest_num,
13
- caller_chan_name,
14
- caller_uuid,
15
- callee_cid_name,
16
- callee_cid_num,
17
- callee_dest_num,
18
- callee_chan_name,
19
- callee_uuid)
20
- @created,
21
- @created_epoch,
22
- @function,
23
- @caller_id_name,
24
- @caller_id_number,
25
- @caller_destination,
26
- @caller_chan_name,
27
- @caller_uuid,
28
- @callee_id_name,
29
- @callee_id_number,
30
- @callee_destination,
31
- @callee_channel_name,
32
- @callee_uuid = created,
33
- created_epoch,
34
- function,
35
- caller_cid_name,
36
- caller_cid_num,
37
- caller_dest_num,
38
- caller_chan_name,
39
- caller_uuid,
40
- callee_cid_name,
41
- callee_cid_num,
42
- callee_dest_num,
43
- callee_chan_name,
44
- callee_uuid
4
+ attr_reader :fields
5
+ def initialize(headers, *data)
6
+ @fields = headers
7
+ @fields.each_with_index do |h,i|
8
+ (class << self; self; end).send(:define_method,h.to_sym) { data[i] }
9
+ end
45
10
  end
46
11
  end
47
12
  end
@@ -0,0 +1,13 @@
1
+ module FSR
2
+ module Model
3
+ class Channel
4
+ attr_reader :fields
5
+ def initialize(headers, *data)
6
+ @fields = headers
7
+ @fields.each_with_index do |h,i|
8
+ (class << self; self; end).send(:define_method,h.to_sym) { data[i] }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module FSR
2
+ module Model
3
+ class Enum
4
+ attr_reader :offered_routes, :supported_routes, :order, :pref, :service, :route
5
+ def initialize(offered_routes,
6
+ supported_routes,
7
+ order,
8
+ pref,
9
+ service,
10
+ route)
11
+ @offered_routes,
12
+ @supported_routes,
13
+ @order,
14
+ @pref,
15
+ @service,
16
+ @route,
17
+ = offered_routes,
18
+ supported_routes,
19
+ order,
20
+ pref,
21
+ service,
22
+ route
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "../model"
2
+ module FSR
3
+ module Model
4
+ class Queue
5
+ attr_reader :fields
6
+ include FSR::Model
7
+ def initialize(headers, *data)
8
+ @fields = headers
9
+ @fields.each_with_index do |h,i|
10
+ (class << self; self; end).send(:define_method,h.to_sym) { data[i] }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "../model"
2
+ module FSR
3
+ module Model
4
+ class Tier
5
+ attr_reader :fields
6
+ include FSR::Model
7
+ def initialize(headers, *data)
8
+ @fields = headers
9
+ @fields.each_with_index do |h,i|
10
+ (class << self; self; end).send(:define_method,h.to_sym) { data[i] }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,83 @@
1
+ # Copyright (c) 2008-2009 The Rubyists, LLC (effortless systems) <rubyists@rubyists.com>
2
+ # Distributed under the terms of the MIT license.
3
+ # The full text can be found in the LICENSE file included with this software
4
+ #
5
+ module FSR
6
+ module Rack
7
+ class Middleware
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ params = ::Rack::Request.new(env)
14
+ return @app.call(env) unless params["section"]
15
+
16
+ path = params["section"] + "/"
17
+
18
+ path << case path
19
+ when "dialplan/"
20
+ dp_req(params)
21
+ when "directory/"
22
+ dir_req(params)
23
+ when "configuration/"
24
+ conf_req(params)
25
+ end
26
+
27
+ env["PATH_INFO"] = "#{env['PATH_INFO']}/#{path}".squeeze('/')
28
+ @app.call(env)
29
+ end
30
+
31
+ private
32
+ def dp_req(params)
33
+ s = [params["Caller-Context"]]
34
+ s << params["Caller-Destination-Number"]
35
+ s << params["Caller-Caller-ID-Number"]
36
+ s.compact.join("/")
37
+ end
38
+
39
+ def dir_req(params)
40
+ s = []
41
+ if params["purpose"]
42
+ s << params["purpose"].gsub("-","_")
43
+ s << params["sip_profile"]
44
+ elsif params["action"] && params["action"] == "sip_auth"
45
+ s << "register"
46
+ s << params["sip_profile"]
47
+ s << params["sip_auth_username"]
48
+ elsif params["user"]
49
+ if params["action"] == "message-count"
50
+ s << "messages"
51
+ s << params["user"]
52
+ s << params["key_value"] if params["tag_name"] == "domain"
53
+ elsif params["Event-Calling-Function"]
54
+ case params["Event-Calling-Function"].to_s
55
+ when /voicemail/
56
+ s << "voicemail"
57
+ s << (params["sip_profile"] || "default")
58
+ s << params["user"]
59
+ when "user_outgoing_channel"
60
+ s << "user_outgoing"
61
+ s << params["user"]
62
+ s << params["domain"] if params["domain"]
63
+ when "user_data_function"
64
+ s << "user_data"
65
+ s << params["user"]
66
+ s << params["domain"] if params["domain"]
67
+ end
68
+ end
69
+ end
70
+ s.join("/")
71
+ end
72
+
73
+ def conf_req(params)
74
+ s = []
75
+ if params["key_name"] == "name"
76
+ s << params["key_value"]
77
+ end
78
+ s.join("/")
79
+ end
80
+
81
+ end
82
+ end
83
+ end
data/spec/fsr/app.rb CHANGED
@@ -4,5 +4,7 @@ describe "Basic FSR::App module" do
4
4
  require "fsr/app"
5
5
  FSA.should == FSR::App
6
6
  end
7
+
8
+
7
9
  end
8
10
 
@@ -49,3 +49,18 @@ describe "Testing FSR::App::PlayAndGetDigits" do
49
49
  end
50
50
 
51
51
  end
52
+
53
+ describe "Testing FSR::App::PlayAndGetDigits - handling of non-existant files" do
54
+
55
+ it "Raise if files specifed absolutely aren't present" do
56
+ lambda { FSR::App::PlayAndGetDigits.new("/path/soundfile.wav", "/path/invalid.wav") }.
57
+ should.raise(Errno::ENOENT)
58
+ end
59
+
60
+ it "Not raise if files specifed absolutely aren't present" do
61
+ file_name = File.expand_path(__FILE__)
62
+ lambda { FSR::App::PlayAndGetDigits.new(file_name, "invalid.wav") }.
63
+ should.not.raise(Errno::ENOENT)
64
+ end
65
+
66
+ end
@@ -9,3 +9,18 @@ describe "Testing FSR::App::Playback" do
9
9
  end
10
10
 
11
11
  end
12
+
13
+ describe "Testing FSR::App::Playback - handling of non-existant files" do
14
+
15
+ it "Raise if files specifed absolutely aren't present" do
16
+ lambda { FSR::App::Playback.new("/path/non-existing.wav") }.
17
+ should.raise(Errno::ENOENT)
18
+ end
19
+
20
+ it "Not raise if not an absolute file" do
21
+ file_name = File.expand_path(__FILE__)
22
+ lambda { FSR::App::Playback.new("shout://scfire-ntc-aa01.stream.aol.com/stream/1035") }.
23
+ should.not.raise(Errno::ENOENT)
24
+ end
25
+
26
+ end
@@ -0,0 +1,58 @@
1
+ require './spec/helper'
2
+ require "fsr/cmd"
3
+ FSR::Cmd.load_command("call_center")
4
+
5
+ describe "Testing FSR::Cmd::Callcenter" do
6
+ ## Call Center ##
7
+ # Interface to mod_callcenter
8
+ it "FSR::Cmd::Callcenter should list agents " do
9
+ cmd = FSR::Cmd::CallCenter.new nil, :agent
10
+ cmd.list.raw.should == "callcenter_config agent list"
11
+ end
12
+
13
+ it "FSR::Cmd::Callcenter should add an agent defaulting callback" do
14
+ cmd = FSR::Cmd::CallCenter.new nil, :agent
15
+ cmd.add("1000@default").raw.should == "callcenter_config agent add '1000@default' callback"
16
+ end
17
+
18
+ it "FSR::Cmd::Callcenter should add an agent uuidstandby set" do
19
+ cmd = FSR::Cmd::CallCenter.new nil, :agent
20
+ cmd.add("1000@default", "uuid-standby").raw.should == "callcenter_config agent add '1000@default' uuid-standby"
21
+ end
22
+
23
+ it "FSR::Cmd::Callcenter should delete an agent " do
24
+ cmd = FSR::Cmd::CallCenter.new nil, :agent
25
+ cmd.del("1000@default").raw.should == "callcenter_config agent del 1000@default"
26
+ end
27
+
28
+ it "FSR::Cmd::Callcenter should set an attribute of an agent " do
29
+ cmd = FSR::Cmd::CallCenter.new nil, :agent
30
+ cmd.set("1000@default", :contact, 'user/1000').raw.should == "callcenter_config agent set contact '1000@default' 'user/1000'"
31
+ end
32
+
33
+ it "FSR::Cmd::Callcenter should set an attribute with dashes in it on an agent " do
34
+ cmd = FSR::Cmd::CallCenter.new nil, :agent
35
+ cmd.set("1000@default", :max_no_answer, 10).raw.should == "callcenter_config agent set max_no_answer '1000@default' 10"
36
+ end
37
+
38
+ it "FSR::Cmd::Callcenter should list tiers " do
39
+ cmd = FSR::Cmd::CallCenter.new nil, :tier
40
+ cmd.list("helpdesk@default").raw.should == "callcenter_config tier list helpdesk@default"
41
+ end
42
+
43
+ it "FSR::Cmd::Callcenter should add a tier " do
44
+ cmd = FSR::Cmd::CallCenter.new nil, :tier
45
+ cmd.add("1000@default", "helpdesk@default").raw.should == "callcenter_config tier add helpdesk@default 1000@default 1"
46
+ end
47
+
48
+ it "FSR::Cmd::Callcenter should delete a tier " do
49
+ cmd = FSR::Cmd::CallCenter.new nil, :tier
50
+ cmd.del("1000@default", "helpdesk@default").raw.should == "callcenter_config tier del helpdesk@default 1000@default"
51
+ end
52
+
53
+ it "FSR::Cmd::Callcenter should set an attribute of a tier entry " do
54
+ cmd = FSR::Cmd::CallCenter.new nil, :tier
55
+ cmd.set("1000@default", "helpdesk@default", :state, "Logged Out").raw.should == "callcenter_config tier set state helpdesk@default 1000@default 'Logged Out'"
56
+ end
57
+
58
+ end
@@ -6,8 +6,8 @@ describe "Testing FSR::Cmd::Calls" do
6
6
  ## Calls ##
7
7
  # Interface to calls
8
8
  it "FSR::Cmd::Calls should send show calls" do
9
- sofia = FSR::Cmd::Calls.new
10
- sofia.raw.should == "show calls"
9
+ cmd = FSR::Cmd::Calls.new
10
+ cmd.raw.should == "show calls"
11
11
  end
12
12
 
13
13
  end