frankly-ruby 1.0.1

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: 1520d64622a8a0b2a7b15fca5f94b1c3c6d6aaca
4
+ data.tar.gz: 0f5bf8fa25670944d15f2c3791210e4bcda30412
5
+ SHA512:
6
+ metadata.gz: 5d27b5a6d48cac7c2e17c802c15b348eedb4b9b2c6434bcc0f54b4a2f73d3625f4dde23f4c36ce3b901a283b0600a627c62b0c74bf458d3f1548fe3d710f46da
7
+ data.tar.gz: ea5b9fd52c84958f3912aae40512e6787fefa1310b12ba0aab28c4c7c5fe6f4271aef4af95dd7b400088e33b77c1e1829b206a2772bcd8fdcd59d089bd0ed893
@@ -0,0 +1,72 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+ class Announcement
27
+ def self.create_announcement(address, headers, sessionToken, payload)
28
+ headers[:params] = { token: sessionToken }
29
+ RestClient::Request.execute(
30
+ method: 'post',
31
+ url: Util.build_url(address, 'announcements'),
32
+ headers: headers,
33
+ payload: payload
34
+ )
35
+ end
36
+
37
+ def self.read_announcement(address, headers, sessionToken, announcement_id)
38
+ headers[:params] = { token: sessionToken }
39
+ RestClient::Request.execute(
40
+ method: 'get',
41
+ url: Util.build_url(address, 'announcements/' + announcement_id.to_s),
42
+ headers: headers
43
+ )
44
+ end
45
+
46
+ def self.delete_announcement(address, headers, sessionToken, announcement_id)
47
+ headers[:params] = { token: sessionToken }
48
+ RestClient::Request.execute(
49
+ method: 'delete',
50
+ url: Util.build_url(address, 'announcements/' + announcement_id.to_s),
51
+ headers: headers
52
+ )
53
+ end
54
+
55
+ def self.read_announcement_list(address, headers, sessionToken)
56
+ headers[:params] = { token: sessionToken }
57
+ RestClient::Request.execute(
58
+ method: 'get',
59
+ url: Util.build_url(address, 'announcements'),
60
+ headers: headers
61
+ )
62
+ end
63
+
64
+ def self.read_announcement_room_list(address, headers, sessionToken, announcement_id)
65
+ headers[:params] = { token: sessionToken }
66
+ RestClient::Request.execute(
67
+ method: 'get',
68
+ url: Util.build_url(address, 'announcements/' + announcement_id.to_s + '/rooms'),
69
+ headers: headers
70
+ )
71
+ end
72
+ end
@@ -0,0 +1,37 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+ class Auth
27
+ def self.nonce(address)
28
+ RestClient.get Util.build_url(address, 'auth/nonce')
29
+ end
30
+
31
+ def self.open(address, identityToken)
32
+ headers = Util.build_headers
33
+ headers[:params] = { identity_token: identityToken }
34
+ session = RestClient.get(Util.build_url(address, 'auth'), headers)
35
+ session
36
+ end
37
+ end
@@ -0,0 +1,71 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+ class Files
27
+ def self.create_file(address, headers, sessionToken, payload)
28
+ headers[:params] = { token: sessionToken }
29
+ RestClient::Request.execute(
30
+ method: 'post',
31
+ url: Util.build_url(address, 'files'),
32
+ headers: headers,
33
+ payload: payload
34
+ )
35
+ end
36
+
37
+ def self.update_file(headers, sessionToken, destination_url, file_obj, file_size, mime_type, encoding = nil)
38
+ headers[:params] = { token: sessionToken }
39
+ headers['content-length'] = file_size
40
+ headers['content-type'] = mime_type
41
+ headers['content-encoding'] = encoding
42
+
43
+ file_bin = file_obj.read
44
+ file_obj.close
45
+
46
+ RestClient::Request.execute(
47
+ method: 'put',
48
+ url: destination_url,
49
+ headers: headers,
50
+ payload: file_bin
51
+ )
52
+ end
53
+
54
+ def self.update_file_from_path(headers, sessionToken, destination_url, file_path)
55
+ file_obj = File.open(file_path, 'rb')
56
+ file_size = File.size(file_path)
57
+ mime_type = MimeMagic.by_magic(file_obj)
58
+ encoding = CharlockHolmes::EncodingDetector.detect(File.read(file_path))[:type]
59
+ update_file(headers, sessionToken, destination_url, file_obj, file_size, mime_type, encoding)
60
+ end
61
+
62
+ def self.upload_file(headers, sessionToken, file_obj, file_size, mime_type, encoding = nil, params)
63
+ cf = create_file(address, headers, sessionToken, params)
64
+ update_file(headers, sessionToken, cf['url'], file_obj, file_size, mime_type, encoding)
65
+ end
66
+
67
+ def self.upload_file_from_path(headers, sessionToken, file_path, params)
68
+ cf = create_file(address, headers, sessionToken, params)
69
+ update_file_from_path(headers, sessionToken, cf['url'], file_path)
70
+ end
71
+ end
@@ -0,0 +1,84 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+ class Generic
27
+ def self.create(address, headers, sessionToken, path, params, payload)
28
+ headers[:params] = params
29
+ headers[:params][:token] = sessionToken
30
+ RestClient::Request.execute(
31
+ method: 'post',
32
+ url: Util.build_url(address, path),
33
+ headers: headers,
34
+ payload: payload
35
+ )
36
+ end
37
+
38
+ def self.read(address, headers, sessionToken, path, params, payload)
39
+ headers[:params] = params
40
+ headers[:params][:token] = sessionToken
41
+ RestClient::Request.execute(
42
+ method: 'get',
43
+ url: Util.build_url(address, path),
44
+ headers: headers,
45
+ payload: payload
46
+ )
47
+ end
48
+
49
+ def self.update(address, headers, sessionToken, path, params, payload)
50
+ headers[:params] = params
51
+ headers[:params][:token] = sessionToken
52
+ RestClient::Request.execute(
53
+ method: 'put',
54
+ url: Util.build_url(address, path),
55
+ headers: headers,
56
+ payload: payload
57
+ )
58
+ end
59
+
60
+ def self.delete(address, headers, sessionToken, path, params, payload)
61
+ headers[:params] = params
62
+ headers[:params][:token] = sessionToken
63
+ RestClient::Request.execute(
64
+ method: 'delete',
65
+ url: Util.build_url(address, path),
66
+ headers: headers,
67
+ payload: payload
68
+ )
69
+ end
70
+
71
+ def self.upload(address, headers, sessionToken, url, params, payload, content_length, content_type, content_encoding)
72
+ headers[:params] = params
73
+ headers[:params][:token] = sessionToken
74
+ headers['content-length'] = content_length
75
+ headers['content-type'] = content_type
76
+ headers['content-encoding'] = content_encoding
77
+ RestClient::Request.execute(
78
+ method: 'put',
79
+ url: url,
80
+ headers: headers,
81
+ payload: payload
82
+ )
83
+ end
84
+ end
@@ -0,0 +1,50 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+
27
+ class Message
28
+ def self.create_room_message(address, headers, sessionToken, room_id, payload)
29
+ headers[:params] = { token: sessionToken }
30
+ if payload.key?(:announcement)
31
+ headers[:params][:announcement] = payload.delete(:announcement)
32
+ end
33
+ RestClient::Request.execute(
34
+ method: 'post',
35
+ url: Util.build_url(address, 'rooms/' + room_id.to_s + '/messages'),
36
+ headers: headers,
37
+ payload: payload.to_json
38
+ )
39
+ end
40
+
41
+ def self.read_room_message_list(address, headers, sessionToken, room_id, params)
42
+ headers[:params] = params
43
+ headers[:params][:token] = sessionToken
44
+ RestClient::Request.execute(
45
+ method: 'get',
46
+ url: Util.build_url(address, 'rooms/' + room_id.to_s + '/messages'),
47
+ headers: headers
48
+ )
49
+ end
50
+ end
@@ -0,0 +1,73 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+ class Rooms
27
+ def self.create_room(address, headers, sessionToken, payload)
28
+ headers[:params] = { token: sessionToken }
29
+ RestClient::Request.execute(
30
+ method: 'post',
31
+ url: Util.build_url(address, 'rooms'),
32
+ headers: headers,
33
+ payload: payload
34
+ )
35
+ end
36
+
37
+ def self.read_room_list(address, headers, sessionToken)
38
+ headers[:params] = { token: sessionToken }
39
+ RestClient::Request.execute(
40
+ method: 'get',
41
+ url: Util.build_url(address, 'rooms'),
42
+ headers: headers
43
+ )
44
+ end
45
+
46
+ def self.read_room(address, headers, sessionToken, room_id)
47
+ headers[:params] = { token: sessionToken }
48
+ RestClient::Request.execute(
49
+ method: 'get',
50
+ url: Util.build_url(address, 'rooms/' + room_id.to_s),
51
+ headers: headers
52
+ )
53
+ end
54
+
55
+ def self.update_room(address, headers, sessionToken, room_id, payload)
56
+ headers[:params] = { token: sessionToken }
57
+ RestClient::Request.execute(
58
+ method: 'put',
59
+ url: Util.build_url(address, 'rooms/' + room_id.to_s),
60
+ headers: headers,
61
+ payload: payload
62
+ )
63
+ end
64
+
65
+ def self.delete_room(address, headers, sessionToken, room_id)
66
+ headers[:params] = { token: sessionToken }
67
+ RestClient::Request.execute(
68
+ method: 'delete',
69
+ url: Util.build_url(address, 'rooms/' + room_id.to_s),
70
+ headers: headers
71
+ )
72
+ end
73
+ end
@@ -0,0 +1,38 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # @!visibility private
26
+ class Util
27
+ def self.build_url(base_url, path)
28
+ base_url + path
29
+ end
30
+
31
+ def self.build_headers
32
+ headers = {}
33
+ headers['accept'] = 'application/json'
34
+ headers['content-type'] = 'application/json'
35
+ headers['user-agent'] = 'Frankly-SDK/1.0.0 (Ruby)'
36
+ headers
37
+ end
38
+ end
@@ -0,0 +1,655 @@
1
+ ##
2
+ # The MIT License (MIT)
3
+ #
4
+ # Copyright (c) 2015 Frankly Inc.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+ ##
24
+
25
+ # = Usage
26
+ # The sections below explain how to use the module to authenticate and query the <b>
27
+ # Frankly API</b>.
28
+ #
29
+ # All operations to the API are made from instances of the <b>FranklyClient</b> class. Those
30
+ # objects expose methods to the application which map to remote procedure calls (RPC)
31
+ # on the <b>Frankly</b> servers, they also negotiate and maintain the state required by the
32
+ # API's security policies.
33
+ #
34
+ # Here's how <b>FranklyClient</b> instances are created:
35
+ # require 'frankly-ruby'
36
+ # client = FranklyClient.new
37
+ #
38
+ # == Authentication
39
+ # Before performing any operation (calling any method) the client instance needs to authenticate
40
+ # against Frankly API. The API supports different level of permissions but this module is design
41
+ # to only allow <em>admin</em> authentication.
42
+ #
43
+ # When authenticating as an <em>admin</em> user the client needs to be given the <b>app_key</b>
44
+ # and <b>app_secret</b> values obtained from the {Frankly Console}[https://console.franklychat.com/].
45
+ #
46
+ # Here's how to perform authentication:
47
+ # require 'frankly-ruby'
48
+ #
49
+ # app_key = 'app_key from Frankly Console'
50
+ # app_secret = 'app_secret from Frankly Console'
51
+ #
52
+ # client = FranklyClient.new
53
+ # client.open(app_key, app_secret)
54
+ #
55
+ # If the call to <b>open</b> returns then authentication was successful and the application can move
56
+ # on and use this instance of <b>FranklyClient</b> to perform other operations.
57
+ #
58
+ # <em>Publishing the</em> <b>app_secret</b> <em>value to the public can have security implications
59
+ # and could be used by an attacker to alter the content of an application.</em>
60
+ #
61
+ # == Rooms
62
+ # One of the central concepts in the <b>Frankly API</b> is the chat room. An application can create,
63
+ # update and delete chat rooms. A chat room can be seen as a collection of messages, with some
64
+ # associated meta-data like the title, description or avatar image to be displayed when the end users
65
+ # access the mobile or web app embedding a <b>Frankly SDK</b>.
66
+ #
67
+ # This code snippet shows how to create chat rooms:
68
+ # require 'frankly-ruby'
69
+ #
70
+ # room_payload = {
71
+ # title: 'Hi',
72
+ # description: 'My First Chat Room',
73
+ # status: 'active'
74
+ # }
75
+ # room = client.create_room(room_payload)
76
+ #
77
+ # As we can see here, when creating a room the application must specify a <em>status</em> property
78
+ # which can be one of the following:
79
+ # * <b>unpublished</b> in this state the room will not be shown to clients fetching the list of
80
+ # available rooms in the app, this is useful if the application needs to create rooms that shouldn't
81
+ # be available yet because they still need to be modified.
82
+ #
83
+ # * <b>active</b> in this state the room will be displayed in all clients fetching the list of available
84
+ # rooms that end users can join to start chatting with each other.
85
+ #
86
+ # * <b>inactive</b> this last state is an intermediary state between the first two, the room will be
87
+ # part of fetching operations but they will not be displayed in the mobile or web app UI, it is useful
88
+ # for testing purposes.
89
+ #
90
+ # == Message
91
+ # Frankly being a chat platform it allows applications to send and receive messages. Naturally
92
+ # <b>FranklyClient</b> instances can publish and fetch messages to chat rooms.
93
+ #
94
+ # This code snippet shows how to create messages:
95
+ # require 'frankly-ruby'
96
+ #
97
+ # message1_payload = {
98
+ # contents: [{
99
+ # type: 'text/plain',
100
+ # value: 'Hello World!'
101
+ # }]
102
+ # }
103
+ # message1 = client.create_room_message(room['id'],create_payload)
104
+ #
105
+ # message2_payload = {
106
+ # contents: [{
107
+ # type: 'image/*',
108
+ # url: 'https://app.franklychat.com/files/...'
109
+ # }]
110
+ # }
111
+ # message2 = client.create_room_message(room['id'],create_payload)
112
+ #
113
+ # Let's explain quickly what's happening here: messages published to chat rooms actually support multiple
114
+ # parts, they may contain few text entries, or a text and an image, etc... So the <em>contents</em> property
115
+ # is actually a list of objects. Fields of the content objects are:
116
+ # * <b>type</b> which is the mime type of the actual content it represent and gives the application
117
+ # informations about how to render the content. This is mandatory.
118
+ #
119
+ # * <b>value</b> which is used for inline resources directly embedded into the message.
120
+ #
121
+ # * <b>url</b> which is used for remote resources that the application can upload and download in parallel of
122
+ # sending or receiving messages. One of <em>value</em> or <em>url</em> must be specified.
123
+ #
124
+ # Typically, text messages are inlined because they are small enough resources that they can be embedded into
125
+ # the message without impact user experience. Images on the other end may take a while to download and rendering
126
+ # can be optimized using caching mechanisms to avoid downloading large resources too often, that's why they should
127
+ # provided as a remote resource (we'll see later in the <em>Files</em> section how to generate remote resource URLs).
128
+ #
129
+ # <em>Keep in mind that messages will be broadcasted to every client application currently listening for messages
130
+ # on the same chat room when they are created.</em>
131
+ #
132
+ # == Announcements
133
+ # Announcements are a different type of messages which are only available to admin users.
134
+ # A client authenticated with admin priviledges can create announcements in the app, which can then be published
135
+ # to one or more rooms at a later time.
136
+ #
137
+ # In mobile and web apps embedding a <b>Frankly SDK</b>, announcements are rendered differently from regular messages,
138
+ # they are highlighted and can be forced to stick at the top of the chat room UI to give some context to end users
139
+ # about what is currently ongoing.
140
+ #
141
+ # Here's how an app using the frankly module would create and then publish announcements:
142
+ # require 'frankly-ruby'
143
+ #
144
+ # anno_payload = {
145
+ # sticky: true,
146
+ # contents: [{
147
+ # type: 'text/plain',
148
+ # value: 'Hello World!'
149
+ # }]
150
+ # }
151
+ #
152
+ # anno = client.create_announcement(anno_payload)
153
+ # client.create_room_message(room.id, {announcement: anno['id']})
154
+ # As we can see here, the announcement is created with the same structure than a regular message. The content of the
155
+ # announcement is actually what is going to be set as the message content when published to a room and obeys the same
156
+ # rules that were described in the <em>Messages</em> section regarding inline and remote content.
157
+ #
158
+ # == Files
159
+ # Objects of the <b>Frankly API</b> can have URL properties set to reference remote resources like images. All these
160
+ # URLs must be within the <b>+https://app.franklychat.com+</b> domain, which means an application must upload these
161
+ # resources to Frankly servers.
162
+ #
163
+ # Uploading a file happens in two steps, first the application needs to request a new file URL to the <b>Frankly API</b>,
164
+ # then it can use that URL to upload a resource to Frankly servers. Lukily the frankly module abstracts this nicely in a
165
+ # single operation, here's an example of how to set an image for a chat room:
166
+ # require 'frankly-ruby'
167
+ #
168
+ # file_payload = {
169
+ # category: 'useravatar',
170
+ # type: 'image'
171
+ # }
172
+ #
173
+ # file = client.upload_file_from_path('./path/to/image.pnp',file_payload)
174
+ # room = client.update_room(room.id, {avatar_image_url = file['url']})
175
+ #
176
+ # The object returned by a call to <b>+upload_file_from_path+</b> and other upload methods is created in the first step
177
+ # described above. The <b>+category+</b> parameter shown here is a hint given the the <b>Frankly API</b> to know what
178
+ # formatting rules should be applied to the resource. This is useful to provide a better integration with Frankly and
179
+ # better user experience as files will be optimized for different situations based on their category.
180
+ #
181
+ # Here are the file categories currently available:
182
+ # * <b>chat</b>
183
+ # The default category which is usually applied to images sent by end users.
184
+ #
185
+ # * <b>useravatar</b>
186
+ # This category optimizes files intended to be displayed as part of a user profile.
187
+ #
188
+ # * <b>roomavatar</b>
189
+ # This category optimizes files intended to be displayed on room lists.
190
+ #
191
+ # * <b>featuredavatar</b>
192
+ # Used for files intended to be displayed to represent featued rooms.
193
+ #
194
+ # * <b>sticker</b>
195
+ # This category optimizes files that are used for sticker messages.
196
+ #
197
+ # * <b>stickerpack</b>
198
+ # for being used as an avatar of a sticker pack.
199
+ #
200
+
201
+ # @!visibility private
202
+ require 'charlock_holmes'
203
+ require 'io/console'
204
+ require 'json'
205
+ require 'jwt'
206
+ require 'mimemagic'
207
+ require 'rest-client'
208
+ require 'uri'
209
+
210
+ require 'frankly-ruby/auth'
211
+ require 'frankly-ruby/announcement'
212
+ require 'frankly-ruby/files'
213
+ require 'frankly-ruby/generic'
214
+ require 'frankly-ruby/message'
215
+ require 'frankly-ruby/rooms'
216
+ require 'frankly-ruby/util'
217
+
218
+ # This function generates an identity token suitable for a single authentication attempt
219
+ # of a client against the Frankly API or SDK
220
+ #
221
+ # @param app_key [String]
222
+ # The key that specifies which app this client is authenticating for, this value is
223
+ # provided by the Frankly Console.
224
+ #
225
+ # @param app_secret [String]
226
+ # The secret value associated the the key allowing the client to securely authenticate
227
+ # against the Frankly API.
228
+ #
229
+ # @param nonce [String]
230
+ # The nonce value got from Frankly SDK or API whether the identity generation comes from
231
+ # an client device or app backend.
232
+ #
233
+ # @param user_id [String]
234
+ # This argument must be set to make the SDK operate on behalf of a specific user of the app.
235
+ # For backend services willing to interact with the API directly this may be omitted.
236
+ #
237
+ # @param role [String]
238
+ # For backend services using the Frankly API this can be set to 'admin' to generate a token
239
+ # allowing the client to get admin priviledges and perform operations that regular users are forbidden to.
240
+ #
241
+ # @return [String]
242
+ # The function returns the generated identity token as a string.
243
+ def generate_identity_token(app_key, app_secret, nonce, user_id = nil, role = nil)
244
+ auth_header = {
245
+ typ: 'JWS',
246
+ alg: 'HS256',
247
+ cty: 'frankly-it;v1'
248
+ }
249
+
250
+ auth_claims = {
251
+ aak: app_key,
252
+ iat: Time.now.to_i,
253
+ exp: Time.now.to_i + 10 * 24 * 60 * 60,
254
+ nce: nonce
255
+ }
256
+
257
+ auth_claims[:uid] = user_id unless user_id.nil?
258
+ auth_claims[:role] = role unless role.nil?
259
+
260
+ JWT.encode(auth_claims, app_secret, 'HS256', auth_header)
261
+ end
262
+
263
+ # Instances of this class can be used to authenticate and query the Frankly REST
264
+ # APIs.
265
+ class FranklyClient
266
+ def initialize(address='https://app.franklychat.com/')
267
+ @base_url = address
268
+ @headers = {}
269
+ @session_token = ''
270
+ end
271
+
272
+
273
+
274
+ # This should be the first method called on an instance of FranklyClient,
275
+ # after succesfully returning the client can be used to interact with the Frankly
276
+ # API.
277
+ #
278
+ # @param app_key [String]
279
+ # The key that specifies which app this client is authenticating for, this value is
280
+ # provided by the Frankly Console.
281
+ #
282
+ # @param app_secret [String]
283
+ # The secret value associated the the key allowing the client to securely authenticate
284
+ # against the Frankly API.
285
+ #
286
+ # @return [nil]
287
+ # The method doesn't return anything, it modified the internal
288
+ # state of the object it is called on.
289
+
290
+ def open(app_key, app_secret)
291
+ nonce = Auth.nonce(@base_url)[1..-2]
292
+
293
+ identity_token = generate_identity_token(app_key, app_secret, nonce, nil, 'admin')
294
+ session = JSON.parse Auth.open(@base_url, identity_token)
295
+ @session_token = session['token']
296
+ @headers = Util.build_headers
297
+ end
298
+
299
+ # Discards all internal state maintained by this client.
300
+ def close
301
+ @session_token = nil
302
+ @headers = nil
303
+ end
304
+
305
+ # Creates a new room object in the app.
306
+ # The properties of that new room are given as hash to the method.
307
+ #
308
+ # @param payload [Hash]
309
+ # A hash containing the properties of the new room. See the Rooms
310
+ # section above to see how properly format this argument
311
+ #
312
+ # @return [Hash]
313
+ # The method returns a hash that represents the newly created room.
314
+ def create_room(payload)
315
+ JSON.parse Rooms.create_room(@base_url, @headers, @session_token, payload.to_json)
316
+ end
317
+
318
+ # Retrieves the list of all available rooms from the app.
319
+ #
320
+ # @return [Array]
321
+ # The method returns a list of hashes ordered by id, which may be empty if there are no
322
+ # rooms in the app.
323
+ def read_room_list
324
+ JSON.parse Rooms.read_room_list(@base_url, @headers, @session_token)
325
+ end
326
+
327
+ # Retrieves a room object with id specified as first argument from the app.
328
+ #
329
+ # @param room_id [Int]
330
+ # The identifier of the room to fetch.
331
+ #
332
+ # @return [Hash]
333
+ # The method returns a hash that represents the fetched room.
334
+ def read_room(room_id)
335
+ JSON.parse Rooms.read_room(@base_url, @headers, @session_token, room_id)
336
+ end
337
+
338
+ # Updates an existing room object in the app and return that object.
339
+ # The properties of that new room are given as a hash to the method.
340
+ #
341
+ # @param room_id [Integer]
342
+ # The identifier of the room to update.
343
+ #
344
+ # @param payload [Hash]
345
+ # A hash containing the properties of the new room. See the Rooms
346
+ # section above to see how properly format this argument
347
+ #
348
+ # @return [Hash]
349
+ # The method returns a hash that represents the newly updated room.
350
+ def update_room(room_id, payload)
351
+ JSON.parse Rooms.update_room(@base_url, @headers, @session_token,
352
+ room_id, payload.to_json)
353
+ end
354
+
355
+ # Deletes an room object with id sepecified as first argument from the app.
356
+ # Note that this will cause all messages sent to this room to be deleted as well,
357
+ # a safer approach could be to change the room status to 'unpublished' to hide it without erasing data.
358
+ # This operation cannot be undone!
359
+ #
360
+ # @param room_id [Int]
361
+ # The identifier of the room to delete.
362
+ #
363
+ # @return [nil]
364
+ # The method doesn't return anything on success and throws an exception on failure.
365
+ def delete_room(room_id)
366
+ Rooms.delete_room(@base_url, @headers, @session_token, room_id)
367
+ end
368
+
369
+ # This method exposes a generic interface for creating objects through the Frankly API.
370
+ # Every create_* method is implemented on top of this one.
371
+ #
372
+ # @param path [Array]
373
+ # An Array of strings representing the collection to create an object in.
374
+ #
375
+ # @param params [Hash]
376
+ # Parameters passed as part of the request.
377
+ #
378
+ # @param payload [Hash]
379
+ # Dict-like object representing the object to create.
380
+ #
381
+ # @return [Hash/Array]
382
+ # The method returns either a hash, or an array of hashes representing the
383
+ # object or objects that were created.
384
+ def create(path, params = {}, payload = {})
385
+ JSON.parse Generic.create(@base_url, @headers, @session_token, path, params, payload)
386
+ end
387
+
388
+ # This method exposes a generic interface for reading objects through the Frankly API.
389
+ # Every read_* method is implemented on top of this one.
390
+ #
391
+ # @param path [Array]
392
+ # An Array of strings representing the collection to read an object in.
393
+ #
394
+ # @param params [Hash]
395
+ # Parameters passed as part of the request.
396
+ #
397
+ # @param payload [Hash]
398
+ # Dict-like object representing the object to create.
399
+ #
400
+ # @return [Hash/Array]
401
+ # The method returns the object read from the API at the specified path.
402
+ def read(path, params = {}, payload = {})
403
+ JSON.parse Generic.read(@base_url, @headers, @session_token, path, params, payload)
404
+ end
405
+
406
+ # This method exposes a generic interface for updating objects through the Frankly API.
407
+ # Every read_* method is implemented on top of this one.
408
+ #
409
+ # @param path [Array]
410
+ # An Array of strings representing the collection to read an object in.
411
+ #
412
+ # @param params [Hash]
413
+ # Parameters passed as part of the request.
414
+ #
415
+ # @param payload [Hash]
416
+ # Dict-like object representing the object to create.
417
+ #
418
+ # @return [Hash/Array]
419
+ # The method returns the object updated on the API at the specified path.
420
+ def update(path, params = {}, payload = {})
421
+ JSON.parse Generic.update(@base_url, @headers, @session_token, path, params, payload)
422
+ end
423
+
424
+ # This method exposes a generic interface for deleting objects through the Frankly API.
425
+ # Every delete_* method is implemented on top of this one.
426
+ #
427
+ # @param path [Array]
428
+ # An Array of strings representing the collection to delete an object in.
429
+ #
430
+ # @param params [Hash]
431
+ # Parameters passed as part of the request.
432
+ #
433
+ # @param payload [Hash]
434
+ # A hash representing the body of the request.
435
+ #
436
+ # @return [nil]
437
+ # The method doesn't return anything on success and throws
438
+ # an exception on failure.
439
+ def delete(path, params = {}, payload = {})
440
+ JSON.parse Generic.delete(@base_url, @headers, @session_token, path, params, payload)
441
+ end
442
+
443
+ # This method exposes a generic interface for uploading file contents through the Frankly API.
444
+ # Every upload_* method is implemented on top of this one.
445
+ #
446
+ # @param url [String]
447
+ # The URL at which the file is hosted on Frankly servers. This can be obtained
448
+ # from the url field of an object returned by create_file for example.
449
+ #
450
+ # @param params [Hash]
451
+ # Parameters passed as part of the request.
452
+ #
453
+ # @param payload [Hash]
454
+ # A hash representing the body of the request.
455
+ #
456
+ # @param content_length [Int]
457
+ # The size of the new file content (in bytes).
458
+ #
459
+ # @param content_type [String]
460
+ # The mime type of the new file content.
461
+ #
462
+ # @param content_encoding [String]
463
+ # The encoding of the new file content ('gzip' for example).
464
+ #
465
+ # @return [nil]
466
+ # The method doesn't return anything on success and throws an exception on failure.
467
+ def upload(url, params, payload, content_length, content_type, content_encoding)
468
+ JSON.parse Generic.upload(@base_url, @headers, @session_token, url, params, payload, content_length, content_type, content_encoding)
469
+ end
470
+
471
+ # Creates a new announcement object in the app.
472
+ # The properties of that new announcement are given as hash to the method.
473
+ #
474
+ # @param payload [Hash]
475
+ # A hash containing the properties of the new announcement. See the Announcement
476
+ # section above to see how properly format this argument
477
+ #
478
+ # @return [Hash]
479
+ # The method returns a hash that represents the newly created announcement.
480
+ def create_announcement(payload)
481
+ JSON.parse Announcement.create_announcement(@base_url, @headers, @session_token, payload.to_json)
482
+ end
483
+
484
+ # Retrieves an announcement object with id sepecified as first argument from the app.
485
+ #
486
+ # @param announcement_id [Int]
487
+ # The identifier of the announcement to fetch.
488
+ #
489
+ # @return [Hash]
490
+ # The method returns a hash representing the announcement wit the specified id in the app.
491
+ def read_announcement(announcement_id)
492
+ JSON.parse Announcement.read_announcement(@base_url, @headers, @session_token, announcement_id)
493
+ end
494
+
495
+ # Deletes an announcement object with id sepecified as first argument from the app.
496
+ # Note that deleting an announcement doesn't remove messages from rooms it has already been published to.
497
+ # This operation cannot be undone!
498
+ #
499
+ # @param announcement_id [Int]
500
+ # The identifier of the announcement to delete.
501
+ #
502
+ # @return [nil]
503
+ # The method doesn't return anything on success and throws an exception on failure.
504
+ def delete_announcement(announcement_id)
505
+ Announcement.delete_announcement(@base_url, @headers, @session_token, announcement_id)
506
+ end
507
+
508
+ # Retrieves a list of announcements available in the app.
509
+ #
510
+ # @return [Array]
511
+ # The method returns an array of annoucement hashes ordered by id, which may be empty if
512
+ # there are no announcements in the app.
513
+ def read_announcement_list
514
+ JSON.parse Announcement.read_announcement_list(@base_url, @headers, @session_token)
515
+ end
516
+
517
+ # Retrieves the list of rooms that an annoucement has been published to.
518
+ #
519
+ # @param announcement_id [Int]
520
+ # The identifier of the announcement to get the list of rooms for.
521
+ #
522
+ # @return [Array]
523
+ # The method returns a list of room objects ordered by id, which may be empty
524
+ # if the announcement haven't been published yet.
525
+ def read_announcement_room_list(announcement_id)
526
+ JSON.parse Announcement.read_announcement_room_list(@base_url, @headers, @session_token, announcement_id)
527
+ end
528
+
529
+ # Creates a new message object in the room with id specified as first argument.
530
+ # The properties of that new message are given as hash to the method.
531
+ #
532
+ # @param room_id [Int]
533
+ # The identifier of the room to create the message in.
534
+ #
535
+ # @param payload [Hash]
536
+ # A hash containing the properties of the new message. See the Messages
537
+ # section above to see how properly format this argument
538
+ #
539
+ # @return [Hash]
540
+ # The method returns a hash that represents the newly created message.
541
+ def create_room_message(room_id, payload)
542
+ JSON.parse Message.create_room_message(@base_url, @headers, @session_token, room_id, payload)
543
+ end
544
+
545
+ # Creates a new message object in the room with id specified as first argument.
546
+ # The properties of that new message are given as hash to the method.
547
+ #
548
+ # @param room_id [Int]
549
+ # The identifier of the room to create the message in.
550
+ #
551
+ # @param params [Hash]
552
+ # A hash that defines the range of the messages that are fetched. See the Messages
553
+ # section above to see how properly format this argument.
554
+ #
555
+ # @return [Array]
556
+ # The method returns an array of room hashes which may be empty if no messages satisfy the query.
557
+ def read_room_message_list(room_id, params)
558
+ JSON.parse Message.read_room_message_list(@base_url, @headers, @session_token, room_id, params)
559
+ end
560
+
561
+ # Creates a new file object on Frankly servers and returns that object.
562
+ # The properties of that new file are given as a hash to the method.
563
+ #
564
+ # @param payload [Hash]
565
+ # A hash containing the properties of the new file. See the Files
566
+ # section above to see how properly format this argument.
567
+ #
568
+ # @return [Hash]
569
+ # The method returns a hash that represents the newly created file.
570
+ def create_file(payload)
571
+ JSON.parse Files.create_file(@base_url, @headers, @session_token, payload.to_json)
572
+ end
573
+
574
+ # Creates a new file object on Frankly servers and returns that object.
575
+ # The properties of that new file are given as a hash to the method.
576
+ #
577
+ # @param destination_url [String]
578
+ # The URL at which the file is hosted on Frankly servers. This can be obtained
579
+ # from the url field of an object returned by create_file for example.
580
+ #
581
+ # @param file_obj [File]
582
+ # A file-like object (as returned by File.open(..., "rb") for example) providing
583
+ # the new content of the file.
584
+ #
585
+ # @param file_size [Int]
586
+ # The size of the new file content (in bytes).
587
+ #
588
+ # @param mime_type [String]
589
+ # The mime type of the new file content.
590
+ #
591
+ # @param encoding [String]
592
+ # The encoding of the new file content ('gzip' for example).
593
+ #
594
+ # @return [nil]
595
+ # The method doesn't return anything on success and throws an exception on failure.
596
+ def update_file(destination_url, file_obj, file_size, mime_type, encoding = nil)
597
+ Files.upload_file(@base_url, @headers, @session_token, destination_url, file_obj, file_size, mime_type, encoding)
598
+ end
599
+
600
+ # Creates a new file object on Frankly servers and returns that object.
601
+ # The properties of that new file are given as a hash to the method.
602
+ #
603
+ # @param destination_url [String]
604
+ # The URL at which the file is hosted on Frankly servers. This can be obtained
605
+ # from the url field of an object returned by create_file for example.
606
+ #
607
+ # @param file_path [String]
608
+ # A path to a local providing the new file content
609
+ #
610
+ # @return [nil]
611
+ # The method doesn't return anything on success and throws an exception on failure.
612
+ def update_file_from_path(destination_url, file_path)
613
+ Files.update_file_from_path(@base_url, @headers, @session_token, destination_url, file_path)
614
+ end
615
+
616
+ # This method is convenience wrapper for creating a new file object on the Frankly API and setting its content.
617
+ #
618
+ # @param file_obj [File]
619
+ # A file-like object (as returned by File.open(..., "rb") for example) providing
620
+ # the new content of the file.
621
+ #
622
+ # @param file_size [Int]
623
+ # The size of the new file content (in bytes).
624
+ #
625
+ # @param mime_type [String]
626
+ # The mime type of the new file content.
627
+ #
628
+ # @param encoding [String]
629
+ # The encoding of the new file content ('gzip' for example).
630
+ #
631
+ # @param params [Hash]
632
+ # A hash containing the properties of the new file. See the Files
633
+ # section above to see how properly format this argument.
634
+ #
635
+ # @return [Hash]
636
+ # The method returns a hash that represents the newly created file.
637
+ def upload_file(file_obj, file_size, mime_type, encoding = nil, params)
638
+ Files.upload_file(@base_url, @headers, @session_token, destination_url, file_obj, file_size, mime_type, encoding, params)
639
+ end
640
+
641
+ # This method is convenience wrapper for creating a new file object on the Frankly API and setting its content.
642
+ #
643
+ # @param file_path [String]
644
+ # A path to a local providing the new file content
645
+ #
646
+ # @param params [Hash]
647
+ # A hash containing the properties of the new file. See the Files
648
+ # section above to see how properly format this argument.
649
+ #
650
+ # @return [Hash]
651
+ # The method returns a hash that represents the newly created file.
652
+ def upload_file_from_path(file_path, params)
653
+ Files.upload_file_from_path(@base_url, @headers, @session_token, file_path, params)
654
+ end
655
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: frankly-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Phox
8
+ - Achille Roussel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-06-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: io-console
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.4'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.2
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '0.4'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.2
34
+ - !ruby/object:Gem::Dependency
35
+ name: json
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.8.1
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '1.8'
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.8.1
54
+ - !ruby/object:Gem::Dependency
55
+ name: jwt
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.4'
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.4.1
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.4'
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 1.4.1
74
+ - !ruby/object:Gem::Dependency
75
+ name: rest-client
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '1.8'
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 1.8.0
84
+ type: :runtime
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1.8'
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 1.8.0
94
+ - !ruby/object:Gem::Dependency
95
+ name: minitest
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '5.4'
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 5.4.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.4'
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: 5.4.3
114
+ - !ruby/object:Gem::Dependency
115
+ name: rake
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - "~>"
119
+ - !ruby/object:Gem::Version
120
+ version: '10.4'
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: 10.4.2
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '10.4'
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: 10.4.2
134
+ description:
135
+ email:
136
+ executables: []
137
+ extensions: []
138
+ extra_rdoc_files: []
139
+ files:
140
+ - lib/frankly-ruby.rb
141
+ - lib/frankly-ruby/announcement.rb
142
+ - lib/frankly-ruby/auth.rb
143
+ - lib/frankly-ruby/files.rb
144
+ - lib/frankly-ruby/generic.rb
145
+ - lib/frankly-ruby/message.rb
146
+ - lib/frankly-ruby/rooms.rb
147
+ - lib/frankly-ruby/util.rb
148
+ homepage: https://github.com/franklyinc/frankly-ruby/
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 2.4.5
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: Frankly Ruby SDK
172
+ test_files: []
173
+ has_rdoc: