signal_api 0.0.1
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.
- data/.gitignore +19 -0
 - data/.travis.yml +5 -0
 - data/Gemfile +4 -0
 - data/LICENSE +22 -0
 - data/README.md +43 -0
 - data/Rakefile +49 -0
 - data/lib/signal_api/carrier.rb +43 -0
 - data/lib/signal_api/contact.rb +60 -0
 - data/lib/signal_api/core_ext/array.rb +7 -0
 - data/lib/signal_api/core_ext/hash.rb +7 -0
 - data/lib/signal_api/core_ext/nil_class.rb +7 -0
 - data/lib/signal_api/core_ext/string.rb +7 -0
 - data/lib/signal_api/coupon_group.rb +47 -0
 - data/lib/signal_api/deliver_sms.rb +54 -0
 - data/lib/signal_api/exceptions.rb +19 -0
 - data/lib/signal_api/list.rb +224 -0
 - data/lib/signal_api/mocks/api_mock.rb +70 -0
 - data/lib/signal_api/mocks/contact.rb +13 -0
 - data/lib/signal_api/mocks/deliver_sms.rb +14 -0
 - data/lib/signal_api/mocks/list.rb +19 -0
 - data/lib/signal_api/mocks/short_url.rb +9 -0
 - data/lib/signal_api/segment.rb +161 -0
 - data/lib/signal_api/short_url.rb +56 -0
 - data/lib/signal_api/signal_http_api.rb +49 -0
 - data/lib/signal_api/util/email_address.rb +10 -0
 - data/lib/signal_api/util/phone.rb +37 -0
 - data/lib/signal_api/version.rb +3 -0
 - data/lib/signal_api.rb +114 -0
 - data/signal_api.gemspec +27 -0
 - data/test/api/carrier_test.rb +43 -0
 - data/test/api/contact_test.rb +93 -0
 - data/test/api/coupon_group_test.rb +36 -0
 - data/test/api/deliver_sms_test.rb +66 -0
 - data/test/api/general_test.rb +26 -0
 - data/test/api/list_test.rb +261 -0
 - data/test/api/segment_test.rb +144 -0
 - data/test/api/short_url_test.rb +50 -0
 - data/test/mocks/contact_mock_test.rb +24 -0
 - data/test/mocks/deliver_sms_mock_test.rb +21 -0
 - data/test/mocks/list_mock_test.rb +33 -0
 - data/test/mocks/short_url_mock_test.rb +17 -0
 - data/test/test_helper.rb +20 -0
 - metadata +248 -0
 
| 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module ApiMock
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def self.included(base)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  base.extend(ClassMethods)
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                module ClassMethods
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @@mock_method_definitions = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @@mock_method_calls = {}
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def mock_method_calls
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @@mock_method_calls
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def mock_method_definitions
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @@mock_method_definitions
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def mock_method(method, *parameter_names)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @@mock_method_definitions[method] = parameter_names
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @@mock_method_calls[method] = []
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    define_method method do |*args|
         
     | 
| 
      
 25 
     | 
    
         
            +
                      method_args = self.class.mock_method_definitions[method]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      called_args = {}
         
     | 
| 
      
 28 
     | 
    
         
            +
                      method_args.each_with_index do |method_arg, i|
         
     | 
| 
      
 29 
     | 
    
         
            +
                        called_args[method_arg] = args[i]
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                      additional_info_method = method.to_s + "_additional_info"
         
     | 
| 
      
 33 
     | 
    
         
            +
                      if self.class.method_defined?(additional_info_method)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        called_args.merge!(send(additional_info_method))
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      self.class.mock_method_calls[method] << called_args
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def mock_class_method(method, *parameter_names)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @@mock_method_definitions[method] = parameter_names
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @@mock_method_calls[method] = []
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    (class << self; self; end).instance_eval do
         
     | 
| 
      
 46 
     | 
    
         
            +
                      define_method method do |*args|
         
     | 
| 
      
 47 
     | 
    
         
            +
                        method_args = mock_method_definitions[method]
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        called_args = {}
         
     | 
| 
      
 50 
     | 
    
         
            +
                        method_args.each_with_index do |method_arg, i|
         
     | 
| 
      
 51 
     | 
    
         
            +
                          called_args[method_arg] = args[i]
         
     | 
| 
      
 52 
     | 
    
         
            +
                        end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                        additional_info_method = method.to_s + "_additional_info"
         
     | 
