essential 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7fef856a4598b665b03c68baaf34c34eb79a8d8d
4
+ data.tar.gz: 81c1e44539dfbe8b6dc59dd7f61165640247a2a7
5
+ SHA512:
6
+ metadata.gz: 2f81a83c772e1190736131d8c99444538b1451b2ce609625e4528474584e992eb78f9d2cb45ab0067ddedb15e3a8dafede902da1c3233cba1db48b0c3233d803
7
+ data.tar.gz: 061610d3b785a2d8ee7d9dffa12605b93c9da1a59c6401b6668a170f420c534727a2480e3519b175450272160a3fe47d4f3c9e057003213572a11e5cd37da373
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://www.rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ essential (0.1.0)
5
+ rest-client (~> 1.8)
6
+
7
+ GEM
8
+ remote: http://www.rubygems.org/
9
+ specs:
10
+ domain_name (0.5.20160128)
11
+ unf (>= 0.0.5, < 1.0.0)
12
+ http-cookie (1.0.2)
13
+ domain_name (~> 0.5)
14
+ mime-types (2.99.1)
15
+ minitest (5.8.4)
16
+ netrc (0.11.0)
17
+ rake (10.5.0)
18
+ rest-client (1.8.0)
19
+ http-cookie (>= 1.0.2, < 2.0)
20
+ mime-types (>= 1.16, < 3.0)
21
+ netrc (~> 0.7)
22
+ unf (0.1.4)
23
+ unf_ext
24
+ unf_ext (0.0.7.2)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ essential!
31
+ minitest (~> 5.8.4)
32
+ rake
33
+
34
+ BUNDLED WITH
35
+ 1.11.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2016- Essential Platform Services, Inc. (https://essential.to)
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.
@@ -0,0 +1,107 @@
1
+ # essential-ruby
2
+
3
+ ## Quick Start
4
+
5
+ ```ruby
6
+ require 'essential'
7
+
8
+ Essential.sid = ENV['ESSENTIAL_SID']
9
+ Essential.token = ENV['ESSENTIAL_TOKEN']
10
+
11
+ default_channel = Essential::Messaging::Channel.list.first
12
+
13
+ message = default_channel.messages.create(
14
+ subscriber: '2065551212',
15
+ body: "Hello there."
16
+ )
17
+ puts message.sid
18
+
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Initial Setup
24
+
25
+ ```ruby
26
+ require 'essential'
27
+ # Essential.api_base = 'http://127.0.0.1:3000'
28
+ Essential.sid = ENV['ESSENTIAL_SID']
29
+ Essential.token = ENV['ESSENTIAL_TOKEN']
30
+
31
+ ```
32
+
33
+ ### Account
34
+
35
+ ```ruby
36
+ account = Essential::Account.retrieve
37
+ ```
38
+
39
+ ### Channels
40
+
41
+ ```ruby
42
+ account.channels.map{|ch| {ch.sid => ch.name}}.reduce(&:merge)
43
+ # => {"ch_p03Gjl8Uzn0RkZSpHXHnrw"=>"default", "ch_QsbrYCSo2m0sShMLOlZqtw"=>"yradnoces"}
44
+ channel = Essential::Messaging::Channel.retrieve('ch_p03Gjl8Uzn0RkZSpHXHnrw')
45
+ channel.update(name: 'default', onreceived_url: 'http:/api.example.com/hook')
46
+ ```
47
+
48
+ ### Subscribers
49
+
50
+ ```ruby
51
+ channel = Essential::Messaging::Channel.list.first
52
+
53
+ # create a subscriber
54
+ subscriber = channel.subscribers.create(phone_number: '2065551212')
55
+ puts subscriber.sid
56
+ # => sub_WfnIr-f-7FBMFr4nVKkMdg
57
+
58
+ # unsubscribe
59
+ subscriber.unsubscribe
60
+
61
+ # re-subscribe
62
+ subscriber = channel.subscribers.create(phone_number: '2065551212')
63
+ puts subscriber.sid
64
+ # => sub_WfnIr-f-7FBMFr4nVKkMdg
65
+ ```
66
+
67
+ ### Messages
68
+
69
+ ```ruby
70
+ # This example magically finds the correct channel
71
+ # by either using an existing subscriber, or falling
72
+ # back on the channel named 'default'.
73
+ message = Essential::Messaging::Message.create(
74
+ subscriber: '2065551212',
75
+ body: 'magic channel'
76
+ )
77
+
78
+ # Here we specify a subscriber explicitly
79
+ message = Essential::Messaging::Message.create(
80
+ subscriber: 'sub_pDTv7LSV-R-AzL7oEpBfoQ',
81
+ body: 'subscriber by sid'
82
+ )
83
+
84
+ # Here we specify a channel
85
+ message = Essential::Messaging::Message.create(
86
+ subscriber: '2065551212',
87
+ channel: 'yradnoces',
88
+ body: 'explicit channel'
89
+ )
90
+ ```
91
+
92
+ ### Properties
93
+
94
+ ```ruby
95
+ subscriber = channel.subscribers.create(phone_number: '2065551212')
96
+
97
+ # set new properties
98
+ subscriber.properties.create(name: 'external_id', value: 1234)
99
+ subscriber.properties.create(name: 'name', value: 'Brendan Ribera')
100
+ subscriber.properties.create(name: 'state', value: 'WA')
101
+
102
+ # print them
103
+ puts JSON.pretty_generate(subscriber.properties.as_json)
104
+
105
+ # update one
106
+ subscriber.properties.create(name: 'name', value: 'Nabnerb Arebir')
107
+ ```
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ task :default => [:test]
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'lib'
7
+ t.libs << 'test'
8
+ t.pattern = "test/**/*_test.rb"
9
+ end
@@ -0,0 +1,26 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'essential/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'essential'
7
+ s.version = Essential::VERSION
8
+ s.date = '2016-04-06'
9
+ s.summary = 'Essential Ruby Library'
10
+ s.description = 'A GEM for interacting with the Essential.to service.'
11
+ s.authors = ['Brendan Ribera']
12
+ s.email = 'brendan@madronavl.com'
13
+ s.homepage = 'http://github.com/madrona-labs/essential-ruby'
14
+ s.license = 'MIT'
15
+
16
+ s.add_dependency('rest-client', '~> 1.8')
17
+
18
+ s.add_development_dependency('rake', '~> 10.5')
19
+ s.add_development_dependency('minitest', '~> 5.8')
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- test/*`.split("\n")
23
+ # s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+
25
+ s.require_paths = ['lib']
26
+ end
@@ -0,0 +1,32 @@
1
+ require 'json'
2
+ require 'rest-client'
3
+ require 'set'
4
+ require 'uri'
5
+
6
+ require 'essential/version'
7
+ require 'essential/client'
8
+
9
+ # Resources
10
+ require 'essential/resource'
11
+ require 'essential/resource/paginator_proxy'
12
+
13
+ # Top-level Resources
14
+ require 'essential/account'
15
+
16
+ # Messaging Resources
17
+ require 'essential/messaging/message'
18
+ require 'essential/messaging/property'
19
+ require 'essential/messaging/transport'
20
+ require 'essential/messaging/subscriber'
21
+ require 'essential/messaging/channel'
22
+
23
+ module Essential
24
+ @api_base = 'https://api.essential.to'
25
+ @utc_offset = nil
26
+
27
+ class << self
28
+ attr_accessor :api_base, :sid, :token, :utc_offset
29
+ end
30
+
31
+ include Client
32
+ end
@@ -0,0 +1,56 @@
1
+ module Essential
2
+ class Account < Resource
3
+ include Essential::Resource::Update
4
+
5
+ attr_property :name, :token, :unsubscribed_send_raises, :created_at, :updated_at
6
+ attr_schema created_at: Time, updated_at: Time
7
+
8
+ def self.retrieve(opts={}, headers: {})
9
+ me = self.new(headers: headers)
10
+ me.fetch
11
+ me
12
+ end
13
+
14
+ def self.url
15
+ "/v2/account"
16
+ end
17
+
18
+ def self.api_status(params: {}, headers: @headers)
19
+ # permitted:
20
+ # :start_date, :end_date
21
+ resp = self.request(
22
+ :get,
23
+ url: '/v2/account/analytics/api_status',
24
+ params: params,
25
+ headers: headers
26
+ )
27
+ JSON.parse(resp)
28
+ end
29
+
30
+ def initialize(sid: nil, headers: nil)
31
+ sid ||= Essential.sid
32
+
33
+ super(sid: sid, headers: headers)
34
+ end
35
+
36
+ def url
37
+ self.class.url
38
+ end
39
+
40
+ def channels
41
+ Essential::Resource::PaginatorProxy.new(Essential::Messaging::Channel, headers: @headers)
42
+ end
43
+
44
+ def subscribers
45
+ Essential::Resource::PaginatorProxy.new(Essential::Messaging::Subscriber, headers: @headers)
46
+ end
47
+
48
+ def transports
49
+ Essential::Resource::PaginatorProxy.new(Essential::Messaging::Transport, headers: @headers)
50
+ end
51
+
52
+ def messages
53
+ Essential::Resource::PaginatorProxy.new(Essential::Messaging::Message, headers: @headers)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,65 @@
1
+ require 'essential/errors/api_error'
2
+
3
+ module Essential
4
+ module Client
5
+ module ClassMethods
6
+ def request(method, url, sid: nil, token: nil, params: {}, headers: {})
7
+ # GET -> :get, etc
8
+ method = method.to_s.downcase.to_sym
9
+
10
+ sid ||= self.sid
11
+ token ||= self.token
12
+
13
+ uri = URI.join(self. api_base, url)
14
+
15
+ headers = {
16
+ 'Content-Type' => 'application/json',
17
+ 'Accept' => 'application/json',
18
+ 'User-Agent' => user_agent(),
19
+ }.merge(headers || {})
20
+
21
+ case method
22
+ when :get, :delete
23
+ uri.query = URI.encode_www_form(params) if params && params.any?
24
+ else
25
+ payload = params.to_json
26
+ end
27
+
28
+ opts = {
29
+ method: method,
30
+ url: uri.to_s,
31
+ user: sid,
32
+ password: token,
33
+ timeout: 10, # TODO config
34
+ open_timeout: 10, # TODO: config
35
+ headers: headers,
36
+ payload: payload
37
+ }
38
+
39
+ if $debug
40
+ puts format('%s %s', method.to_s.upcase, uri)
41
+ puts format('opts: %s', JSON.pretty_generate(opts))
42
+ end
43
+
44
+ begin
45
+ response = RestClient::Request.execute(opts)
46
+ rescue StandardError => e
47
+ raise Essential::APIError.from_exception(e)
48
+ end
49
+
50
+ response
51
+ end
52
+
53
+ protected
54
+
55
+ def user_agent
56
+ format('Essential Ruby (%s)', Essential::VERSION)
57
+ end
58
+ end
59
+
60
+ def self.included(base)
61
+ base.extend(ClassMethods)
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,54 @@
1
+ module Essential
2
+ class APIError < StandardError
3
+ private_class_method :new
4
+
5
+ attr_reader :http_status, :body
6
+ attr_reader :type, :message, :code, :params
7
+
8
+ def self.from_exception(e)
9
+ case e
10
+ # when SocketError
11
+ # when NoMethodError
12
+ when RestClient::ExceptionWithResponse
13
+ new(
14
+ http_status: e.http_code,
15
+ body: e.http_body
16
+ )
17
+ when RestClient::Exception
18
+ new(http_status: e.http_code)
19
+ # when Errno::ECONNREFUSED
20
+ else
21
+ raise e
22
+ end
23
+ end
24
+
25
+ def initialize(http_status: nil, body: nil)
26
+ @http_status = http_status
27
+
28
+ if body
29
+ begin
30
+ @body = JSON.parse(body)
31
+ if @body.key?('error')
32
+ error = @body['error']
33
+ @type = error['type']
34
+ @message = error['message']
35
+ @code = error['code']
36
+ @params = error['params']
37
+ end
38
+ rescue JSON::ParserError
39
+ @body = body
40
+ end
41
+ end
42
+ end
43
+
44
+ def to_s
45
+ parts = []
46
+ parts << format('<%s>', self.http_status)
47
+ parts << self.type
48
+ parts << self.message if self.message
49
+ parts << self.params.to_json if self.params
50
+ parts.join(' - ')
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ module Essential::Messaging
2
+ class Channel < Essential::Resource
3
+ extend Essential::Resource::List
4
+ include Essential::Resource::Update
5
+
6
+ attr_property :name, :onreceived_url, :created_at, :updated_at
7
+ attr_schema created_at: Time, updated_at: Time
8
+
9
+ attr_relation account_sid: 'Essential::Account'
10
+
11
+ def transports
12
+ Essential::Resource::PaginatorProxy.new(
13
+ Transport,
14
+ params: {channel: self.sid},
15
+ headers: @headers
16
+ )
17
+ end
18
+
19
+ def subscribers
20
+ Essential::Resource::PaginatorProxy.new(
21
+ Subscriber,
22
+ params: {channel: self.sid},
23
+ headers: @headers
24
+ )
25
+ end
26
+
27
+ def messages
28
+ Essential::Resource::PaginatorProxy.new(
29
+ Message,
30
+ params: {channel: self.sid},
31
+ headers: @headers
32
+ )
33
+ end
34
+
35
+ end
36
+ end