friendfeed 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.12
1
+ 0.1.13
data/bin/tw2ff CHANGED
@@ -246,7 +246,8 @@ EOF
246
246
  picture_urls[name] = friend.profile_image_url
247
247
  end
248
248
  }
249
- friends << Config('twitter.username')
249
+ twitter_me = Config('twitter.username')
250
+ friends << twitter_me
250
251
 
251
252
  Status('friends') { friends.sort }
252
253
  Status('friends_to_watch') { to_watch.sort }
@@ -264,6 +265,13 @@ EOF
264
265
  ffcli.change_picture_to_url(id, url)
265
266
  end
266
267
  }
268
+
269
+ printf <<-EOS, 'http://friendfeed.com/friends/twitter?username=' + URI.escape(twitter_me)
270
+
271
+ You may also want to check out the following page
272
+ to see if someone is joining FriendFeed:
273
+ %s
274
+ EOS
267
275
  end
268
276
  end
269
277
 
@@ -329,7 +337,7 @@ EOF
329
337
  liked = Set[]
330
338
  tw_url = {}
331
339
 
332
- ffcli.get_user_liked_entries.each { |like|
340
+ ffcli.get_user_liked_entries(nil, 'service' => 'twitter').each { |like|
333
341
  url = like['link']
334
342
  case TWITTER_URI.route_to(url).to_s
335
343
  when %r{\A([A-Za-z0-9_]+)/statuses/([0-9]+)\z}
@@ -342,13 +350,18 @@ EOF
342
350
  # Favorite FriendFeed-liked entry in Twitter
343
351
  (liked - favorited).each { |id|
344
352
  putinfo "Adding a favorite in Twitter: %s", tw_url[id]
345
- twcli.favorite_create(id)
353
+ begin
354
+ twcli.favorite_create(id)
355
+ rescue
356
+ # Maybe already favorited a long ago
357
+ end
346
358
  }
347
359
 
348
360
  # Find Twitter-liked entries in FriendFeed that aren't liked yet
349
361
  (
350
- ffcli.get_user_friend_entries(nil, 'num' => 1000) +
351
- ffcli.get_user_discussed_entries
362
+ ffcli.get_user_friend_entries(nil, 'service' => 'twitter') +
363
+ ffcli.get_user_discussed_entries(nil, 'service' => 'twitter')
364
+ # Currently imaginary friends entries are not checked
352
365
  ).sort_by { |entry|
353
366
  entry["published"]
354
367
  }.each { |entry|
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{friendfeed}
8
- s.version = "0.1.12"
8
+ s.version = "0.1.13"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Akinori MUSHA"]
12
- s.date = %q{2010-02-12}
12
+ s.date = %q{2010-02-18}
13
13
  s.default_executable = %q{tw2ff}
14
14
  s.description = %q{This is a Ruby library to provide access to FriendFeed API's.
15
15
 
@@ -34,6 +34,7 @@ manipulating friends, groups and services for your personal purposes.
34
34
  "lib/friendfeed.rb",
35
35
  "lib/friendfeed/compat.rb",
36
36
  "lib/friendfeed/unofficial.rb",
37
+ "lib/friendfeed/v1.rb",
37
38
  "test/friendfeed_test.rb",
38
39
  "test/test_helper.rb"
39
40
  ]
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ # -*- mode: ruby -*-
2
2
  #--
3
3
  # friendfeed.rb - provides access to FriendFeed API's
4
4
  #++
@@ -8,486 +8,7 @@
8
8
  # terms as Ruby.
9
9
  #
10
10
 
11
- require 'rubygems'
12
- require 'json'
13
- require 'mechanize'
14
- require 'uri'
15
- require 'friendfeed/compat'
16
-
17
11
  module FriendFeed
18
- ROOT_URI = URI.parse("https://friendfeed.com/")
19
-
20
- # Client library for FriendFeed API.
21
- class Client
22
- attr_reader :nickname
23
-
24
- #
25
- # Official API
26
- #
27
-
28
- API_URI = ROOT_URI + "/api/"
29
-
30
- private
31
-
32
- def get_api_agent
33
- @api_agent ||= Mechanize.new
34
- end
35
-
36
- def validate
37
- call_api('validate')
38
- end
39
-
40
- def require_api_login
41
- @nickname or raise 'not logged in'
42
- end
43
-
44
- def call_subscription_api(path)
45
- require_api_login
46
-
47
- uri = API_URI + path
48
-
49
- agent = Mechanize.new
50
- agent.auth('username', @nickname)
51
- JSON.parse(agent.post(uri, { 'apikey' => @remote_key }).body)
52
- end
53
-
54
- public
55
-
56
- attr_reader :nickname, :remote_key
57
-
58
- # Performs a login with a +nickname+ and +remote key+ and returns
59
- # self. This enables call of any official API that requires
60
- # authentication. It is not needed to call this method if you
61
- # have called login(), which internally obtains a remote key and
62
- # calls this method. An exception is raised if authentication
63
- # fails.
64
- def api_login(nickname, remote_key)
65
- @nickname = nickname
66
- @remote_key = remote_key
67
- @api_agent = get_api_agent()
68
- @api_agent.auth(@nickname, @remote_key)
69
- validate
70
-
71
- self
72
- end
73
-
74
- # Calls an official API specified by a +path+ with optional
75
- # +get_parameters+ and +post_parameters+, and returns an object
76
- # parsed from a JSON response. If +post_parameters+ is given, a
77
- # POST request is issued. A GET request is issued otherwise.
78
- def call_api(path, get_parameters = nil, post_parameters = nil, raw = false)
79
- api_agent = get_api_agent()
80
-
81
- uri = API_URI + path
82
- if get_parameters
83
- uri.query = get_parameters.map { |key, value|
84
- key = key.to_s
85
- if array = Array.try_convert(value)
86
- value = array.join(',')
87
- else
88
- value = value.to_s
89
- end
90
- URI.encode(key) + "=" + URI.encode(value)
91
- }.join('&')
92
- end
93
-
94
- if post_parameters
95
- body = api_agent.post(uri, post_parameters).body
96
- else
97
- body = api_agent.get_file(uri)
98
- end
99
-
100
- if raw
101
- body
102
- else
103
- JSON.parse(body)
104
- end
105
- end
106
-
107
- # Gets profile information of a user of a given +nickname+,
108
- # defaulted to the authenticated user, in hash.
109
- def get_profile(nickname = nil)
110
- nickname ||= @nickname
111
- nickname or require_api_login
112
- call_api('user/%s/profile' % URI.encode(nickname))
113
- end
114
-
115
- # Edits profile information of the authenticated user. The fields
116
- # "name" and "picture" are supported.
117
- def edit_profile(hash)
118
- nickname or require_api_login
119
- call_api('user/%s/profile' % URI.encode(nickname), nil, hash)
120
- end
121
-
122
- # Gets an array of profile information of users of given
123
- # +nicknames+.
124
- def get_profiles(nicknames)
125
- call_api('profiles', 'nickname' => nicknames)['profiles']
126
- end
127
-
128
- # Gets an array of profile information of friends of a user of a
129
- # given +nickname+ (defaulted to the authenticated user) is
130
- # subscribing to.
131
- def get_real_friends(nickname = nil)
132
- nickname ||= @nickname
133
- nickname or require_api_login
134
- nicknames = []
135
- get_profile(@nickname)['subscriptions'].each { |subscription|
136
- if nickname = subscription['nickname']
137
- nicknames << nickname
138
- end
139
- }
140
- get_profiles(nicknames)
141
- end
142
-
143
- # Gets an array of profile information of the authenticated user's
144
- # imaginary friends.
145
- def get_imaginary_friends
146
- nickname or require_api_login
147
- profiles = []
148
- get_profile(@nickname)['subscriptions'].each { |subscription|
149
- if subscription['nickname'].nil?
150
- profiles << get_profile(subscription['id'])
151
- end
152
- }
153
- profiles
154
- end
155
-
156
- # Gets profile information of one of the authenticated user's
157
- # imaginary friends.
158
- def get_imaginary_friend(id)
159
- get_profile(id)
160
- end
161
-
162
- # Gets an array of the most recent public entries.
163
- def get_public_entries(options = nil)
164
- call_api('feed/public', options)['entries']
165
- end
166
-
167
- # Gets an array of the entries the authenticated user would see on
168
- # their home page.
169
- def get_home_entries(options = nil)
170
- require_api_login
171
- call_api('feed/home', options)['entries']
172
- end
173
-
174
- # Gets an array of the entries for the authenticated user's list
175
- # of a given +nickname+
176
- def get_list_entries(nickname, options = nil)
177
- require_api_login
178
- call_api('feed/list/%s' % URI.encode(nickname), options)['entries']
179
- end
180
-
181
- # Gets an array of the most recent entries from a user of a given
182
- # +nickname+ (defaulted to the authenticated user).
183
- def get_user_entries(nickname = nil, options = nil)
184
- nickname ||= @nickname
185
- nickname or require_api_login
186
- call_api('feed/user/%s' % URI.encode(nickname), options)['entries']
187
- end
188
-
189
- # Gets an array of the most recent entries from users of given
190
- # +nicknames+.
191
- def get_multi_user_entries(nicknames, options = nil)
192
- new_options = { 'nickname' => nicknames }
193
- new_options.merge!(options) if options
194
- call_api('feed/user', new_options)['entries']
195
- end
196
-
197
- # Gets an array of the most recent entries a user of a given
198
- # +nickname+ (defaulted to the authenticated user) has commented
199
- # on.
200
- def get_user_commented_entries(nickname = nil, options = nil)
201
- nickname ||= @nickname
202
- nickname or require_api_login
203
- call_api('feed/user/%s/comments' % URI.encode(nickname), options)['entries']
204
- end
205
-
206
- # Gets an array of the most recent entries a user of a given
207
- # +nickname+ (defaulted to the authenticated user) has like'd.
208
- def get_user_liked_entries(nickname = nil, options = nil)
209
- nickname ||= @nickname
210
- nickname or require_api_login
211
- call_api('feed/user/%s/likes' % URI.encode(nickname), options)['entries']
212
- end
213
-
214
- # Gets an array of the most recent entries a user of a given
215
- # +nickname+ (defaulted to the authenticated user) has commented
216
- # on or like'd.
217
- def get_user_discussed_entries(nickname = nil, options = nil)
218
- nickname ||= @nickname
219
- nickname or require_api_login
220
- call_api('feed/user/%s/discussion' % URI.encode(nickname), options)['entries']
221
- end
222
-
223
- # Gets an array of the most recent entries from friends of a user
224
- # of a given +nickname+ (defaulted to the authenticated user).
225
- def get_user_friend_entries(nickname = nil, options = nil)
226
- nickname ||= @nickname
227
- nickname or require_api_login
228
- call_api('feed/user/%s/friends' % URI.encode(nickname), options)['entries']
229
- end
230
-
231
- # Gets an array of the most recent entries in a room of a given
232
- # +nickname+.
233
- def get_room_entries(nickname, options = nil)
234
- call_api('feed/room/%s' % URI.encode(nickname), options)['entries']
235
- end
236
-
237
- # Gets an array of the entries the authenticated user would see on
238
- # their rooms page.
239
- def get_rooms_entries(options = nil)
240
- call_api('feed/rooms', options)['entries']
241
- end
242
-
243
- # Gets an entry of a given +entryid+. An exception is raised when
244
- # it fails.
245
- def get_entry(entryid)
246
- call_api('feed/entry/%s' % URI.encode(entryid))['entries'].first
247
- end
248
-
249
- # Gets an array of entries of given +entryids+. An exception is
250
- # raised when it fails.
251
- def get_entries(entryids)
252
- call_api('feed/entry', 'entry_id' => entryids)['entries']
253
- end
254
-
255
- # Gets an array of entries that match a given +query+.
256
- def search(query, options = nil)
257
- new_options = { 'q' => query }
258
- new_options.merge!(options) if options
259
- call_api('feed/search', 'q' => new_options)['entries']
260
- end
261
-
262
- # Gets an array of entries that link to a given +url+.
263
- def search_for_url(url, options = nil)
264
- new_options = { 'url' => url }
265
- new_options.merge!(options) if options
266
- call_api('feed/url', new_options)['entries']
267
- end
268
-
269
- # Gets an array of entries that link to a given +domain+.
270
- def search_for_domain(url, options = nil)
271
- new_options = { 'url' => url }
272
- new_options.merge!(options) if options
273
- call_api('feed/domain', new_options)['entries']
274
- end
275
-
276
- # Publishes (shares) a given entry.
277
- def add_entry(title, options = nil)
278
- require_api_login
279
- new_options = { 'title' => title }
280
- if options
281
- options.each { |key, value|
282
- case key = key.to_s
283
- when 'title', 'link', 'comment', 'room'
284
- new_options[key] = value
285
- when 'images'
286
- value.each_with_index { |value, i|
287
- if url = String.try_convert(value)
288
- link = nil
289
- else
290
- if array = Array.try_convert(value)
291
- value1, value2 = *array
292
- elsif hash = Hash.try_convert(value)
293
- value1, value2 = *hash.values_at('url', 'link')
294
- else
295
- raise TypeError, "Each image must be specified by <image URL>, [<image URL>, <link URL>], or {'url' => <image URL>, 'link' => <link URL>}."
296
- end
297
- url = String.try_convert(value1) or
298
- raise TypeError, "can't convert #{value1.class} into String"
299
- link = String.try_convert(value2) or
300
- raise TypeError, "can't convert #{value2.class} into String"
301
- end
302
- new_options['image%d_url' % i] = url
303
- new_options['image%d_link' % i] = link if link
304
- }
305
- when 'audios'
306
- value.each_with_index { |value, i|
307
- if url = String.try_convert(value)
308
- link = nil
309
- else
310
- if array = Array.try_convert(value)
311
- value1, value2 = *array
312
- elsif hash = Hash.try_convert(value)
313
- value1, value2 = *hash.values_at('url', 'link')
314
- else
315
- raise TypeError, "Each audio must be specified by <audio URL>, [<audio URL>, <link URL>], or {'url' => <audio URL>, 'link' => <link URL>}."
316
- end
317
- url = String.try_convert(value1) or
318
- raise TypeError, "can't convert #{value1.class} into String"
319
- link = String.try_convert(value2) or
320
- raise TypeError, "can't convert #{value2.class} into String"
321
- end
322
- new_options['audio%d_url' % i] = url
323
- new_options['audio%d_link' % i] = link if link
324
- }
325
- when 'files'
326
- value.each_with_index { |value, i|
327
- if file = IO.try_convert(value)
328
- link = nil
329
- else
330
- if array = Array.try_convert(value)
331
- value1, value2 = *array
332
- elsif hash = Hash.try_convert(value)
333
- value1, value2 = *hash.values_at('file', 'link')
334
- else
335
- raise TypeError, "Each file must be specified by <file IO>, [<file IO>, <link URL>], or {'file' => <file IO>, 'link' => <link URL>}."
336
- end
337
- file = IO.try_convert(value1) or
338
- raise TypeError, "can't convert #{value1.class} into IO"
339
- link = String.try_convert(value2) or
340
- raise TypeError, "can't convert #{value2.class} into String"
341
- end
342
- new_options['file%d' % i] = file
343
- new_options['file%d_link' % i] = link if link
344
- }
345
- end
346
- }
347
- end
348
- call_api('share', nil, new_options)['entries'].first
349
- end
350
-
351
- alias publish add_entry
352
- alias share add_entry
353
-
354
- # Adds a comment to a given entry.
355
- def add_comment(entryid, body)
356
- require_api_login
357
- call_api('comment', nil, {
358
- 'entry' => entryid,
359
- 'body' => body,
360
- })
361
- end
362
-
363
- # Edits a given comment.
364
- def edit_comment(entryid, commentid, body)
365
- require_api_login
366
- call_api('comment', nil, {
367
- 'entry' => entryid,
368
- 'comment' => commentid,
369
- 'body' => body,
370
- })
371
- end
372
-
373
- # Deletes a given comment.
374
- def delete_comment(entryid, commentid)
375
- require_api_login
376
- call_api('comment/delete', nil, {
377
- 'entry' => entryid,
378
- 'comment' => commentid,
379
- })
380
- end
381
-
382
- # Undeletes a given comment that is already deleted.
383
- def undelete_comment(entryid, commentid)
384
- require_api_login
385
- call_api('comment/delete', nil, {
386
- 'entry' => entryid,
387
- 'comment' => commentid,
388
- 'undelete' => 'on',
389
- })
390
- end
391
-
392
- # Adds a "like" to a given entry.
393
- def add_like(entryid)
394
- require_api_login
395
- call_api('like', nil, {
396
- 'entry' => entryid,
397
- })
398
- end
399
-
400
- # Deletes an existing "like" from a given entry.
401
- def delete_like(entryid)
402
- require_api_login
403
- call_api('like/delete', nil, {
404
- 'entry' => entryid,
405
- })
406
- end
407
-
408
- # Deletes an existing entry of a given +entryid+.
409
- def delete_entry(entryid)
410
- require_api_login
411
- call_api('entry/delete', nil, {
412
- 'entry' => entryid,
413
- })
414
- end
415
-
416
- # Undeletes a given entry that is already deleted.
417
- def undelete_entry(entryid)
418
- require_api_login
419
- call_api('entry/delete', nil, {
420
- 'entry' => entryid,
421
- 'undelete' => 'on',
422
- })
423
- end
424
-
425
- # Hides an existing entry of a given +entryid+.
426
- def hide_entry(entryid)
427
- require_api_login
428
- call_api('entry/hide', nil, {
429
- 'entry' => entryid,
430
- })
431
- end
432
-
433
- # Unhides a given entry that is already hidden.
434
- def unhide_entry(entryid)
435
- require_api_login
436
- call_api('entry/hide', nil, {
437
- 'entry' => entryid,
438
- 'unhide' => 'on',
439
- })
440
- end
441
-
442
- # Gets a picture of a user of a given +nickname+ (defaulted to the
443
- # authenticated user) in blob. Size can be 'small' (default),
444
- # 'medium' or 'large',
445
- def get_picture(nickname = nil, size = 'small')
446
- nickname ||= @nickname
447
- nickname or require_api_login
448
- call_api('/%s/picture' % URI.escape(nickname), { 'size' => size }, nil, true)
449
- end
450
-
451
- # Gets a picture of a room of a given +nickname+ in blob. Size
452
- # can be 'small' (default), 'medium' or 'large',
453
- def get_room_picture(nickname, size = 'small')
454
- call_api('/rooms/%s/picture' % URI.escape(nickname), { 'size' => size }, nil, true)
455
- end
456
-
457
- # Gets profile information of a room of a given +nickname+ in
458
- # hash.
459
- def get_room_profile(nickname)
460
- call_api('room/%s/profile' % URI.encode(nickname))
461
- end
462
-
463
- # Gets profile information of the authenticated user's list of a
464
- # given +nickname+ in hash.
465
- def get_list_profile(nickname)
466
- call_api('list/%s/profile' % URI.encode(nickname))
467
- end
468
-
469
- # Subscribes to a user of a given +nickname+ and returns a status
470
- # string.
471
- def subscribe_to_user(nickname)
472
- call_subscription_api('user/%s/subscribe' % URI.encode(nickname))['status']
473
- end
474
-
475
- # Unsubscribes from a user of a given +nickname+ and returns a
476
- # status string.
477
- def unsubscribe_from_user(nickname)
478
- call_subscription_api('user/%s/subscribe?unsubscribe=1' % URI.encode(nickname))['status']
479
- end
480
-
481
- # Subscribes to a room of a given +nickname+ and returns a status
482
- # string.
483
- def subscribe_to_room(nickname)
484
- call_subscription_api('room/%s/subscribe' % URI.encode(nickname))['status']
485
- end
486
-
487
- # Unsubscribes from a room of a given +nickname+ and returns a
488
- # status string.
489
- def unsubscribe_from_room(nickname)
490
- call_subscription_api('room/%s/subscribe?unsubscribe=1' % URI.encode(nickname))['status']
491
- end
492
- end
12
+ autoload :Client, 'friendfeed/v1'
13
+ autoload :V2, 'friendfeed/v2'
493
14
  end
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env ruby
1
+ # -*- mode:ruby -*-
2
2
  #--
3
3
  # friendfeed/compat.rb - defines compatibility methods for older Ruby
4
4
  #++
5
- # Copyright (c) 2009 Akinori MUSHA <knu@iDaemons.org>
5
+ # Copyright (c) 2009, 2010 Akinori MUSHA <knu@iDaemons.org>
6
6
  #
7
7
  # All rights reserved. You can redistribute and/or modify it under the same
8
8
  # terms as Ruby.
@@ -1,18 +1,17 @@
1
- #!/usr/bin/env ruby
1
+ # -*- mode: ruby -*-
2
2
  #--
3
3
  # friendfeed/unofficial.rb - provides access to FriendFeed unofficial API's
4
4
  #++
5
- # Copyright (c) 2009 Akinori MUSHA <knu@iDaemons.org>
5
+ # Copyright (c) 2009, 2010 Akinori MUSHA <knu@iDaemons.org>
6
6
  #
7
7
  # All rights reserved. You can redistribute and/or modify it under the same
8
8
  # terms as Ruby.
9
9
  #
10
10
 
11
- require 'friendfeed'
12
- require 'rubygems'
13
11
  require 'json'
14
12
  require 'mechanize'
15
13
  require 'uri'
14
+ require 'friendfeed/v1'
16
15
 
17
16
  module FriendFeed
18
17
  class Client
@@ -20,7 +19,8 @@ module FriendFeed
20
19
  # Unofficial API
21
20
  #
22
21
 
23
- LOGIN_URI = ROOT_URI + "/account/login?v=2"
22
+ ROOT_URI = URI.parse("https://friendfeed.com/")
23
+ LOGIN_URI = ROOT_URI + "/account/login?v=2"
24
24
 
25
25
  private
26
26
 
@@ -89,7 +89,8 @@ module FriendFeed
89
89
 
90
90
  # Gets a list of services of a user or a room of a given
91
91
  # +nickname+, defaulted to the authenticated user.
92
- def get_services(nickname = @nickname)
92
+ def get_services(nickname = nil)
93
+ nickname ||= @nickname
93
94
  agent = get_login_agent()
94
95
 
95
96
  services_uri = ROOT_URI + ("/%s/services" % URI.encode(nickname))
@@ -0,0 +1,490 @@
1
+ # -*- mode: ruby -*-
2
+ #--
3
+ # friendfeed.rb - provides access to FriendFeed API's
4
+ #++
5
+ # Copyright (c) 2009, 2010 Akinori MUSHA <knu@iDaemons.org>
6
+ #
7
+ # All rights reserved. You can redistribute and/or modify it under the same
8
+ # terms as Ruby.
9
+ #
10
+
11
+ require 'json'
12
+ require 'mechanize'
13
+ require 'uri'
14
+ require 'friendfeed/compat'
15
+
16
+ module FriendFeed
17
+ # Client library for FriendFeed API.
18
+ class Client
19
+ attr_reader :nickname
20
+
21
+ #
22
+ # Official API
23
+ #
24
+
25
+ API_URI = URI.parse("https://friendfeed.com/api/")
26
+
27
+ private
28
+
29
+ def get_api_agent
30
+ @api_agent ||= Mechanize.new
31
+ end
32
+
33
+ def validate
34
+ call_api('validate')
35
+ end
36
+
37
+ def require_api_login
38
+ @nickname or raise 'not logged in'
39
+ end
40
+
41
+ def call_subscription_api(path)
42
+ require_api_login
43
+
44
+ uri = API_URI + path
45
+
46
+ agent = Mechanize.new
47
+ agent.auth('username', @nickname)
48
+ JSON.parse(agent.post(uri, { 'apikey' => @remote_key }).body)
49
+ end
50
+
51
+ public
52
+
53
+ attr_reader :nickname, :remote_key
54
+
55
+ # Performs a login with a +nickname+ and +remote key+ and returns
56
+ # self. This enables call of any official API that requires
57
+ # authentication. It is not needed to call this method if you
58
+ # have called login(), which internally obtains a remote key and
59
+ # calls this method. An exception is raised if authentication
60
+ # fails.
61
+ def api_login(nickname, remote_key)
62
+ @nickname = nickname
63
+ @remote_key = remote_key
64
+ @api_agent = get_api_agent()
65
+ @api_agent.auth(@nickname, @remote_key)
66
+ validate
67
+
68
+ self
69
+ end
70
+
71
+ # Calls an official API specified by a +path+ with optional
72
+ # +get_parameters+ and +post_parameters+, and returns an object
73
+ # parsed from a JSON response. If +post_parameters+ is given, a
74
+ # POST request is issued. A GET request is issued otherwise.
75
+ def call_api(path, get_parameters = nil, post_parameters = nil, raw = false)
76
+ api_agent = get_api_agent()
77
+
78
+ uri = API_URI + path
79
+ if get_parameters
80
+ uri.query = get_parameters.map { |key, value|
81
+ key = key.to_s
82
+ if array = Array.try_convert(value)
83
+ value = array.join(',')
84
+ else
85
+ value = value.to_s
86
+ end
87
+ URI.encode(key) + "=" + URI.encode(value)
88
+ }.join('&')
89
+ end
90
+
91
+ if post_parameters
92
+ body = api_agent.post(uri, post_parameters).body
93
+ else
94
+ body = api_agent.get_file(uri)
95
+ end
96
+
97
+ if raw
98
+ body
99
+ else
100
+ JSON.parse(body)
101
+ end
102
+ end
103
+
104
+ # Gets profile information of a user of a given +nickname+,
105
+ # defaulted to the authenticated user, in hash.
106
+ def get_profile(nickname = nil)
107
+ nickname ||= @nickname
108
+ nickname or require_api_login
109
+ call_api('user/%s/profile' % URI.encode(nickname))
110
+ end
111
+
112
+ # Edits profile information of the authenticated user. The fields
113
+ # "name" and "picture" are supported.
114
+ def edit_profile(hash)
115
+ nickname or require_api_login
116
+ call_api('user/%s/profile' % URI.encode(nickname), nil, hash)
117
+ end
118
+
119
+ # Gets an array of profile information of users of given
120
+ # +nicknames+.
121
+ def get_profiles(nicknames)
122
+ call_api('profiles', 'nickname' => nicknames)['profiles']
123
+ end
124
+
125
+ # Gets an array of profile information of friends of a user of a
126
+ # given +nickname+ (defaulted to the authenticated user) is
127
+ # subscribing to.
128
+ def get_real_friends(nickname = nil)
129
+ nickname ||= @nickname
130
+ nickname or require_api_login
131
+ nicknames = []
132
+ get_profile(@nickname)['subscriptions'].each { |subscription|
133
+ if nickname = subscription['nickname']
134
+ nicknames << nickname
135
+ end
136
+ }
137
+ get_profiles(nicknames)
138
+ end
139
+
140
+ # Gets an array of profile information of the authenticated user's
141
+ # imaginary friends.
142
+ def get_imaginary_friends
143
+ nickname or require_api_login
144
+ profiles = []
145
+ get_profile(@nickname)['subscriptions'].each { |subscription|
146
+ if subscription['nickname'].nil?
147
+ profiles << get_profile(subscription['id'])
148
+ end
149
+ }
150
+ profiles
151
+ end
152
+
153
+ # Gets profile information of one of the authenticated user's
154
+ # imaginary friends.
155
+ def get_imaginary_friend(id)
156
+ get_profile(id)
157
+ end
158
+
159
+ # Gets an array of the most recent public entries.
160
+ def get_public_entries(options = nil)
161
+ call_api('feed/public', options)['entries']
162
+ end
163
+
164
+ # Gets an array of the entries the authenticated user would see on
165
+ # their home page.
166
+ def get_home_entries(options = nil)
167
+ require_api_login
168
+ call_api('feed/home', options)['entries']
169
+ end
170
+
171
+ # Gets an array of the entries for the authenticated user's list
172
+ # of a given +nickname+
173
+ def get_list_entries(nickname, options = nil)
174
+ require_api_login
175
+ call_api('feed/list/%s' % URI.encode(nickname), options)['entries']
176
+ end
177
+
178
+ # Gets an array of the most recent entries from a user of a given
179
+ # +nickname+ (defaulted to the authenticated user).
180
+ def get_user_entries(nickname = nil, options = nil)
181
+ nickname ||= @nickname
182
+ nickname or require_api_login
183
+ call_api('feed/user/%s' % URI.encode(nickname), options)['entries']
184
+ end
185
+
186
+ # Gets an array of the most recent entries from users of given
187
+ # +nicknames+.
188
+ def get_multi_user_entries(nicknames, options = nil)
189
+ new_options = { 'nickname' => nicknames }
190
+ new_options.merge!(options) if options
191
+ call_api('feed/user', new_options)['entries']
192
+ end
193
+
194
+ # Gets an array of the most recent entries a user of a given
195
+ # +nickname+ (defaulted to the authenticated user) has commented
196
+ # on.
197
+ def get_user_commented_entries(nickname = nil, options = nil)
198
+ nickname ||= @nickname
199
+ nickname or require_api_login
200
+ call_api('feed/user/%s/comments' % URI.encode(nickname), options)['entries']
201
+ end
202
+
203
+ # Gets an array of the most recent entries a user of a given
204
+ # +nickname+ (defaulted to the authenticated user) has like'd.
205
+ def get_user_liked_entries(nickname = nil, options = nil)
206
+ nickname ||= @nickname
207
+ nickname or require_api_login
208
+ call_api('feed/user/%s/likes' % URI.encode(nickname), options)['entries']
209
+ end
210
+
211
+ # Gets an array of the most recent entries a user of a given
212
+ # +nickname+ (defaulted to the authenticated user) has commented
213
+ # on or like'd.
214
+ def get_user_discussed_entries(nickname = nil, options = nil)
215
+ nickname ||= @nickname
216
+ nickname or require_api_login
217
+ call_api('feed/user/%s/discussion' % URI.encode(nickname), options)['entries']
218
+ end
219
+
220
+ # Gets an array of the most recent entries from friends of a user
221
+ # of a given +nickname+ (defaulted to the authenticated user).
222
+ def get_user_friend_entries(nickname = nil, options = nil)
223
+ nickname ||= @nickname
224
+ nickname or require_api_login
225
+ call_api('feed/user/%s/friends' % URI.encode(nickname), options)['entries']
226
+ end
227
+
228
+ # Gets an array of the most recent entries in a room of a given
229
+ # +nickname+.
230
+ def get_room_entries(nickname, options = nil)
231
+ call_api('feed/room/%s' % URI.encode(nickname), options)['entries']
232
+ end
233
+
234
+ # Gets an array of the entries the authenticated user would see on
235
+ # their rooms page.
236
+ def get_rooms_entries(options = nil)
237
+ call_api('feed/rooms', options)['entries']
238
+ end
239
+
240
+ # Gets an entry of a given +entryid+. An exception is raised when
241
+ # it fails.
242
+ def get_entry(entryid)
243
+ call_api('feed/entry/%s' % URI.encode(entryid))['entries'].first
244
+ end
245
+
246
+ # Gets an array of entries of given +entryids+. An exception is
247
+ # raised when it fails.
248
+ def get_entries(entryids)
249
+ call_api('feed/entry', 'entry_id' => entryids)['entries']
250
+ end
251
+
252
+ # Gets an array of entries that match a given +query+.
253
+ def search(query, options = nil)
254
+ new_options = { 'q' => query }
255
+ new_options.merge!(options) if options
256
+ call_api('feed/search', 'q' => new_options)['entries']
257
+ end
258
+
259
+ # Gets an array of entries that link to a given +url+.
260
+ def search_for_url(url, options = nil)
261
+ new_options = { 'url' => url }
262
+ new_options.merge!(options) if options
263
+ call_api('feed/url', new_options)['entries']
264
+ end
265
+
266
+ # Gets an array of entries that link to a given +domain+.
267
+ def search_for_domain(url, options = nil)
268
+ new_options = { 'url' => url }
269
+ new_options.merge!(options) if options
270
+ call_api('feed/domain', new_options)['entries']
271
+ end
272
+
273
+ # Publishes (shares) a given entry.
274
+ def add_entry(title, options = nil)
275
+ require_api_login
276
+ new_options = { 'title' => title }
277
+ if options
278
+ options.each { |key, value|
279
+ case key = key.to_s
280
+ when 'title', 'link', 'comment', 'room'
281
+ new_options[key] = value
282
+ when 'images'
283
+ value.each_with_index { |value, i|
284
+ if url = String.try_convert(value)
285
+ link = nil
286
+ else
287
+ if array = Array.try_convert(value)
288
+ value1, value2 = *array
289
+ elsif hash = Hash.try_convert(value)
290
+ value1, value2 = *hash.values_at('url', 'link')
291
+ else
292
+ raise TypeError, "Each image must be specified by <image URL>, [<image URL>, <link URL>], or {'url' => <image URL>, 'link' => <link URL>}."
293
+ end
294
+ url = String.try_convert(value1) or
295
+ raise TypeError, "can't convert #{value1.class} into String"
296
+ link = String.try_convert(value2) or
297
+ raise TypeError, "can't convert #{value2.class} into String"
298
+ end
299
+ new_options['image%d_url' % i] = url
300
+ new_options['image%d_link' % i] = link if link
301
+ }
302
+ when 'audios'
303
+ value.each_with_index { |value, i|
304
+ if url = String.try_convert(value)
305
+ link = nil
306
+ else
307
+ if array = Array.try_convert(value)
308
+ value1, value2 = *array
309
+ elsif hash = Hash.try_convert(value)
310
+ value1, value2 = *hash.values_at('url', 'link')
311
+ else
312
+ raise TypeError, "Each audio must be specified by <audio URL>, [<audio URL>, <link URL>], or {'url' => <audio URL>, 'link' => <link URL>}."
313
+ end
314
+ url = String.try_convert(value1) or
315
+ raise TypeError, "can't convert #{value1.class} into String"
316
+ link = String.try_convert(value2) or
317
+ raise TypeError, "can't convert #{value2.class} into String"
318
+ end
319
+ new_options['audio%d_url' % i] = url
320
+ new_options['audio%d_link' % i] = link if link
321
+ }
322
+ when 'files'
323
+ value.each_with_index { |value, i|
324
+ if file = IO.try_convert(value)
325
+ link = nil
326
+ else
327
+ if array = Array.try_convert(value)
328
+ value1, value2 = *array
329
+ elsif hash = Hash.try_convert(value)
330
+ value1, value2 = *hash.values_at('file', 'link')
331
+ else
332
+ raise TypeError, "Each file must be specified by <file IO>, [<file IO>, <link URL>], or {'file' => <file IO>, 'link' => <link URL>}."
333
+ end
334
+ file = IO.try_convert(value1) or
335
+ raise TypeError, "can't convert #{value1.class} into IO"
336
+ link = String.try_convert(value2) or
337
+ raise TypeError, "can't convert #{value2.class} into String"
338
+ end
339
+ new_options['file%d' % i] = file
340
+ new_options['file%d_link' % i] = link if link
341
+ }
342
+ end
343
+ }
344
+ end
345
+ call_api('share', nil, new_options)['entries'].first
346
+ end
347
+
348
+ alias publish add_entry
349
+ alias share add_entry
350
+
351
+ # Adds a comment to a given entry.
352
+ def add_comment(entryid, body)
353
+ require_api_login
354
+ call_api('comment', nil, {
355
+ 'entry' => entryid,
356
+ 'body' => body,
357
+ })
358
+ end
359
+
360
+ # Edits a given comment.
361
+ def edit_comment(entryid, commentid, body)
362
+ require_api_login
363
+ call_api('comment', nil, {
364
+ 'entry' => entryid,
365
+ 'comment' => commentid,
366
+ 'body' => body,
367
+ })
368
+ end
369
+
370
+ # Deletes a given comment.
371
+ def delete_comment(entryid, commentid)
372
+ require_api_login
373
+ call_api('comment/delete', nil, {
374
+ 'entry' => entryid,
375
+ 'comment' => commentid,
376
+ })
377
+ end
378
+
379
+ # Undeletes a given comment that is already deleted.
380
+ def undelete_comment(entryid, commentid)
381
+ require_api_login
382
+ call_api('comment/delete', nil, {
383
+ 'entry' => entryid,
384
+ 'comment' => commentid,
385
+ 'undelete' => 'on',
386
+ })
387
+ end
388
+
389
+ # Adds a "like" to a given entry.
390
+ def add_like(entryid)
391
+ require_api_login
392
+ call_api('like', nil, {
393
+ 'entry' => entryid,
394
+ })
395
+ end
396
+
397
+ # Deletes an existing "like" from a given entry.
398
+ def delete_like(entryid)
399
+ require_api_login
400
+ call_api('like/delete', nil, {
401
+ 'entry' => entryid,
402
+ })
403
+ end
404
+
405
+ # Deletes an existing entry of a given +entryid+.
406
+ def delete_entry(entryid)
407
+ require_api_login
408
+ call_api('entry/delete', nil, {
409
+ 'entry' => entryid,
410
+ })
411
+ end
412
+
413
+ # Undeletes a given entry that is already deleted.
414
+ def undelete_entry(entryid)
415
+ require_api_login
416
+ call_api('entry/delete', nil, {
417
+ 'entry' => entryid,
418
+ 'undelete' => 'on',
419
+ })
420
+ end
421
+
422
+ # Hides an existing entry of a given +entryid+.
423
+ def hide_entry(entryid)
424
+ require_api_login
425
+ call_api('entry/hide', nil, {
426
+ 'entry' => entryid,
427
+ })
428
+ end
429
+
430
+ # Unhides a given entry that is already hidden.
431
+ def unhide_entry(entryid)
432
+ require_api_login
433
+ call_api('entry/hide', nil, {
434
+ 'entry' => entryid,
435
+ 'unhide' => 'on',
436
+ })
437
+ end
438
+
439
+ # Gets a picture of a user of a given +nickname+ (defaulted to the
440
+ # authenticated user) in blob. Size can be 'small' (default),
441
+ # 'medium' or 'large',
442
+ def get_picture(nickname = nil, size = 'small')
443
+ nickname ||= @nickname
444
+ nickname or require_api_login
445
+ call_api('/%s/picture' % URI.escape(nickname), { 'size' => size }, nil, true)
446
+ end
447
+
448
+ # Gets a picture of a room of a given +nickname+ in blob. Size
449
+ # can be 'small' (default), 'medium' or 'large',
450
+ def get_room_picture(nickname, size = 'small')
451
+ call_api('/rooms/%s/picture' % URI.escape(nickname), { 'size' => size }, nil, true)
452
+ end
453
+
454
+ # Gets profile information of a room of a given +nickname+ in
455
+ # hash.
456
+ def get_room_profile(nickname)
457
+ call_api('room/%s/profile' % URI.encode(nickname))
458
+ end
459
+
460
+ # Gets profile information of the authenticated user's list of a
461
+ # given +nickname+ in hash.
462
+ def get_list_profile(nickname)
463
+ call_api('list/%s/profile' % URI.encode(nickname))
464
+ end
465
+
466
+ # Subscribes to a user of a given +nickname+ and returns a status
467
+ # string.
468
+ def subscribe_to_user(nickname)
469
+ call_subscription_api('user/%s/subscribe' % URI.encode(nickname))['status']
470
+ end
471
+
472
+ # Unsubscribes from a user of a given +nickname+ and returns a
473
+ # status string.
474
+ def unsubscribe_from_user(nickname)
475
+ call_subscription_api('user/%s/subscribe?unsubscribe=1' % URI.encode(nickname))['status']
476
+ end
477
+
478
+ # Subscribes to a room of a given +nickname+ and returns a status
479
+ # string.
480
+ def subscribe_to_room(nickname)
481
+ call_subscription_api('room/%s/subscribe' % URI.encode(nickname))['status']
482
+ end
483
+
484
+ # Unsubscribes from a room of a given +nickname+ and returns a
485
+ # status string.
486
+ def unsubscribe_from_room(nickname)
487
+ call_subscription_api('room/%s/subscribe?unsubscribe=1' % URI.encode(nickname))['status']
488
+ end
489
+ end
490
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friendfeed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akinori MUSHA
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-12 00:00:00 +09:00
12
+ date: 2010-02-18 00:00:00 +09:00
13
13
  default_executable: tw2ff
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -58,6 +58,7 @@ files:
58
58
  - lib/friendfeed.rb
59
59
  - lib/friendfeed/compat.rb
60
60
  - lib/friendfeed/unofficial.rb
61
+ - lib/friendfeed/v1.rb
61
62
  - test/friendfeed_test.rb
62
63
  - test/test_helper.rb
63
64
  has_rdoc: true