| 
      
 55 
     | 
    
         
            +
                        if method_defined?(additional_info_method)
         
     | 
| 
      
 56 
     | 
    
         
            +
                          called_args.merge!(send(additional_info_method))
         
     | 
| 
      
 57 
     | 
    
         
            +
                        end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                        mock_method_calls[method] << called_args
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def clear_mock_data
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @@mock_method_calls.keys.each { |k| @@mock_method_calls[k] = [] }
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'signal_api/mocks/api_mock'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 4 
     | 
    
         
            +
              class List
         
     | 
| 
      
 5 
     | 
    
         
            +
                include ApiMock
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                mock_method(:create_subscription, :subscription_type, :contact, :options)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def create_subscription_additional_info
         
     | 
| 
      
 10 
     | 
    
         
            +
                  { :list_id => @list_id }
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                mock_method(:destroy_subscription, :subscription_type, :contact)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def destroy_subscription_additional_info
         
     | 
| 
      
 16 
     | 
    
         
            +
                  { :list_id => @list_id }
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,161 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # The type of segment
         
     | 
| 
      
 4 
     | 
    
         
            +
              class SegmentType
         
     | 
| 
      
 5 
     | 
    
         
            +
                DYNAMIC = "DYNAMIC"
         
     | 
| 
      
 6 
     | 
    
         
            +
                STATIC = "SEGMENT"
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # Represents a user to be added to a segment
         
     | 
| 
      
 10 
     | 
    
         
            +
              class SegmentUser
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_reader :mobile_phone, :email_address, :user_data
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Create a new segment on the Signal platform.
         
     | 
| 
      
 14 
     | 
    
         
            +
                #
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @param [String] identifying_attribute The mobile phone or email address of the user
         
     | 
| 
      
 16 
     | 
    
         
            +
                # @param [Hash] user_data <b>Optional</b> A collection of key/value pairs to store along
         
     | 
| 
      
 17 
     | 
    
         
            +
                #                         with this user's segment record for later use
         
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(identifying_attribute, user_data={})
         
     | 
| 
      
 19 
     | 
    
         
            +
                  if Phone.valid?(identifying_attribute)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @mobile_phone = identifying_attribute
         
     | 
| 
      
 21 
     | 
    
         
            +
                  elsif EmailAddress.valid?(identifying_attribute)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @email_address = identifying_attribute
         
     | 
| 
      
 23 
     | 
    
         
            +
                  else
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise InvalidParameterException.new("identifying_attribute must be a valid mobile phone number or email address")
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  @user_data = user_data unless user_data.empty?
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Create, manage, and add users to a segment.
         
     | 
| 
      
 32 
     | 
    
         
            +
              class Segment < SignalHttpApi
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # The name of the segment
         
     | 
| 
      
 35 
     | 
    
         
            +
                attr_reader :name
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # The description of the segment
         
     | 
| 
      
 38 
     | 
    
         
            +
                attr_reader :description
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # The ID of the segment
         
     | 
| 
      
 41 
     | 
    
         
            +
                attr_reader :id
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                # The account_id of the segment
         
     | 
| 
      
 44 
     | 
    
         
            +
                attr_reader :account_id
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # Type type of the segment
         
     | 
| 
      
 47 
     | 
    
         
            +
                attr_reader :segment_type
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def initialize(id, name=nil, description=nil, segment_type=nil, account_id=nil)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @description = description
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @id = id
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @account_id = account_id
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  if segment_type == "DYNAMIC"
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @segment_type = SegmentType::DYNAMIC
         
     | 
| 
      
 58 
     | 
    
         
            +
                  elsif segment_type == "SEGMENT"
         
     | 
| 
      
 59 
     | 
    
         
            +
                    @segment_type = SegmentType::STATIC
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                # Create a new segment on the Signal platform.
         
     | 
| 
      
 64 
     | 
    
         
            +
                #
         
     | 
| 
      
 65 
     | 
    
         
            +
                # @param [String] name The name of the segment
         
     | 
| 
      
 66 
     | 
    
         
            +
                # @param [String] description A description of the segment
         
     | 
| 
      
 67 
     | 
    
         
            +
                # @param [SegmentType] segment_type The type of the segment
         
     | 
| 
      
 68 
     | 
    
         
            +
                #
         
     | 
| 
      
 69 
     | 
    
         
            +
                # @return [Segment] A Segment object representing the segment on the Signal platform
         
     | 
