tjplurker 1.3.1 → 1.3.2

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.
@@ -0,0 +1,718 @@
1
+ # :title:TJPlurker API Documentation
2
+ # encoding: utf-8
3
+ require 'oauth'
4
+ require 'json'
5
+ require 'logger'
6
+ require 'open-uri'
7
+
8
+ $tjpLog = Logger.new(STDOUT)
9
+ $tjpLog.level = Logger::INFO
10
+ $tjpLog.formatter = proc{ |severity, datetime, progname, msg|
11
+ "#{severity} [#{datetime}] in #{progname} -- #{msg}\n"
12
+ }
13
+
14
+ module TJP
15
+ # It's core class of TJPlurker based on {Plurk API 2.0}[http://www.plurk.com/API].
16
+ # Note that every API wrapped methods in this class returns a JSON object
17
+ # All mehtods will retry again when request timeout occurs.
18
+ class TJPlurker
19
+ # It will automatically authorize if +access_token+ and +access_token_secret+ are both given.
20
+ # If you do not have access token and secret, leave the parameters blank,
21
+ # and you will be asked to enter verification code to get access token and secret.
22
+ # key:: consumer key
23
+ # secret:: consumer secret
24
+ # return:: OAuth::AccessToken
25
+ def initialize(key, secret, token=nil, token_secret=nil)
26
+ @key, @secret, @token, @token_secret = key, secret, token, token_secret
27
+ @consumer = OAuth::Consumer.new(@key, @secret, {
28
+ :site => 'http://www.plurk.com',
29
+ :scheme => :header,
30
+ :http_method => :post,
31
+ :request_token_path => '/OAuth/request_token',
32
+ :access_token_path => '/OAuth/access_token',
33
+ :authorize_path => '/OAuth/authorize'
34
+ })
35
+ end
36
+
37
+
38
+ # return:: authorize URL
39
+ def get_authorize_url
40
+ @request_token = @consumer.get_request_token
41
+ return @request_token.authorize_url
42
+ end
43
+
44
+ # Change or get access token and secret.
45
+ # If parameters are not both given, user will be asked to enter verfication code,
46
+ # otherwise, replace the access token and secret.
47
+ # return:: access token and access token secret in Array
48
+ def authorize(access_token=nil, access_token_secret=nil)
49
+ if access_token && access_token_secret
50
+ #@access_token = OAuth::AccessToken.new(@consumer, access_token, access_token_secret)
51
+ @token, @token_secret = access_token, access_token_secret
52
+ else
53
+ puts "Authorize URL: #{get_authorize_url}"
54
+ print "Please Enter your verification code: "
55
+ verify = gets.chomp!
56
+ access_token = @request_token.get_access_token :oauth_verifier=>verify
57
+ @token, @token_secret = access_token.token, access_token.secret
58
+ end
59
+ $tjpLog.info(self.class){"Access Token: #{@token}, Access Token Secret: #{@token_secret}"}
60
+ return @token, @token_secret
61
+ end
62
+
63
+ # url:: plurk APP url in String
64
+ # body:: options in Hash
65
+ # return:: result in JSON
66
+ def api(url, body=nil, headers=nil)
67
+ # clone consumer for supporting thread
68
+ access_token = OAuth::AccessToken.new(@consumer.clone, @token, @token_secret)
69
+ resp = access_token.post(url, body, headers).body
70
+ json = JSON.parse(resp)
71
+ $tjpLog.debug(self.class){"Response: #{json}"}
72
+ $tjpLog.error(self.class){json["error_text"]} if json.is_a?(Hash) && json["error_text"]
73
+ return json
74
+ end
75
+
76
+ # :section: Users
77
+
78
+ # Returns info about current user's karma, including current karma,
79
+ # karma growth, karma graph and the latest reason why the karma has dropped.
80
+ def get_karma_stats
81
+ method = "/APP/Users/getKarmaStats"
82
+ api(method)
83
+ end
84
+
85
+ # :section: Profile
86
+
87
+ # Returns data that's private for the current user.
88
+ # This can be used to construct a profile and render a timeline of the latest plurks.
89
+ def get_own_profile
90
+ method = "/APP/Profile/getOwnProfile"
91
+ api(method)
92
+ end
93
+
94
+ # Fetches public information such as a user's public plurks and basic information.
95
+ # Fetches also if the current user is following the user, are friends with or is a fan.
96
+ def get_public_profile user_id
97
+ method = "/APP/Profile/getPublicProfile"
98
+ attr = {:user_id=>user_id}
99
+ api(method, attr)
100
+ end
101
+
102
+ # :section: Real Time Notifications
103
+
104
+ # Get instant notifications when there are new plurks and responses on a user's timeline.
105
+ # Generally you don't need call this because comet_channel will automatically do that for you.
106
+ # For details, see http://www.plurk.com/API#realtime
107
+ # return:: channel name and comet server in Hash
108
+ def get_user_channel
109
+ method = "/APP/Realtime/getUserChannel"
110
+ api(method)
111
+ end
112
+
113
+ # It will do GET requests to user's comet server to get new notification data.
114
+ # The request will sleep for about 50 seconds before returning a response if there is
115
+ # no new data added to your channel.
116
+ # It will automatically get comet server URL from /APP/Realtime/getUserChannel
117
+ # if there is no comet server yet, and renew +offset+ each time it was called.
118
+ # You don't need to worry about URL and +offset+.
119
+ # For details, see http://www.plurk.com/API#realtime
120
+ # return:: plurk notification in Hash
121
+ def comet_channel
122
+ #Assign new channel if @user_channel is nil
123
+ @user_channel ||= get_user_channel
124
+ begin
125
+ res = Net::HTTP.get_response(URI.parse(@user_channel['comet_server']))
126
+ json = JSON.parse(res.body.sub!(/CometChannel\.scriptCallback\((.*)\);/){|match| $1})
127
+ rescue Timeout::Error => ex
128
+ $tjpLog.warn(self.class){"Request timeout, retry."}
129
+ retry
130
+ rescue Errno::ECONNRESET => ex
131
+ $tjpLog.warn(self.class){"Connection reset, retry."}
132
+ retry
133
+ rescue => ex
134
+ $tjpLog.fatal(self.class){"Unknown error, skip."}
135
+ puts ex.class, ex.message, ex.backtrace
136
+ return
137
+ end
138
+ #Update the offset
139
+ @user_channel['comet_server'].sub!(/[\d]+$/, json["new_offset"].to_s)
140
+ if json['data']
141
+ json['data'].each{|member|
142
+ notification = NotificationData.new(member)
143
+ # Prevent duplicate notification
144
+ return if notification.id == @id_buffer
145
+ $tjpLog.info(self.class){"Notification: #{notification.user_id}: \"#{notification.content}\""}
146
+ @id_buffer = notification.id
147
+ yield(notification)
148
+ }
149
+ end
150
+ json
151
+ end
152
+
153
+ # :section: Polling
154
+
155
+ # You should use this call to find out if there any new plurks posted to the user's timeline.
156
+ # It's much more efficient than doing it with timeline_get_plurks, so please use it :)
157
+ # offset:: Return plurks newer than offset, formatted as 2009-6-20T21:55:34 in String or in Time.
158
+ # limit:: The max number of plurks to be returned (default: 20)
159
+ def get_plurks offset, limit=nil
160
+ method = "/APP/Polling/getPlurks"
161
+ offset = offset.utc.strftime("%Y-%m-%dT%H:%M:%S") if offset.is_a? Time
162
+ attr = {:offset=>offset, :limit=>limit}
163
+ api(method, attr)
164
+ end
165
+
166
+ # Use this call to find out if there are unread plurks on a user's timeline.
167
+ def get_unread_count
168
+ method = "/APP/Polling/getUnreadCount"
169
+ api(method)
170
+ end
171
+
172
+ # :section: Timeline
173
+
174
+ # Get one plurk from user's timeline
175
+ # plurk_id:: Can be Integer or String
176
+ def get_plurk plurk_id
177
+ method = "/APP/Timeline/getPlurk"
178
+ attr = {:plurk_id=>plurk_id}
179
+ api(method, attr)
180
+ end
181
+
182
+ # Get plurks from user's timeline
183
+ # offset:: Return plurks older than offset, formatted as 2009-6-20T21:55:34 in String or in Time.
184
+ # limit:: The max number of plurks to be returned (default: 20)
185
+ # filter:: Can be only_user, only_responded, only_private or only_favorite
186
+ def timeline_get_plurks offset=nil, limit=nil, filter=nil
187
+ method = "/APP/Timeline/getPlurks"
188
+ offset = offset.utc.strftime("%Y-%m-%dT%H:%M:%S") if offset.is_a? Time
189
+ attr = {:offset=>offset, :limit=>limit, :filter=>filter}
190
+ api(method, attr)
191
+ end
192
+
193
+ # Get unread plurks from user's timeline
194
+ # offset:: Return plurks newer than offset, formatted as 2009-6-20T21:55:34 in String or in Time.
195
+ # limit:: The max number of plurks to be returned (default: 20)
196
+ # filter:: Can be only_user, only_responded, only_private or only_favorite
197
+ def get_unread_plurks offset=nil, limit=nil, filter=nil
198
+ method = "/APP/Timeline/getUnreadPlurks"
199
+ offset = offset.utc.strftime("%Y-%m-%dT%H:%M:%S") if offset.is_a? Time
200
+ attr = {:offset=>offset, :limit=>limit, :filter=>filter}
201
+ api(method, attr)
202
+ end
203
+
204
+ # Get public plurks from user's timeline
205
+ # user_id:: The user_id of the public plurks owner to get. Can be integer (like 34) or nick name (like amix).
206
+ # offset:: Return plurks newer than offset, formatted as 2009-6-20T21:55:34 in String or in Time.
207
+ # limit:: The max number of plurks to be returned (default: 20)
208
+ # filter:: Can be only_user, only_responded, only_private or only_favorite
209
+ def get_public_plurks user_id, offset=nil, limit=nil, filter=nil
210
+ method = "/APP/Timeline/getPublicPlurks"
211
+ offset = offset.utc.strftime("%Y-%m-%dT%H:%M:%S") if offset.is_a? Time
212
+ attr = {:user_id=>user_id, :offset=>offset, :limit=>limit, :filter=>filter}
213
+ api(method, attr)
214
+ end
215
+
216
+ # qualifier:: The Plurk's qualifier, must be in English. Can be following:
217
+ # loves, likes, shares, gives, hates, wants, has, will, asks, wishes, was,
218
+ # feels, thinks, says, is, :, freestyle, hopes, needs, wonders
219
+ # limited_to:: Limit the plurk only to some users (also known as private plurking).
220
+ # Should can be a JSON list of friend ids in String formatting or Ruby Array, e.g.
221
+ # \[3,4,66,34] or "\[3,4,66,34]" will only be plurked to these user ids.
222
+ # If it's [0] then the Plurk is privatley posted to the poster's friends.
223
+ # no_comments:: If set to 1 or "1", then responses are disabled for this plurk.
224
+ # If set to 2 or "2", then only friends can respond to this plurk.
225
+ def plurk_add content, qualifier=':', limited_to=nil, no_comments=nil, lang='tr_ch'
226
+ method = "/APP/Timeline/plurkAdd"
227
+ limited_to = limited_to.to_s if limited_to.is_a? Array
228
+ attr = {:content=>content, :qualifier=>qualifier, :limited_to=>limited_to, :no_comments=>no_comments, :lang=>lang}
229
+ api(method, attr)
230
+ end
231
+
232
+ # plurk_id:: The id of the plurk.
233
+ def plurk_delete plurk_id
234
+ method = "/APP/Timeline/plurkDelete"
235
+ attr = {:plurk_id=>plurk_id}
236
+ api(method, attr)
237
+ end
238
+
239
+ # plurk_id:: The id of the plurk.
240
+ # content:: The content of plurk.
241
+ def plurk_edit plurk_id, content
242
+ method = "/APP/Timeline/plurkEdit"
243
+ attr = {:plurk_id=>plurk_id, :content=>content}
244
+ api(method, attr)
245
+ end
246
+
247
+ # ids:: The plurk ids, formated as JSON String or Ruby Array, e.g. "[342,23242,2323]" or [342,23242,2323]
248
+ def mute_plurks ids
249
+ method = "/APP/Timeline/mutePlurks"
250
+ ids = ids.to_s if ids.is_a? Array
251
+ attr = {:ids=>ids}
252
+ api(method, attr)
253
+ end
254
+
255
+ # ids:: The plurk ids, formated as JSON String or Ruby Array, e.g. "[342,23242,2323]" or [342,23242,2323]
256
+ def unmute_plurks
257
+ method = "/APP/Timeline/unmutePlurks"
258
+ ids = ids.to_s if ids.is_a? Array
259
+ attr = {:ids=>ids}
260
+ api(method, attr)
261
+ end
262
+
263
+ # ids:: The plurk ids, formated as JSON String or Ruby Array, e.g. "[342,23242,2323]" or [342,23242,2323]
264
+ def favorite_plurks ids
265
+ method = "/APP/Timeline/favoritePlurks"
266
+ ids = ids.to_s if ids.is_a? Array
267
+ attr = {:ids=>ids}
268
+ api(method, attr)
269
+ end
270
+
271
+ # ids:: The plurk ids, formated as JSON String or Ruby Array, e.g. "[342,23242,2323]" or [342,23242,2323]
272
+ def unfavorite_plurks ids
273
+ method = "/APP/Timeline/unfavoritePlurks"
274
+ ids = ids.to_s if ids.is_a? Array
275
+ attr = {:ids=>ids}
276
+ api(method, attr)
277
+ end
278
+
279
+ # ids:: The plurk ids, formated as JSON String or Ruby Array, e.g. "[342,23242,2323]" or [342,23242,2323]
280
+ # note_position:: If true responses_seen of the plurks will be updated as well (to match response_count).
281
+ def mark_as_read ids, note_position=nil
282
+ method = "/APP/Timeline/markAsRead"
283
+ ids = ids.to_s if ids.is_a? Array
284
+ attr = {:ids=>ids, :note_position=>note_position}
285
+ api(method, attr)
286
+ end
287
+
288
+ # :section: Response
289
+
290
+ # Fetches responses for plurk with plurk_id and some basic info about the users.
291
+ # plurk_id:: The plurk that the responses belong to.
292
+ # from_response:: Only fetch responses from an offset - could be 5, 10 or 15 (default: 0)
293
+ def response_get plurk_id, from_response=nil
294
+ method = "/APP/Responses/get"
295
+ attr = {:plurk_id=>plurk_id, :from_response=>from_response}
296
+ api(method, attr)
297
+ end
298
+
299
+ # Adds a responses to plurk_id. Language is inherited from the plurk.
300
+ # plurk_id:: The plurk that the responses belong to.
301
+ # content:: The response's text.
302
+ # qualifier:: The Plurk's qualifier, must be in English. Refers to plurk_add.
303
+ def response_add plurk_id, content, qualifier=':'
304
+ method = "/APP/Responses/responseAdd"
305
+ attr = {:plurk_id=>plurk_id, :content=>content, :qualifier=>qualifier}
306
+ api(method, attr)
307
+ end
308
+
309
+ #Deletes a response. A user can delete own responses or responses that are posted to own plurks.
310
+ # response_id:: The id of the response to delete.
311
+ # plurk_id:: The plurk that the response belongs to.
312
+ def response_delete response_id, plurk_id
313
+ method = "/APP/Responses/responseDelete"
314
+ attr = {:response_id=>response_id, :plurk_id=>plurk_id}
315
+ api(method, attr)
316
+ end
317
+
318
+ # :section: Friends and Fans
319
+
320
+ # Returns user_id's friend list in chucks of 100 friends at a time.
321
+ # However, We suggest you use get_friends instead of get_friends_by_offset
322
+ # limit:: The max number of friends to be returned.
323
+ # offset:: Can be Numeric or String, e.g. 10, "20", 30, "40" etc.
324
+ # return:: An Array
325
+ def get_friends_by_offset user_id, limit=100, offset=0
326
+ method = "/APP/FriendsFans/getFriendsByOffset"
327
+ attr = {:user_id=>user_id, :offset=>offset, :limit=>limit}
328
+ api(method, attr)
329
+ end
330
+
331
+ # Returns user_id's fans list in chucks of 100 fans at a time.
332
+ # However, We suggest you use get_fans instead of get_fans_by_offset
333
+ # limit:: The max number of friends to be returned.
334
+ # offset:: Can be Numeric or String, e.g. 10, "20", 30, "40" etc.
335
+ # return:: An Array
336
+ def get_fans_by_offset user_id, limit=100, offset=0
337
+ method = "/APP/FriendsFans/getFansByOffset"
338
+ attr = {:user_id=>user_id, :offset=>offset, :limit=>limit}
339
+ api(method, attr)
340
+ end
341
+
342
+ # Returns users that the current logged in user follows as fan - in chucks of 100 fans at a time.
343
+ # However, We suggest you use get_following instead of get_following_by_offset
344
+ # limit:: The max number of friends to be returned.
345
+ # offset:: Can be Numeric or String, e.g. 10, "20", 30, "40" etc.
346
+ # return:: An Array
347
+ def get_following_by_offset limit=100, offset=0
348
+ method = "/APP/FriendsFans/getFollowingByOffset"
349
+ attr = {:offset=>offset, :limit=>limit}
350
+ api(method, attr)
351
+ end
352
+
353
+ # Create a friend request to friend_id. User with friend_id has to accept a friendship.
354
+ # friend_id:: The ID of the user you want to befriend.
355
+ def become_friend friend_id
356
+ method = "/APP/FriendsFans/becomeFriend"
357
+ attr = {:friend_id=>friend_id}
358
+ api(method, attr)
359
+ end
360
+
361
+ # Remove friend with ID friend_id. friend_id won't be notified.
362
+ # friend_id:: The ID of the user you want to remove
363
+ def remove_as_friend friend_id
364
+ method = "/APP/FriendsFans/removeAsFriend"
365
+ attr = {:friend_id=>friend_id}
366
+ api(method, attr)
367
+ end
368
+
369
+ # Become fan of fan_id. To stop being a fan of someone, use set_following
370
+ # fan_id:: The ID of the user you want to become fan of
371
+ def become_fan fan_id
372
+ method = "/APP/FriendsFans/becomeFan"
373
+ attr = {:fan_id=>fan_id}
374
+ api(method, attr)
375
+ end
376
+
377
+ # Update following of user_id. A user can befriend someone, but can unfollow them.
378
+ # This request is also used to stop following someone as a fan.
379
+ # user_id:: The ID of the user you want to follow/unfollow
380
+ # follow:: Normally, true if the user should be followed, and false if the user should be unfollowed.
381
+ # Actually, toggle the follwing state no matter you give true or false
382
+ def set_following user_id, follow=true
383
+ method = "/APP/FriendsFans/setFollowing"
384
+ attr = {:user_id=>user_id, :follow=>follow}
385
+ api(method, attr)
386
+ end
387
+
388
+ # Returns a JSON object of the logged in users friends (nick name and full name).
389
+ # This information can be used to construct auto-completion for private plurking.
390
+ # Notice that a friend list can be big, depending on how many friends a user has,
391
+ # so this list should be lazy-loaded in your application.
392
+ def get_completion
393
+ method = "/APP/FriendsFans/getCompletion"
394
+ api(method)
395
+ end
396
+
397
+ # :section: Alerts
398
+ # ===General data structures
399
+ # The data returned by getActive and getHistory can be of following nature:
400
+ # Friendship request:
401
+ # {"type": "friendship_request", "from_user": {"nick_name": ...}, "posted": ...}
402
+ #
403
+ # Friendship pending:
404
+ # {"type": "friendship_pending", "to_user": {"nick_name": ...}, "posted": ...}
405
+ #
406
+ # New fan notification: (does not require actions from the user)
407
+ # {"type": "new_fan", "new_fan": {"nick_name": ...}, "posted": ...}
408
+ #
409
+ # Friendship accepted notification: (does not require actions from the user)
410
+ # {"type": "friendship_accepted", "friend_info": {"nick_name": ...}, "posted": ...}
411
+ #
412
+ # New friend notification: (does not require actions from the user)
413
+ # {"type": "new_friend", "new_friend": {"nick_name": ...}, "posted": ...}
414
+
415
+ # Return a JSON list of current active alerts.
416
+ def get_active
417
+ method = "/APP/Alerts/getActive"
418
+ api(method)
419
+ end
420
+
421
+ # Return a JSON list of past 30 alerts.
422
+ def get_history
423
+ method = "/APP/Alerts/getHistory"
424
+ api(method)
425
+ end
426
+
427
+ # user_id:: The user_id that has asked for friendship.
428
+ def add_as_fan user_id
429
+ method = "/APP/Alerts/addAsFan"
430
+ attr = {:user_id=>user_id}
431
+ api(method, attr)
432
+ end
433
+
434
+ # Accept all friendship requests as fans.
435
+ def add_all_as_fan
436
+ method = "/APP/Alerts/addAllAsFan"
437
+ api(method)
438
+ end
439
+
440
+ # Accept all friendship requests as friends.
441
+ def add_all_as_friends
442
+ method = "/APP/Alerts/addAllAsFriends"
443
+ api(method)
444
+ end
445
+
446
+ # Accept user_id as friend.
447
+ # user_id:: The user_id that has asked for friendship.
448
+ def add_as_friend user_id
449
+ method = "/APP/Alerts/addAsFriend"
450
+ attr = {:user_id=>user_id}
451
+ api(method, attr)
452
+ end
453
+
454
+ # Deny friendship to user_id.
455
+ # user_id:: The user_id that has asked for friendship.
456
+ def deny_friendship user_id
457
+ method = "/APP/Alerts/denyFriendship"
458
+ attr = {:user_id=>user_id}
459
+ api(method, attr)
460
+ end
461
+
462
+ # Remove notification to user with id user_id.
463
+ # user_id:: The user_id that the current user has requested friendship for.
464
+ def remove_notification user_id
465
+ method = "/APP/Alerts/removeNotification"
466
+ attr = {:user_id=>user_id}
467
+ api(method, attr)
468
+ end
469
+
470
+ # :section: Search
471
+
472
+ # Returns the latest 20 plurks on a search term.
473
+ # query:: The query after Plurks.
474
+ # offset:: A plurk_id of the oldest Plurk in the last search result.
475
+ def plurk_search query, offset=nil
476
+ method = "/APP/PlurkSearch/search"
477
+ attr = {:query=>query, :offset=>offset}
478
+ api(method, attr)
479
+ end
480
+
481
+ # Returns 10 users that match query, users are sorted by karma.
482
+ # query:: The query after users.
483
+ # offset:: Page offset, like 10, 20, 30 etc.
484
+ def user_search query, offset=0
485
+ method = "/APP/UserSearch/search"
486
+ attr = {:query=>query, :offset=>offset}
487
+ api(method, attr)
488
+ end
489
+
490
+ # :section: Emoticons
491
+
492
+ # Emoticons are a big part of Plurk since they make it easy to express feelings.
493
+ # Check out current Plurk emoticons. This call returns a JSON object that looks like:
494
+ # {"karma": {"0": [[":-))", "http:\/\/statics.plurk.com\/XXX.gif"], ...], ...},
495
+ # "recuited": {"10": [["(bigeyes)", "http:\/\/statics.plurk.com\/XXX.gif"], ...], ...} }
496
+ # emoticons["karma"][25] denotes that the user has to have karma over 25 to use these emoticons.
497
+ # emoticons["recuited"][10] means that the user has to have user.recuited >= 10 to use these emoticons.
498
+ # It's important to check for these things on the client as well,
499
+ # since the emoticon levels are checked in the models.
500
+ def emoticons_get
501
+ method = "/APP/Emoticons/get"
502
+ api(method)
503
+ end
504
+
505
+ # :section: Blocks
506
+
507
+ # offset:: What page should be shown, e.g. 0, 10, 20.
508
+ def blocks_get offset=0
509
+ method = "/APP/Blocks/get"
510
+ attr = {:offset=>offset}
511
+ api(method, attr)
512
+ end
513
+
514
+ # user_id:: The id of the user that should be blocked.
515
+ def block user_id
516
+ method = "/APP/Blocks/block"
517
+ attr = {:user_id=>user_id}
518
+ api(method, attr)
519
+ end
520
+
521
+ # user_id: The id of the user that should be unblocked.
522
+ def unblock user_id
523
+ method = "/APP/Blocks/unblock"
524
+ attr = {:user_id=>user_id}
525
+ api(method, attr)
526
+ end
527
+
528
+ # :section: Cliques
529
+
530
+ def get_cliques
531
+ method = "/APP/Cliques/getCliques"
532
+ api(method)
533
+ end
534
+
535
+ # clique_name:: The name of the new clique
536
+ def get_clique clique_name
537
+ method = "/APP/Cliques/getClique"
538
+ attr = {:clique_name=>clique_name}
539
+ api(method, attr)
540
+ end
541
+
542
+ # clique_name:: The name of the new clique
543
+ def create_clique clique_name
544
+ method = "/APP/Cliques/createClique"
545
+ attr = {:clique_name=>clique_name}
546
+ api(method, attr)
547
+ end
548
+
549
+ # clique_name:: The name of the clique to rename
550
+ # new_name:: The name of the new clique
551
+ def rename_clique clique_name, new_name
552
+ method = "/APP/Cliques/renameClique"
553
+ attr = {:clique_name=>clique_name, :new_name=>new_name}
554
+ api(method, attr)
555
+ end
556
+
557
+ # clique_name:: The name of the clique
558
+ # user_id:: The user to add to the clique
559
+ def cliques_add clique_name, user_id
560
+ method = "/APP/Cliques/add"
561
+ attr = {:clique_name=>clique_name, :user_id=>user_id}
562
+ api(method, attr)
563
+ end
564
+
565
+ # clique_name:: The name of the clique
566
+ # user_id:: The user to remove from the clique
567
+ def cliques_remove clique_name, user_id
568
+ method = "/APP/Cliques/remove"
569
+ attr = {:clique_name=>clique_name, :user_id=>user_id}
570
+ api(method, attr)
571
+ end
572
+
573
+ # :section: PlurkTop
574
+
575
+ def get_collections
576
+ method = "/APP/PlurkTop/getCollections"
577
+ api(method)
578
+ end
579
+
580
+ # collection_name:: only get plurks in specified collection
581
+ # offset:: offset of Plurks in PlurkTop, should be an float, e.g. 0.99.
582
+ # limit:: number of plurks returned (default: 30)
583
+ # sorting:: the way to sort plurks in PlurkTop, can be "hot" for sorting by popularity or "new" for posted time.
584
+ def plurk_top_get_plurks collection_name, limit=nil, offset=nil, sorting=nil
585
+ method = "/APP/PlurkTop/getPlurks"
586
+ attr = {:collection_name=>collection_name, :limit=>limit, :offset=>offset, :sorting=>sorting}
587
+ api(method, attr)
588
+ end
589
+
590
+ # :section: TJPlurker Provided
591
+ # Those methos were all provided by TJPlukrer instead of Plurk
592
+
593
+ # Improved from get_friends_by_offset for getting all friends from a user
594
+ # return:: An Array
595
+ def get_friends user_id, at_least=nil
596
+ list = []
597
+ offset = 0;
598
+ loop{
599
+ set = get_friends_by_offset(user_id, 100, offset)
600
+ size = set.size
601
+ break if size == 0
602
+ list |= set
603
+ break if at_least && list.size>=at_least
604
+ offset += size
605
+ }
606
+ return list
607
+ end
608
+
609
+ # Improved from get_fans_by_offset for getting all fans from a user
610
+ # return:: An Array
611
+ def get_fans user_id, at_least=nil
612
+ list = []
613
+ offset = 0;
614
+ loop{
615
+ set = get_fans_by_offset(user_id, 100, offset)
616
+ size = set.size
617
+ break if size == 0
618
+ list |= set
619
+ break if at_least && list.size>=at_least
620
+ offset += size
621
+ }
622
+ return list
623
+ end
624
+
625
+ # Improved from get_following_by_offset for getting all fans from a user
626
+ # return:: An Array
627
+ def get_following at_least=nil
628
+ list = []
629
+ offset = 0;
630
+ loop{
631
+ set = get_following_by_offset(100, offset)
632
+ size = set.size
633
+ break if size == 0
634
+ list |= set
635
+ break if at_least && list.size>=at_least
636
+ offset += size
637
+ }
638
+ return list
639
+ end
640
+
641
+ # Used to follow a lot of users.
642
+ # level:: e.g. 1 for following user's all friends, 2 for following user's all friends and all friends of all friends.
643
+ def super_become_fan fan_id, level=1
644
+ return if level<=0
645
+ become_fan(fan_id)
646
+ list = []
647
+ offset = 0;
648
+ loop{
649
+ set = get_friends_by_offset(fan_id, 100, offset)
650
+ size = set.size
651
+ break if size == 0
652
+ tg = ThreadGroup.new
653
+ set.each{|i|
654
+ tg.add Thread.new{
655
+ wait_sec = 1
656
+ until become_fan(i["uid"]).key?("success_text")
657
+ $tjpLog.info(self.class){"Trying to become #{i["uid"]}'s fan in #{wait_sec} seconds"}
658
+ sleep(wait_sec)
659
+ wait_sec *= 2
660
+ end
661
+ $tjpLog.info(self.class){"Become #{i["uid"]}'s fan successfully"}
662
+ }
663
+ }
664
+ tg.list.each{|i| i.join }
665
+ list |= set
666
+ offset += size
667
+ }
668
+ list.each{|i|
669
+ super_become_fan(i["uid"], level-1)
670
+ }
671
+ end
672
+ end
673
+
674
+ # Format plurk notification. See TJPlurker#comet_channel
675
+ class NotificationData
676
+ # Can be +new_plurk+ or +new_response+.
677
+ attr_reader :type
678
+ attr_reader :response_count
679
+ attr_reader :plurk_id
680
+ attr_reader :lang
681
+ attr_reader :user_id
682
+ attr_reader :qualifier
683
+ attr_reader :content
684
+ # Notification ID.
685
+ attr_reader :id
686
+ # Time of the listened post.
687
+ attr_reader :posted
688
+ attr_reader :owner_id
689
+ # The original JSON object from server response.
690
+ attr_reader :origin
691
+
692
+ def initialize member
693
+ @type = member['type']
694
+ @response_count = member['response_count']
695
+ @plurk_id = member['plurk_id']
696
+
697
+ @lang = @type=="new_plurk" ? member['lang'] : member['response']['lang']
698
+ @user_id = @type=="new_plurk" ? member['user_id'] : member['response']['user_id']
699
+ @qualifier = @type=="new_plurk" ? member['qualifier'] : member['response']['qualifier']
700
+ @content = @type=="new_plurk" ? member['content'] : member['response']['content']
701
+ @id = @type=="new_plurk" ? member['id'] : member['response']['id']
702
+ @posted = @type=="new_plurk" ? member['posted'] : member['response']['posted']
703
+
704
+ @owner_id = @type=="new_plurk" ? member['owner_id'] : member['plurk']['owner_id']
705
+
706
+ @origin = member
707
+ end
708
+ end
709
+
710
+ module_function
711
+ # Convert user name into user_id, e.g. Given "tonytonyjan", return 5874158 in Integer
712
+ # return:: user id in Integer
713
+ def get_uid user_name
714
+ open("http://www.plurk.com/#{user_name}").read =~ /"user_id": (\d*)/
715
+ raise "User \"#{user_name}\" not found." unless $1
716
+ return $1.to_i
717
+ end
718
+ end