frankly-ruby 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: