rixi 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/VERSION +1 -1
  2. data/lib/rixi.rb +121 -48
  3. data/rixi.gemspec +2 -2
  4. data/sample_safari.rb +3 -1
  5. metadata +15 -15
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/lib/rixi.rb CHANGED
@@ -3,12 +3,9 @@ require 'cgi'
3
3
  require 'oauth2'
4
4
  require 'json'
5
5
 
6
+ # monkey patch
6
7
  module OAuth2
7
8
  class Client
8
- # Initializes an AccessToken by making a request to the token endpoint
9
- #
10
- # @param [Hash] params a Hash of params for the token endpoint
11
- # @return [AccessToken] the initalized AccessToken
12
9
  def get_token(params)
13
10
  opts = { :raise_errors => true, :parse => params.delete(:parse)}
14
11
  if options[:token_method] == :post
@@ -19,13 +16,15 @@ module OAuth2
19
16
  end
20
17
  response = request(options[:token_method], token_url, opts)
21
18
  raise Error.new(response) unless response.parsed.is_a?(Hash) && response.parsed['access_token']
22
-
23
- ##
24
- ## デフォルトではヘッダーでのAccessToken指定が出来ないため
25
- ##
26
- AccessToken.new(self, response.parsed.delete("access_token"),
27
- :mode => :header,
28
- :header_format => "OAuth %s")
19
+
20
+ # デフォルトではヘッダーでのAccessToken指定が出来ないため
21
+ # modeとheader_formatを追加
22
+ #AccessToken.from_hash(self, response.parsed)
23
+ response = response.parsed
24
+ AccessToken.new(self, response.delete("access_token") || response.delete(:access_token),
25
+ {:mode => :header,
26
+ :header_format => "OAuth %s"
27
+ }.merge(response))
29
28
  end
30
29
  end
31
30
  end
@@ -40,26 +39,30 @@ class Rixi
40
39
  end
41
40
 
42
41
  attr_reader :consumer_key, :consumer_secret, :redirect_uri, :token, :client
43
-
42
+
44
43
  SITE = 'http://api.mixi-platform.com'
45
44
  AUTH_URL ='https://mixi.jp/connect_authorize.pl'
46
45
  TOKEN_URL ='https://secure.mixi-platform.com/2/token'
47
-
46
+
48
47
  def initialize(params = { })
49
48
  if params[:consumer_key] == nil && params[:consumer_secret] == nil
50
49
  raise "Rixi needs a consumer_key or consumer_secret."
51
50
  end
52
-
53
- @consumer_key = params[:consumer_key]
54
- @consumer_secret = params[:consumer_secret]
55
- @redirect_uri = params[:redirect_uri]
56
- @scope = scope_to_query(params[:scope])
51
+
52
+ @consumer_key = params.delete :consumer_key
53
+ @consumer_secret = params.delete :consumer_secret
54
+ @redirect_uri = params.delete :redirect_uri
55
+ @scope = scope_to_query(params.delete(:scope))
56
+
57
+ params.merge!({
58
+ :site => SITE,
59
+ :authorize_url => AUTH_URL,
60
+ :token_url => TOKEN_URL
61
+ })
57
62
  @client = OAuth2::Client.new(
58
63
  @consumer_key,
59
64
  @consumer_secret,
60
- :site => SITE,
61
- :authorize_url => AUTH_URL,
62
- :token_url => TOKEN_URL
65
+ params
63
66
  )
64
67
  end
65
68
 
@@ -91,7 +94,7 @@ class Rixi
91
94
  # 次期バージョンが出来るとするならAPIの種類毎に
92
95
  # モジュールに切り分けて実装したいです。
93
96
  #
94
- # 注:%d は省略可能なpathを表現するために使ってます
97
+ # 注:%o は省略可能なpathを表現するために使ってます
95
98
  # 例えば、友人のつぶやき一覧の取得をするAPIは以下で、
96
99
  # /2/voice/statuses/friends_timeline/[Group-ID]?since_id=[つぶやきのID]