| 
      
 70 
     | 
    
         
            +
                def self.create(name, description, segment_type)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  if name.blank? || description.blank? || segment_type.blank?
         
     | 
| 
      
 72 
     | 
    
         
            +
                    raise InvalidParameterException.new("name, description, and segment_type are all required")
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  unless [SegmentType::DYNAMIC, SegmentType::STATIC].include?(segment_type)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    raise InvalidParameterException.new("Invalid segment type")
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  builder = Builder::XmlMarkup.new
         
     | 
| 
      
 80 
     | 
    
         
            +
                  body = builder.filter_group do |filter_group|
         
     | 
| 
      
 81 
     | 
    
         
            +
                    filter_group.description(description)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    filter_group.name(name)
         
     | 
| 
      
 83 
     | 
    
         
            +
                    filter_group.filter_group_type(segment_type)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  SignalApi.logger.info "Attempting to create a segment: name => #{name}, description => \"#{description}\", type = #{segment_type}}"
         
     | 
| 
      
 87 
     | 
    
         
            +
                  SignalApi.logger.debug "Segment data: #{body}"
         
     | 
| 
      
 88 
     | 
    
         
            +
                  with_retries do
         
     | 
| 
      
 89 
     | 
    
         
            +
                    response = post("/api/filter_groups/create.xml",
         
     | 
| 
      
 90 
     | 
    
         
            +
                                    :body => body,
         
     | 
| 
      
 91 
     | 
    
         
            +
                                    :format => :xml,
         
     | 
| 
      
 92 
     | 
    
         
            +
                                    :headers => common_headers)
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                    if response.code == 200
         
     | 
| 
      
 95 
     | 
    
         
            +
                      data = response.parsed_response['subscription_list_filter_group']
         
     | 
| 
      
 96 
     | 
    
         
            +
                      new(data['id'], data['name'], data['description'], lookup_segment_type(data['filter_group_type_id']), data['account_id'])
         
     | 
| 
      
 97 
     | 
    
         
            +
                    else
         
     | 
| 
      
 98 
     | 
    
         
            +
                      handle_api_failure(response)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                # Add mobile phone numbers to a segment.
         
     | 
| 
      
 104 
     | 
    
         
            +
                #
         
     | 
| 
      
 105 
     | 
    
         
            +
                # @param [Array<SegmentUser>] segment_users An array of SegmentUsers to add to the segment
         
     | 
| 
      
 106 
     | 
    
         
            +
                # @return [Hash] A hash containing some stats regarding the operation
         
     | 
| 
      
 107 
     | 
    
         
            +
                def add_users(segment_users)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  if segment_users.blank?
         
     | 
| 
      
 109 
     | 
    
         
            +
                    raise InvalidParameterException.new("An array of SegmentUser objects must be provided")
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  builder = Builder::XmlMarkup.new
         
     | 
| 
      
 113 
     | 
    
         
            +
                  body = builder.users(:type => :array) do |users|
         
     | 
| 
      
 114 
     | 
    
         
            +
                    segment_users.each do |segment_user|
         
     | 
| 
      
 115 
     | 
    
         
            +
                      users.user do |user|
         
     | 
| 
      
 116 
     | 
    
         
            +
                        user.mobile_phone(segment_user.mobile_phone) if segment_user.mobile_phone
         
     | 
| 
      
 117 
     | 
    
         
            +
                        user.email(segment_user.email_address) if segment_user.email_address
         
     | 
| 
      
 118 
     | 
    
         
            +
                        user.user_data(segment_user.user_data) if segment_user.user_data
         
     | 
| 
      
 119 
     | 
    
         
            +
                      end
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  SignalApi.logger.info "Attempting to add users to segment #{@id}"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  self.class.with_retries do
         
     | 
| 
      
 125 
     | 
    
         
            +
                    response = self.class.post("/api/filter_segments/#{@id}/update.xml",
         
     | 
| 
      
 126 
     | 
    
         
            +
                                               :body => body,
         
     | 
| 
      
 127 
     | 
    
         
            +
                                               :format => :xml,
         
     | 
| 
      
 128 
     | 
    
         
            +
                                               :headers => self.class.common_headers)
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                    if response.code == 200
         
     | 
| 
      
 131 
     | 
    
         
            +
                      data = response.parsed_response['subscription_list_segment_results']
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                      if data['users_not_found'] && data['users_not_found']['user_not_found']
         
     | 
