ringcentral-avatars 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b81a6e0a914a3dd91979611efbdccf01ff20777b
4
- data.tar.gz: a552c45e8d29216d21811f875b92fa0e1bf9e115
3
+ metadata.gz: 36141cadb78befc9afe2c8383721e8645d9e320a
4
+ data.tar.gz: 55e6cc5ed25ab49f57391a51c65e92450c813f13
5
5
  SHA512:
6
- metadata.gz: 63170405d21dd1a21526405b70a3c5404b2914b05516d9455232a0cb32ff9f8037d878a39bea8d9bca3637cf032ccd0c784cb0e339e4f1fa96b3060114a89a9e
7
- data.tar.gz: c9524a420f36a8c2f888c4ea16c194521454fe3f57802f16254e77999130a007cf69774718f8ba131ae887628286da23443626135a69a1f3b9f4e033d1e66313
6
+ metadata.gz: ff2d64ea6868369971ebb40ce485118416c8ef7052c9b0421bda7d1c98e41e48147b6a501bfc1f1494e07d8e13fe696528de97cffc5fe50fa572d684ff5ce36c
7
+ data.tar.gz: 9734754fe66688298036dd7c5fd08ec67ec564f4e9732c27462475c230bcaf7364e054023d8cb04a0b92dcba7ee80e1b3d379053ff490b43c541b01e95ab56d1
@@ -1,5 +1,11 @@
1
1
  CHANGELOG
2
2
  ---------
3
+ - **2016-12-28**: 0.5.0
4
+ - Add auto-retry for `429` and `503` errors.
5
+ - Add test script to try PNG, JPG, and GIF filetypes
6
+ - Add article `NEWS.md`
7
+ - **2016-11-19**: 0.4.1
8
+ - Fix RubyDoc.info documentation rendering
3
9
  - **2016-11-19**: 0.4.0
4
10
  - Add PNG metadata support
5
11
  - Add demo scripts in `./scripts` directory
