promoter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 95792b0b464ff9072200693024cf2cf5d115ef39
4
+ data.tar.gz: a5d4acfaaa3381413c4fe093167f35453c4df479
5
+ SHA512:
6
+ metadata.gz: 38f0998be10fee79e559bfa8303a52a155034e1e7a60eadfa8aaa20a08c544f3fd91cb1f972f475b0ac6b3f1bb18e2d9172e2309c60857515f0acc86f0141ed0
7
+ data.tar.gz: 8cde91e251abc021b76eb4c4e8d387cce2c16fa9bb42198db60e83db2d8a5766ba2c0f3a1fb0a1ddc672ebce7e09df01c4d4356bf87840bb4adc8a0255b2c2b1
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /bin
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in promoter.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Chris O'Sullivan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Promoter
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/promoter`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'promoter'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install promoter
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/promoter/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/promoter.rb ADDED
@@ -0,0 +1,15 @@
1
+ require "promoter/version"
2
+ require "promoter/errors"
3
+ require "promoter/request"
4
+ require "promoter/campaign"
5
+ require "promoter/contact"
6
+ require "promoter/contact_list"
7
+ require "promoter/feedback"
8
+ require "promoter/metric"
9
+
10
+ module Promoter
11
+ class << self
12
+ attr_accessor :api_key
13
+ attr_accessor :debug
14
+ end
15
+ end
@@ -0,0 +1,39 @@
1
+ module Promoter
2
+
3
+ class Campaign
4
+
5
+ API_URL = "https://app.promoter.io/api/campaigns"
6
+
7
+ attr_reader :id, :name, :drip_duration, :contact_count, :eligible_count,
8
+ :last_surveyed_date, :launch_date
9
+
10
+ def initialize(attrs)
11
+ @id = attrs["id"]
12
+ @name = attrs["name"]
13
+ @drip_duration = attrs["drip_duration"]
14
+ @contact_count = attrs["all_count"]
15
+ @eligible_count = attrs["eligible_count"]
16
+ @last_surveyed_date = Time.parse(attrs["last_surveyed_date"]) if attrs["last_surveyed_date"]
17
+ @launch_date = Time.parse(attrs["launch_date"]) if attrs["launch_date"]
18
+ end
19
+
20
+ def self.all(page=1)
21
+ response = Request.get("#{API_URL}/?page=#{page}")
22
+ response['results'].map {|attrs| new(attrs)}
23
+ end
24
+
25
+ # Parameter Optional? Description
26
+ # all_contacts yes Can be set to true,false
27
+ # If set to true, the call will send surveys to all
28
+ # contacts in your specified contact list.
29
+ # If set to false, the call will send surveys to
30
+ # contacts who have been added or updated since you
31
+ # last sent surveys. The default behavior is when
32
+ # all_contacts is set to false.
33
+ def self.send_surveys(campaign_id, all_contacts=false)
34
+ response = Request.post("#{API_URL}/#{campaign_id}/send-surveys/",
35
+ { all_contacts: all_contacts, response_format: :plain })
36
+ response.match /Success\, surveys sent\./
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ module Promoter
2
+
3
+ class Contact
4
+
5
+ attr_reader :id, :email, :first_name, :last_name, :created_date, :attributes
6
+
7
+ API_URL = "https://app.promoter.io/api/contacts"
8
+
9
+ def initialize(attrs)
10
+ @id = attrs["id"]
11
+ @email = attrs["email"]
12
+ @first_name = attrs["first_name"]
13
+ @last_name = attrs["last_name"]
14
+ @created_date = Time.parse(attrs["created_date"]) if attrs["created_date"]
15
+ @attributes = attrs["attributes"]
16
+ end
17
+
18
+ def self.all(page=1)
19
+ response = Request.get("#{API_URL}/?page=#{page}")
20
+ response['results'].map {|attrs| new(attrs)}
21
+ end
22
+
23
+ def self.find(id)
24
+ response = Request.get("#{API_URL}/#{id}")
25
+ new(response)
26
+ end
27
+
28
+ # Contact Params
29
+ # Parameter Optional? Description
30
+ # email no The email of the contact to add to the organization.
31
+ # first_name yes The first name of the contact to add to the organization.
32
+ # last_name yes The last name of the contact to add to the organization.
33
+ # contact_list yes A list of Contact List Id’s to associate a contact to.
34
+ # If one is not provided the contact will be
35
+ # associated to a default generated contact list.
36
+ # attributes yes A dictionary of key value pairs of custom
37
+ # attributes that will be associated with the
38
+ # contact and contact list.
39
+ # send yes A boolean value set to true in order to express
40
+ # intent to survey this contact for a given campaign.
41
+ # campaign yes The campaign id you would like to associate the
42
+ # contact to. Note: Campaign must have a contact
43
+ # list associated to it in order for the contact to
44
+ # be added correctly. Otherwise, the contact will
45
+ # be associated to a default generated contact list
46
+ # for your given organization.
47
+ def self.create(attributes)
48
+ response = Request.post(API_URL + "/", attributes)
49
+ new(response)
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,31 @@
1
+ module Promoter
2
+
3
+ class ContactList
4
+
5
+ attr_reader :id, :name
6
+
7
+ API_URL = "https://app.promoter.io/api/lists"
8
+
9
+ def initialize(attrs)
10
+ @id = attrs['id']
11
+ @name = attrs['name']
12
+ end
13
+
14
+ def self.all(page=1)
15
+ response = Request.get("#{API_URL}/?page=#{page}")
16
+ response['results'].map {|attrs| new(attrs)}
17
+ end
18
+
19
+ def self.contact_ids_for(contact_list_id)
20
+ response = Request.get("#{API_URL}/#{contact_list_id}/contacts")
21
+ response['results'].map {|attrs| attrs["id"]}
22
+ end
23
+
24
+ def self.remove_contact(params={})
25
+ contact_list_id = params[:contact_list_id]
26
+ contact_id = params[:contact_id]
27
+ Request.delete("#{API_URL}/#{contact_list_id}/contacts/#{contact_id}")
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ module Promoter
2
+ module Errors
3
+ class BadRequest < StandardError; end
4
+ class Unauthorized < StandardError; end
5
+ class Forbidden < StandardError; end
6
+ class NotFound < StandardError; end
7
+ class MethodNotAllowed < StandardError; end
8
+ class NotAcceptable < StandardError; end
9
+ class Gone < StandardError; end
10
+ class TooManyRequests < StandardError; end
11
+ class InternalServerError < StandardError; end
12
+ class ServiceUnavailable < StandardError; end
13
+
14
+ # Error Code Meaning
15
+ # 400 Bad Request – Something is wrong with your request
16
+ # 401 Unauthorized – Your API key is incorrect or invalid
17
+ # 403 Forbidden – The resource requested is hidden for administrators only
18
+ # 404 Not Found – The specified resource could not be found
19
+ # 405 Method Not Allowed – You tried to access a resource with an invalid method
20
+ # 406 Not Acceptable – You requested a format that isn’t json
21
+ # 410 Gone – The resource requested has been removed from our servers
22
+ # 429 Too Many Requests – You’re requesting too much! Slown down!
23
+ # 500 Internal Server Error – We had a problem with our server. Try again later.
24
+ # 503 Service Unavailable – We’re temporarially offline for maintanance. Please try again later.
25
+ def check_for_error(status_code)
26
+ case status_code.to_i
27
+ when 400
28
+ raise BadRequest.new("Something is wrong with your request")
29
+ when 401
30
+ raise Unauthorized.new("Your API key is incorrect or invalid")
31
+ when 403
32
+ raise Forbidden.new("The resource requested is hidden for administrators only")
33
+ when 404
34
+ raise NotFound.new("The specified resource could not be found")
35
+ when 405
36
+ raise MethodNotAllowed.new("You tried to access a resource with an invalid method")
37
+ when 406
38
+ raise NotAcceptable.new("You requested a format that isn’t json")
39
+ when 410
40
+ raise Gone.new("The resource requested has been removed from our servers")
41
+ when 429
42
+ raise TooManyRequests.new("You’re requesting too much! Slown down!")
43
+ when 500
44
+ raise InternalServerError.new("We had a problem with our server. Try again later.")
45
+ when 503
46
+ raise ServiceUnavailable.new("We’re temporarially offline for maintanance. Please try again later.")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
1
+ module Promoter
2
+
3
+ class Feedback
4
+
5
+ attr_reader :id, :contact, :score, :score_type, :posted_date, :comment, :follow_up_url, :url
6
+
7
+ API_URL = "https://app.promoter.io/api/feedback"
8
+
9
+ def initialize(attrs)
10
+ @id = attrs["id"]
11
+ @contact = Contact.new(attrs["contact"])
12
+ @score = attrs["score"]
13
+ @score_type = attrs["score_type"]
14
+ @posted_date = Time.parse(attrs["posted_date"])
15
+ @comment = attrs["comment"]
16
+ @follow_up_url = attrs["followup_href"]
17
+ @follow_up_href = attrs["href"]
18
+ end
19
+
20
+ # Parameter Required Description
21
+ # score false Filtering by score can be achieved with
22
+ # a range 0-10
23
+ # score_type false Filtering by score type can be achieved
24
+ # with a list of values promoter,
25
+ # detractor, passive
26
+ # survey__campaign false Filtering by campaign can be achieved
27
+ # by the given id of your campaign id
28
+ # survey__campaign__status false Filtering by campaign status can be
29
+ # achieved by providing one of the
30
+ # campaign status values: ACTIVE, COMPLETE.
31
+ # NOTE: This url parameter does not require quotes around the value.
32
+ # e.g. (<api-url>?survey__campaign__status=ACTIVE)
33
+ def self.all(attrs={})
34
+ response = Request.get("#{API_URL}/?#{query_string(attrs)}")
35
+ response['results'].map {|attrs| new(attrs)}
36
+ end
37
+
38
+ def self.find(id)
39
+ response = Request.get("#{API_URL}/#{id}")
40
+ new(response)
41
+ end
42
+
43
+ private
44
+
45
+ def self.query_string(attrs)
46
+ # campaign_id is preferable to survey_campaign (which is what promoter expects)
47
+ if attrs.has_key?(:campaign_id)
48
+ attrs[:survey_campaign] = attrs.delete(:campaign_id)
49
+ end
50
+ URI.encode_www_form(attrs)
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ module Promoter
2
+
3
+ class Metric
4
+
5
+ attr_accessor :campaign_name, :nps, :organization_nps
6
+
7
+ API_URL = "https://app.promoter.io/api/metrics"
8
+
9
+ def initialize(attrs)
10
+ @campaign_name = attrs["campaign"]
11
+ @nps = attrs["nps"].to_f
12
+ @organization_nps = attrs["organization_nps"].to_f
13
+ end
14
+
15
+ def self.all(page=1)
16
+ response = Request.get("#{API_URL}/?page=#{page}")
17
+ response['results'].map {|attrs| new(attrs)}
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ module Promoter
5
+
6
+ class Request
7
+
8
+ include HTTParty
9
+ extend Errors
10
+
11
+ def self.get(url)
12
+ response = HTTParty.get(url, headers: auth_header)
13
+ parse_response(response)
14
+ end
15
+
16
+ def self.post(url, params)
17
+ response_format = params.delete(:response_format) || :json
18
+ response = HTTParty.post(url, body: params.to_json, headers: auth_header)
19
+ parse_response(response, response_format)
20
+ end
21
+
22
+ def self.delete(url)
23
+ response = HTTParty.delete(url, headers: auth_header)
24
+ parse_response(response)
25
+ end
26
+
27
+ private
28
+
29
+ def self.parse_response(response, response_format=:json)
30
+ check_for_error(response.response.code)
31
+ display_debug(response.body)
32
+ if response_format == :json
33
+ JSON.parse(response.body.to_s)
34
+ else
35
+ response.body.to_s
36
+ end
37
+ end
38
+
39
+ def self.display_debug(response)
40
+ if Promoter.debug
41
+ puts "-" * 20 + " DEBUG " + "-" * 20
42
+ puts response
43
+ puts "-" * 18 + " END DEBUG " + "-" * 18
44
+ end
45
+ end
46
+
47
+ def self.auth_header
48
+ if Promoter.api_key.empty?
49
+ raise Unauthorized.new("You need to set your promoter api key. You can register for a Promoter API key with a Promoter.io Account.")
50
+ end
51
+ { "Authorization" => "Token #{Promoter.api_key}",
52
+ 'Content-Type' => 'application/json' }
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,3 @@
1
+ module Promoter
2
+ VERSION = "0.1.0"
3
+ end
data/promoter.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'promoter/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "promoter"
8
+ spec.version = Promoter::VERSION
9
+ spec.authors = ["Chris O'Sullivan"]
10
+ spec.email = ["thechrisoshow@gmail.com"]
11
+
12
+ spec.summary = %q{promoter is a wrapper for the promoter.io REST API}
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.9"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "webmock"
25
+ spec.add_development_dependency "byebug"
26
+
27
+ spec.add_dependency "httparty"
28
+ spec.add_dependency "json"
29
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: promoter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris O'Sullivan
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: httparty
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: json
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - thechrisoshow@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - lib/promoter.rb
126
+ - lib/promoter/campaign.rb
127
+ - lib/promoter/contact.rb
128
+ - lib/promoter/contact_list.rb
129
+ - lib/promoter/errors.rb
130
+ - lib/promoter/feedback.rb
131
+ - lib/promoter/metric.rb
132
+ - lib/promoter/request.rb
133
+ - lib/promoter/version.rb
134
+ - promoter.gemspec
135
+ homepage:
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.4.8
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: promoter is a wrapper for the promoter.io REST API
159
+ test_files: []