friendfeed 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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