97
100
  # Group-IDはpathにも含まれますが省略可能です
@@ -99,13 +102,6 @@ class Rixi
99
102
  # 指定するとして、:optional_pathが存在しなければAPIのパスから
100
103
  # 省略することとします。
101
104
  #
102
- # 注2:mixiチェック用API /2/share はPOSTメソッドでリクエストする際に、
103
- # データをJSON形式で与えるため、未実装です。
104
- #
105
- # 注3:DiaryAPIもmultipart/form-data形式として投稿しなければならないため
106
- # 現状、未実装です
107
- #
108
- # 注4:画像投稿系のAPIは未対応です
109
105
  #
110
106
  def self.api_settings
111
107
  # method name, path for API endpoints, http method
@@ -117,11 +113,12 @@ class Rixi
117
113
  show_status /2/voice/statuses/show/%s get
118
114
  show_favorites /2/voice/favorites/show/%s get
119
115
  update_status /2/voice/statuses/update post
120
- delete_statsu /2/voice/statuses/destroy/%s post
116
+ delete_status /2/voice/statuses/destroy/%s post
121
117
  create_replies /2/voice/statuses/replies/create/%s post
122
118
  delete_replies /2/voice/replies/destroy/%s/%s post
123
119
  create_favorite /2/voice/favorites/create/%s post
124
120
  delete_favorite /2/voice/favorites/destory/%s/%s post
121
+ share /2/share post_json
125
122
  albums /2/photo/albums/%s/@self/%o get
126
123
  recent_album /2/photo/albums/%s/%s get
127
124
  photos_in_album /2/photo/mediaItems/%s/@self/%s/%o get
@@ -129,14 +126,26 @@ class Rixi
129
126
  comments_album /2/photo/comments/albums/%s/@self/%s get
130
127
  comments_photo /2/photo/comments/mediaItems/%s/@self/%s/%s get
131
128
  favorites_photo /2/phoho/favorites/mediaItems/%s/@self/%s/%s get
132
- create_album /2/photo/albums/%s/@self post
129
+ create_album /2/photo/albums/%s/@self post_json
133
130
  delete_album /2/photo/albums/%s/@self/%s delete
134
- create_comment_album /2/photo/comments/albums/%s/@self/%s post
131
+ create_comment_album /2/photo/comments/albums/%s/@self/%s post_json
135
132
  delete_comment_album /2/photo/comments/albums/%s/@self/%s/%s delete
136
133
  upload_photo /2/photo/mediaItems/%s/@self/%s post_image
137
- create_comment_photo /2/photo/comments/mediaItems/%s/@self/%s/%s/ delete
134
+ delete_photo /2/photo/mediaItems/%s/@self/%s/%s delete
135
+ create_comment_photo /2/photo/comments/mediaItems/%s/@self/%s/%s/ post_json
136
+ delete_comment_photo /2/photo/comments/mediaItems/%s/@self/%s/%s/ delete
138
137
  create_favorite_photo /2/photo/favorites/mediaItems/%s/@self/%s/%s/ post
139
138
  delete_favorite_photo /2/photo/favorites/mediaItems/%s/@self/%s/%s/ delete
139
+ spot /2/spots/%s get
140
+ search_spot /2/search/spots get
141
+ spots_list /2/spots/%s/@self get
142
+ create_myspot /2/spots/%s/@self post
143
+ delete_myspot /2/spots/%s/@self delete
144
+ get_checkins /2/checkins/%s/%s get
145
+ get_checkin /2/checkins/%s/@self/%s get
146
+ checkin /2/checkins/%s post_multipart
147
+ checkin_with_photo /2/checkins/%s post_multipart
148
+ diary /2/diary/articles/@me/@self post_multipart
140
149
  messages_inbox /2/messages/%s/@inbox/%o get
141
150
  messages_outbox /2/messages/%s/@outbox/%o get
142
151
  create_message /2/messages/%s/@self/@outbox post