@@ -0,0 +1,164 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ringcentral-avatars (0.5.0)
5
+ avatarly (~> 1.5, >= 1.5.0)
6
+ chunky_png (~> 1.3, >= 1.3.8)
7
+ faraday (~> 0.9, >= 0.9)
8
+ mime-types (~> 3.0, >= 3.1)
9
+ ringcentral_sdk (~> 2, >= 2.0.2)
10
+ ruby_identicon (~> 0, >= 0.0.5)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ avatarly (1.5.0)
16
+ rfc822
17
+ rmagick
18
+ unicode_utils
19
+ celluloid (0.17.3)
20
+ celluloid-essentials
21
+ celluloid-extras
22
+ celluloid-fsm
23
+ celluloid-pool
24
+ celluloid-supervision
25
+ timers (>= 4.1.1)
26
+ celluloid-essentials (0.20.5)
27
+ timers (>= 4.1.1)
28
+ celluloid-extras (0.20.5)
29
+ timers (>= 4.1.1)
30
+ celluloid-fsm (0.20.5)
31
+ timers (>= 4.1.1)
32
+ celluloid-pool (0.20.5)
33
+ timers (>= 4.1.1)
34
+ celluloid-supervision (0.20.6)
35
+ timers (>= 4.1.1)
36
+ chunky_png (1.3.8)
37
+ concurrent-ruby (1.0.3)
38
+ coveralls (0.8.17)
39
+ json (>= 1.8, < 3)
40
+ simplecov (~> 0.12.0)
41
+ term-ansicolor (~> 1.3)
42
+ thor (~> 0.19.1)
43
+ tins (~> 1.6)
44
+ docile (1.1.5)
45
+ dotenv (2.1.1)
46
+ dry-configurable (0.5.0)
47
+ concurrent-ruby (~> 1.0)
48
+ dry-container (0.6.0)
49
+ concurrent-ruby (~> 1.0)
50
+ dry-configurable (~> 0.1, >= 0.1.3)
51
+ dry-core (0.2.1)
52
+ concurrent-ruby (~> 1.0)
53
+ dry-equalizer (0.2.0)
54
+ dry-logic (0.4.0)
55
+ dry-container (~> 0.2, >= 0.2.6)
56
+ dry-core (~> 0.1)
57
+ dry-equalizer (~> 0.2)
58
+ dry-types (0.9.3)
59
+ concurrent-ruby (~> 1.0)
60
+ dry-configurable (~> 0.1)
61
+ dry-container (~> 0.3)
62
+ dry-core (~> 0.2, >= 0.2.1)
63
+ dry-equalizer (~> 0.2)
64
+ dry-logic (~> 0.4, >= 0.4.0)
65
+ inflecto (~> 0.0.0, >= 0.0.2)
66
+ dry-validation (0.10.4)
67
+ concurrent-ruby (~> 1.0)
68
+ dry-configurable (~> 0.1, >= 0.1.3)
69
+ dry-container (~> 0.2, >= 0.2.8)
70
+ dry-core (~> 0.2, >= 0.2.1)
71
+ dry-equalizer (~> 0.2)
72
+ dry-logic (~> 0.4, >= 0.4.0)
73
+ dry-types (~> 0.9, >= 0.9.0)
74
+ faraday (0.9.2)
75
+ multipart-post (>= 1.2, < 3)
76
+ faraday_middleware (0.10.1)
77
+ faraday (>= 0.7.4, < 1.0)
78
+ faraday_middleware-oauth2_refresh (0.0.3)
79
+ faraday (~> 0.9, >= 0.9)
80
+ faraday_middleware (~> 0, >= 0)
81
+ faraday_middleware-request-retry (0.2.0)
82
+ faraday (~> 0, >= 0)
83
+ faraday_middleware (~> 0, >= 0)
84
+ hitimes (1.2.4)
85
+ httpclient (2.8.3)
86
+ inflecto (0.0.2)
87
+ json (2.0.2)
88
+ jsondoc (0.1.3)
89
+ jwt (1.5.6)
90
+ logger (1.2.8)
91
+ metaclass (0.0.4)
92
+ mime (0.4.3)
93
+ mime-types (3.1)
94
+ mime-types-data (~> 3.2015)
95
+ mime-types-data (3.2016.0521)
96
+ mime_builder (0.0.4)
97
+ mime (~> 0.4, >= 0.4.3)
98
+ mime-types (~> 3.1)
99
+ multi_json (~> 1, >= 1.12.1)
100
+ mocha (1.2.1)
101
+ metaclass (~> 0.0.1)
102
+ multi_json (1.12.1)
103
+ multi_xml (0.6.0)
104
+ multipart-post (2.0.0)
105
+ oauth2 (1.2.0)
106
+ faraday (>= 0.8, < 0.10)
107
+ jwt (~> 1.0)
108
+ multi_json (~> 1.3)
109
+ multi_xml (~> 0.5)
110
+ rack (>= 1.2, < 3)
111
+ power_assert (0.4.1)
112
+ pubnub (4.0.17)
113
+ celluloid (~> 0.17)
114
+ dry-validation (~> 0.10)
115
+ httpclient (~> 2.8)
116
+ json (>= 1.8, < 3)
117
+ rack (2.0.1)
118
+ rake (11.3.0)
119
+ rfc822 (0.1.5)
120
+ ringcentral_sdk (2.0.3)
121
+ dotenv (~> 2.1, >= 2.1.0)
122
+ faraday (~> 0, >= 0)
123
+ faraday_middleware (~> 0, >= 0)
124
+ faraday_middleware-oauth2_refresh (~> 0)
125
+ faraday_middleware-request-retry (~> 0.1, >= 0.1.0)
126
+ jsondoc (~> 0.1, >= 0.1.0)
127
+ logger (~> 1)
128
+ mime (~> 0.4, >= 0.4.3)
129
+ mime-types (~> 3.1)
130
+ mime_builder (~> 0, >= 0.0.4)
131
+ multi_json (~> 1.3)
132
+ oauth2 (~> 1.0, >= 1.0.0)
133
+ pubnub (~> 4.0)
134
+ rmagick (2.16.0)
135
+ ruby_identicon (0.0.5)
136
+ chunky_png (~> 1.3.5)
137
+ simplecov (0.12.0)
138
+ docile (~> 1.1.0)
139
+ json (>= 1.8, < 3)
140
+ simplecov-html (~> 0.10.0)
141
+ simplecov-html (0.10.0)
142
+ term-ansicolor (1.4.0)
143
+ tins (~> 1.0)
144
+ test-unit (3.2.3)
145
+ power_assert
146
+ thor (0.19.4)
147
+ timers (4.1.2)
148
+ hitimes
149
+ tins (1.13.0)
150
+ unicode_utils (1.4.0)
151
+
152
+ PLATFORMS
153
+ ruby
154
+
155
+ DEPENDENCIES
156
+ coveralls (~> 0)
157
+ mocha (~> 1)
158
+ rake (~> 11)
159
+ ringcentral-avatars!
160
+ simplecov (~> 0)
161
+ test-unit (~> 3)
162
+
163
+ BUNDLED WITH
164
+ 1.13.6
data/NEWS.md ADDED
@@ -0,0 +1,278 @@
1
+ Using The Profile Image API and Default Images
2
+ ==============================================
3
+
4
+ The RingCentral Profile Image API is a powerful API that can be used to upload images that are used in the corporate address book both individually and administratively across users. Some popular use cases include:
5
+
6
+ 1. Syncing images from Active Directory or Okta
7
+ 2. Uploading images from mobile apps
8
+ 3. Setting default images for users
9
+
10
+ For this article, we'll cover API basics and then discuss how to set default images using either user initials like Gmail/Office 365 or Identicons. The initials will look like the following in the RingCentral for Desktop softphone. The avatars will update in the softphone in real-time as they are changed on the backend:
11
+
12
+ ![](https://raw.githubusercontent.com/ringcentral-ruby/ringcentral-avatars-ruby/master/docs/images/ringcentral-avatars-softphone.png)
13
+
14
+ We will cover:
15
+
16
+ 1. API basics
17
+ 1. User profile image information
18
+ 1. Example user object
19
+ 2. Update user profile image
20
+ 1. Example request
21
+ 3. Subscribing for avatar updates
22
+ 1. Example request
23
+ 2. Example response
24
+ 3. Retrieving the user image
25
+ 2. Default images recipe
26
+ 1. Getting a list of extensions without avatars
27
+ 2. Creating the default image
28
+ 3. Identifying auto-generated default images
29
+ 4. Wrapping it up
30
+ 1. Notes
31
+ 2. Throttling
32
+
33
+ This article uses the Ruby language and leverages the community [`ringcentral_sdk`](https://rubygems.org/gems/ringcentral_sdk) SDK gem. It presents code which is implemented in a similar way in the [`ringcentral-avatars`](https://rubygems.org/gems/ringcentral-avatars) Ruby gem for discussion purposes. If you just want to use the functionality, you can use the Ruby gem directly.
34
+
35
+ ## API basics
36
+
37
+ When working with the Profile API, there are a few basic APIs to use:
38
+
39
+ | method | endpoint | notes |
40
+ |--------|----------|-------|
41
+ | `GET` | `account/~/extension/~` | Get your own extension info with profile image information. |
42
+ | `GET` | `account/~/extension` | Get a list of extension with profile image information. |
43
+ | `PUT` | `account/~/extension/~/profile-image` | Update the user's profile image with a binary image file. |
44
+ | n/a | `account/~/extension` | Event filter for webhook and PubNub-based subscriptions |
45
+
46
+ ### User profile image information
47
+
48
+ To retrieve the extension `profileImage` information for a user, retrieve the user's `account/~/extension/~` endpoint.
49
+
50
+ #### Example user object
51
+
52
+ ```json
53
+ {
54
+ "uri": "https://platform.devtest.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222",
55
+ "id": 22222222,
56
+ "extensionNumber": "102",
57
+ "contact": {
58
+ "firstName": "Alice"
59
+ "businessPhone": "+6505550102"
60
+ },
61
+ "name": "Alice",
62
+ "type": "User",
63
+ "status": "Enabled",
64
+ "permissions": {
65
+ "admin": {
66
+ "enabled": false
67
+ },
68
+ "internationalCalling": {
69
+ "enabled": false
70
+ }
71
+ },
72
+ "profileImage": {
73
+ "uri": "https://media.devtest.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/profile-image",
74
+ "etag": "0123456789abcdef0123456789abcdef",
75
+ "contentType": "image/png",
76
+ "lastModified": "2016-11-01T00:00:00.000Z",
77
+ "scales": [
78
+ {
79
+ "uri": "https://media.devtest.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/profile-image/90x90"
80
+ },
81
+ {
82
+ "uri": "https://media.devtest.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/profile-image/195x195"
83
+ },
84
+ {
85
+ "uri": "https://media.devtest.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/profile-image/584x584"
86
+ }
87
+ ]
88
+ }
89
+ }
90
+ ```
91
+
92
+ ### Update user profile image
93
+
94
+ To update an image make a `PUT` request to the user's `account/~/extension/~/profile-image` endpoint using `multipart/formdata` and the `image` attribute.
95
+
96
+ #### Example request
97
+
98
+ Using the Ruby SDK, you can do the following:
99
+
100
+ ```ruby
101
+ url = 'account/~/extension/~/profile-image'
102
+ file = Faraday::UploadIO.new '/path/to/myimage.png', 'image/png'
103
+
104
+ client.http.put url, image: file
105
+ ```
106
+
107
+ ### Subscribing for avatar updates
108
+
109
+ Client applications can subscribe for updates by using the Subscription API using either webhooks or PubNub using the `account/~/extension` event filter. The app will be notified of changes in real time and can retrieve the relevant images. This type of client-side update is implemented in the RingCentral for Desktop softphone app.
110
+
111
+ #### Example request
112
+
113
+ ```ruby
114
+ # Create an observable subscription and add your observer
115
+ sub = client.create_subscription()
116
+ sub.subscribe([ "/restapi/v1.0/account/~/extension" ])
117
+ sub.add_observer MyObserver.new()
118
+ ```
119
+
120
+ #### Example event
121
+
122
+ When a user's extension has changed for any reason, including, profile image updates, an event is fired that matches `account/~/extension` filter mentioned above with the following example format. Once you have the `extensionId` you can retrieve the user extension if to see if the `etag` has changed. If so, you can retrieve and update the image in your app.
123
+
124
+ ```ruby
125
+ {
126
+ "uuid":"11112222-0000-0000-0000-333344445555",
127
+ "event":"/restapi/v1.0/account/11111111/extension",
128
+ "timestamp":"2016-11-23T16:42:08.482Z",
129
+ "subscriptionId":"11112222-1111-1111-1111-333344445555",
130
+ "body": {
131
+ "extensions":[
132
+ {"extensionId":"22222222","eventType":"Update"}
133
+ ]
134
+ }
135
+ }
136
+ ```
137
+
138
+ ## Default images recipe
139
+
140
+ To create default images we want to do a few things:
141
+
142
+ 1. Get a list of all extensions which do not have avatars
143
+ 2. Create and upload default images for extensions
144
+
145
+ ### Getting a list of extensions without avatars
146
+
147
+ To get a list of extensions without avatars, we need to get a list of all extensions and then filter for users without avatars. Since we do not have a way to do this server-side, we will retrieve all extensions and then filter client-side.
148
+
149
+ For the client-side filter, we will look for the `profileImage.etag` property. The `etag` property will not exist if there is no avatar which is an easy way to identify users that need a default avatar.
150
+
151
+ For example:
152
+
153
+ ```ruby
154
+ require 'ringcentral_sdk'
155
+
156
+ client = RingCentralSdk.new ...
157
+ client.authorize ...
158
+
159
+ # Retrieve up to 1000 extensions
160
+ res = client.http.get do |req|
161
+ req.url 'account/~/extension'
162
+ req.params['perPage'] = 1000
163
+ end
164
+
165
+ # Filter for users without avatars
166
+ res.body['records'].each do |ext|
167
+ next unless ext['profileImage'].key? 'etag'
168
+ end
169
+ ```
170
+
171
+ The above will work with up to 1000 users. For over 1000 users, you will need to either follow the `navigation.nextPage` property yourself or use the `RingCentralSdk::REST::Cache::Extensions` gem. `RingCentral::Avatars` uses the extension cache similar to the following:
172
+
173
+ ```ruby
174
+ # Load the cache
175
+ cache = RingCentralSdk::REST::Cache::Extensions.new client
176
+ cache.retrieve_all
177
+
178
+ # Cycle through the users
179
+ cache.extensions_hash.each do |ext_id, ext|
180
+ next unless ext['profileImage'].key? 'etag'
181
+ end
182
+ ```
183
+
184
+ ### Creating the default image
185
+
186
+ The default image can be created in one of several ways that including:
187
+
188
+ 1. User initials, like Gmail, Office 365, etc.
189
+ 2. Identicons, like GitHub, Stack Overflow, Wordpress, etc.
190
+
191
+ Both of these are supported directly within `ringcentral-avatars` using `avatarly` and `ruby_identicon` to generate default images. They also both generate blobs:
192
+
193
+ ```ruby
194
+ # Using Initials
195
+ require 'avatarly'
196
+ blob = Avatarly.generate_avatar 'AZ'
197
+
198
+ # Using Identicons
199
+ require 'ruby_identicon'
200
+ blob = RubyIdenticon.create 'AZ'
201
+ ```
202
+
203
+ More information can be found for these particular libraries:
204
+
205
+ * [`avatarly`](https://rubygems.org/gems/avatarly)
206
+ * [`ruby_identicon`](https://rubygems.org/gems/ruby_identicon)
207
+
208
+ ### Identifying auto-generated default images
209
+
210
+ Sometimes there may be a need to identify and overwrite only auto-generated images. The code above will not do this because auto-generated images will have an `etag` like user submitted images.
211
+
212
+ To resolve this, you can add a tag to the image itself which means each image will need to be retrieved and inspected. `ringcentral-avatars` supports setting PNG metadata attributes that can be used to identify default avatars. This can be done using [`chunky_png`](https://rubygems.org/gems/chunky_png):
213
+
214
+ ```ruby
215
+ require 'chunky_png'
216
+
217
+ img = ChunkyPNG::Image.from_blob blob
218
+ img.metadata = { 'Description' => 'My Default Avatar' }
219
+ blob = img.to_blob
220
+ ```
221
+
222
+ For JPEG, Exif can be implemented and is left as a future exercise.
223
+
224
+ ### Wrapping it up
225
+
226
+ Much of this code has been implemented in the [`ringcentral-avatars`](https://rubygems.org/gems/ringcentral-avatars) gem and can be inspected in the gem's source code on GitHub. To use the gem to update your avatar, you can simply use the following commands:
227
+
228
+ ```ruby
229
+ require 'ringcentral-avatars'
230
+ require 'ringcentral_sdk'
231
+
232
+ client = RingCentralSdk.new [...]
233
+
234
+ avatars = RingCentral::Avatars.new client # Default options
235
+ avatars = RingCentral::Avatars.new client, avatar_opts: {font_size: 275} # Avatarly options
236
+
237
+ avatars.create_defaults # create default avatars only
238
+ avatars.create_all # create all avatars, overwriting existing avatars
239
+
240
+ avatars.create_mine # does not overwrite existing user avatar
241
+ avatars.create_mine overwrite: true # overwrite existing user avatar
242
+
243
+ avatars.create_avatar ext # create a default for an extension hash
244
+ avatars.create_avatar ext, overwrite: true # overwrite existing for an extension hash
245
+ ```
246
+
247
+ ## Notes
248
+
249
+ ### Throttling
250
+
251
+ When retrieving and uploading many images, your application can be throttled if it is making API requests above the rate specified in your usage plan. To resolve this, you can make calls one at a time and examine the response status and headers. For example:
252
+
253
+ 1. A `429` status will indicate your app is being throttled. It should wait the specified amount of seconds specified in the `Retry-After` header and then retry the request.
254
+ 2. A `X-Rate-Limit-Remaining` of `0` will indicate that the app has used up its allotment of API calls for the window and should wait the amount of seconds specified in the `X-Rate-Limit-Window` header.
255
+
256
+ Pseudo code for this is:
257
+
258
+ ```ruby
259
+ if res.status == 429
260
+ // Wait for the specified time
261
+ sleep res.headers['Retry-After'].to_i
262
+ // Retry the request
263
+ client.http.get ...
264
+ elsif res.headers['X-Rate-Limit-Remaining'].to_i == 0
265
+ sleep res.headers['X-Rate-Limit-Window'].to_i
266
+ end
267
+ ```
268
+
269
+ In a future release, this type of throttling should be automatically built into the Ruby SDK.
270
+
271
+ ## Summary
272
+
273
+ The RingCentral Profile Image API is a useful way to upload corporate address book images individually and administratively. It can be used for exciting use cases like directory sync, upload from mobile phones and setting default images.
274
+
275
+ If you have questions on this API or this gem, please feel free to ask on the following sites:
276
+
277
+ * [Stack Overflow](http://stackoverflow.com/questions/tagged/ringcentral)
278
+ * [GitHub](https://github.com/ringcentral-ruby/ringcentral-avatars-ruby/issues)
data/README.md CHANGED
@@ -4,6 +4,7 @@ RingCentral Avatars
4
4
  [![Gem Version][gem-version-svg]][gem-version-link]
5
5
  [![Build Status][build-status-svg]][build-status-link]
6
6
  [![Dependency Status][dependency-status-svg]][dependency-status-link]
7
+ [![Codacy Badge][codacy-svg]][codacy-link]
7
8
  [![Code Climate][codeclimate-status-svg]][codeclimate-status-link]
8
9
  [![Scrutinizer Code Quality][scrutinizer-status-svg]][scrutinizer-status-link]
9
10
  [![Downloads][downloads-svg]][downloads-link]
@@ -49,7 +50,7 @@ $ gem install ringcentral-avatars
49
50
  require 'ringcentral-avatars'
50
51
  require 'ringcentral_sdk'
51
52
 
52
- client = RingCentralSdk.new [...]
53
+ client = RingCentralSdk::REST::Client.new [...]
53
54
 
54
55
  avatars = RingCentral::Avatars.new client # Default options
55
56
  avatars = RingCentral::Avatars.new client, avatar_opts: {font_size: 275} # Avatarly options
@@ -64,7 +65,8 @@ avatars.create_avatar ext # create a default for an extension h
64
65
  avatars.create_avatar ext, overwrite: true # overwrite existing for an extension hash
65
66
  ```
66
67
 
67
- See [Avatarly](https://github.com/lucek/avatarly) for avatar customization options. The default avatar size is `600`.
68
+ * For batch operations, consider using [RingCentral SDK's] `config.retry = true` option for automatic handling of rate limiting using 429 headers.
69
+ * For avatar customization, see [Avatarly](https://github.com/lucek/avatarly) options. The default avatar size is `600`.
68
70
 
69
71
  ### Adding PNG Metadata
70
72
 
@@ -103,10 +105,36 @@ $ ruby get_avatar.rb
103
105
  $ ruby avatar_info.rb
104
106
  ```
105
107
 
108
+ ## Test Uploads
109
+
110
+ The `scripts` directory contains test images for `png`, `jpg`, and `gif` file types: `test_filetype_png.png`, `test_filetype_jpg.jpg`, and `test_filetype_gif.gif`.
111
+
112
+ ### Test Upload Script
113
+
114
+ This repo also includes test scripts to upload PNG, JPG, and GIF format images.
115
+
116
+ ```bash
117
+ $ cd ringcentral-avatars-ruby/scripts
118
+ $ vi .env
119
+ $ ruby test_filetype.rb --filetype=png
120
+ $ ruby test_filetype.rb --filetype=jpg
121
+ $ ruby test_filetype.rb --filetype=gif
122
+ ```
123
+
124
+ ### Test cURL Command
125
+
126
+ ```bash
127
+ $ curl -v -H 'Authorization: Bearer <MY_ACCESS_TOKEN>' -F image=@test_filetype_gif.gif 'https://platform.devtest.ringcentral.com/restapi/v1.0/account/~/extension/~/profile-image'
128
+ ```
129
+
106
130
  ### Change Log
107
131
 
108
132
  See [CHANGELOG.md](CHANGELOG.md)
109
133
 
134
+ ## Credits
135
+
136
+ Test icons files are adapted from freeware [Filetype Icons](http://www.iconarchive.com/show/filetype-icons-by-graphicloads.html) by [GraphicLoads](http://www.iconarchive.com/artist/graphicloads.html).
137
+
110
138
  ## Links
111
139
 
112
140
  Project Repo
@@ -145,6 +173,8 @@ RingCentral Avatars &copy; 2016 by John Wang
145
173
  [downloads-link]: https://rubygems.org/gems/ringcentral-avatars
146
174
  [build-status-svg]: https://api.travis-ci.org/ringcentral-ruby/ringcentral-avatars-ruby.svg?branch=master
147
175
  [build-status-link]: https://travis-ci.org/ringcentral-ruby/ringcentral-avatars-ruby
176
+ [codacy-svg]: https://api.codacy.com/project/badge/Grade/e82eac58a42d4463885627f78098bbb0
177
+ [codacy-link]: https://www.codacy.com/app/johncwang/ringcentral-avatars-ruby
148
178
  [coverage-status-svg]: https://coveralls.io/repos/ringcentral-ruby/ringcentral-avatars-ruby/badge.svg?branch=master
149
179
  [coverage-status-link]: https://coveralls.io/r/ringcentral-ruby/ringcentral-avatars-ruby?branch=master
150
180
  [dependency-status-svg]: https://gemnasium.com/ringcentral-ruby/ringcentral-avatars-ruby.svg
@@ -2,7 +2,7 @@ require 'ringcentral-avatars/creator'
2
2
 
3
3
  module RingCentral
4
4
  module Avatars
5
- VERSION = '0.4.1'
5
+ VERSION = '0.5.0'.freeze
6
6
 
7
7
  class << self
8
8
  def new(client, opts = {})
@@ -3,6 +3,8 @@ require 'chunky_png'
3
3
  require 'ruby_identicon'
4
4
 
5
5
  require 'faraday'
6
+ require 'faraday_middleware-request-retry'
7
+ require 'logger'
6
8
  require 'mime/types'
7
9
  require 'ringcentral_sdk'
8
10
  require 'tempfile'
@@ -11,16 +13,17 @@ module RingCentral
11
13
  module Avatars
12
14
  class Creator
13
15
  DEFAULT_SIZE = 600
14
- DEFAULT_FORMAT = 'png'
16
+ DEFAULT_FORMAT = 'png'.freeze
15
17
  PNG_DEFAULT_METADATA = {
16
18
  'Description' => 'RingCentral Default Avatar'
17
- }
19
+ }.freeze
18
20
 
19
21
  attr_accessor :avatar_opts
20
22
  attr_accessor :avatars
21
23
  attr_accessor :client
22
24
  attr_accessor :extensions
23
25
  attr_accessor :png_metadata
26
+ attr_accessor :retry
24
27
 
25
28
  ##
26
29
  # Requires RingCentralSdk instance
@@ -30,12 +33,16 @@ module RingCentral
30
33
  if !opts.key?(:initials_opts) && opts.key?(:avatar_opts)
31
34
  opts[:initials_opts] = opts[:avatar_opts]
32
35
  end
33
- if opts.key(:png_metadata)
36
+ if opts.key? :png_metadata
34
37
  opts[:png_metadata] = PNG_DEFAULT_METADATA.merge(opts[:png_metadata])
35
38
  else
36
39
  opts[:png_metadata] = PNG_DEFAULT_METADATA
37
40
  end
41
+ opts[:logger] = @client.config.logger
42
+ @retry = opts.key?(:retry) && opts[:retry] ? true : false
43
+ opts[:retry] = @retry
38
44
  @avatars = RingCentral::Avatars::MultiAvatar.new opts
45
+ @retry_util = FaradayMiddleware::Request::RetryUtil.new logger: client.config.logger
39
46
  load_extensions
40
47
  end
41
48
 
@@ -52,7 +59,7 @@ module RingCentral
52
59
  # Defaults to overwriting existing avatar
53
60
  def create_all(opts = {})
54
61
  opts[:overwrite] = true unless opts.key?(:overwrite)
55
- @extensions.extensions_hash.each do |ext_id, ext|
62
+ @extensions.extensions_hash.each do |_ext_id, ext|
56
63
  create_avatar ext, opts
57
64
  end
58
65
  load_extensions
@@ -62,10 +69,13 @@ module RingCentral
62
69
  # Convenience method for creating avatar for authorized extension
63
70
  # Defaults to not overwriting existing avatar
64
71
  def create_mine(opts = {})
65
- res_ext = @client.http.get 'account/~/extension/~'
66
- res_av = create_avatar res_ext.body, opts
67
- load_extensions
68
- res_av
72
+ try_req = true
73
+ while try_req
74
+ res_ext = @client.http.get 'account/~/extension/~'
75
+ try_req = retry_status res_ext
76
+ end
77
+ res_avt = create_avatar res_ext.body, opts
78
+ res_avt
69
79
  end
70
80
 
71
81
  ##
@@ -73,16 +83,29 @@ module RingCentral
73
83
  # Defaults to not overwriting existing avatar
74
84
  def create_avatar(ext, opts = {})
75
85
  opts[:overwrite] = false unless opts.key?(:overwrite)
76
- return if has_avatar(ext) && !opts[:overwrite]
86
+ if avatar?(ext) && !opts[:overwrite]
87
+ return nil
88
+ end
77
89
  url = "account/~/extension/#{ext['id']}/profile-image"
78
- image = @avatars.avatar_faraday_uploadio ext['name']
79
- @client.http.put url, image: image
90
+ res_avt = nil
91
+ try_req = true
92
+ while try_req
93
+ image = @avatars.avatar_faraday_uploadio ext['name']
94
+ res_avt = @client.http.put url, image: image
95
+ try_req = retry_status res_avt
96
+ end
97
+ res_avt
98
+ end
99
+
100
+ def retry_status(res)
101
+ return false unless @retry
102
+ @retry_util.retry_status(res.status, res.headers['Retry-After'])
80
103
  end
81
104
 
82
105
  ##
83
106
  # Determines if extension has an existing avatar
84
107
  # Checks by looking for the presence of the `etag` property
85
- def has_avatar(ext)
108
+ def avatar?(ext)
86
109
  ext['profileImage'].key?('etag') ? true : false
87
110
  end
88
111
 
@@ -124,23 +147,24 @@ end
124
147
  module RingCentral
125
148
  module Avatars
126
149
  class MultiAvatar
127
- DEFAULT_STYLE = 'initials'
150
+ DEFAULT_STYLE = 'initials'.freeze
128
151
  AVATARLY_DEFAULTS = {
129
152
  size: 600,
130
153
  format: 'png'
131
- }
154
+ }.freeze
132
155
  IDENTICON_DEFAULTS = {
133
156
  grid_size: 5,
134
157
  square_size: 70,
135
158
  background_color: 0xffffffff
136
- }
137
- IDENTICON_DEFAULT_FORMAT = 'png'
159
+ }.freeze
160
+ IDENTICON_DEFAULT_FORMAT = 'png'.freeze
138
161
 
139
162
  def initialize(opts = {})
140
163
  @avatarly_opts = inflate_avatarly_opts opts[:initials_opts]
141
164
  @identicon_opts = inflate_identicon_opts opts[:identicon_opts]
142
165
  @style = opts.key?(:style) ? opts[:style] : DEFAULT_STYLE
143
166
  @png_metadata = opts.key?(:png_metadata) ? opts[:png_metadata] : {}
167
+ @logger = opts.key?(:logger) ? opts[:logger] : Logger.new(STDOUT)
144
168
  end
145
169
 
146
170
  def inflate_avatarly_opts(avatarly_opts = {})
@@ -155,7 +179,7 @@ module RingCentral
155
179
 
156
180
  def avatar_blob(text, style = nil)
157
181
  style = @style if style.nil?
158
- blob = @style == 'initials' \
182
+ blob = style == 'initials' \
159
183
  ? Avatarly.generate_avatar(text, @avatarly_opts) \
160
184
  : RubyIdenticon.create(text, @identicon_opts)
161
185
  inflate_avatar_blob_png blob
@@ -179,7 +203,8 @@ module RingCentral
179
203
 
180
204
  def avatar_faraday_uploadio(text, style = nil)
181
205
  file = avatar_temp_file text, style
182
- image = Faraday::UploadIO.new file.path, avatar_mime_type
206
+ @logger.debug "Building Avatar Temp File: #{file.path}"
207
+ Faraday::UploadIO.new file.path, avatar_mime_type
183
208
  end
184
209
 
185
210
  def avatar_format
@@ -188,7 +213,7 @@ module RingCentral
188
213
 
189
214
  def avatar_mime_type
190
215
  types = MIME::Types.type_for avatar_format
191
- if types.length == 0
216
+ if types.empty?
192
217
  raise "Unknown avatar format: #{avatar_format}"
193
218
  end
194
219
  types[0].to_s
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ringcentral-avatars
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Wang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-19 00:00:00.000000000 Z
11
+ date: 2016-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avatarly
@@ -96,20 +96,20 @@ dependencies:
96
96
  requirements:
97
97
  - - "~>"
98
98
  - !ruby/object:Gem::Version
99
- version: '1'
99
+ version: '2'
100
100
  - - ">="
101
101
  - !ruby/object:Gem::Version
102
- version: 1.3.4
102
+ version: 2.0.2
103
103
  type: :runtime
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '1'
109
+ version: '2'
110
110
  - - ">="
111
111
  - !ruby/object:Gem::Version
112
- version: 1.3.4
112
+ version: 2.0.2
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ruby_identicon
115
115
  requirement: !ruby/object:Gem::Requirement
@@ -164,14 +164,14 @@ dependencies:
164
164
  requirements:
165
165
  - - "~>"
166
166
  - !ruby/object:Gem::Version
167
- version: '11'
167
+ version: '12'
168
168
  type: :development
169
169
  prerelease: false
170
170
  version_requirements: !ruby/object:Gem::Requirement
171
171
  requirements:
172
172
  - - "~>"
173
173
  - !ruby/object:Gem::Version
174
- version: '11'
174
+ version: '12'
175
175
  - !ruby/object:Gem::Dependency
176
176
  name: simplecov
177
177
  requirement: !ruby/object:Gem::Requirement
@@ -208,7 +208,9 @@ extra_rdoc_files: []
208
208
  files:
209
209
  - CHANGELOG.md
210
210
  - Gemfile
211
+ - Gemfile.lock
211
212
  - LICENSE.md
213
+ - NEWS.md
212
214
  - README.md
213
215
  - Rakefile
214
216
  - lib/ringcentral-avatars.rb
@@ -233,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
233
235
  version: '0'
234
236
  requirements: []
235
237
  rubyforge_project:
236
- rubygems_version: 2.6.7
238
+ rubygems_version: 2.5.2
237
239
  signing_key:
238
240
  specification_version: 4
239
241
  summary: RingCentral library for auto-generating Gmail style avatars