tjplurker 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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