@@ -146,7 +155,7 @@ class Rixi
146
155
  people_images /2/people/images/%s/@self/%o get
147
156
  create_people_image /2/people/images/%s/@self post
148
157
  set_people_image /2/people/images/%s/@self/%s put
149
- delete_people_imag /2/people/images/%s/@self/%s delete
158
+ delete_people_image /2/people/images/%s/@self/%s delete
150
159
  ".strip.split("\n").map {|l| l.strip.split(/\s+/)}
151
160
  end
152
161
 
@@ -163,10 +172,12 @@ class Rixi
163
172
  path.sub!("/%o","")
164
173
  end
165
174
  end
175
+ extend_expire()
166
176
  __send__ http_method, path % args, params
167
177
  end
168
178
  else
169
179
  define_method method_name do |params = { }|
180
+ extend_expire()
170
181
  __send__ http_method, path, params
171
182
  end
172
183
  end
@@ -175,36 +186,59 @@ class Rixi
175
186
  # define_methodで定義されたメソッドは最終的に
176
187
  # これらのメソッドを呼ぶ
177
188
  def get(path, params = { })
178
- extend_expire()
179
189
  parse_response(@token.get(path, :params => params))
180
190
  end
181
191
 
182
192
  def post(path, params = { })
183
- extend_expire()
184
193
  parse_response(@token.post(path,:params => params))
185
194
  end
186
195
 
187
- # img"rb"で開いたFileのインスタンスで渡す
196
+ # 画像params[:image], タイトルは params[:title]で渡す
197
+ # 画像はバイナリ文字列で渡す
188
198
  def post_image(path, params = { })
189
- extend_expire()
190
199
  path += "?title="+ CGI.escape(params[:title]) if params[:title]
191
- parse_response(@token.post(path,
192
- {
200
+ parse_response(@token.post(path,{
193
201
  :headers => {
194
202
  :content_type => "image/jpeg",
195
203
  :content_length => params[:image].size.to_s,
204
+ },:body => params[:image]}))
205
+ end
206
+
207
+ # params[:json]はハッシュで渡して関数内でJSON化する
208
+ def post_json(path, params = { })
209
+ parse_response(@token.post(path,{
210
+ :headers => {
211
+ :content_type => "application/json; charset=utf-8",
212
+ :content_length => params[:json].size.to_s
213
+ },:body => params[:json]}))
214
+ end
215
+
216
+ # JSON形式+写真を投稿することが可能なAPIについて
217
+ def post_multipart(path, params ={ })
218
+ if params[:image]
219
+ now = Time.now.strftime("%Y%m%d%H%M%S")
220
+ content_type = "multipart/form-data; boundary=boundary#{now}"
221
+ body = application_json(now,params[:json])
222
+ body << attach_photos(now,params[:image])
223
+ body << end_boundary(now)
224
+ else
225
+ content_type = "application/json"
226
+ body = params[:json]
227
+ end
228
+
229
+ parse_response(@token.post(path,{
230
+ :headers => {
231
+ :content_type => content_type,
232
+ :content_length => body.size.to_s
196
233
  },
197
- :body => params[:image].read
198
- }))
234
+ :body => body}))
199
235
  end
200
236
 
201
237
  def delete(path, params = { })
202
- extend_expire()
203
- parse_response(@token.delete(path, :params => params))
238
+ @token.delete(path, :params => params).response.env[:status].to_s
204
239
  end
205
240
 
206
241
  def put(path, params = { })
207
- extend_expire()
208
242
  parse_response(@token.put(path, :params => params))
209
243
  end
210
244
 
@@ -220,14 +254,53 @@ class Rixi
220
254
  voice_statuses_update(:statsus => status)
221
255
  end
222
256
 
223
- def parse_response(res)
224
- res = res.response.env
257
+ def parse_response(response)
258
+ res = response.response.env
225
259
  case res[:status].to_i
226
260
  when 400...600
227
- raise APIError.new("API Error", res)
261
+ puts "API ERROR: status_code=" + res[:status].to_s
262
+ JSON.parse(res[:body])
228
263
  else