| 
      
 134 
     | 
    
         
            +
                        if data['users_not_found']['user_not_found'].respond_to?(:join)
         
     | 
| 
      
 135 
     | 
    
         
            +
                          SignalApi.logger.warn data['users_not_found']['user_not_found'].join(", ")
         
     | 
| 
      
 136 
     | 
    
         
            +
                        else
         
     | 
| 
      
 137 
     | 
    
         
            +
                          SignalApi.logger.warn data['users_not_found']['user_not_found']
         
     | 
| 
      
 138 
     | 
    
         
            +
                        end
         
     | 
| 
      
 139 
     | 
    
         
            +
                      end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                      { :total_users_processed => (data['total_users_processed'] || 0).to_i,
         
     | 
| 
      
 142 
     | 
    
         
            +
                        :total_users_added     => (data['total_users_added'] || 0).to_i,
         
     | 
| 
      
 143 
     | 
    
         
            +
                        :total_users_not_found => (data['total_users_not_found'] || 0).to_i,
         
     | 
| 
      
 144 
     | 
    
         
            +
                        :total_duplicate_users => (data['total_duplicate_users'] || 0).to_i }
         
     | 
| 
      
 145 
     | 
    
         
            +
                    else
         
     | 
| 
      
 146 
     | 
    
         
            +
                      self.class.handle_api_failure(response)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    end
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
                end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                private
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                def self.lookup_segment_type(segment_type_id)
         
     | 
| 
      
 154 
     | 
    
         
            +
                  case segment_type_id
         
     | 
| 
      
 155 
     | 
    
         
            +
                  when 1 then SegmentType::DYNAMIC
         
     | 
| 
      
 156 
     | 
    
         
            +
                  when 2 then SegmentType::STATIC
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # Manage short URLs via Signal's URL shortening service
         
     | 
| 
      
 4 
     | 
    
         
            +
              class ShortUrl < SignalHttpApi
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # The shortened URL
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :short_url
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # The target URL that was shortened
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :target_url
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # The ID of the shortend URL on the Signal platform
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_reader :id
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                # The domain of the short URL
         
     | 
| 
      
 16 
     | 
    
         
            +
                attr_reader :domain
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(id, target_url, short_url, domain)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @id = id
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @target_url = target_url
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @short_url = short_url
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @domain = domain
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # Create a short URL for the provided target URL
         
     | 
| 
      
 26 
     | 
    
         
            +
                #
         
     | 
| 
      
 27 
     | 
    
         
            +
                # @param [String] target The target URL that is to be shortened
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @param [String] domain The short URL domain to use
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @return [ShortUrl] A ShortUrl object representing the short URL on the Signal platform
         
     | 
| 
      
 31 
     | 
    
         
            +
                def self.create(target, domain)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  body = <<-END
         
     | 
| 
      
 33 
     | 
    
         
            +
            <short_url>
         
     | 
