login_radius 1.0.1 → 2.0.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: 5a38dc6be5450d4639073fdfc10aafe6ca6ce3c5
4
- data.tar.gz: 74689a0d9bd22acc90e7e1c1e9ae0073c53bbf82
3
+ metadata.gz: 6b9ff9727e8d0ec474fcf86616bc1061c3116ab6
4
+ data.tar.gz: fba790fc62a2bab90af335da1323da95ece34ede
5
5
  SHA512:
6
- metadata.gz: 4997319c001d5f59e575c8000763198079063dc5a6c4e1e639ad3ca0529f17f6c986c4da7ca2a96d02c5108e5241efb24e20c9dd377687624fe60a3817a3c5de
7
- data.tar.gz: ff62c2061bfdff0465a9ba2e2c3340b4709f3786552571b7ea3c1541a8b7212af6c98cbbc7922066b83ecef0a0775358f6e274204a69e0ba09faf99680aaa1d4
6
+ metadata.gz: 476acd90921456e1b9c66c833ab8294c8ce2b52edacd4e7e2413f7b3723e9fbdf41296709ce24a4c84d7cde817c668a69d2ce1abc7874ea48841d7a78bab15e7
7
+ data.tar.gz: 646fe415604be6fca129a1062821ce849882afb280c59c65f8787cea6f584bb28288b0bab817a410a2449a455b47a5d165814c00e1cdbccb09040c0e58b30ec1
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jordan Prince
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # LoginRadius
2
+
3
+ Ruby wrapper for the LoginRadius API. Get social graph information and send messages using LoginRadius'
4
+ many social network clients!
5
+
6
+ Optional Asynchronous EventMachine friendly option!
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'login_radius'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install login_radius
21
+
22
+ ## Usage
23
+
24
+ Take a peek:
25
+
26
+ @LoginRadius = {
27
+ :sitename => "<LOGINRADIUS_SITE_NAME>",
28
+ :appkey => "<LOGINRADIUS_APPKEY>",
29
+ :appsecret => "<LOGINRADIUS_APPSECRET>",
30
+ :objectId => "<LOGINRADIUS_OBJECT_ID>"
31
+ }
32
+ @user_profile = LoginRadiusRaas::RaasApi.new(@LoginRadius);
33
+
34
+
35
+ ### How to get a token and actually make a client
36
+
37
+ On the LoginRadius website, you are able to enter your own callback URL for your site. You will need
38
+ to setup a route on whatever framework you use, maybe "/callback." Then, get the gem forward(www.example.com)
39
+ and use it to set up a public web address for your localhost server. Then, you can enter the callback on LoginRadius
40
+ as https://example.com/callback, for instance.
41
+
42
+ Paste their example login stuff onto your index page, and then configuration provider on your LoginRadius site.
43
+
44
+ Now you're ready to go with testing!
45
+
46
+ When LoginRadius hits your callback after a user logs in, you'll see parameters like this:
47
+
48
+ Parameters: {"token"=>"yourtokenhere"}
49
+
50
+ This token is the token used in the above example. This is what you'll need to get your access token and fetch user's profile from LoginRadius.
51
+ Just paste it into the code above, and you can immediately grab their user profile on the callback,
52
+ login, and grab their contacts.
data/lib/hash.rb CHANGED
@@ -1,13 +1,12 @@
1
- class Hash
2
- def self.lr_convert_hash_keys(value) #lr_ appended so no method naming conflicts with other gems
3
- case value
4
- when Array
5
- value.map { |v| lr_convert_hash_keys(v) }
6
- # or `value.map(&method(:convert_hash_keys))`
7
- when Hash
8
- Hash[value.map { |k, v| [k.to_s.lr_underscore, lr_convert_hash_keys(v)] }]
9
- else
10
- value
11
- end
12
- end
1
+ class Hash
2
+ def self.lr_convert_hash_keys(value) #lr_ appended so no method naming conflicts with other gems
3
+ case value
4
+ when Array
5
+ value.map { |v| lr_convert_hash_keys(v) }
6
+ when Hash
7
+ Hash[value.map { |k, v| [k.to_s.lr_underscore, lr_convert_hash_keys(v)] }]
8
+ else
9
+ value
10
+ end
11
+ end
13
12
  end
