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.
- data/lib/tjplurker/core.rb +718 -0
- data/lib/tjplurker/legacy.rb +489 -0
- data/lib/tjplurker/robot.rb +145 -0
- data/lib/tjplurker.rb +2 -0
- metadata +29 -3
@@ -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
|