tjplurker 1.0
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.rb +248 -0
- metadata +59 -0
data/lib/tjplurker.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
# :title:TJPlurker API Documentation
|
2
|
+
require 'logger'
|
3
|
+
require 'json'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
$tjpLog = Logger.new(STDOUT)
|
7
|
+
$tjpLog.level = Logger::INFO
|
8
|
+
$tjpLog.formatter = proc{ |severity, datetime, progname, msg|
|
9
|
+
"#{severity} [#{datetime}] in #{progname} -- #{msg}\n"
|
10
|
+
}
|
11
|
+
# It's a wrapper of Plurk API.
|
12
|
+
# Note that every methods in this class returns a JSON object
|
13
|
+
# which was converted from Plurk server's response.
|
14
|
+
# All mehtods will retry again when request timeout occurs.
|
15
|
+
class TJPlurker
|
16
|
+
# Plurk user ID.
|
17
|
+
attr_reader :user
|
18
|
+
|
19
|
+
# If +auto_login+ sets +true+, it will autologin while constructing.
|
20
|
+
def initialize api_key, user, passwd, auto_login=true
|
21
|
+
@user, @passwd, @api_key = user, passwd, api_key
|
22
|
+
@cookie = nil
|
23
|
+
@user_channel = nil
|
24
|
+
@id_buffer = nil
|
25
|
+
login if auto_login
|
26
|
+
end
|
27
|
+
|
28
|
+
# If no_data sets true, the successful login message was simplified as follow:
|
29
|
+
#
|
30
|
+
# {"success_text": "ok"}
|
31
|
+
#
|
32
|
+
# Otherwise, more details of user's profile were retured.
|
33
|
+
def login no_data=true
|
34
|
+
method = "/API/Users/login"
|
35
|
+
attr = {:username=>@user, :password=>@passwd, :api_key=>@api_key}
|
36
|
+
attr[:no_data] = '1' if no_data
|
37
|
+
api(method, attr)
|
38
|
+
end
|
39
|
+
|
40
|
+
def plurk_add content, qualifier=':', limited_to=nil, no_comments=nil, lang='tr_ch'
|
41
|
+
method = "/API/Timeline/plurkAdd"
|
42
|
+
attr = {:api_key=>@api_key, :content=>content, :qualifier=>qualifier,:limited_to=>limited_to, :no_comments=>no_comments, :lang=>lang}
|
43
|
+
api(method, attr)
|
44
|
+
end
|
45
|
+
|
46
|
+
def response_add plurk_id, content, qualifier=':'
|
47
|
+
method = "/API/Responses/responseAdd"
|
48
|
+
attr = {:api_key=>@api_key, :plurk_id=>plurk_id, :content=>content, :qualifier=>qualifier}
|
49
|
+
api(method, attr)
|
50
|
+
end
|
51
|
+
|
52
|
+
def become_fan fan_id
|
53
|
+
method = "/API/FriendsFans/becomeFan"
|
54
|
+
attr = {:api_key=>@api_key, :fan_id=>fan_id}
|
55
|
+
api(method, attr)
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_all_as_friends
|
59
|
+
method = "/API/Alerts/addAllAsFriends"
|
60
|
+
attr = {:api_key=>@api_key}
|
61
|
+
api(method, attr)
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_friends_by_offset user_id, limit=100, offset='0'
|
65
|
+
method = "/API/FriendsFans/getFriendsByOffset"
|
66
|
+
attr = {:api_key=>@api_key, :user_id=>user_id, :offset=>offset, :limit=>limit}
|
67
|
+
api(method, attr)
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_public_profile user_id
|
71
|
+
method = "/API/Profile/getPublicProfile"
|
72
|
+
attr = {:api_key=>@api_key, :user_id=>user_id}
|
73
|
+
api(method, attr)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Warning:: It has bugs in offecial Plurk API.
|
77
|
+
def get_plurks limit=nil, offset=nil
|
78
|
+
method = "/API/Polling/getPlurks"
|
79
|
+
attr = {:api_key=>@api_key, :limit=>limit, :offset=>offset}
|
80
|
+
api(method, attr)
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_user_channel
|
84
|
+
method = "/API/Realtime/getUserChannel"
|
85
|
+
attr = {:api_key=>@api_key}
|
86
|
+
api(method, attr)
|
87
|
+
end
|
88
|
+
|
89
|
+
def comet_channel
|
90
|
+
#Assign new channel if @user_channel is nil
|
91
|
+
@user_channel ||= get_user_channel
|
92
|
+
begin
|
93
|
+
res = Net::HTTP.get_response(URI.parse(@user_channel['comet_server']))
|
94
|
+
json = JSON.parse(res.body.sub!(/CometChannel\.scriptCallback\((.*)\);/){|match| $1})
|
95
|
+
rescue Timeout::Error => ex
|
96
|
+
$tjpLog.warn(self.class){"Request timeout, retry."}
|
97
|
+
retry
|
98
|
+
rescue => ex
|
99
|
+
$tjpLog.fatal(self.class){"Unknown error, stop."}
|
100
|
+
puts ex.backtrace
|
101
|
+
exit
|
102
|
+
end
|
103
|
+
#Update the offset
|
104
|
+
@user_channel['comet_server'].sub!(/[\d]+$/, json["new_offset"].to_s)
|
105
|
+
if json['data']
|
106
|
+
json['data'].each{|member|
|
107
|
+
notification = NotificationData.new(member)
|
108
|
+
return if notification.id == @id_buffer
|
109
|
+
$tjpLog.info(self.class){"Notification: #{notification.user_id}: \"#{notification.content}\""}
|
110
|
+
@id_buffer = notification.id
|
111
|
+
yield(notification)
|
112
|
+
}
|
113
|
+
end
|
114
|
+
json
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def api method, attr
|
119
|
+
#Build POST Request
|
120
|
+
req = Net::HTTP::Post.new(method)
|
121
|
+
req.set_form_data(attr)
|
122
|
+
req["Cookie"] = @cookie
|
123
|
+
#Build GET Request
|
124
|
+
#path = method + "?" + URI.encode_www_form(attr)
|
125
|
+
#req2 = Net::HTTP::Get.new(path)
|
126
|
+
#req2["Cookie"] = @cookie
|
127
|
+
|
128
|
+
#Build HTTP connection
|
129
|
+
http = Net::HTTP.new('www.plurk.com', 80)
|
130
|
+
begin
|
131
|
+
resp = http.start{
|
132
|
+
$tjpLog.info(self.class){"Request: #{method}, #{attr}"}
|
133
|
+
http.request(req)
|
134
|
+
}
|
135
|
+
@cookie ||= resp['set-cookie']
|
136
|
+
json = JSON.parse(resp.body)
|
137
|
+
$tjpLog.debug(self.class){"Response: #{json}"}
|
138
|
+
$tjpLog.error(self.class){json["error_text"]} if json["error_text"]
|
139
|
+
rescue Timeout::Error => ex
|
140
|
+
$tjpLog.warn(self.class){"Request timeout, retrying."}
|
141
|
+
retry
|
142
|
+
rescue JSON::ParserError => ex
|
143
|
+
$tjpLog.error(self.class){"JSON parse error, request failed."}
|
144
|
+
rescue => ex
|
145
|
+
$tjpLog.fatal(self.class){"Unknown error, stop"}
|
146
|
+
puts ex.class, ex.message, ex.backtrace
|
147
|
+
exit
|
148
|
+
end
|
149
|
+
return json
|
150
|
+
end
|
151
|
+
|
152
|
+
class NotificationData
|
153
|
+
|
154
|
+
# Can be +new_plurk+ or +new_response+.
|
155
|
+
attr_reader :type
|
156
|
+
attr_reader :response_count
|
157
|
+
attr_reader :plurk_id
|
158
|
+
attr_reader :lang
|
159
|
+
attr_reader :user_id
|
160
|
+
attr_reader :qualifier
|
161
|
+
attr_reader :content
|
162
|
+
# Notification ID.
|
163
|
+
attr_reader :id
|
164
|
+
# Time of the listened post.
|
165
|
+
attr_reader :posted
|
166
|
+
attr_reader :owner_id
|
167
|
+
# The original JSON object from server response.
|
168
|
+
attr_reader :origin
|
169
|
+
|
170
|
+
def initialize member
|
171
|
+
@type = member['type']
|
172
|
+
@response_count = member['response_count']
|
173
|
+
@plurk_id = member['plurk_id']
|
174
|
+
|
175
|
+
@lang = @type=="new_plurk" ? member['lang'] : member['response']['lang']
|
176
|
+
@user_id = @type=="new_plurk" ? member['user_id'] : member['response']['user_id']
|
177
|
+
@qualifier = @type=="new_plurk" ? member['qualifier'] : member['response']['qualifier']
|
178
|
+
@content = @type=="new_plurk" ? member['content'] : member['response']['content']
|
179
|
+
@id = @type=="new_plurk" ? member['id'] : member['response']['id']
|
180
|
+
@posted = @type=="new_plurk" ? member['posted'] : member['response']['posted']
|
181
|
+
|
182
|
+
@owner_id = @type=="new_plurk" ? member['owner_id'] : member['plurk']['owner_id']
|
183
|
+
|
184
|
+
@origin = member
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class Robot
|
189
|
+
def initialize *params
|
190
|
+
case params.size
|
191
|
+
when 1
|
192
|
+
@tjplurker = params[0]
|
193
|
+
when 3
|
194
|
+
api_key, user, passwd = params
|
195
|
+
@tjplurker = TJPlurker.new(api_key, user, passwd)
|
196
|
+
when 4
|
197
|
+
api_key, user, passwd, auto_login = params
|
198
|
+
@tjplurker = TJPlurker.new(api_key, user, passwd, auto_login)
|
199
|
+
end
|
200
|
+
@services = []
|
201
|
+
end
|
202
|
+
|
203
|
+
def start
|
204
|
+
$tjpLog.info(self.class){"Start robot."}
|
205
|
+
Thread.new{
|
206
|
+
loop{
|
207
|
+
@tjplurker.add_all_as_friends
|
208
|
+
sleep(60)
|
209
|
+
}
|
210
|
+
}
|
211
|
+
loop{
|
212
|
+
@tjplurker.comet_channel{|data|
|
213
|
+
@services.each{|service|
|
214
|
+
service.serve(@tjplurker, data)
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_service service
|
221
|
+
@services << service
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class Service
|
226
|
+
def initialize &proc
|
227
|
+
if block_given?
|
228
|
+
@serve = proc
|
229
|
+
else
|
230
|
+
@serve = Proc.new{|tjplurker, data| p data}
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def serve tjplurker, data
|
235
|
+
@serve[tjplurker, data]
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
if __FILE__ == $0
|
241
|
+
pk = Plurker.new("you api key", "your id", "your password")
|
242
|
+
puts pk.login
|
243
|
+
loop{
|
244
|
+
pk.comet_channel{|date|
|
245
|
+
puts data
|
246
|
+
}
|
247
|
+
}
|
248
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tjplurker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tony Jian
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-05-23 00:00:00.000000000 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
requirement: &18468612 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.4.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *18468612
|
26
|
+
description: description...
|
27
|
+
email: tonytonyjan.cs97@g2.nctu.edu.tw
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- lib/tjplurker.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://code.google.com/p/tjplurker
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.5.2
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: A safe Plurk API wrapper based on Ruby and mainly designed for easily making
|
58
|
+
plurk robot.
|
59
|
+
test_files: []
|