| 
      
 34 
     | 
    
         
            +
              <target_url><![CDATA[#{target}]]></target_url>
         
     | 
| 
      
 35 
     | 
    
         
            +
              <domain_id>1</domain_id>
         
     | 
| 
      
 36 
     | 
    
         
            +
            </short_url>
         
     | 
| 
      
 37 
     | 
    
         
            +
                  END
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  SignalApi.logger.info "Attempting to create a short URL for #{target}"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  with_retries do
         
     | 
| 
      
 41 
     | 
    
         
            +
                    response = post('/api/short_urls.xml',
         
     | 
| 
      
 42 
     | 
    
         
            +
                                    :body => body,
         
     | 
| 
      
 43 
     | 
    
         
            +
                                    :format => :xml,
         
     | 
| 
      
 44 
     | 
    
         
            +
                                    :headers => common_headers)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    if response.code == 201
         
     | 
| 
      
 47 
     | 
    
         
            +
                      data = response.parsed_response['short_url']
         
     | 
| 
      
 48 
     | 
    
         
            +
                      new(data['id'], data['target_url'], "http://#{domain}/#{data['slug']}", domain)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    else
         
     | 
| 
      
 50 
     | 
    
         
            +
                      handle_api_failure(response)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              class SignalHttpApi
         
     | 
| 
      
 3 
     | 
    
         
            +
                include HTTParty
         
     | 
| 
      
 4 
     | 
    
         
            +
                base_uri SignalApi.base_uri
         
     | 
| 
      
 5 
     | 
    
         
            +
                default_timeout SignalApi.timeout
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                protected
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def self.with_retries
         
     | 
| 
      
 10 
     | 
    
         
            +
                  if SignalApi.retries <= 0
         
     | 
| 
      
 11 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 12 
     | 
    
         
            +
                  else
         
     | 
| 
      
 13 
     | 
    
         
            +
                    retry_counter = 0
         
     | 
| 
      
 14 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 15 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 16 
     | 
    
         
            +
                    rescue NonRetryableException => e
         
     | 
| 
      
 17 
     | 
    
         
            +
                      SignalApi.logger.error "Non retryable exception: #{e.message}"
         
     | 
| 
      
 18 
     | 
    
         
            +
                      raise
         
     | 
| 
      
 19 
     | 
    
         
            +
                    rescue Exception => e
         
     | 
| 
      
 20 
     | 
    
         
            +
                      SignalApi.logger.error "Exception: #{e.message}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                      sleep 1
         
     | 
| 
      
 22 
     | 
    
         
            +
                      retry_counter += 1
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                      if retry_counter < SignalApi.retries
         
     | 
| 
      
 25 
     | 
    
         
            +
                        SignalApi.logger.warn "Re-trying..."
         
     | 
| 
      
 26 
     | 
    
         
            +
                        retry
         
     | 
| 
      
 27 
     | 
    
         
            +
                      else
         
     | 
| 
      
 28 
     | 
    
         
            +
                        SignalApi.logger.error "All retry attempts have failed."
         
     | 
| 
      
 29 
     | 
    
         
            +
                        raise
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def self.handle_api_failure(response)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  if response.code == 401
         
     | 
| 
      
 37 
     | 
    
         
            +
                    raise AuthFailedException.new("Authentication to the Signal platform failed.  Make sure your API key is correct.")
         
     | 
| 
      
 38 
     | 
    
         
            +
                  else
         
     | 
| 
      
 39 
     | 
    
         
            +
                    message = "API request failed with a response code of #{response.code}.  Respone body: #{response.body}"
         
     | 
| 
      
 40 
     | 
    
         
            +
                    SignalApi.logger.error message
         
     | 
| 
      
 41 
     | 
    
         
            +
                    raise ApiException.new(message)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def self.common_headers
         
     | 
| 
      
 46 
     | 
    
         
            +
                  { 'Content-Type' => 'application/xml', 'api_token' => SignalApi.api_key }
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Phone
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # Clean up phone number by removing special characters and country codes (if provided)
         
     | 
| 
      
 5 
     | 
    
         
            +
                def self.sanitize(phone_number)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  return nil if phone_number.nil?
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # Remove all non-numeric characters, ex - "=", "+", "(", ")", ".", "a", "A", " "
         
     | 
| 
      
 9 
     | 
    
         
            +
                  sanitized_phone_number = phone_number.gsub(/[^\d]/, '')
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  # Remove the US/Canadian country code (+1) if was provided
         
     | 
| 
      
 12 
     | 
    
         
            +
                  if sanitized_phone_number.length > 10 && sanitized_phone_number[0,1] == "1"
         
     | 
| 
      
 13 
     | 
    
         
            +
                    sanitized_phone_number = sanitized_phone_number[1, sanitized_phone_number.size]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  sanitized_phone_number
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def self.valid?(phone_number)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  return false if phone_number.nil? || phone_number.strip.empty?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  return false if self.sanitize(phone_number).size != 10
         
     | 
| 
      
 22 
     | 
    
         
            +
                  return true
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def self.format(phone_number, international=false)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  if Phone.valid?(phone_number)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    phone_number = Phone.sanitize(phone_number)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    unless international
         
     | 
| 
      
 29 
     | 
    
         
            +
                      "#{phone_number[0..2]}-#{phone_number[3..5]}-#{phone_number[6..9]}" # 312-343-1326
         
     | 
| 
      
 30 
     | 
    
         
            +
                    else
         
     | 
| 
      
 31 
     | 
    
         
            +
                      phone_number
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/signal_api.rb
    ADDED
    
    | 
         @@ -0,0 +1,114 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "httparty"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "builder"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "logger"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module SignalApi
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              # Interact with the Signal platform via its published web API.
         
     | 
| 
      
 8 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Set your Signal API key.
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                # @param [String] api_key Your Signal API key
         
     | 
| 
      
 13 
     | 
    
         
            +
                #
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 15 
     | 
    
         
            +
                #   SignalApi.api_key = 'foobar123456abcxyz77'
         
     | 
| 
      
 16 
     | 
    
         
            +
                def api_key=(api_key)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @api_key = api_key
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                # Get your Signal API key.
         
     | 
| 
      
 21 
     | 
    
         
            +
                def api_key
         
     | 
| 
      
 22 
     | 
    
         
            +
                  if @api_key.nil? || @api_key.strip == ""
         
     | 
| 
      
 23 
     | 
    
         
            +
                    raise InvalidApiKeyException.new("The api_key is blank or nil.  Use SignalApi.api_key= to set it.")
         
     | 
| 
      
 24 
     | 
    
         
            +
                  else
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @api_key
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # Set the logger to be used by Signal.
         
     | 
| 
      
 30 
     | 
    
         
            +
                #
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @param [Logger] logger The logger you would like Signal to use
         
     | 
| 
      
 32 
     | 
    
         
            +
                #
         
     | 
| 
      
 33 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 34 
     | 
    
         
            +
                #   SignalApi.logger = Rails.logger
         
     | 
| 
      
 35 
     | 
    
         
            +
                #   SignalApi.logger = Logger.new(STDERR)
         
     | 
| 
      
 36 
     | 
    
         
            +
                def logger=(logger)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @logger = logger
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Get the logger used by Signal.
         
     | 
| 
      
 41 
     | 
    
         
            +
                def logger
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @logger ||= Logger.new("/dev/null")
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                # Set the number of times failed API calls should be retried.  Defaults to 0.
         
     | 
| 
      
 46 
     | 
    
         
            +
                #
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @param [Fixnum] retries The number of times API calls should be retried
         
     | 
| 
      
 48 
     | 
    
         
            +
                #
         
     | 
| 
      
 49 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 50 
     | 
    
         
            +
                #   SignalApi.retries = 3
         
     | 
| 
      
 51 
     | 
    
         
            +
                def retries=(retries)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @retries = retries
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                # Get the number of times failed API calls should be retried.
         
     | 
| 
      
 56 
     | 
    
         
            +
                def retries
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @retries || 0
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                # Set the default timeout for API calls.  Defaults to 15 seconds.
         
     | 
| 
      
 61 
     | 
    
         
            +
                #
         
     | 
| 
      
 62 
     | 
    
         
            +
                # @param [Fixnum] timeout The default timeout (in seconds) for API calls
         
     | 
| 
      
 63 
     | 
    
         
            +
                #
         
     | 
| 
      
 64 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 65 
     | 
    
         
            +
                #   SignalApi.timeout = 5
         
     | 
| 
      
 66 
     | 
    
         
            +
                def timeout=(timeout)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  @timeout = timeout
         
     | 
| 
      
 68 
     | 
    
         
            +
                  api_classes.each { |clazz| clazz.default_timeout @timeout }
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # Get the default timeout for API calls.
         
     | 
| 
      
 72 
     | 
    
         
            +
                def timeout
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @timeout || 15
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 77 
     | 
    
         
            +
                def base_uri=(base_uri)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @base_uri = base_uri
         
     | 
| 
      
 79 
     | 
    
         
            +
                  api_classes.each { |clazz| clazz.base_uri @base_uri }
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 83 
     | 
    
         
            +
                def base_uri
         
     | 
| 
      
 84 
     | 
    
         
            +
                  @base_uri || "https://app.signalhq.com"
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                private
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def api_classes
         
     | 
| 
      
 90 
     | 
    
         
            +
                  [ List, Segment, ShortUrl ]
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
              end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            require "signal_api/core_ext/nil_class"
         
     | 
| 
      
 97 
     | 
    
         
            +
            require "signal_api/core_ext/string"
         
     | 
| 
      
 98 
     | 
    
         
            +
            require "signal_api/core_ext/array"
         
     | 
| 
      
 99 
     | 
    
         
            +
            require "signal_api/core_ext/hash"
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
            require "signal_api/util/phone"
         
     | 
| 
      
 102 
     | 
    
         
            +
            require "signal_api/util/email_address"
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            require "signal_api/contact"
         
     | 
| 
      
 105 
     | 
    
         
            +
            require "signal_api/exceptions"
         
     | 
| 
      
 106 
     | 
    
         
            +
            require "signal_api/signal_http_api"
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            require "signal_api/deliver_sms"
         
     | 
| 
      
 109 
     | 
    
         
            +
            require "signal_api/list"
         
     | 
| 
      
 110 
     | 
    
         
            +
            require "signal_api/segment"
         
     | 
| 
      
 111 
     | 
    
         
            +
            require "signal_api/short_url"
         
     | 
| 
      
 112 
     | 
    
         
            +
            require "signal_api/coupon_group"
         
     | 
| 
      
 113 
     | 
    
         
            +
            require "signal_api/carrier"
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
    
        data/signal_api.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.expand_path('../lib/signal_api/version', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Gem::Specification.new do |gem|
         
     | 
| 
      
 5 
     | 
    
         
            +
              gem.authors       = ["John Wood"]
         
     | 
| 
      
 6 
     | 
    
         
            +
              gem.email         = ["john@signalhq.com"]
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem.description   = %q{Ruby implementation of the Signal API}
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem.summary       = %q{Ruby implementation of the Signal API}
         
     | 
| 
      
 9 
     | 
    
         
            +
              gem.homepage      = "http://dev.signalhq.com"
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              gem.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 13 
     | 
    
         
            +
              gem.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem.name          = "signal_api"
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem.require_paths = ["lib"]
         
     | 
| 
      
 16 
     | 
    
         
            +
              gem.version       = SignalApi::VERSION
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              gem.add_dependency('httparty', '~> 0.8.1')
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem.add_dependency('builder', '~> 3.0.0')
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              gem.add_development_dependency('fakeweb', '~> 1.3.0')
         
     | 
| 
      
 22 
     | 
    
         
            +
              gem.add_development_dependency('shoulda', '~> 3.0.1')
         
     | 
| 
      
 23 
     | 
    
         
            +
              gem.add_development_dependency('rake', '~> 0.9.2.2')
         
     | 
| 
      
 24 
     | 
    
         
            +
              gem.add_development_dependency('yard', '~> 0.7.5')
         
     | 
| 
      
 25 
     | 
    
         
            +
              gem.add_development_dependency('bluecloth', '~> 2.2.0')
         
     | 
| 
      
 26 
     | 
    
         
            +
              gem.add_development_dependency('mocha', '~> 0.10.5')
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class CarrierTest < Test::Unit::TestCase
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 6 
     | 
    
         
            +
                SignalApi.api_key = 'foobar'
         
     | 
| 
      
 7 
     | 
    
         
            +
                FakeWeb.allow_net_connect = false
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def teardown
         
     | 
| 
      
 11 
     | 
    
         
            +
                FakeWeb.clean_registry
         
     | 
| 
      
 12 
     | 
    
         
            +
                FakeWeb.allow_net_connect = true
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              should "be able to lookup a valid carrier" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                body = <<-END
         
     | 
| 
      
 17 
     | 
    
         
            +
            <?xml version="1.0" encoding="UTF-8"?>
         
     | 
| 
      
 18 
     | 
    
         
            +
            <carrier>
         
     | 
| 
      
 19 
     | 
    
         
            +
              <name>AT&T</name>
         
     | 
| 
      
 20 
     | 
    
         
            +
              <id type="integer">6</id>
         
     | 
| 
      
 21 
     | 
    
         
            +
            </carrier>
         
     | 
| 
      
 22 
     | 
    
         
            +
            END
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                FakeWeb.register_uri(:get, SignalApi.base_uri + '/app/carriers/lookup/3125551212.xml', :content_type => 'application/xml', :status => ['200', 'Ok'], :body => body)
         
     | 
| 
      
 25 
     | 
    
         
            +
                carrier = SignalApi::Carrier.lookup('3125551212')
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal 6, carrier.id
         
     | 
| 
      
 27 
     | 
    
         
            +
                assert_equal "AT&T", carrier.name
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              should "should throw exceptions for missing params" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                assert_raise SignalApi::InvalidParameterException do 
         
     | 
| 
      
 32 
     | 
    
         
            +
                  SignalApi::Carrier.lookup(nil)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              should "show throw and exception for mobile not found" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                FakeWeb.register_uri(:get, SignalApi.base_uri + '/app/carriers/lookup/3125551212.xml', :content_type => 'application/xml', :status => '404')
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_raise SignalApi::InvalidMobilePhoneException do 
         
     | 
| 
      
 39 
     | 
    
         
            +
                  SignalApi::Carrier.lookup('3125551212')
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            end
         
     |