229
264
  JSON.parse(res[:body])
230
265
  end
231
266
  end
267
+
268
+ # build request body
269
+ def application_json(time,json)
270
+ return <<-"EOF".force_encoding("UTF-8")
271
+ --boundary#{time}\r
272
+ Content-Disposition: form-data; name="request"\r
273
+ Content-Type: application/json\r
274
+ \r
275
+ #{json.to_json}\r
276
+ EOF
277
+ end
278
+
279
+ def attach_photos(time, imgs)
280
+ if imgs.instance_of?(Array)
281
+ count = 1
282
+ else
283
+ count = ""
284
+ imgs = [imgs]
285
+ end
286
+
287
+ attach = ""
288
+ imgs.each do |img|
289
+ tmp = <<"IMAGE".force_encoding("UTF-8")
290
+ --boundary#{time}\r
291
+ Content-Disposition: form-data; name="photo#{count}"; filename="#{time+count.to_s}.jpg"\r
292
+ Content-Type: image/jpeg\r
293
+ \r
294
+ #{img}\r
295
+ IMAGE
296
+ count+=1 if count != ""
297
+ attach << tmp
298
+ end
299
+ attach
300
+ end
301
+
302
+ def end_boundary(time)
303
+ "--boundary#{time}--"
304
+ end
232
305
 
233
306
  end
data/rixi.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rixi}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{ainame }]
12
- s.date = %q{2011-08-18}
12
+ s.date = %q{2011-08-22}
13
13
  s.description = %q{Rixi is a simply library for mixi graph api in Ruby.}
14
14
  s.email = %q{ainame954@facebook.com}
15
15
  s.extra_rdoc_files = [
data/sample_safari.rb CHANGED
@@ -64,7 +64,9 @@ config = YAML.load_file("setting.yml")
64
64
  M = Rixi.new( :consumer_key => config['consumer_key'],
65
65
  :consumer_secret => config['consumer_secret'],
66
66
  :redirect_uri => 'http://0.0.0.0:4567/callback',
67
- :scope => scope)
67
+ :scope => scope,
68
+ :connection_opts => {:proxy => ENV["https_proxy"]},
69
+ :raise_errors => false)
68
70
 
69
71
  browser = Watir::Safari.new
70
72
  browser.goto M.authorized_uri
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rixi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-18 00:00:00.000000000Z
12
+ date: 2011-08-22 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: oauth2
16
- requirement: &70222871326180 !ruby/object:Gem::Requirement
16
+ requirement: &70166902590920 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70222871326180
24
+ version_requirements: *70166902590920
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: json
27
- requirement: &70222871325260 !ruby/object:Gem::Requirement
27
+ requirement: &70166902589980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70222871325260
35
+ version_requirements: *70166902589980
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70222871324500 !ruby/object:Gem::Requirement
38
+ requirement: &70166902589100 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.3.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70222871324500
46
+ version_requirements: *70166902589100
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &70222871323880 !ruby/object:Gem::Requirement
49
+ requirement: &70166902588060 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70222871323880
57
+ version_requirements: *70166902588060
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: jeweler
60
- requirement: &70222871323340 !ruby/object:Gem::Requirement
60
+ requirement: &70166902587220 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.6.4
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70222871323340
68
+ version_requirements: *70166902587220
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rcov
71
- requirement: &70222871322840 !ruby/object:Gem::Requirement
71
+ requirement: &70166902586280 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70222871322840
79
+ version_requirements: *70166902586280
80
80
  description: Rixi is a simply library for mixi graph api in Ruby.
81
81
  email: ainame954@facebook.com
82
82
  executables: []
@@ -113,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
113
  version: '0'
114
114
  segments:
115
115
  - 0
116
- hash: 921506224466776057
116
+ hash: -3097028528826085841
117
117
  required_rubygems_version: !ruby/object:Gem::Requirement
118
118
  none: false
119
119
  requirements: