diandian-oauth 0.0.3 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +8 -2
- data/diandian-oauth.gemspec +1 -1
- data/lib/diandian_oauth.rb +4 -3
- data/lib/diandian_oauth/api.rb +8 -1
- data/lib/diandian_oauth/api/interface.rb +232 -29
- data/lib/diandian_oauth/client.rb +39 -11
- data/lib/diandian_oauth/client/callbacks.rb +49 -0
- data/lib/diandian_oauth/exceptions.rb +223 -6
- data/lib/diandian_oauth/models/response.rb +77 -0
- data/lib/diandian_oauth/models/response_meta.rb +61 -0
- data/test/diandian_oauth/authorize_test.rb +5 -4
- data/test/diandian_oauth/interface_test.rb +51 -10
- metadata +4 -1
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/secretworry/faraday.git
|
3
|
+
revision: b34ecbb6cd4d0b2280cdb19a15f1d39a9b0eb309
|
4
|
+
specs:
|
5
|
+
faraday (0.8.0)
|
6
|
+
multipart-post (~> 1.1)
|
7
|
+
|
1
8
|
GEM
|
2
9
|
remote: http://rubygems.org/
|
3
10
|
specs:
|
@@ -8,8 +15,6 @@ GEM
|
|
8
15
|
i18n (~> 0.6)
|
9
16
|
multi_json (~> 1.0)
|
10
17
|
builder (3.0.0)
|
11
|
-
faraday (0.8.1)
|
12
|
-
multipart-post (~> 1.1)
|
13
18
|
httpauth (0.1)
|
14
19
|
i18n (0.6.0)
|
15
20
|
jwt (0.1.5)
|
@@ -30,4 +35,5 @@ PLATFORMS
|
|
30
35
|
DEPENDENCIES
|
31
36
|
activemodel (~> 3.2.6)
|
32
37
|
activesupport (~> 3.2.1)
|
38
|
+
faraday!
|
33
39
|
oauth2 (~> 0.8.0)
|
data/diandian-oauth.gemspec
CHANGED
data/lib/diandian_oauth.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
require 'active_support/core_ext'
|
1
2
|
require 'diandian_oauth/api'
|
2
3
|
require 'diandian_oauth/client'
|
3
4
|
require 'diandian_oauth/exceptions'
|
4
|
-
require '
|
5
|
+
require 'diandian_oauth/models/response'
|
5
6
|
require 'logger'
|
6
7
|
module DiandianOAuth
|
7
|
-
VERSION = '0.
|
8
|
+
VERSION = '0.1.1'
|
8
9
|
module Logger
|
9
10
|
def logger *args
|
10
11
|
if args.empty?
|
@@ -16,4 +17,4 @@ module DiandianOAuth
|
|
16
17
|
end
|
17
18
|
extend Logger
|
18
19
|
logger STDOUT
|
19
|
-
end
|
20
|
+
end
|
data/lib/diandian_oauth/api.rb
CHANGED
@@ -18,15 +18,22 @@ module DiandianOAuth
|
|
18
18
|
interface :user_likes, Interface::UserLikes
|
19
19
|
interface :user_followings, Interface::UserFollowings
|
20
20
|
interface :my_tags, Interface::MyTags
|
21
|
-
interface :blog, Interface::Blog
|
22
21
|
interface :blog_info, Interface::BlogInfo
|
23
22
|
interface :blog_avatar, Interface::BlogAvatar
|
24
23
|
interface :blog_followers, Interface::BlogFollowers
|
25
24
|
interface :posts, Interface::Posts
|
25
|
+
interface :post_info, Interface::PostInfo
|
26
|
+
interface :create_post, Interface::CreatePost
|
27
|
+
interface :delete_post, Interface::DeletePost
|
28
|
+
interface :reblog_post, Interface::ReblogPost
|
26
29
|
interface :home_feeds, Interface::HomeFeeds
|
27
30
|
interface :tag_feeds, Interface::TagFeeds
|
28
31
|
interface :follow, Interface::Follow
|
29
32
|
interface :unfollow, Interface::Unfollow
|
33
|
+
interface :watch_tag, Interface::WatchTag
|
34
|
+
interface :unwatch_tag, Interface::UnwatchTag
|
30
35
|
interface :submissions, Interface::Submissions
|
36
|
+
interface :submit, Interface::Submit
|
37
|
+
interface :reject_submission, Interface::RejectSubmission
|
31
38
|
end
|
32
39
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module DiandianOAuth
|
3
2
|
class API
|
4
3
|
module Interface
|
@@ -40,20 +39,43 @@ module DiandianOAuth
|
|
40
39
|
end
|
41
40
|
end #Param
|
42
41
|
|
42
|
+
class Params
|
43
|
+
def initialize(params = {})
|
44
|
+
@params = params.symbolize_keys!
|
45
|
+
end
|
46
|
+
def [] key
|
47
|
+
@params[key.to_sym]
|
48
|
+
end
|
49
|
+
|
50
|
+
def []= key, value
|
51
|
+
@params[key.to_sym] = value
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_a
|
55
|
+
@params.reduce([]) do |all, (key, value)|
|
56
|
+
case value
|
57
|
+
when Array
|
58
|
+
value.each{|v| all << [key, v]}
|
59
|
+
else
|
60
|
+
all << [key, value]
|
61
|
+
end
|
62
|
+
all
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_h
|
67
|
+
@params
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
43
71
|
class Base
|
44
72
|
def request_url params = {}
|
45
73
|
raise 'subclasses must implement this method'
|
46
74
|
end
|
47
75
|
|
48
|
-
# when the access_token is out-of-date, refresh it automatically
|
49
|
-
def apply! access_token, params, &block
|
50
|
-
access_token.refresh! if access_token.expired?
|
51
|
-
self.apply access_token, params, &block
|
52
|
-
end
|
53
|
-
|
54
76
|
def apply access_token, params, &block
|
55
|
-
raise
|
56
|
-
params
|
77
|
+
raise TokenExpiredError if access_token.expired?
|
78
|
+
params = Params.new( params || {})
|
57
79
|
action = case request_verb
|
58
80
|
when /get/ then :get
|
59
81
|
when /post/ then :post
|
@@ -62,30 +84,27 @@ module DiandianOAuth
|
|
62
84
|
else raise "unrecognized verb '#{request_verb}'"
|
63
85
|
end # case
|
64
86
|
options = {
|
65
|
-
:
|
87
|
+
:body => extract_params(params).to_a,
|
66
88
|
:raise_errors => false,
|
67
89
|
:parse => :json
|
68
90
|
}
|
69
91
|
request_url = self.request_url(params)
|
70
92
|
if DiandianOAuth.logger.debug?
|
71
|
-
DiandianOAuth.logger.debug("request with action:'#{action}', request_url:'#{request_url}'")
|
93
|
+
DiandianOAuth.logger.debug("request with action:'#{action}', request_url:'#{request_url}', options:'#{options}'")
|
72
94
|
end
|
73
|
-
access_token.request( action, request_url, options, &block)
|
95
|
+
DiandianOAuth::Response.from_response access_token.request( action, request_url, options, &block)
|
74
96
|
end
|
75
97
|
protected
|
76
98
|
def request_verb
|
77
99
|
self.class.verb
|
78
100
|
end
|
79
101
|
def extract_params params
|
80
|
-
params.
|
81
|
-
self.class.params.each_pair.reduce({}) do |result, ele|
|
82
|
-
key = ele[0]
|
83
|
-
param = ele[1]
|
102
|
+
self.class.params.reduce(Params.new) do |result, (key, value)|
|
84
103
|
param_value = params[key]
|
85
|
-
if param_value
|
104
|
+
if param_value
|
86
105
|
result[key] = param_value
|
87
|
-
elsif
|
88
|
-
raise
|
106
|
+
elsif value.required
|
107
|
+
raise ParamIsRequiredError.new( "'#{key}' is required")
|
89
108
|
end
|
90
109
|
result
|
91
110
|
end
|
@@ -137,8 +156,9 @@ module DiandianOAuth
|
|
137
156
|
protected
|
138
157
|
def blog_request_url params
|
139
158
|
blog_cname = params[:blogCName]
|
140
|
-
|
141
|
-
|
159
|
+
blog_uuid = params[:blogUuid]
|
160
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
161
|
+
API.url_for "/blog/#{blog_cname||blog_uuid}"
|
142
162
|
end
|
143
163
|
end #BlogInterface
|
144
164
|
|
@@ -155,7 +175,7 @@ module DiandianOAuth
|
|
155
175
|
size = params[:size]
|
156
176
|
if size
|
157
177
|
unless BlogAvatar.is_valid_size size
|
158
|
-
raise
|
178
|
+
raise IllegalParamError.new("'#{size}' is illegal")
|
159
179
|
end
|
160
180
|
end # if
|
161
181
|
end
|
@@ -166,13 +186,24 @@ module DiandianOAuth
|
|
166
186
|
|
167
187
|
end #BlogAvatar
|
168
188
|
|
189
|
+
class PostInfo < Base
|
190
|
+
param :id, :required => true
|
191
|
+
def request_url params={}
|
192
|
+
blog_cname = params[:blogCName]
|
193
|
+
blog_uuid = params[:blogUuid]
|
194
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
195
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/posts"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
169
199
|
class BlogFollowers < Base
|
170
200
|
param :limit, :required => false
|
171
201
|
param :offset, :required => false
|
172
202
|
def request_url params={}
|
173
203
|
blog_cname = params[:blogCName]
|
174
|
-
|
175
|
-
|
204
|
+
blog_uuid = params[:blogUuid]
|
205
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
206
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/info"
|
176
207
|
end
|
177
208
|
end #BlogFollowers
|
178
209
|
|
@@ -186,8 +217,9 @@ module DiandianOAuth
|
|
186
217
|
param :filter, :required => false
|
187
218
|
def request_url params={}
|
188
219
|
blog_cname = params[:blogCName]
|
189
|
-
|
190
|
-
|
220
|
+
blog_uuid = params[:blogUuid]
|
221
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
222
|
+
path = "/blog/#{blog_cname||blog_uuid}/posts"
|
191
223
|
if params[:type]
|
192
224
|
path = path + "/#{type}"
|
193
225
|
end
|
@@ -195,6 +227,107 @@ module DiandianOAuth
|
|
195
227
|
end
|
196
228
|
end # Posts
|
197
229
|
|
230
|
+
class CreatePost < Base
|
231
|
+
verb :post
|
232
|
+
param :type, :required => true
|
233
|
+
param :state, :required => true
|
234
|
+
param :tag, :required => false
|
235
|
+
param :slug, :required => false
|
236
|
+
#text
|
237
|
+
param :title, :required => false
|
238
|
+
param :body, :required => false
|
239
|
+
#photo
|
240
|
+
param :caption, :required => false
|
241
|
+
param :layout, :required => false
|
242
|
+
param :data, :required => false
|
243
|
+
param :itemDesc, :required => false
|
244
|
+
#link
|
245
|
+
param :title, :required => false
|
246
|
+
param :url, :required => false
|
247
|
+
param :description, :required => false
|
248
|
+
|
249
|
+
#audio
|
250
|
+
param :caption, :required => false
|
251
|
+
param :data, :required => false
|
252
|
+
param :musicName, :required => false
|
253
|
+
param :musicSinger, :required => false
|
254
|
+
param :albumName, :required => false
|
255
|
+
|
256
|
+
#video
|
257
|
+
param :caption, :required => false
|
258
|
+
param :sourceUrl, :required => false
|
259
|
+
|
260
|
+
def request_url params={}
|
261
|
+
blog_cname = params[:blogCName]
|
262
|
+
blog_uuid = params[:blogUuid]
|
263
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
264
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/post"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
class EditPost < Base
|
269
|
+
verb :post
|
270
|
+
param :id, :required => true
|
271
|
+
param :tag, :required => false
|
272
|
+
param :slug, :required => false
|
273
|
+
#text
|
274
|
+
param :title, :required => false
|
275
|
+
param :body, :required => false
|
276
|
+
#photo
|
277
|
+
param :caption, :required => false
|
278
|
+
param :layout, :required => false
|
279
|
+
param :data, :required => false
|
280
|
+
param :itemDesc, :required => false
|
281
|
+
#link
|
282
|
+
param :title, :required => false
|
283
|
+
param :url, :required => false
|
284
|
+
param :description, :required => false
|
285
|
+
|
286
|
+
#audio
|
287
|
+
param :caption, :required => false
|
288
|
+
param :data, :required => false
|
289
|
+
param :musicName, :required => false
|
290
|
+
param :musicSinger, :required => false
|
291
|
+
param :albumName, :required => false
|
292
|
+
|
293
|
+
#video
|
294
|
+
param :caption, :required => false
|
295
|
+
param :sourceUrl, :required => false
|
296
|
+
|
297
|
+
def request_url params={}
|
298
|
+
blog_cname = params[:blogCName]
|
299
|
+
blog_uuid = params[:blogUuid]
|
300
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
301
|
+
type = params[:type]
|
302
|
+
raise ParamIsRequiredError.new("type is required for interface #{self.class.name}") unless type
|
303
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/post/edit"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class DeletePost < Base
|
308
|
+
verb :post
|
309
|
+
param :id, :required => true
|
310
|
+
def request_url params={}
|
311
|
+
blog_cname = params[:blogCName]
|
312
|
+
blog_uuid = params[:blogUuid]
|
313
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
314
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/post/delete"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
class ReblogPost < Base
|
319
|
+
verb :post
|
320
|
+
param :id, :required => true
|
321
|
+
param :tag, :required => false
|
322
|
+
param :comment, :required => false
|
323
|
+
def request_url params={}
|
324
|
+
blog_cname = params[:blogCName]
|
325
|
+
blog_uuid = params[:blogUuid]
|
326
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
327
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/post/reblog"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
198
331
|
class HomeFeeds < Base
|
199
332
|
param :limit, :required => false
|
200
333
|
param :offset, :required => false
|
@@ -218,7 +351,7 @@ module DiandianOAuth
|
|
218
351
|
|
219
352
|
def request_url params={}
|
220
353
|
tag = params[:tag]
|
221
|
-
raise
|
354
|
+
raise ParamIsRequiredError.new("tag is required for interface #{self.class.name}") unless tag
|
222
355
|
API.url_for "/tag/posts/#{tag}"
|
223
356
|
end
|
224
357
|
end #TagFeeds
|
@@ -239,11 +372,81 @@ module DiandianOAuth
|
|
239
372
|
end
|
240
373
|
end # Unfollow
|
241
374
|
|
375
|
+
class WatchTag < Base
|
376
|
+
verb :post
|
377
|
+
def request_url params={}
|
378
|
+
tag = params[:tag]
|
379
|
+
raise ParamIsRequiredError.new("tag is required for interface #{self.class.name}") unless tag
|
380
|
+
API.url_for '/tag/watch/#{tag}'
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
class UnwatchTag < Base
|
385
|
+
verb :post
|
386
|
+
def request_url params={}
|
387
|
+
tag = params[:tag]
|
388
|
+
raise ParamIsRequiredError.new("tag is required for interface #{self.class.name}") unless tag
|
389
|
+
API.url_for '/tag/watch/#{tag}'
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
242
393
|
class Submissions < Base
|
243
394
|
def request_url params={}
|
244
395
|
blog_cname = params[:blogCName]
|
245
|
-
|
246
|
-
|
396
|
+
blog_uuid = params[:blogUuid]
|
397
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
398
|
+
API.url_for "/blog/#{blog_cname||blog_uuid}/submission"
|
399
|
+
end
|
400
|
+
end #Submissions
|
401
|
+
|
402
|
+
class Submit < Base
|
403
|
+
verb :post
|
404
|
+
param :tag, :required => false
|
405
|
+
param :slug, :required => false
|
406
|
+
#text
|
407
|
+
param :title, :required => false
|
408
|
+
param :body, :required => false
|
409
|
+
#photo
|
410
|
+
param :caption, :required => false
|
411
|
+
param :layout, :required => false
|
412
|
+
param :data, :required => false
|
413
|
+
param :itemDesc, :required => false
|
414
|
+
#link
|
415
|
+
param :title, :required => false
|
416
|
+
param :url, :required => false
|
417
|
+
param :description, :required => false
|
418
|
+
|
419
|
+
#audio
|
420
|
+
param :caption, :required => false
|
421
|
+
param :data, :required => false
|
422
|
+
param :musicName, :required => false
|
423
|
+
param :musicSinger, :required => false
|
424
|
+
param :albumName, :required => false
|
425
|
+
|
426
|
+
#video
|
427
|
+
param :caption, :required => false
|
428
|
+
param :sourceUrl, :required => false
|
429
|
+
|
430
|
+
def request_url params={}
|
431
|
+
blog_cname = params[:blogCName]
|
432
|
+
blog_uuid = params[:blogUuid]
|
433
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
434
|
+
type = params[:type]
|
435
|
+
raise ParamIsRequiredError.new("type is required for interface #{self.class.name}") unless type
|
436
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/submission/#{type}"
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
class RejectSubmission < Base
|
441
|
+
verb :post
|
442
|
+
param :reason, :required => false
|
443
|
+
def request_url params={}
|
444
|
+
blog_cname = params[:blogCName]
|
445
|
+
blog_uuid = params[:blogUuid]
|
446
|
+
raise ParamIsRequiredError.new("blogCName or blogUuid is required for interface #{self.class.name}") unless blog_cname || blog_uuid
|
447
|
+
id = params[:id]
|
448
|
+
raise ParamIsRequiredError.new("id is required for interface #{self.class.name}") unless id
|
449
|
+
API.url_for "/blog/#{blog_cname || blog_uuid}/submission/reject/#{id}"
|
247
450
|
end
|
248
451
|
end
|
249
452
|
end # Interface
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'oauth2'
|
2
|
+
require 'diandian_oauth/client/callbacks'
|
2
3
|
module DiandianOAuth
|
3
4
|
class Client
|
4
|
-
|
5
|
+
include DiandianOAuth::Client::Callbacks
|
6
|
+
attr_accessor :api, :client
|
5
7
|
def initialize client_id, client_secret, options={}
|
6
8
|
@api = options[:api] || DiandianOAuth::API.new
|
7
9
|
@redirect_uri = options[:redirect_uri]
|
@@ -9,7 +11,16 @@ module DiandianOAuth
|
|
9
11
|
:authorize_url => @api.authorize_url,
|
10
12
|
:token_url => @api.token_url
|
11
13
|
}
|
12
|
-
|
14
|
+
self.config_client_middleware(@client)
|
15
|
+
end
|
16
|
+
|
17
|
+
def config_client_middleware client
|
18
|
+
client.options[:connection_build] = Proc.new do |builder|
|
19
|
+
builder.request :multipart
|
20
|
+
builder.request :url_encoded
|
21
|
+
builder.adapter :net_http
|
22
|
+
end
|
23
|
+
end
|
13
24
|
|
14
25
|
def authorize_url response_type='code', scope=[]
|
15
26
|
if response_type.is_a? Array
|
@@ -38,13 +49,14 @@ module DiandianOAuth
|
|
38
49
|
else
|
39
50
|
begin
|
40
51
|
DiandianOAuth.logger.warn('redirect_url is required for authorization_code grant type') unless @redirect_uri
|
41
|
-
@access_token = @client.get_token(
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
52
|
+
@access_token = @client.auth_code.get_token(code_or_hash, {:redirect_uri => @redirect_uri})
|
53
|
+
#@access_token = @client.get_token(
|
54
|
+
# :client_id => @client.id,
|
55
|
+
# :client_secret => @client.secret,
|
56
|
+
# :grant_type => 'authorization_code',
|
57
|
+
# :code => code_or_hash,
|
58
|
+
# :redirect_uri => @redirect_uri
|
59
|
+
#)
|
48
60
|
rescue OAuth2::Error => e
|
49
61
|
DiandianOAuth.logger.error e.to_s
|
50
62
|
raise e
|
@@ -60,8 +72,24 @@ module DiandianOAuth
|
|
60
72
|
if interface
|
61
73
|
access_token = self.access_token
|
62
74
|
raise 'access_token is required' unless access_token
|
63
|
-
if force
|
64
|
-
|
75
|
+
response = if force
|
76
|
+
begin
|
77
|
+
token_expired = false
|
78
|
+
response = interface.apply access_token, args[0], &block
|
79
|
+
response.validate!
|
80
|
+
rescue TokenExpiredError => e
|
81
|
+
if DiandianOAuth.logger.debug?
|
82
|
+
DiandianOAuth.logger.debug("token '#{access_token.inspect}' expired")
|
83
|
+
end
|
84
|
+
new_access_token = access_token.refresh!
|
85
|
+
self.token_refreshed new_access_token
|
86
|
+
if DiandianOAuth.logger.debug?
|
87
|
+
DiandianOAuth.logger.debug("refreshed '#{access_token.inspect}' with '#{new_access_token}'")
|
88
|
+
end
|
89
|
+
self.access_token = access_token = new_access_token
|
90
|
+
token_expired = true
|
91
|
+
end while token_expired
|
92
|
+
response
|
65
93
|
else
|
66
94
|
interface.apply access_token, args[0], &block
|
67
95
|
end # force
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module DiandianOAuth
|
2
|
+
class Client
|
3
|
+
module Callbacks
|
4
|
+
class Callback
|
5
|
+
attr_accessor :executor
|
6
|
+
def initialize proc_or_method
|
7
|
+
self.executor = proc_or_method
|
8
|
+
end
|
9
|
+
def apply client, *args, &block
|
10
|
+
case executor
|
11
|
+
when Symbol then client.send(executor, *args, &block)
|
12
|
+
when Proc then executor.call( client, *args, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def self.included base
|
17
|
+
base.extend ClassMethods
|
18
|
+
base.send :include, InstanceMethods
|
19
|
+
base.class_eval do
|
20
|
+
self.callbacks = {}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def callbacks name=nil
|
26
|
+
if name
|
27
|
+
@callbacks[name] ||= []
|
28
|
+
else
|
29
|
+
@callbacks
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def callbacks= callbacks
|
33
|
+
@callbacks = callbacks
|
34
|
+
end
|
35
|
+
def token_refreshed proc_or_method
|
36
|
+
self.callbacks(:token_refreshed) << Callback.new( proc_or_method)
|
37
|
+
end
|
38
|
+
private
|
39
|
+
end
|
40
|
+
module InstanceMethods
|
41
|
+
def token_refreshed access_token
|
42
|
+
self.class.callbacks[:token_refreshed].each do |callback|
|
43
|
+
callback.apply(self, access_token)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,19 +1,236 @@
|
|
1
1
|
module DiandianOAuth
|
2
2
|
|
3
|
-
class
|
3
|
+
class Error < ::StandardError
|
4
4
|
end
|
5
5
|
|
6
|
-
class
|
6
|
+
class TokenExpiredError < Error
|
7
7
|
end
|
8
8
|
|
9
|
-
class
|
9
|
+
class RefreshTokenExpireError < Error
|
10
10
|
end
|
11
11
|
# APIException
|
12
|
-
class
|
12
|
+
class APIError < Error
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
|
+
class ResponseError < APIError
|
16
|
+
end
|
17
|
+
|
18
|
+
class InvalidateRequestError < ResponseError
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class UnauthorizedClientError < ResponseError
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
class AccessDeniedError < ResponseError
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class UnsupportedResponseTypeError < ResponseError
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class InvalidScopeError < ResponseError
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class TemporarilyUnavailableError < ResponseError
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class ParamIsRequiredError < APIError
|
43
|
+
end
|
44
|
+
class IllegalParamError < APIError
|
45
|
+
end
|
46
|
+
## 400000
|
47
|
+
class ClientError < APIError
|
48
|
+
end
|
49
|
+
|
50
|
+
## 400001
|
51
|
+
class ParameterError < APIError
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
## 400010
|
56
|
+
class EmailError < APIError
|
57
|
+
end
|
58
|
+
|
59
|
+
## 400011
|
60
|
+
class PasswordError < APIError
|
61
|
+
end
|
62
|
+
|
63
|
+
## 400012
|
64
|
+
class EccentricAccountError < APIError
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
## 400013
|
69
|
+
class EmailFormatError < APIError
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
## 400014
|
74
|
+
class PasswordFormatError < APIError
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
## 400015
|
79
|
+
class EmailExistsError < APIError
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
## 400020
|
86
|
+
class BindingFailError < APIError
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
## 40003x
|
91
|
+
class RelationError < APIError
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
## 400030
|
96
|
+
class FollowError < RelationError
|
97
|
+
|
98
|
+
end
|
99
|
+
## 400031
|
100
|
+
class UnfollowError < RelationError
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
## 400040
|
105
|
+
class IllegalContentError < APIError
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
## 40005x
|
110
|
+
class InboxError < APIError
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
## 400050
|
115
|
+
class InboxContentCannotBeEmptyError < APIError
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
## 400051
|
120
|
+
class InboxContentTooLongError < APIError
|
121
|
+
|
15
122
|
end
|
16
|
-
|
123
|
+
|
124
|
+
## 400052
|
125
|
+
class InboxClosedError < APIError
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
## 400053
|
130
|
+
class CannotSendToOwnBlogError < APIError
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
## 400060
|
135
|
+
class OperationTooFastError < APIError
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
## 400070
|
140
|
+
class BlogClosedError < APIError
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
## 40008x
|
146
|
+
class VerifyCodeError < APIError
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
## 400080
|
151
|
+
class VerifyCodeExpiredError < VerifyCodeError
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
## 400081
|
157
|
+
class VerifyCodeWrongError < VerifyCodeError
|
158
|
+
|
17
159
|
end
|
160
|
+
|
161
|
+
## 401xxx
|
162
|
+
class AuthorizationError < APIError
|
163
|
+
end
|
164
|
+
|
165
|
+
## 401000
|
166
|
+
class UnauthorizedError < AuthorizationError
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
## 403xxx
|
171
|
+
class ForbiddenError < APIError
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
## 403000
|
176
|
+
class VisitForbiddenError < ForbiddenError
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
## 403001
|
181
|
+
class BlogManagerRequiredError < ForbiddenError
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
## 404xxx
|
186
|
+
class NotFoundError < APIError
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
## 404000
|
191
|
+
class UrlNotFoundError < NotFoundError
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
## 404002
|
196
|
+
class BlogNotFoundError < NotFoundError
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
## 404003
|
201
|
+
class ContentNotFoundError < NotFoundError
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
## 404004
|
206
|
+
class UserNotFoundError < NotFoundError
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
## 500xxx
|
211
|
+
class ServerError < APIError
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
## 500000
|
216
|
+
class InternalServerError < APIError
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
## 500001
|
221
|
+
class PostTypeError < APIError
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
## 500002
|
226
|
+
class InboxError < APIError
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
## 503001
|
231
|
+
class UpgradingError < APIError
|
232
|
+
|
233
|
+
end
|
234
|
+
|
18
235
|
# End APIException
|
19
236
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module DiandianOAuth
|
2
|
+
class Response
|
3
|
+
attr_accessor :error, :meta, :response, :internal
|
4
|
+
def self.from_response response
|
5
|
+
response_json = response.parsed
|
6
|
+
result = Response.new
|
7
|
+
result.internal = response
|
8
|
+
result.error = response_json['error']
|
9
|
+
return result if result.error
|
10
|
+
result.meta = response_json['meta']
|
11
|
+
result.response = response_json['response']
|
12
|
+
result
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate
|
16
|
+
!error && meta['status'] == 200
|
17
|
+
end
|
18
|
+
alias_method :success?, :validate
|
19
|
+
|
20
|
+
# throw exception when an error occurs
|
21
|
+
def validate!
|
22
|
+
puts "error: '#{self.inspect}'"
|
23
|
+
unless self.validate
|
24
|
+
if error
|
25
|
+
exception =
|
26
|
+
case error[:error]
|
27
|
+
when 'invalid_request' then DiandianOAuth::InvalidateRequestError
|
28
|
+
when 'unauthorized_client' then DiandianOAuth::UnauthorizedClientError
|
29
|
+
when 'access_denied' then DiandianOAuth::AccessDeniedError
|
30
|
+
when 'unsupported_response_type' then DiandianOAuth::UnsupportedResponseTypeError
|
31
|
+
when 'invalid_scope' then DiandianOAuth::InvalidScopeError
|
32
|
+
when 'server_error' then DiandianOAuth::ServerError
|
33
|
+
else APIError
|
34
|
+
end
|
35
|
+
raise exception
|
36
|
+
else
|
37
|
+
exception =
|
38
|
+
case meta[:status]
|
39
|
+
when 400000 then DiandianOAuth::ClientError
|
40
|
+
when 400001 then DiandianOAuth::ParameterError
|
41
|
+
when 400010 then DiandianOAuth::EmailError
|
42
|
+
when 400011 then DiandianOAuth::PasswordError
|
43
|
+
when 400012 then DiandianOAuth::EccentricAccountError
|
44
|
+
when 400013 then DiandianOAuth::EmailFormatError
|
45
|
+
when 400014 then DiandianOAuth::PasswordFormatError
|
46
|
+
when 400015 then DiandianOAuth::EmailExistsError
|
47
|
+
when 400020 then DiandianOAuth::BindingFailError
|
48
|
+
when 400030 then DiandianOAuth::FollowError
|
49
|
+
when 400031 then DiandianOAuth::UnfollowError
|
50
|
+
when 400040 then DiandianOAuth::IllegalContentError
|
51
|
+
when 400050 then DiandianOAuth::InboxContentCannotBeEmptyError
|
52
|
+
when 400051 then DiandianOAuth::InboxContentTooLongError
|
53
|
+
when 400052 then DiandianOAuth::InboxClosedError
|
54
|
+
when 400053 then DiandianOAuth::CannotSendToOwnBlogError
|
55
|
+
when 400060 then DiandianOAuth::OperationTooFastError
|
56
|
+
when 400070 then DiandianOAuth::BlogClosedError
|
57
|
+
when 400080 then DiandianOAuth::VerifyCodeExpiredError
|
58
|
+
when 400081 then DiandianOAuth::VerifyCodeWrongError
|
59
|
+
when 401000 then DiandianOAuth::UnauthorizedError
|
60
|
+
when 403000 then DiandianOAuth::VisitForbiddenError
|
61
|
+
when 403001 then DiandianOAuth::BlogManagerRequiredError
|
62
|
+
when 404002 then DiandianOAuth::BlogNotFoundError
|
63
|
+
when 404003 then DiandianOAuth::ContentNotFoundError
|
64
|
+
when 404004 then DiandianOAuth::UserNotFoundError
|
65
|
+
when 500000 then DiandianOAuth::InternalServerError
|
66
|
+
when 500001 then DiandianOAuth::PostTypeError
|
67
|
+
when 500002 then DiandianOAuth::InboxError
|
68
|
+
when 503001 then DiandianOAuth::UpgradingError
|
69
|
+
else DiandianOAuth::APIError
|
70
|
+
end
|
71
|
+
raise exception
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module DiandianOAuth
|
2
|
+
class ResponseMeta
|
3
|
+
attr_accessor :status, :message
|
4
|
+
def self.from_response response_json
|
5
|
+
meta = response_json['meta']
|
6
|
+
response_meta = ResponseMeta.new
|
7
|
+
response_meta.status = meta['status']
|
8
|
+
response_meta.message = meta['msg']
|
9
|
+
response_meta
|
10
|
+
end
|
11
|
+
|
12
|
+
def success?
|
13
|
+
self.validate
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate
|
17
|
+
self.status == 200
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate!
|
21
|
+
if !self.validate
|
22
|
+
exception =
|
23
|
+
case self.status
|
24
|
+
when 400000 then DiandianOAuth::ClientError
|
25
|
+
when 400001 then DiandianOAuth::ParameterError
|
26
|
+
when 400010 then DiandianOAuth::EmailError
|
27
|
+
when 400011 then DiandianOAuth::PasswordError
|
28
|
+
when 400012 then DiandianOAuth::EccentricAccountError
|
29
|
+
when 400013 then DiandianOAuth::EmailFormatError
|
30
|
+
when 400014 then DiandianOAuth::PasswordFormatError
|
31
|
+
when 400015 then DiandianOAuth::EmailExistsError
|
32
|
+
when 400020 then DiandianOAuth::BindingFailError
|
33
|
+
when 400030 then DiandianOAuth::FollowError
|
34
|
+
when 400031 then DiandianOAuth::UnfollowError
|
35
|
+
when 400040 then DiandianOAuth::IllegalContentError
|
36
|
+
when 400050 then DiandianOAuth::InboxContentCannotBeEmptyError
|
37
|
+
when 400051 then DiandianOAuth::InboxContentTooLongError
|
38
|
+
when 400052 then DiandianOAuth::InboxClosedError
|
39
|
+
when 400053 then DiandianOAuth::CannotSendToOwnBlogError
|
40
|
+
when 400060 then DiandianOAuth::OperationTooFastError
|
41
|
+
when 400070 then DiandianOAuth::BlogClosedError
|
42
|
+
when 400080 then DiandianOAuth::VerifyCodeExpiredError
|
43
|
+
when 400081 then DiandianOAuth::VerifyCodeWrongError
|
44
|
+
when 401000 then DiandianOAuth::UnauthorizedError
|
45
|
+
when 403000 then DiandianOAuth::VisitForbiddenError
|
46
|
+
when 403001 then DiandianOAuth::BlogManagerRequiredError
|
47
|
+
when 404002 then DiandianOAuth::BlogNotFoundError
|
48
|
+
when 404003 then DiandianOAuth::ContentNotFoundError
|
49
|
+
when 404004 then DiandianOAuth::UserNotFoundError
|
50
|
+
when 500000 then DiandianOAuth::InternalServerError
|
51
|
+
when 500001 then DiandianOAuth::PostTypeError
|
52
|
+
when 500002 then DiandianOAuth::InboxError
|
53
|
+
when 503001 then DiandianOAuth::UpgradingError
|
54
|
+
else DiandianOAuth::APIError
|
55
|
+
end
|
56
|
+
raise exception, self.message
|
57
|
+
end
|
58
|
+
self
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.join( File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
3
|
class AuthorizeTest < ActiveSupport::TestCase
|
4
|
-
CLIENT_ID="
|
5
|
-
CLIENT_SECRET="
|
4
|
+
CLIENT_ID="fr2ejCbPrO"
|
5
|
+
CLIENT_SECRET="C5Cgprqe3DC674vdnaQlujko9ItuSAOB24qa"
|
6
6
|
|
7
7
|
test 'authorize_url' do
|
8
8
|
assert_nothing_raised do
|
@@ -12,11 +12,12 @@ class AuthorizeTest < ActiveSupport::TestCase
|
|
12
12
|
end
|
13
13
|
|
14
14
|
test 'access_token' do
|
15
|
-
code = '
|
15
|
+
code = 'dJGgxE'
|
16
16
|
unless code.empty?
|
17
17
|
assert_nothing_raised do
|
18
|
-
client = DiandianOAuth::Client.new CLIENT_ID, CLIENT_SECRET, :redirect_uri => 'http://example.com/callback'
|
18
|
+
client = DiandianOAuth::Client.new CLIENT_ID, CLIENT_SECRET, :redirect_uri => 'http://example.com/users/auth/diandian/callback'
|
19
19
|
access_token = client.access_token code
|
20
|
+
p access_token
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
require File.join( File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
+
require 'faraday/request/diandian_multipart'
|
4
|
+
|
3
5
|
class InterfaceTest < ActiveSupport::TestCase
|
4
|
-
CLIENT_ID="
|
5
|
-
CLIENT_SECRET="
|
6
|
+
CLIENT_ID="fr2ejCbPrO"
|
7
|
+
CLIENT_SECRET="C5Cgprqe3DC674vdnaQlujko9ItuSAOB24qa"
|
6
8
|
ACCESS_TOKEN = {
|
7
|
-
:access_token => '
|
8
|
-
:refresh_token => "
|
9
|
+
:access_token => '92eb54ba-4be0-4a75-ae2a-d185d0a0f751',
|
10
|
+
:refresh_token => "fa522c29-fc69-4d45-ab59-b9e26b9e5ed5",
|
9
11
|
:token_type => "bearer",
|
10
|
-
:expires_in =>
|
11
|
-
:expires_at =>
|
12
|
+
:expires_in => 3406,
|
13
|
+
:expires_at => 1344410022,
|
12
14
|
:scope => "write read",
|
13
15
|
:uid => "11449"
|
14
16
|
}
|
@@ -22,10 +24,46 @@ class InterfaceTest < ActiveSupport::TestCase
|
|
22
24
|
test 'user_info' do
|
23
25
|
client = self.client
|
24
26
|
client.access_token= ACCESS_TOKEN
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
p client.user_info
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'user_info!' do
|
31
|
+
client = self.client
|
32
|
+
client.access_token = ACCESS_TOKEN.merge(:expires_at => Time.now.to_i - 1.day.to_i)
|
33
|
+
puts "expired?: '#{client.access_token.expired?}'"
|
34
|
+
p client.user_info!
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'create_post' do
|
38
|
+
client = self.client
|
39
|
+
client.access_token = ACCESS_TOKEN
|
40
|
+
p client.create_post :blogCName => 'secretworry.diandian.com',
|
41
|
+
:type => 'text',
|
42
|
+
:state => 'published',
|
43
|
+
:title => 'Hello from diandian ruby client'
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'create_photo_post' do
|
47
|
+
client = self.client
|
48
|
+
client.access_token = ACCESS_TOKEN
|
49
|
+
Faraday::Request.register_middleware :diandian_multipart => Faraday::Request::DiandianMultipart
|
50
|
+
p client.user_info!
|
51
|
+
p client.create_post! :blogCName => 'tree-hollow.diandian.com',
|
52
|
+
:type => 'photo',
|
53
|
+
:state => 'published',
|
54
|
+
:data => [Faraday::UploadIO.new('/Users/siyudu/Pictures/test/blue_700_342.jpg', 'image/jpeg'), Faraday::UploadIO.new('/Users/siyudu/Pictures/test/white_700_342.jpg', 'image/jpeg')]
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'submissions' do
|
58
|
+
client = self.client
|
59
|
+
client.access_token = ACCESS_TOKEN
|
60
|
+
p client.submissions :blogCName => 'secretworry.diandian.com'
|
61
|
+
end
|
62
|
+
|
63
|
+
test 'delete_post' do
|
64
|
+
client = self.client
|
65
|
+
client.access_token = ACCESS_TOKEN
|
66
|
+
p client.delete_post :blogCName => 'secretworry.diandian.com', :id => '3fdc4740-dcce-11e1-a2d7-782bcb43b268'
|
29
67
|
end
|
30
68
|
|
31
69
|
test 'posts' do
|
@@ -35,6 +73,9 @@ class InterfaceTest < ActiveSupport::TestCase
|
|
35
73
|
end
|
36
74
|
|
37
75
|
def client
|
76
|
+
DiandianOAuth::Client.token_refreshed (lambda{|client, token|
|
77
|
+
p "token_refreshed: '#{token}'"
|
78
|
+
})
|
38
79
|
@client ||= DiandianOAuth::Client.new CLIENT_ID, CLIENT_SECRET, :redirect_uri => 'http://example.com/callback'
|
39
80
|
end
|
40
81
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: diandian-oauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Rainer Du
|
@@ -69,7 +69,10 @@ files:
|
|
69
69
|
- lib/diandian_oauth/api.rb
|
70
70
|
- lib/diandian_oauth/api/interface.rb
|
71
71
|
- lib/diandian_oauth/client.rb
|
72
|
+
- lib/diandian_oauth/client/callbacks.rb
|
72
73
|
- lib/diandian_oauth/exceptions.rb
|
74
|
+
- lib/diandian_oauth/models/response.rb
|
75
|
+
- lib/diandian_oauth/models/response_meta.rb
|
73
76
|
- test/diandian_oauth/api_test.rb
|
74
77
|
- test/diandian_oauth/authorize_test.rb
|
75
78
|
- test/diandian_oauth/interface_test.rb
|