layer-ruby 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +5 -0
- data/Guardfile +4 -0
- data/README.md +18 -53
- data/layer-ruby.gemspec +2 -2
- data/lib/layer.rb +17 -0
- data/lib/layer/announcement.rb +7 -1
- data/lib/layer/block.rb +14 -0
- data/lib/layer/client.rb +9 -8
- data/lib/layer/client/platform.rb +22 -0
- data/lib/layer/client/rest.rb +41 -0
- data/lib/layer/content.rb +50 -0
- data/lib/layer/conversation.rb +63 -1
- data/lib/layer/exceptions.rb +52 -0
- data/lib/layer/message.rb +38 -0
- data/lib/layer/operations.rb +1 -0
- data/lib/layer/operations/create.rb +7 -0
- data/lib/layer/operations/delete.rb +9 -0
- data/lib/layer/operations/find.rb +11 -0
- data/lib/layer/operations/list.rb +6 -0
- data/lib/layer/operations/paginate.rb +23 -0
- data/lib/layer/operations/patch.rb +8 -0
- data/lib/layer/patch/hash.rb +1 -1
- data/lib/layer/relation_proxy.rb +1 -1
- data/lib/layer/resource.rb +9 -4
- data/lib/layer/resource_collection.rb +30 -0
- data/lib/layer/version.rb +1 -1
- data/lib/layer/webhook.rb +59 -0
- metadata +18 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78be9a887246783d87ee5441bb6d713d7d11e0e9
|
4
|
+
data.tar.gz: c96c5872a9539077b4c86abc8fcda78bace25fcf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d02be7b2d37304b8d8e18f4ebc8afba4b697c9272ef357e7bee0244f642294553565a09f59482fd04e1ea260c0ee90250b012bef36e7509aedc39d3eceb457b
|
7
|
+
data.tar.gz: f5ca37c2018d18ab8052b2b9df63e15b24d9e396cd92a504b8ac6a5b6ca5391987259969f5f8b7e790d91a960c88eaacd81af5992e904c76dcdf9f98a6d952ed
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
#
|
1
|
+
# Ruby Client for Layer
|
2
2
|
|
3
|
-
[](https://travis-ci.org/benedikt/layer-ruby)
|
3
|
+
[](https://travis-ci.org/benedikt/layer-ruby)
|
4
4
|
[](http://badge.fury.io/rb/layer-ruby)
|
5
|
+
[](http://rubydoc.info/gems/layer-ruby)
|
5
6
|
|
6
|
-
Ruby
|
7
|
+
Ruby client for the [Layer Platform API](https://developer.layer.com/docs/platform) and [Layer Client REST API](https://developer.layer.com/docs/client/rest).
|
7
8
|
|
8
9
|
## Installation
|
9
10
|
|
@@ -23,11 +24,11 @@ Or install it yourself as:
|
|
23
24
|
|
24
25
|
## Usage
|
25
26
|
|
26
|
-
Please refer to the [Layer Platform API documentation](https://developer.layer.com/docs/platform) for details about the required payloads and responses.
|
27
|
+
Please refer to the [Layer Platform API documentation](https://developer.layer.com/docs/platform) and [Layer Client REST API documentation](https://developer.layer.com/docs/client/rest) for details about the required payloads and responses.
|
27
28
|
|
28
29
|
### Configuration
|
29
30
|
|
30
|
-
To use
|
31
|
+
To use the Layer Platform API, you need your Layer APP ID as well as a Layer Platform API Token. The gem reads both values from the `LAYER_APP_ID` and `LAYER_PLATFORM_TOKEN` environment variables. Alternatively you can specify the values by configuring the `Layer::Client` like this:
|
31
32
|
|
32
33
|
```ruby
|
33
34
|
Layer::Client.configure do |config|
|
@@ -36,70 +37,34 @@ Layer::Client.configure do |config|
|
|
36
37
|
end
|
37
38
|
```
|
38
39
|
|
39
|
-
###
|
40
|
-
|
41
|
-
```ruby
|
42
|
-
conversation = Layer::Conversation.create({ participants: ['1', '2'] })
|
43
|
-
```
|
44
|
-
|
45
|
-
### Retrieving Conversations
|
46
|
-
|
47
|
-
To retrieve a existing conversation, just use `Conversation.find` passing it the conversation id:
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
|
51
|
-
```
|
52
|
-
|
53
|
-
### Updating Conversations
|
40
|
+
### Using the gem with multiple applications at once
|
54
41
|
|
55
|
-
|
42
|
+
It's possible to create a new instance of `Layer::Client` and passing both the app id and the token to the initializer:
|
56
43
|
|
57
44
|
```ruby
|
58
|
-
|
59
|
-
conversation.participants << 3
|
60
|
-
conversation.metadata[:foo] = 'bar'
|
61
|
-
conversation.save
|
45
|
+
client = Layer::Client.new('YOUR_APP_ID_HERE', 'YOUR_PLATFORM_TOKEN_HERE')
|
62
46
|
```
|
63
47
|
|
48
|
+
The client will not use any global configuration. You can pass the client as a second parameter to any operations (`create`, `find`) described above.
|
64
49
|
|
65
|
-
###
|
66
|
-
|
67
|
-
In order to send messages, you first have to load (or create) a Conversation. Afterwards you can send a message to the conversation like this:
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
|
71
|
-
conversation.messages.create({ sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
|
72
|
-
```
|
73
|
-
|
74
|
-
### Sending Announcements
|
50
|
+
### Using the Layer Client REST API
|
75
51
|
|
76
|
-
You can
|
52
|
+
To use the Layer Client REST API, you need a way to generate identitiy tokens. You might want to use the [layer-identity_token](https://github.com/dreimannzelt/layer-identity_token) gem for that. Using this gem, you can create a new client using the REST API like this:
|
77
53
|
|
78
54
|
```ruby
|
79
|
-
Layer::
|
55
|
+
client = Layer::Client.authenticate { |nonce| Layer::IdentityToken.new('user_id_here', nonce) }
|
80
56
|
```
|
81
57
|
|
82
|
-
|
83
|
-
|
84
|
-
Managing block lists is also possible:
|
58
|
+
Afterwards, pass the client as an additional argument to the resource's methods:
|
85
59
|
|
86
60
|
```ruby
|
87
|
-
|
88
|
-
|
89
|
-
user.blocks.create({ user_id: 'other_user' }) # Adds the other user to the block list
|
90
|
-
user.blocks.delete('other_user') # Removes the other user from the block list
|
91
|
-
user.blocks.all.first.delete # Removes the first entry from the block list
|
61
|
+
# Finds all conversations of the authenticated user
|
62
|
+
Layer::Conversation.all(client)
|
92
63
|
```
|
93
64
|
|
94
|
-
###
|
65
|
+
### Documentation
|
95
66
|
|
96
|
-
|
97
|
-
|
98
|
-
```ruby
|
99
|
-
client = Layer::Client.new('YOUR_APP_ID_HERE', 'YOUR_PLATFORM_TOKEN_HERE')
|
100
|
-
```
|
101
|
-
|
102
|
-
The client will not use any global configuration. You can pass the client as a second parameter to any operations (`create`, `find`) described above.
|
67
|
+
Please refer to [the full documentation](http://rubydoc.info/gems/layer-ruby) for details on how to use Announcements, Block Lists, Conversations, Messages, Rich Content, and WebHooks.
|
103
68
|
|
104
69
|
## Development
|
105
70
|
|
data/layer-ruby.gemspec
CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.10"
|
25
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
-
spec.add_development_dependency "rspec"
|
27
|
-
spec.add_development_dependency "
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.3"
|
27
|
+
spec.add_development_dependency "yard", "~> 0.8"
|
28
28
|
end
|
data/lib/layer.rb
CHANGED
@@ -1,14 +1,31 @@
|
|
1
1
|
require 'layer/version'
|
2
|
+
require 'layer/exceptions'
|
2
3
|
require 'layer/client'
|
3
4
|
require 'layer/patch'
|
4
5
|
require 'layer/operations'
|
5
6
|
require 'layer/resource'
|
7
|
+
require 'layer/resource_collection'
|
6
8
|
require 'layer/relation_proxy'
|
7
9
|
require 'layer/conversation'
|
10
|
+
require 'layer/content'
|
8
11
|
require 'layer/message'
|
9
12
|
require 'layer/user'
|
10
13
|
require 'layer/block'
|
11
14
|
require 'layer/announcement'
|
15
|
+
require 'layer/webhook'
|
16
|
+
|
17
|
+
|
18
|
+
# @!macro [new] platform-api
|
19
|
+
# @note This is only available via the Platform API.
|
20
|
+
|
21
|
+
# @!macro [new] rest-api
|
22
|
+
# @note This is only available via the REST API.
|
23
|
+
# @see file:README.md#label-Using+the+Layer+Client+REST+API Using the Client REST API
|
24
|
+
|
25
|
+
# @!macro [new] various-apis
|
26
|
+
# @note This is available in both the REST and the Platform API. Please refer to the respective documentation to see which methods are available.
|
27
|
+
# @see file:README.md#label-Using+the+Layer+Client+REST+API Using the Client REST API
|
12
28
|
|
13
29
|
module Layer
|
30
|
+
|
14
31
|
end
|
data/lib/layer/announcement.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
module Layer
|
2
|
+
# @example
|
3
|
+
# Layer::Announcement.create({ recipients: 'everyone', sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
|
4
|
+
#
|
5
|
+
# @see https://developer.layer.com/docs/platform#send-an-announcement Layer Platform API Documentation about announcements
|
6
|
+
# @!macro platform-api
|
2
7
|
class Announcement < Resource
|
3
8
|
include Operations::Create
|
4
9
|
|
10
|
+
# @!parse extend Layer::Operations::Create::ClassMethods
|
11
|
+
|
5
12
|
def sent_at
|
6
13
|
Time.parse(attributes['sent_at'])
|
7
14
|
end
|
8
15
|
|
9
16
|
end
|
10
17
|
end
|
11
|
-
|
data/lib/layer/block.rb
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
module Layer
|
2
|
+
# Managing block lists is also possible:
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# user = Layer::User.find('user_id')
|
6
|
+
# user.blocks.all # Returns a list of blocks
|
7
|
+
# user.blocks.create({ user_id: 'other_user' }) # Adds the other user to the block list
|
8
|
+
# user.blocks.delete('other_user') # Removes the other user from the block list
|
9
|
+
# user.blocks.all.first.delete # Removes the first entry from the block list
|
10
|
+
#
|
11
|
+
# @see https://developer.layer.com/docs/platform#block-users Layer Platform API Documentation about block lists
|
12
|
+
# @!macro platform-api
|
2
13
|
class Block < Resource
|
3
14
|
include Operations::Delete
|
15
|
+
|
16
|
+
# @!parse extend Layer::Operations::Delete::ClassMethods
|
17
|
+
|
4
18
|
end
|
5
19
|
end
|
data/lib/layer/client.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rest-client'
|
2
2
|
require 'securerandom'
|
3
3
|
|
4
|
+
require 'layer/client/platform'
|
5
|
+
require 'layer/client/rest'
|
6
|
+
|
4
7
|
module Layer
|
5
8
|
class Client
|
6
9
|
class << self
|
@@ -21,13 +24,10 @@ module Layer
|
|
21
24
|
def normalize_id(id)
|
22
25
|
id.to_s.split('/').last
|
23
26
|
end
|
24
|
-
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@app_id = self.class.normalize_id(app_id)
|
30
|
-
@token = token
|
28
|
+
def authenticate(app_id = self.app_id, &block)
|
29
|
+
Layer::Client::REST.new(app_id, &block)
|
30
|
+
end
|
31
31
|
end
|
32
32
|
|
33
33
|
def get(*args)
|
@@ -63,10 +63,9 @@ module Layer
|
|
63
63
|
private
|
64
64
|
|
65
65
|
def request(method, url, payload = {}, headers = {})
|
66
|
-
url = "https://api.layer.com
|
66
|
+
url = "https://api.layer.com#{url}" unless url.start_with?('https://api.layer.com')
|
67
67
|
|
68
68
|
headers = {
|
69
|
-
'Authorization' => "Bearer #{token}",
|
70
69
|
'Accept' => 'application/vnd.layer+json; version=1.0',
|
71
70
|
'Content-Type' => 'application/json',
|
72
71
|
'If-None-Match' => SecureRandom.uuid
|
@@ -76,6 +75,8 @@ module Layer
|
|
76
75
|
|
77
76
|
response = RestClient::Request.execute(method: method, url: url, payload: payload, headers: headers)
|
78
77
|
response.empty? ? nil : JSON.parse(response)
|
78
|
+
rescue RestClient::Exception
|
79
|
+
raise Layer::Exceptions::Exceptions.build_exception($!)
|
79
80
|
end
|
80
81
|
|
81
82
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Layer
|
2
|
+
class Client
|
3
|
+
class Platform < Layer::Client
|
4
|
+
|
5
|
+
attr_reader :app_id, :token
|
6
|
+
|
7
|
+
def initialize(app_id = self.class.app_id, token = self.class.token)
|
8
|
+
@app_id = self.class.normalize_id(app_id)
|
9
|
+
@token = token
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def request(method, url, payload = {}, headers = {})
|
15
|
+
url = "https://api.layer.com/apps/#{app_id}#{url}" unless url.start_with?('https://api.layer.com')
|
16
|
+
headers['Authorization'] ||= "Bearer #{token}"
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Layer
|
2
|
+
class Client
|
3
|
+
class REST < Layer::Client
|
4
|
+
|
5
|
+
def self.authenticate(app_id, nonce = nil)
|
6
|
+
client = Layer::Client.new
|
7
|
+
|
8
|
+
nonce ||= client.post('/nonces')['nonce']
|
9
|
+
|
10
|
+
identity_token = yield(nonce)
|
11
|
+
|
12
|
+
response = client.post('/sessions', { identity_token: identity_token, app_id: app_id })
|
13
|
+
response['session_token']
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :token, :app_id, :block
|
17
|
+
|
18
|
+
def initialize(app_id = self.class.app_id, &block)
|
19
|
+
@app_id = self.class.normalize_id(app_id)
|
20
|
+
@block = block
|
21
|
+
authenticate
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def request(method, url, payload = {}, headers = {})
|
27
|
+
url = "https://api.layer.com#{url}" unless url.start_with?('https://api.layer.com')
|
28
|
+
headers['Authorization'] ||= "Layer session-token=\"#{token}\""
|
29
|
+
|
30
|
+
super
|
31
|
+
rescue Layer::Exceptions::Exceptions::AuthenticationRequired => exception
|
32
|
+
authenticate(exception.response_json['data']['nonce'])
|
33
|
+
retry
|
34
|
+
end
|
35
|
+
|
36
|
+
def authenticate(nonce = nil)
|
37
|
+
@token = self.class.authenticate(app_id, nonce, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Layer
|
2
|
+
# @example
|
3
|
+
# content = Layer::Content.create('image/png', File.open('photo.png'))
|
4
|
+
#
|
5
|
+
# message = Layer::Message.create({
|
6
|
+
# sender: { name: 'Server' },
|
7
|
+
# parts: [
|
8
|
+
# { body: content.to_json, mime_type: content.mime_type }
|
9
|
+
# ]
|
10
|
+
# })
|
11
|
+
#
|
12
|
+
# @see https://developer.layer.com/docs/client/rest#rich-content Layer REST API documentation about rich content
|
13
|
+
# @!macro rest-api
|
14
|
+
class Content < Resource
|
15
|
+
include Operations::Create
|
16
|
+
include Operations::Find
|
17
|
+
|
18
|
+
# @!parse extend Layer::Operations::Create::ClassMethods
|
19
|
+
# @!parse extend Layer::Operations::Find::ClassMethods
|
20
|
+
|
21
|
+
def self.create(mime_type, file, client = self.client)
|
22
|
+
response = client.post(url, {}, headers = {
|
23
|
+
'Upload-Content-Type' => mime_type,
|
24
|
+
'Upload-Content-Length' => file.size
|
25
|
+
})
|
26
|
+
|
27
|
+
attributes = response.merge('size' => file.size)
|
28
|
+
|
29
|
+
from_response(attributes, client).tap do |content|
|
30
|
+
content.upload(file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.url
|
35
|
+
'/content'
|
36
|
+
end
|
37
|
+
|
38
|
+
def upload(file)
|
39
|
+
RestClient.put(upload_url, file)
|
40
|
+
end
|
41
|
+
|
42
|
+
def url
|
43
|
+
attributes['refresh_url'] || "#{self.class.url}/#{Layer::Client.normalize_id(id)}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json(*args)
|
47
|
+
{ id: id, size: size }.to_json(*args)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/layer/conversation.rb
CHANGED
@@ -1,20 +1,82 @@
|
|
1
1
|
module Layer
|
2
|
+
# @example Creating a new conversation
|
3
|
+
# conversation = Layer::Conversation.create({ participants: ['1', '2'] })
|
4
|
+
#
|
5
|
+
# @example Finding an existing conversation
|
6
|
+
# conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
|
7
|
+
#
|
8
|
+
# @example Updating an existing conversation
|
9
|
+
# conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
|
10
|
+
# conversation.participants << 3
|
11
|
+
# conversation.metadata[:foo] = 'bar'
|
12
|
+
# conversation.save
|
13
|
+
#
|
14
|
+
# @see https://developer.layer.com/docs/platform#retrieving-conversations Layer Platform API Documentation about conversations
|
15
|
+
# @see https://developer.layer.com/docs/client/rest#conversations Layer REST API Documentation about conversations
|
16
|
+
# @!macro various-apis
|
2
17
|
class Conversation < Resource
|
3
18
|
include Operations::Find
|
19
|
+
include Operations::Paginate
|
4
20
|
include Operations::Create
|
21
|
+
include Operations::Delete
|
5
22
|
include Operations::Patch
|
6
23
|
|
24
|
+
# @!parse extend Layer::Operations::Find::ClassMethods
|
25
|
+
# @!parse extend Layer::Operations::Paginate::ClassMethods
|
26
|
+
# @!parse extend Layer::Operations::Create::ClassMethods
|
27
|
+
# @!parse extend Layer::Operations::Delete::ClassMethods
|
28
|
+
|
29
|
+
# Destroys the conversation with the given id for all participants
|
30
|
+
#
|
31
|
+
# @param [String] id of the conversation to destroy
|
32
|
+
# @!macro rest-api
|
33
|
+
def self.destroy(id, client = self.client)
|
34
|
+
id = Layer::Client.normalize_id(id)
|
35
|
+
client.delete("#{url}/#{id}", {}, { params: { destroy: true } })
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the converations messages
|
39
|
+
#
|
40
|
+
# @return [Layer::RelationProxy] the conversation's messages
|
41
|
+
# @!macro various-apis
|
7
42
|
def messages
|
8
|
-
RelationProxy.new(self, Message, [Operations::Create])
|
43
|
+
RelationProxy.new(self, Message, [Operations::Create, Operations::Paginate, Operations::Find])
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the conversations metadata
|
47
|
+
#
|
48
|
+
# @return [Layer::Patch::Hash] the metadata hash
|
49
|
+
def metadata
|
50
|
+
attributes['metadata'] ||= {}
|
9
51
|
end
|
10
52
|
|
53
|
+
# Returns the conversations metadata
|
54
|
+
#
|
55
|
+
# @return [Layer::Patch::Array] the participants array
|
56
|
+
def participants
|
57
|
+
attributes['participants'] ||= []
|
58
|
+
end
|
59
|
+
|
60
|
+
# Whether the conversation is distinct
|
61
|
+
#
|
62
|
+
# @return [Boolean] whether the conversation is distinct
|
11
63
|
def distinct?
|
12
64
|
attributes['distinct']
|
13
65
|
end
|
14
66
|
|
67
|
+
# Returns the time the conversation was created at
|
68
|
+
#
|
69
|
+
# @return [Time] the time the conversation was created at
|
15
70
|
def created_at
|
16
71
|
Time.parse(attributes['created_at'])
|
17
72
|
end
|
18
73
|
|
74
|
+
# Destroys the conversation for all participants
|
75
|
+
#
|
76
|
+
# @!macro rest-api
|
77
|
+
def destroy
|
78
|
+
client.delete(url, {}, { params: { destroy: true } })
|
79
|
+
end
|
80
|
+
|
19
81
|
end
|
20
82
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Layer
|
2
|
+
module Exceptions
|
3
|
+
|
4
|
+
def self.build_exception(original_exception)
|
5
|
+
identifier = JSON.parse(original_exception.http_body)['id']
|
6
|
+
identifier.gsub!(/(?:_|(\/)|^)([a-z\d]*)/i) { $2.capitalize }
|
7
|
+
|
8
|
+
exception = const_get(identifier) rescue Exception
|
9
|
+
exception.new(original_exception)
|
10
|
+
rescue
|
11
|
+
original_exception
|
12
|
+
end
|
13
|
+
|
14
|
+
class Exception < RuntimeError
|
15
|
+
attr_reader :original_exception
|
16
|
+
|
17
|
+
def initialize(original_exception = nil)
|
18
|
+
@original_exception = original_exception
|
19
|
+
end
|
20
|
+
|
21
|
+
def message
|
22
|
+
"#{original_exception.message}\n\n#{JSON.pretty_generate(response_json)}\n\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
def response_json
|
26
|
+
JSON.parse(original_exception.http_body)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ClientException < Exception; end
|
31
|
+
class ServiceUnavailable < ClientException; end
|
32
|
+
class InvalidAppId< ClientException; end
|
33
|
+
class InvalidRequestId < ClientException; end
|
34
|
+
class AuthenticationRequired < ClientException; end
|
35
|
+
class AppSuspended < ClientException; end
|
36
|
+
class UserSuspended < ClientException; end
|
37
|
+
class RateLimitExceeded < ClientException; end
|
38
|
+
class RequestTimeout < ClientException; end
|
39
|
+
class InvalidOperation < ClientException; end
|
40
|
+
class InvalidRequest < ClientException; end
|
41
|
+
class InvalidEndpoint < ClientException; end
|
42
|
+
class InvalidHeader < ClientException; end
|
43
|
+
|
44
|
+
class ResourceException < Exception; end
|
45
|
+
class AccessDenied < ResourceException; end
|
46
|
+
class NotFound < ResourceException; end
|
47
|
+
class ObjectDeleted < ResourceException; end
|
48
|
+
class MissingProperty < ResourceException; end
|
49
|
+
class InvalidProperty < ResourceException; end
|
50
|
+
class Conflict < ResourceException; end
|
51
|
+
end
|
52
|
+
end
|
data/lib/layer/message.rb
CHANGED
@@ -1,13 +1,51 @@
|
|
1
1
|
module Layer
|
2
|
+
# @example Sending messages
|
3
|
+
# conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
|
4
|
+
# conversation.messages.create({ sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
|
5
|
+
#
|
6
|
+
# @see https://developer.layer.com/docs/platform#send-a-message Layer Platform API Documentation about messages
|
7
|
+
# @see https://developer.layer.com/docs/client/rest#messages Layer REST API Documentation about messages
|
8
|
+
# @see Layer::Content Sending rich content using Layer::Content
|
9
|
+
#
|
10
|
+
# @!macro various-apis
|
2
11
|
class Message < Resource
|
12
|
+
include Operations::Find
|
3
13
|
|
14
|
+
# @!parse extend Layer::Operations::Find::ClassMethods
|
15
|
+
|
16
|
+
# Returns the conversation this message belongs to
|
17
|
+
#
|
18
|
+
# @return [Layer::Conversation] the message's conversation
|
4
19
|
def conversation
|
5
20
|
Conversation.from_response(attributes['conversation'], client)
|
6
21
|
end
|
7
22
|
|
23
|
+
# Returns the time the message was sent at
|
24
|
+
#
|
25
|
+
# @return [Time] the time the message was sent at
|
8
26
|
def sent_at
|
9
27
|
Time.parse(attributes['sent_at'])
|
10
28
|
end
|
11
29
|
|
30
|
+
# Marks the message as read by the current user
|
31
|
+
#
|
32
|
+
# @!macro rest-api
|
33
|
+
def read!
|
34
|
+
client.post(receipts_url, { type: 'read' })
|
35
|
+
end
|
36
|
+
|
37
|
+
# Marks the message as delivered to the current user
|
38
|
+
# @!macro rest-api
|
39
|
+
def delivered!
|
40
|
+
client.post(receipts_url, { type: 'delivery' })
|
41
|
+
end
|
42
|
+
|
43
|
+
# The endpoint to send read and delivered receipts to
|
44
|
+
#
|
45
|
+
# @return [String] the url of the endpoint
|
46
|
+
# @!macro rest-api
|
47
|
+
def receipts_url
|
48
|
+
attributes['receipts_url'] || "#{url}/receipts"
|
49
|
+
end
|
12
50
|
end
|
13
51
|
end
|
data/lib/layer/operations.rb
CHANGED
@@ -3,12 +3,19 @@ module Layer
|
|
3
3
|
module Create
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
+
# Creates the resource with the given attributes
|
7
|
+
#
|
8
|
+
# @param attributes [Hash] the resource's attributes
|
9
|
+
# @param client [Layer::Client] the client to use to make this request
|
10
|
+
# @return [Layer::Resource] the created resource
|
11
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
6
12
|
def create(attributes = {}, client = self.client)
|
7
13
|
response = client.post(url, attributes)
|
8
14
|
from_response(response, client)
|
9
15
|
end
|
10
16
|
end
|
11
17
|
|
18
|
+
# @!visibility private
|
12
19
|
def self.included(base)
|
13
20
|
base.extend(ClassMethods)
|
14
21
|
end
|
@@ -3,16 +3,25 @@ module Layer
|
|
3
3
|
module Delete
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
+
# Deletes the resource with the given id
|
7
|
+
#
|
8
|
+
# @param id [String] the resource's id
|
9
|
+
# @param client [Layer::Client] the client to use to make this request
|
10
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
6
11
|
def delete(id, client = self.client)
|
7
12
|
id = Layer::Client.normalize_id(id)
|
8
13
|
client.delete("#{url}/#{id}")
|
9
14
|
end
|
10
15
|
end
|
11
16
|
|
17
|
+
# @!visibility private
|
12
18
|
def self.included(base)
|
13
19
|
base.extend(ClassMethods)
|
14
20
|
end
|
15
21
|
|
22
|
+
# Deletes the resource
|
23
|
+
#
|
24
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
16
25
|
def delete
|
17
26
|
client.delete(url)
|
18
27
|
end
|
@@ -3,6 +3,12 @@ module Layer
|
|
3
3
|
module Find
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
+
# Finds the resource with the given id
|
7
|
+
#
|
8
|
+
# @param id [String] the resource's id
|
9
|
+
# @param client [Layer::Client] the client to use to make this request
|
10
|
+
# @return [Layer::Resource] the found resource
|
11
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
6
12
|
def find(id, client = self.client)
|
7
13
|
id = Layer::Client.normalize_id(id)
|
8
14
|
response = client.get("#{url}/#{id}")
|
@@ -10,10 +16,15 @@ module Layer
|
|
10
16
|
end
|
11
17
|
end
|
12
18
|
|
19
|
+
# @!visibility private
|
13
20
|
def self.included(base)
|
14
21
|
base.extend(ClassMethods)
|
15
22
|
end
|
16
23
|
|
24
|
+
# Reloads the resource
|
25
|
+
#
|
26
|
+
# @return [Layer::Resource] the resource itself
|
27
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
17
28
|
def reload
|
18
29
|
self.attributes = client.get(url)
|
19
30
|
self
|
@@ -3,12 +3,18 @@ module Layer
|
|
3
3
|
module List
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
+
# Finds all resources
|
7
|
+
#
|
8
|
+
# @param client [Layer::Client] the client to use to make this request
|
9
|
+
# @return [Enumerable] the found resources
|
10
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
6
11
|
def all(client = self.client)
|
7
12
|
response = client.get(url)
|
8
13
|
response.map { |attributes| from_response(attributes, client) }
|
9
14
|
end
|
10
15
|
end
|
11
16
|
|
17
|
+
# @!visibility private
|
12
18
|
def self.included(base)
|
13
19
|
base.extend(ClassMethods)
|
14
20
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Layer
|
2
|
+
module Operations
|
3
|
+
module Paginate
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
# Finds all resources from a paginated endpoint
|
7
|
+
#
|
8
|
+
# @param client [Layer::Client] the client to use to make this request
|
9
|
+
# @return [Layer::ResourceCollection] the found resources
|
10
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
11
|
+
def all(client = self.client)
|
12
|
+
Layer::ResourceCollection.new(self, client)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @!visibility private
|
17
|
+
def self.included(base)
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -2,12 +2,20 @@ module Layer
|
|
2
2
|
module Operations
|
3
3
|
module Patch
|
4
4
|
|
5
|
+
# Creates the resource with the given attributes
|
6
|
+
#
|
7
|
+
# @return [Boolean] whether saving was successful
|
8
|
+
# @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
|
5
9
|
def save
|
6
10
|
client.patch(url, patch.operations)
|
7
11
|
patch.reset
|
8
12
|
true
|
9
13
|
end
|
10
14
|
|
15
|
+
# Updates the resource's attributes to the given ones
|
16
|
+
#
|
17
|
+
# @param [Hash] attributes the new attributes
|
18
|
+
# @return [Layer::Patch::Hash] the resources new attributes
|
11
19
|
def attributes=(attributes)
|
12
20
|
@attributes = Layer::Patch::Hash.new(patch, attributes)
|
13
21
|
end
|
data/lib/layer/patch/hash.rb
CHANGED
data/lib/layer/relation_proxy.rb
CHANGED
@@ -7,7 +7,7 @@ module Layer
|
|
7
7
|
@resource_type = resource_type
|
8
8
|
@base = base
|
9
9
|
|
10
|
-
operations.each { |operation| singleton_class.include
|
10
|
+
operations.each { |operation| singleton_class.send(:include, operation::ClassMethods) }
|
11
11
|
|
12
12
|
instance_eval(&block) if block_given?
|
13
13
|
end
|
data/lib/layer/resource.rb
CHANGED
@@ -17,7 +17,7 @@ module Layer
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def client
|
20
|
-
@client ||= Client.new
|
20
|
+
@client ||= Client::Platform.new
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -29,7 +29,7 @@ module Layer
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def url
|
32
|
-
attributes['url']
|
32
|
+
attributes['url'] || (id && "#{self.class.url}/#{Layer::Client.normalize_id(id)}")
|
33
33
|
end
|
34
34
|
|
35
35
|
def id
|
@@ -37,13 +37,18 @@ module Layer
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def respond_to_missing?(method, include_private = false)
|
40
|
-
|
40
|
+
attribute = method.to_s.sub(/=$/, '')
|
41
|
+
|
42
|
+
attributes.has_key?(attribute) || super
|
41
43
|
end
|
42
44
|
|
43
45
|
private
|
44
46
|
|
45
47
|
def method_missing(method, *args, &block)
|
46
|
-
if
|
48
|
+
if method.to_s =~ /=$/
|
49
|
+
attribute = method.to_s.sub(/=$/, '')
|
50
|
+
attributes[attribute] = args.first
|
51
|
+
elsif attributes.has_key?(method.to_s)
|
47
52
|
attributes[method.to_s]
|
48
53
|
else
|
49
54
|
super
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Layer
|
2
|
+
class ResourceCollection < Enumerator
|
3
|
+
|
4
|
+
def initialize(resource, client)
|
5
|
+
@resource = resource
|
6
|
+
@client = client
|
7
|
+
@params = { page_size: 100 }
|
8
|
+
|
9
|
+
super() do |yielder|
|
10
|
+
while response = next_page
|
11
|
+
response.map do |attributes|
|
12
|
+
yielder << resource.from_response(attributes, client)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :resource, :client, :params
|
21
|
+
|
22
|
+
def next_page
|
23
|
+
response = client.get(resource.url, {}, { params: params })
|
24
|
+
return nil if response.empty?
|
25
|
+
params[:from_id] = Layer::Client.normalize_id(response.last['id'])
|
26
|
+
response
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/layer/version.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Layer
|
2
|
+
# @example
|
3
|
+
# webhook = Layer::Webhook.create({
|
4
|
+
# target_config: { foo: :bar },
|
5
|
+
# secret: 'my-secret',
|
6
|
+
# event_types: ['message.sent'],
|
7
|
+
# target_url: 'http://example.com/layer/webhook'
|
8
|
+
# })
|
9
|
+
# @see https://gist.github.com/vtrehan/9ef1e16db5e74305ddf3 Layer Webhook documentation (Prerelease)
|
10
|
+
# @note This feature is still in beta at Layer. Please contact Layer to enable webhooks for your account.
|
11
|
+
#
|
12
|
+
# @!macro platform-api
|
13
|
+
class Webhook < Resource
|
14
|
+
include Operations::Find
|
15
|
+
include Operations::List
|
16
|
+
include Operations::Create
|
17
|
+
include Operations::Delete
|
18
|
+
|
19
|
+
# @!parse extend Layer::Operations::Find::ClassMethods
|
20
|
+
# @!parse extend Layer::Operations::List::ClassMethods
|
21
|
+
# @!parse extend Layer::Operations::Create::ClassMethods
|
22
|
+
# @!parse extend Layer::Operations::Delete::ClassMethods
|
23
|
+
|
24
|
+
# Activate this webhook
|
25
|
+
def activate!
|
26
|
+
client.post("#{url}/activate")
|
27
|
+
end
|
28
|
+
|
29
|
+
# Deactivate this webhook
|
30
|
+
def deactivate!
|
31
|
+
client.post("#{url}/deactivate")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Check if this webhook is unverified
|
35
|
+
# @return [Boolean] whether the webhook is unverified
|
36
|
+
def unverified?
|
37
|
+
status == 'unverified'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Check if this webhook is active
|
41
|
+
# @return [Boolean] whether the webhook is active
|
42
|
+
def active?
|
43
|
+
status == 'active'
|
44
|
+
end
|
45
|
+
|
46
|
+
# Check if this webhook is inactive
|
47
|
+
# @return [Boolean] whether the webhook is inactive
|
48
|
+
def inactive?
|
49
|
+
status == 'inactive'
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the time the webhook was created at
|
53
|
+
# @return [Time] the time the webhook was created at
|
54
|
+
def created_at
|
55
|
+
Time.parse(attributes['created_at'])
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: layer-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benedikt Deicke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -56,30 +56,30 @@ dependencies:
|
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3.3'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '3.3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '0.8'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '0.8'
|
83
83
|
description: Ruby bindings for the Layer Platform API
|
84
84
|
email:
|
85
85
|
- benedikt@benediktdeicke.com
|
@@ -103,13 +103,18 @@ files:
|
|
103
103
|
- lib/layer/announcement.rb
|
104
104
|
- lib/layer/block.rb
|
105
105
|
- lib/layer/client.rb
|
106
|
+
- lib/layer/client/platform.rb
|
107
|
+
- lib/layer/client/rest.rb
|
108
|
+
- lib/layer/content.rb
|
106
109
|
- lib/layer/conversation.rb
|
110
|
+
- lib/layer/exceptions.rb
|
107
111
|
- lib/layer/message.rb
|
108
112
|
- lib/layer/operations.rb
|
109
113
|
- lib/layer/operations/create.rb
|
110
114
|
- lib/layer/operations/delete.rb
|
111
115
|
- lib/layer/operations/find.rb
|
112
116
|
- lib/layer/operations/list.rb
|
117
|
+
- lib/layer/operations/paginate.rb
|
113
118
|
- lib/layer/operations/patch.rb
|
114
119
|
- lib/layer/patch.rb
|
115
120
|
- lib/layer/patch/array.rb
|
@@ -117,9 +122,11 @@ files:
|
|
117
122
|
- lib/layer/patch/hash.rb
|
118
123
|
- lib/layer/relation_proxy.rb
|
119
124
|
- lib/layer/resource.rb
|
125
|
+
- lib/layer/resource_collection.rb
|
120
126
|
- lib/layer/ruby.rb
|
121
127
|
- lib/layer/user.rb
|
122
128
|
- lib/layer/version.rb
|
129
|
+
- lib/layer/webhook.rb
|
123
130
|
homepage: https://github.com/benedikt/layer-ruby
|
124
131
|
licenses:
|
125
132
|
- MIT
|