@@ -0,0 +1,130 @@
1
+ module LoginRadiusRaas
2
+ module AccountApi
3
+ #
4
+ # This API is used to link a user account with a specified providers user account.
5
+ #
6
+ # params = {
7
+ # :accountid => uid,
8
+ # :provider => Provider Name,
9
+ # :providerid => Social ID
10
+ # }
11
+ #
12
+ # return {“isPosted”: “true”}
13
+ #
14
+ def account_link!(params)
15
+ api_client("raas/v1/account/link", {}, params);
16
+ end
17
+
18
+ def account_link(params={})
19
+ account_link!(params)
20
+ rescue LoginRadiusRaas::Exception => e
21
+ false
22
+ end
23
+
24
+ #
25
+ # This API is used to unlink a user account with a specified providers user account.
26
+ #
27
+ # params = {
28
+ # :accountid => uid,
29
+ # :provider => Provider Name,
30
+ # :providerid => Social ID
31
+ # }
32
+ #
33
+ # return {“isPosted”: “true”}
34
+ #
35
+ def account_unlink!(params)
36
+ api_client("raas/v1/account/unlink", {}, params);
37
+ end
38
+
39
+ def account_unlink(params={})
40
+ account_unlink!(params)
41
+ rescue LoginRadiusRaas::Exception => e
42
+ false
43
+ end
44
+ #
45
+ # This API is used to delete a user account
46
+ #
47
+ # accountid => uid;
48
+ #
49
+ # return {“isPosted”: “true”}
50
+ #
51
+ def account_delete!(accountid)
52
+ api_client("raas/v1/account/delete", {:accountid=>accountid});
53
+ end
54
+
55
+ def account_delete(accountid)
56
+ account_delete!(accountid)
57
+ rescue LoginRadiusRaas::Exception => e
58
+ false
59
+ end
60
+ #
61
+ # This API is used to changed username for a user account
62
+ #
63
+ # accountid = uid
64
+ # currentusername = currentusername
65
+ # newusername = newusername
66
+ #
67
+ # return {“isPosted”: “true”}
68
+ #
69
+ def account_change_username!(uid,currentusername,newusername)
70
+ api_client("raas/v1/account/changeusername", {:accountid=>uid},{:currentusername=>currentusername,:newusername=>newusername}, 'json');
71
+ end
72
+
73
+ def account_change_username(uid,currentusername,newusername)
74
+ account_change_username!(uid,currentusername,newusername)
75
+ rescue LoginRadiusRaas::Exception => e
76
+ false
77
+ end
78
+ #
79
+ # This API is used to set username for a user account
80
+ #
81
+ # accountid = uid
82
+ # username = username
83
+ #
84
+ # return {“isPosted”: “true”}
85
+ #
86
+ def account_set_username!(uid,username)
87
+ api_client("raas/v1/account/setusername", {:accountid=>uid},{:newusername=>username}, 'json');
88
+ end
89
+
90
+ def account_set_username(uid,username)
91
+ account_set_username!(uid,username)
92
+ rescue LoginRadiusRaas::Exception => e
93
+ false
94
+ end
95
+ #
96
+ # This API is used to check username for a user account
97
+ #
98
+ # username = username
99
+ #
100
+ # return {“isExist”: “true”}
101
+ #
102
+ def account_check_username!(username)
103
+ api_client("raas/client/auth/checkusername",{:username=>username});
104
+ end
105
+
106
+ def account_check_username(username)
107
+ account_check_username!(username)
108
+ rescue LoginRadiusRaas::Exception => e
109
+ false
110
+ end
111
+
112
+
113
+ #
114
+ # This API is used to retrieve all of the profile data from each of the linked social provider accounts associated with the account. For ex: A user has linked facebook and google account then this api will retrieve both profile data.
115
+ #
116
+ # uid = xxxxxxxxxx;
117
+ #
118
+ # return Array of user profile
119
+ #
120
+ def account_get_profiles_by_uid!(uid)
121
+ api_client("raas/v1/account", {:accountid=>uid});
122
+ end
123
+
124
+ def account_get_profiles_by_uid(uid)
125
+ account_get_profiles_by_uid!(uid)
126
+ rescue LoginRadiusRaas::Exception => e
127
+ false
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,389 @@
1
+ module LoginRadiusRaas
2
+ module BasicApi
3
+ #
4
+ # LoginRadius function - Fetch LoginRadius access token after authentication. It will be valid for the specific duration of time specified in the response.
5
+ # @param string LoginRadius API token
6
+ #
7
+ # @return mixed string|object LoginRadius access token.
8
+ #
9
+ #
10
+ def get_access_token!(token)
11
+ return api_client("api/v2/access_token", {:token=>token,:secret=>appsecret});
12
+ end
13
+
14
+ def get_access_token(token)
15
+ return get_access_token!(token)
16
+ rescue LoginRadiusRaas::Exception => e
17
+ return false
18
+ end
19
+
20
+ #
21
+ # LoginRadius function - To fetch social profile data from the user's social account after authentication. The social profile will be retrieved via oAuth and OpenID protocols. The data is normalized into LoginRadius' standard data format.
22
+ #
23
+ # @param string accessToken LoginRadius access token
24
+ # @param boolean raw If true, raw data is fetched
25
+ #
26
+ # @return object User profile data.
27
+ #
28
+ def get_user_profile!(accessToken, raw)
29
+ return api_client("api/v2/userprofile" + get_row_data(raw), {:access_token=>accessToken});
30
+ end
31
+
32
+ def get_user_profile(accessToken, raw = false)
33
+ return get_user_profile!(accessToken, raw)
34
+ rescue LoginRadiusRaas::Exception => e
35
+ return false
36
+ end
37
+
38
+ #
39
+ # LoginRadius function - To get the Albums data from the user's social account. The data will be normalized into LoginRadius' data format.
40
+ #
41
+ # @param string accessToken LoginRadius access token
42
+ # @param boolean raw If true, raw data is fetched
43
+ #
44
+ # @return object User's albums data.
45
+ #
46
+ #
47
+ def get_albums!(accessToken, raw)
48
+ return api_client("api/v2/album" + get_row_data(raw), {:access_token=>accessToken});
49
+ end
50
+
51
+ def get_albums(accessToken, raw = false)
52
+ return get_albums!(accessToken, raw)
53
+ rescue LoginRadiusRaas::Exception => e
54
+ return false
55
+ end
56
+
57
+ #
58
+ # LoginRadius function - To fetch photo data from the user's social account. The data will be normalized into LoginRadius' data format.
59
+ #
60
+ # @param string accessToken LoginRadius access token
61
+ # @param string albumId ID of the album to fetch photos from
62
+ # @param boolean raw If true, raw data is fetched
63
+ #
64
+ # @return object User's photo data.
65
+ #
66
+ def get_photos!(accessToken, albumId, raw)
67
+ return api_client("api/v2/photo" + get_row_data(raw), {:access_token=>accessToken,:albumid=>albumId});
68
+ end
69
+
70
+ def get_photos(accessToken, albumId, raw = false)
71
+ return get_photos!(accessToken, albumId, raw)
72
+ rescue LoginRadiusRaas::Exception => e
73
+ return false
74
+ end
75
+
76
+ #
77
+ # LoginRadius function - To fetch check-ins data from the user's social account. The data will be normalized into LoginRadius' data format.
78
+ #
79
+ # @param string accessToken LoginRadius access token
80
+ # @param boolean raw If true, raw data is fetched
81
+ #
82
+ # @return object User's check-ins.
83
+ #
84
+ #
85
+ def get_checkins!(accessToken, raw)
86
+ return api_client("api/v2/checkin" + get_row_data(raw), {:access_token=>accessToken});
87
+ end
88
+
89
+ def get_checkins(accessToken, raw = false)
90
+ return get_checkins!(accessToken, raw)
91
+ rescue LoginRadiusRaas::Exception => e
92
+ return false
93
+ end
94
+
95
+ #
96
+ # LoginRadius function - To fetch user's audio files data from the user's social account. The data will be normalized into LoginRadius' data format.
97
+ #
98
+ # @param string accessToken LoginRadius access token
99
+ # @param boolean raw If true, raw data is fetched
100
+ #
101
+ # @return object User's audio files data.
102
+ #
103
+ #
104
+ def get_audio!(accessToken, raw)
105
+ return api_client("api/v2/audio" + get_row_data(raw), {:access_token=>accessToken});
106
+ end
107
+
108
+ def get_audio(accessToken, raw = false)
109
+ return get_audio!(accessToken, raw)
110
+ rescue LoginRadiusRaas::Exception => e
111
+ return false
112
+ end
113
+
114
+ #
115
+ # LoginRadius function - Post messages to the user's contacts. After using the Contact API, you can send messages to the retrieved contacts.
116
+ #
117
+ # @param string $accessToken LoginRadius access token
118
+ # @param string $to Social ID of the receiver
119
+ # @param string $subject Subject of the message
120
+ # @param string $message Message
121
+ #
122
+ # @return bool True on success, false otherwise
123
+ #
124
+ #
125
+ def send_message!(accessToken, to, subject, message)
126
+ param = {
127
+ :access_token => accessToken,
128
+ :to => to,
129
+ :subject => subject,
130
+ :message => message
131
+ }
132
+ return api_client("api/v2/message", param,{});
133
+ end
134
+
135
+ def send_message(accessToken, to, subject, message)
136
+ return send_message!(accessToken, to, subject, message)
137
+ rescue LoginRadiusRaas::Exception => e
138
+ return false
139
+ end
140
+
141
+ #
142
+ # LoginRadius function - To fetch user's contacts/friends/connections data from the user's social account. The data will normalized into LoginRadius' data format.
143
+ #
144
+ # @param string $accessToken LoginRadius access token
145
+ # @param integer $nextCursor Offset to start fetching contacts from
146
+ # @param boolean $raw If true, raw data is fetched
147
+ #
148
+ # @return object User's contacts/friends/followers.
149
+ #
150
+ #
151
+ def get_contacts!(accessToken, nextCursor, raw)
152
+ return api_client("api/v2/contact" + get_row_data(raw), {:access_token=>accessToken,:nextcursor=>nextCursor});
153
+ end
154
+
155
+ def get_contacts(accessToken, nextCursor = '0', raw = false)
156
+ return get_contacts!(accessToken, nextCursor, raw)
157
+ rescue LoginRadiusRaas::Exception => e
158
+ return false
159
+ end
160
+
161
+ #
162
+ # LoginRadius function - To get mention data from the user's social account. The data will be normalized into LoginRadius' data format.
163
+ #
164
+ # @param string $accessToken LoginRadius access token
165
+ # @param boolean $raw If true, raw data is fetched
166
+ #
167
+ # @return object User's twitter mentions.
168
+ #
169
+ def get_mentions!(accessToken, raw)
170
+ return api_client("api/v2/mention" + get_row_data(raw), {:access_token=>accessToken});
171
+ end
172
+
173
+ def get_mentions(accessToken, raw = false)
174
+ return get_mentions!(accessToken, raw)
175
+ rescue LoginRadiusRaas::Exception => e
176
+ return false
177
+ end
178
+
179
+ #
180
+ # LoginRadius function - To fetch information of the people, user is following on Twitter.
181
+ #
182
+ # @param string $accessToken LoginRadius access token
183
+ # @param boolean $raw If true, raw data is fetched
184
+ #
185
+ # @return object Information of the people, user is following.
186
+ #
187
+ def get_following!(accessToken, raw)
188
+ return api_client("api/v2/following" + get_row_data(raw), {:access_token=>accessToken});
189
+ end
190
+
191
+ def get_following(accessToken, raw = false)
192
+ return get_following!(accessToken, raw)
193
+ rescue LoginRadiusRaas::Exception => e
194
+ return false
195
+ end
196
+
197
+ #
198
+ # LoginRadius function - To get the event data from the user's social account. The data will be normalized into LoginRadius' data format.
199
+ #
200
+ # @param string $accessToken LoginRadius access token
201
+ # @param boolean $raw If true, raw data is fetched
202
+ #
203
+ # @return object User's event data.
204
+ #
205
+ def get_events!(accessToken, raw)
206
+ return api_client("api/v2/event" + get_row_data(raw), {:access_token=>accessToken});
207
+ end
208
+
209
+ def get_events(accessToken, raw = false)
210
+ return get_events!(accessToken, raw)
211
+ rescue LoginRadiusRaas::Exception => e
212
+ return false
213
+ end
214
+
215
+ #
216
+ # LoginRadius function - To get posted messages from the user's social account. The data will be normalized into LoginRadius' data format.
217
+ #
218
+ # @param string $accessToken LoginRadius access token
219
+ # @param boolean $raw If true, raw data is fetched
220
+ #
221
+ # @return object User's posted messages.
222
+ #
223
+ def get_posts!(accessToken, raw)
224
+ return api_client("api/v2/post" + get_row_data(raw), {:access_token=>accessToken});
225
+ end
226
+
227
+ def get_posts(accessToken, raw = false)
228
+ return get_posts!(accessToken, raw)
229
+ rescue LoginRadiusRaas::Exception => e
230
+ return false
231
+ end
232
+
233
+ #
234
+ # LoginRadius function - To get the followed company's data in the user's social account. The data will be normalized into LoginRadius' data format.
235
+ #
236
+ # @param string $accessToken LoginRadius access token
237
+ # @param boolean $raw If true, raw data is fetched
238
+ #
239
+ # @return object Companies followed by user.
240
+ #
241
+ def get_followed_companies!(accessToken, raw)
242
+ return api_client("api/v2/company" + get_row_data(raw), {:access_token=>accessToken});
243
+ end
244
+
245
+ def get_followed_companies(accessToken, raw = false)
246
+ return get_followed_companies!(accessToken, raw)
247
+ rescue LoginRadiusRaas::Exception => e
248
+ return false
249
+ end
250
+
251
+ #
252
+ # LoginRadius function - To get group data from the user's social account. The data will be normalized into LoginRadius' data format.
253
+ #
254
+ # @param string $accessToken LoginRadius access token
255
+ # @param boolean $raw If true, raw data is fetched
256
+ #
257
+ # @return object Group data.
258
+ #
259
+ def get_groups!(accessToken, raw)
260
+ return api_client("api/v2/group" + get_row_data(raw), {:access_token=>accessToken});
261
+ end
262
+
263
+ def get_groups(accessToken, raw = false)
264
+ return get_groups!(accessToken, raw)
265
+ rescue LoginRadiusRaas::Exception => e
266
+ return false
267
+ end
268
+
269
+ #
270
+ # LoginRadius function - To get the status messages from the user's social account. The data will be normalized into LoginRadius' data format.
271
+ #
272
+ # @param string $accessToken LoginRadius access token
273
+ # @param boolean $raw If true, raw data is fetched
274
+ #
275
+ # @return object Status messages.
276
+ #
277
+ def get_status!(accessToken, raw)
278
+ return api_client("api/v2/status" + get_row_data(raw), {:access_token=>accessToken});
279
+ end
280
+
281
+ def get_status(accessToken, raw = false)
282
+ return get_status!(accessToken, raw)
283
+ rescue LoginRadiusRaas::Exception => e
284
+ return false
285
+ end
286
+
287
+ #
288
+ # LoginRadius function - To update the status on the user's wall.
289
+ #
290
+ # @param string $accessToken LoginRadius access token
291
+ # @param string $title Title for status message (Optional).
292
+ # @param string $url A web link of the status message (Optional).
293
+ # @param string $imageurl An image URL of the status message (Optional).
294
+ # @param string $status The status message text (Required).
295
+ # @param string $caption Caption of the status message (Optional).
296
+ # @param string $description Description of the status message (Optional).
297
+ #
298
+ # @return boolean Returns true if successful, false otherwise.
299
+ #
300
+ def post_status!(accessToken, title, url, imageurl, status, caption, description)
301
+ param = {
302
+ :access_token => accessToken,
303
+ :title => title,
304
+ :url => url,
305
+ :imageurl => imageurl,
306
+ :status => status,
307
+ :caption => caption,
308
+ :description => description
309
+ }
310
+ return api_client("api/v2/status", param, {});
311
+ end
312
+
313
+ def post_status(accessToken, title, url, imageurl, status, caption, description)
314
+ return post_status!(accessToken, title, url, imageurl, status, caption, description)
315
+ rescue LoginRadiusRaas::Exception => e
316
+ return false
317
+ end
318
+
319
+ #
320
+ # LoginRadius function - To get videos data from the user's social account. The data will be normalized into LoginRadius' data format.
321
+ #
322
+ # @param string $accessToken LoginRadius access token
323
+ # @param boolean $raw If true, raw data is fetched
324
+ #
325
+ # @return object Videos data.
326
+ #
327
+ def get_videos!(accessToken, raw)
328
+ return api_client("api/v2/video" + get_row_data(raw), {:access_token=>accessToken});
329
+ end
330
+
331
+ def get_videos(accessToken, raw = false)
332
+ return get_videos!(accessToken, raw)
333
+ rescue LoginRadiusRaas::Exception => e
334
+ return false
335
+ end
336
+
337
+ #
338
+ # LoginRadius function - To get likes data from the user's social account. The data will be normalized into LoginRadius' data format.
339
+ #
340
+ # @param string $accessToken LoginRadius access token
341
+ # @param boolean $raw If true, raw data is fetched
342
+ #
343
+ # @return object likes data.
344
+ #
345
+ def get_likes!(accessToken, raw)
346
+ return api_client("api/v2/like" + get_row_data(raw), {:access_token=>accessToken});
347
+ end
348
+
349
+ def get_likes(accessToken, raw = false)
350
+ return get_likes!(accessToken, raw)
351
+ rescue LoginRadiusRaas::Exception => e
352
+ return false
353
+ end
354
+
355
+ #
356
+ # LoginRadius function - To get the page data from the user's social account. The data will be normalized into LoginRadius' data format.
357
+ #
358
+ # @param string $accessToken LoginRadius access token
359
+ # @param string $pageName Page name
360
+ # @param boolean $raw If true, raw data is fetched
361
+ #
362
+ # @return object Page data.
363
+ #
364
+ def get_pages!(accessToken, pageName, raw)
365
+ return api_client("api/v2/page" + get_row_data(raw), {:access_token=>accessToken,:pagename=>pageName});
366
+ end
367
+
368
+ def get_pages(accessToken, pageName, raw = false)
369
+ return get_pages!(accessToken, pageName, raw)
370
+ rescue LoginRadiusRaas::Exception => e
371
+ return false
372
+ end
373
+
374
+ #
375
+ # LoginRadius function - To fetch data from the LoginRadius Raw API URL.
376
+ #
377
+ # @param boolean raw If true, raw data is fetched
378
+ #
379
+ # @return string Data to add in API URL.
380
+ #
381
+ def get_row_data(raw)
382
+ if raw
383
+ return '/raw';
384
+ else
385
+ return '';
386
+ end
387
+ end
388
+ end
389
+ end