qqbot 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/.gitignore +15 -15
- data/Gemfile +4 -4
- data/README.md +84 -84
- data/lib/qqbot.rb +46 -46
- data/lib/qqbot/api.rb +314 -314
- data/lib/qqbot/bot.rb +504 -504
- data/lib/qqbot/client.rb +60 -60
- data/lib/qqbot/cookie.rb +28 -28
- data/lib/qqbot/error.rb +4 -4
- data/lib/qqbot/model.rb +57 -57
- data/lib/qqbot/version.rb +3 -3
- data/qqbot.gemspec +33 -33
- metadata +3 -3
data/lib/qqbot/bot.rb
CHANGED
@@ -1,504 +1,504 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module QQBot
|
4
|
-
class Bot
|
5
|
-
def initialize
|
6
|
-
@api = QQBot::Api.new
|
7
|
-
@api.auth_options = login
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.check_response_json(code, body)
|
11
|
-
if code == '200'
|
12
|
-
json = JSON.parse body
|
13
|
-
retcode = json['retcode']
|
14
|
-
if retcode == 0
|
15
|
-
return json['result']
|
16
|
-
elsif retcode == 100012
|
17
|
-
QQBot::LOGGER.info '因为掉线此次请求失败,尝试重新登录'
|
18
|
-
@api.auth_options = relogin
|
19
|
-
else
|
20
|
-
QQBot::LOGGER.info "请求失败,JSON返回码 #{retcode}"
|
21
|
-
end
|
22
|
-
else
|
23
|
-
QQBot::LOGGER.info "请求失败,HTTP返回码 #{code}"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.check_send_msg_response(code, body)
|
28
|
-
if code == '200'
|
29
|
-
json = JSON.parse body
|
30
|
-
if json['errCode'] == 0
|
31
|
-
QQBot::LOGGER.info '发送成功'
|
32
|
-
return true
|
33
|
-
else
|
34
|
-
QQBot::LOGGER.info "发送失败,JSON返回码 #{json['retcode']}"
|
35
|
-
end
|
36
|
-
else
|
37
|
-
QQBot::LOGGER.info "请求失败,HTTP返回码 #{code}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def get_qrcode
|
42
|
-
code, body = @api.get_qrcode
|
43
|
-
|
44
|
-
if code == '200'
|
45
|
-
file_name = File.expand_path('qrcode.png', File.dirname(__FILE__));
|
46
|
-
|
47
|
-
File.open(file_name, 'wb') do |file|
|
48
|
-
file.write body
|
49
|
-
file.close
|
50
|
-
end
|
51
|
-
|
52
|
-
QQBot::LOGGER.info "二维码已经保存在#{file_name}中"
|
53
|
-
|
54
|
-
unless @pid
|
55
|
-
QQBot::LOGGER.info '开启web服务进程'
|
56
|
-
@pid = spawn("ruby -run -e httpd #{file_name} -p 9090")
|
57
|
-
end
|
58
|
-
|
59
|
-
QQBot::LOGGER.info '也可以通过访问 http://localhost:9090 查看二维码'
|
60
|
-
return true
|
61
|
-
else
|
62
|
-
QQBot::LOGGER.info "请求失败,返回码#{code}"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def verify_qrcode
|
67
|
-
url = ''
|
68
|
-
|
69
|
-
until url.start_with? 'http' do
|
70
|
-
sleep 5
|
71
|
-
code, body = @api.verify_qrcode
|
72
|
-
|
73
|
-
if code == '200'
|
74
|
-
result = body.force_encoding("UTF-8")
|
75
|
-
if result.include? '二维码已失效'
|
76
|
-
QQBot::LOGGER.info '二维码已失效,准备重新获取'
|
77
|
-
return unless get_qrcode
|
78
|
-
elsif result.include? 'http'
|
79
|
-
QQBot::LOGGER.info '认证成功'
|
80
|
-
return URI.extract(result).first
|
81
|
-
end
|
82
|
-
else
|
83
|
-
QQBot::LOGGER.info "请求失败,返回码#{code}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def close_qrcode_server
|
89
|
-
if @pid
|
90
|
-
QQBot::LOGGER.info '关闭web服务进程'
|
91
|
-
Process.kill('KILL', @pid)
|
92
|
-
@pid = nil
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def get_ptwebqq(url)
|
97
|
-
code, ptwebqq = @api.get_ptwebqq url
|
98
|
-
|
99
|
-
if code == '302'
|
100
|
-
ptwebqq
|
101
|
-
else
|
102
|
-
QQBot::LOGGER.info "请求失败,返回码#{code}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def get_vfwebqq(ptwebqq)
|
107
|
-
code, body = @api.get_vfwebqq(ptwebqq)
|
108
|
-
|
109
|
-
result = self.class.check_response_json(code, body)
|
110
|
-
result['vfwebqq'] if result
|
111
|
-
end
|
112
|
-
|
113
|
-
def get_psessionid_and_uin(ptwebqq)
|
114
|
-
code, body = @api.get_psessionid_and_uin ptwebqq
|
115
|
-
|
116
|
-
result = self.class.check_response_json(code, body)
|
117
|
-
if result
|
118
|
-
return result['psessionid'], result['uin']
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def login
|
123
|
-
QQBot::LOGGER.info '开始获取二维码'
|
124
|
-
raise QQBot::Error::LoginFailed unless get_qrcode
|
125
|
-
|
126
|
-
QQBot::LOGGER.info '等待扫描二维码'
|
127
|
-
url = verify_qrcode
|
128
|
-
raise QQBot::Error::LoginFailed unless url
|
129
|
-
|
130
|
-
close_qrcode_server
|
131
|
-
|
132
|
-
QQBot::LOGGER.info '开始获取ptwebqq'
|
133
|
-
@ptwebqq = get_ptwebqq url
|
134
|
-
raise QQBot::Error::LoginFailed unless ptwebqq
|
135
|
-
|
136
|
-
QQBot::LOGGER.info '开始获取vfwebqq'
|
137
|
-
vfwebqq = get_vfwebqq ptwebqq
|
138
|
-
raise QQBot::Error::LoginFailed unless vfwebqq
|
139
|
-
|
140
|
-
QQBot::LOGGER.info '开始获取psessionid和uin'
|
141
|
-
psessionid, uin = get_psessionid_and_uin ptwebqq
|
142
|
-
raise QQBot::Error::LoginFailed unless uin && psessionid
|
143
|
-
|
144
|
-
{
|
145
|
-
ptwebqq: @ptwebqq,
|
146
|
-
vfwebqq: vfwebqq,
|
147
|
-
psessionid: psessionid,
|
148
|
-
uin: uin
|
149
|
-
}
|
150
|
-
end
|
151
|
-
|
152
|
-
def relogin
|
153
|
-
QQBot::LOGGER.info '开始获取vfwebqq'
|
154
|
-
vfwebqq = get_vfwebqq ptwebqq
|
155
|
-
raise QQBot::Error::LoginFailed unless vfwebqq
|
156
|
-
|
157
|
-
QQBot::LOGGER.info '开始获取psessionid和uin'
|
158
|
-
psessionid, uin = get_psessionid_and_uin ptwebqq
|
159
|
-
raise QQBot::Error::LoginFailed unless uin && psessionid
|
160
|
-
|
161
|
-
{
|
162
|
-
ptwebqq: @ptwebqq,
|
163
|
-
vfwebqq: vfwebqq,
|
164
|
-
psessionid: psessionid,
|
165
|
-
uin: uin
|
166
|
-
}
|
167
|
-
end
|
168
|
-
|
169
|
-
def poll
|
170
|
-
loop do
|
171
|
-
code, body = @api.poll
|
172
|
-
result = self.class.check_response_json(code, body)
|
173
|
-
|
174
|
-
if result
|
175
|
-
result.each do |item|
|
176
|
-
message = QQBot::Message.new
|
177
|
-
value = item['value']
|
178
|
-
message.type, message.from_id, message.send_id =
|
179
|
-
case item['poll_type']
|
180
|
-
when 'message' then [0, value['from_uin'], value['from_uin']]
|
181
|
-
when 'group_message' then [1, value['from_uin'], value['send_uin']]
|
182
|
-
when 'discu_message' then [2, value['from_uin'], value['send_uin']]
|
183
|
-
else 3
|
184
|
-
end
|
185
|
-
message.time = value['time']
|
186
|
-
message.content = value['content'][1]
|
187
|
-
|
188
|
-
font = QQBot::Font.new
|
189
|
-
font_json = value['content'][0][1]
|
190
|
-
font.color = font_json['color']
|
191
|
-
font.name = font_json['name']
|
192
|
-
font.size = font_json['size']
|
193
|
-
font.style = font_json['style']
|
194
|
-
message.font = font
|
195
|
-
|
196
|
-
yield message if block_given?
|
197
|
-
end
|
198
|
-
end
|
199
|
-
sleep 1
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def get_group_list
|
204
|
-
code, body = @api.get_group_list
|
205
|
-
result = self.class.check_response_json(code, body)
|
206
|
-
|
207
|
-
if result
|
208
|
-
group_map = {}
|
209
|
-
|
210
|
-
gnamelist = result['gnamelist']
|
211
|
-
gnamelist.each do |item|
|
212
|
-
group = QQBot::Group.new
|
213
|
-
group.name = item['name']
|
214
|
-
group.id = item['gid']
|
215
|
-
group.code = item['code']
|
216
|
-
group_map[group.id] = group
|
217
|
-
end
|
218
|
-
|
219
|
-
gmarklist = result['gmarklist']
|
220
|
-
gmarklist.each do |item|
|
221
|
-
group_map[item['uin']].markname = item['markname']
|
222
|
-
end
|
223
|
-
|
224
|
-
group_map.values
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
def get_friend_list_with_category
|
229
|
-
code, body = @api.get_friend_list
|
230
|
-
result = self.class.check_response_json(code, body)
|
231
|
-
|
232
|
-
if result
|
233
|
-
friend_list = self.class.build_friend_list result
|
234
|
-
|
235
|
-
categories = result['categories']
|
236
|
-
has_default_category = false
|
237
|
-
category_list = categories.collect do |item|
|
238
|
-
category = QQBot::Category.new
|
239
|
-
category.name = item['name']
|
240
|
-
category.sort = item['sort']
|
241
|
-
category.id = item['index']
|
242
|
-
category.friends = friend_list.select { |friend| friend.category_id == category.id }
|
243
|
-
has_default_category ||= (category.id == 0)
|
244
|
-
category
|
245
|
-
end
|
246
|
-
|
247
|
-
unless has_default_category
|
248
|
-
category = QQBot::Category.new
|
249
|
-
category.name = '我的好友(默认)'
|
250
|
-
category.sort = 1
|
251
|
-
category.id = 0
|
252
|
-
category.friends = friend_list.select { |friend| friend.category_id == category.id }
|
253
|
-
category_list << category
|
254
|
-
end
|
255
|
-
|
256
|
-
category_list
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
def get_friend_list
|
261
|
-
code, body = @api.get_friend_list
|
262
|
-
result = self.class.check_response_json(code, body)
|
263
|
-
|
264
|
-
if result
|
265
|
-
self.class.build_friend_list(result)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
def self.build_friend_list(json)
|
270
|
-
friend_map = {}
|
271
|
-
|
272
|
-
friends = json['friends']
|
273
|
-
friends.each do |item|
|
274
|
-
friend = QQBot::Friend.new
|
275
|
-
friend.id = item['uin']
|
276
|
-
friend.category_id = item['categories']
|
277
|
-
friend_map[friend.id] = friend
|
278
|
-
end
|
279
|
-
|
280
|
-
marknames = json['marknames']
|
281
|
-
marknames.each do |item|
|
282
|
-
friend_map[item['uin']].markname = item['markname']
|
283
|
-
end
|
284
|
-
|
285
|
-
vipinfo = json['vipinfo']
|
286
|
-
vipinfo.each do |item|
|
287
|
-
friend = friend_map[item['u']]
|
288
|
-
friend.is_vip = item['is_vip']
|
289
|
-
friend.vip_level = item['vip_level']
|
290
|
-
end
|
291
|
-
|
292
|
-
info = json['info']
|
293
|
-
info.each do |item|
|
294
|
-
friend_map[item['uin']].nickname = item['nick']
|
295
|
-
end
|
296
|
-
|
297
|
-
friend_map.values
|
298
|
-
end
|
299
|
-
|
300
|
-
def get_discuss_list
|
301
|
-
code, body = @api.get_discuss_list
|
302
|
-
result = self.class.check_response_json(code, body)
|
303
|
-
|
304
|
-
if result
|
305
|
-
dnamelist = result['dnamelist']
|
306
|
-
dnamelist.collect do |item|
|
307
|
-
discuss = QQBot::Discuss.new
|
308
|
-
discuss.name = item['name']
|
309
|
-
discuss.id = item['did']
|
310
|
-
discuss
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
def send_to_friend(friend_id, content)
|
316
|
-
code, body = @api.send_to_friend(friend_id, content)
|
317
|
-
self.class.check_send_msg_response(code, body)
|
318
|
-
end
|
319
|
-
|
320
|
-
def send_to_group(group_id, content)
|
321
|
-
code, body = @api.send_to_group(group_id, content)
|
322
|
-
self.class.check_send_msg_response(code, body)
|
323
|
-
end
|
324
|
-
|
325
|
-
def send_to_discuss(discuss_id, content)
|
326
|
-
code, body = @api.send_to_discuss(discuss_id, content)
|
327
|
-
self.class.check_send_msg_response(code, body)
|
328
|
-
end
|
329
|
-
|
330
|
-
def send_to_sess(sess_id, content)
|
331
|
-
code, body = @api.send_to_sess(sess_id, content)
|
332
|
-
self.class.check_send_msg_response(code, body)
|
333
|
-
end
|
334
|
-
|
335
|
-
def get_account_info
|
336
|
-
code, body = @api.get_account_info
|
337
|
-
result = self.class.check_response_json(code, body)
|
338
|
-
|
339
|
-
if result
|
340
|
-
# TODO
|
341
|
-
build_user_info(result)
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
def get_friend_info(friend_id)
|
346
|
-
code, body = @api.get_friend_info(friend_id)
|
347
|
-
result = self.class.check_response_json(code, body)
|
348
|
-
|
349
|
-
if result
|
350
|
-
# TODO
|
351
|
-
build_user_info(result)
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
def build_user_info(result)
|
356
|
-
user_info = QQBot::UserInfo.new
|
357
|
-
user_info.phone = result['phone']
|
358
|
-
user_info.occupation = result['occupation']
|
359
|
-
user_info.college = result['college']
|
360
|
-
user_info.id = result['uin']
|
361
|
-
user_info.blood = result['blood']
|
362
|
-
user_info.slogan = result['lnick']
|
363
|
-
user_info.homepage = result['homepage']
|
364
|
-
user_info.vip_info = result['vip_info']
|
365
|
-
user_info.city = result['city']
|
366
|
-
user_info.country = result['country']
|
367
|
-
user_info.province = result['province']
|
368
|
-
user_info.personal = result['personal']
|
369
|
-
user_info.shengxiao = result['shengxiao']
|
370
|
-
user_info.nickname = result['nick']
|
371
|
-
user_info.email = result['email']
|
372
|
-
user_info.account = result['account']
|
373
|
-
user_info.gender = result['gender']
|
374
|
-
user_info.mobile = result['mobile']
|
375
|
-
birthday = QQBot::Birthday.new
|
376
|
-
birthday.year = result['birthday']['year']
|
377
|
-
birthday.month = result['birthday']['month']
|
378
|
-
birthday.day = result['birthday']['day']
|
379
|
-
user_info.birthday = birthday
|
380
|
-
|
381
|
-
user_info
|
382
|
-
end
|
383
|
-
|
384
|
-
def get_recent_list
|
385
|
-
code, body = @api.get_recent_list
|
386
|
-
result = self.class.check_response_json(code, body)
|
387
|
-
|
388
|
-
if result
|
389
|
-
result.collect do |item|
|
390
|
-
recent = QQBot::Recent.new
|
391
|
-
recent.id = item['uin']
|
392
|
-
recent.type = item['type']
|
393
|
-
recent
|
394
|
-
end
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
def get_qq_by_id(id)
|
399
|
-
code, body = @api.get_qq_by_id(id)
|
400
|
-
result = self.class.check_response_json(code, body)
|
401
|
-
|
402
|
-
if result
|
403
|
-
result['account']
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
def get_online_friends
|
408
|
-
code, body = @api.get_online_friends
|
409
|
-
result = self.class.check_response_json(code, body)
|
410
|
-
|
411
|
-
if result
|
412
|
-
result.collect do |item|
|
413
|
-
online = QQBot::Online.new
|
414
|
-
online.id = item['uin']
|
415
|
-
online.client_type = item['client_type']
|
416
|
-
online
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
def get_group_info(group_code)
|
422
|
-
code, body = @api.get_group_info(group_code)
|
423
|
-
result = self.class.check_response_json(code, body)
|
424
|
-
|
425
|
-
if result
|
426
|
-
group_info = QQBot::GroupInfo.new
|
427
|
-
ginfo = result['ginfo']
|
428
|
-
group_info.id = ginfo['gid']
|
429
|
-
group_info.create_time = ginfo['createtime']
|
430
|
-
group_info.memo = ginfo['memo']
|
431
|
-
group_info.name = ginfo['name']
|
432
|
-
group_info.owner_id = ginfo['owner']
|
433
|
-
group_info.markname = ginfo['markname']
|
434
|
-
|
435
|
-
member_map = {}
|
436
|
-
|
437
|
-
minfo = result['minfo']
|
438
|
-
minfo.each do |item|
|
439
|
-
member = QQBot::GroupMember.new
|
440
|
-
member.id = item['uin']
|
441
|
-
member.nickname = item['nick']
|
442
|
-
member.gender = item['gender']
|
443
|
-
member.country = item['country']
|
444
|
-
member.city = item['city']
|
445
|
-
member_map[member.id] = member
|
446
|
-
end
|
447
|
-
|
448
|
-
cards = result['cards']
|
449
|
-
cards.each { |item| member_map[item['muin']].markname = item['card'] } if cards
|
450
|
-
|
451
|
-
vipinfo = result['vipinfo']
|
452
|
-
vipinfo.each do |item|
|
453
|
-
member = member_map[item['u']]
|
454
|
-
member.is_vip = item['is_vip']
|
455
|
-
member.vip_level = item['vip_level']
|
456
|
-
end
|
457
|
-
|
458
|
-
stats = result['stats']
|
459
|
-
stats.each do |item|
|
460
|
-
member = member_map[item['uin']]
|
461
|
-
member.client_type = item['client_type']
|
462
|
-
member.status = item['stat']
|
463
|
-
end
|
464
|
-
|
465
|
-
group_info.members = member_map.values
|
466
|
-
|
467
|
-
group_info
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
def get_discuss_info(discuss_id)
|
472
|
-
code, body = @api.get_discuss_info(discuss_id)
|
473
|
-
result = self.class.check_response_json(code, body)
|
474
|
-
|
475
|
-
if result
|
476
|
-
discuss_info = QQBot::DiscussInfo.new
|
477
|
-
info = result['info']
|
478
|
-
discuss_info.id = info['did']
|
479
|
-
discuss_info.name = info['discu_name']
|
480
|
-
|
481
|
-
member_map = {}
|
482
|
-
|
483
|
-
mem_info = result['mem_info']
|
484
|
-
mem_info.each do |item|
|
485
|
-
member = QQBot::DiscussMember.new
|
486
|
-
member.id = item['uin']
|
487
|
-
member.nickname = item['nick']
|
488
|
-
member_map[member.id] = member
|
489
|
-
end
|
490
|
-
|
491
|
-
mem_status = result['mem_status']
|
492
|
-
mem_status.each do |item|
|
493
|
-
member = member_map[item['uin']]
|
494
|
-
member.client_type = item['client_type']
|
495
|
-
member.status = item['status']
|
496
|
-
end
|
497
|
-
|
498
|
-
discuss_info.members = member_map.values
|
499
|
-
|
500
|
-
discuss_info
|
501
|
-
end
|
502
|
-
end
|
503
|
-
end
|
504
|
-
end
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module QQBot
|
4
|
+
class Bot
|
5
|
+
def initialize
|
6
|
+
@api = QQBot::Api.new
|
7
|
+
@api.auth_options = login
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.check_response_json(code, body)
|
11
|
+
if code == '200'
|
12
|
+
json = JSON.parse body
|
13
|
+
retcode = json['retcode']
|
14
|
+
if retcode == 0
|
15
|
+
return json['result']
|
16
|
+
elsif retcode == 100012
|
17
|
+
QQBot::LOGGER.info '因为掉线此次请求失败,尝试重新登录'
|
18
|
+
@api.auth_options = relogin
|
19
|
+
else
|
20
|
+
QQBot::LOGGER.info "请求失败,JSON返回码 #{retcode}"
|
21
|
+
end
|
22
|
+
else
|
23
|
+
QQBot::LOGGER.info "请求失败,HTTP返回码 #{code}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.check_send_msg_response(code, body)
|
28
|
+
if code == '200'
|
29
|
+
json = JSON.parse body
|
30
|
+
if json['errCode'] == 0
|
31
|
+
QQBot::LOGGER.info '发送成功'
|
32
|
+
return true
|
33
|
+
else
|
34
|
+
QQBot::LOGGER.info "发送失败,JSON返回码 #{json['retcode']}"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
QQBot::LOGGER.info "请求失败,HTTP返回码 #{code}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_qrcode
|
42
|
+
code, body = @api.get_qrcode
|
43
|
+
|
44
|
+
if code == '200'
|
45
|
+
file_name = File.expand_path('qrcode.png', File.dirname(__FILE__));
|
46
|
+
|
47
|
+
File.open(file_name, 'wb') do |file|
|
48
|
+
file.write body
|
49
|
+
file.close
|
50
|
+
end
|
51
|
+
|
52
|
+
QQBot::LOGGER.info "二维码已经保存在#{file_name}中"
|
53
|
+
|
54
|
+
unless @pid
|
55
|
+
QQBot::LOGGER.info '开启web服务进程'
|
56
|
+
@pid = spawn("ruby -run -e httpd #{file_name} -p 9090")
|
57
|
+
end
|
58
|
+
|
59
|
+
QQBot::LOGGER.info '也可以通过访问 http://localhost:9090 查看二维码'
|
60
|
+
return true
|
61
|
+
else
|
62
|
+
QQBot::LOGGER.info "请求失败,返回码#{code}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def verify_qrcode
|
67
|
+
url = ''
|
68
|
+
|
69
|
+
until url.start_with? 'http' do
|
70
|
+
sleep 5
|
71
|
+
code, body = @api.verify_qrcode
|
72
|
+
|
73
|
+
if code == '200'
|
74
|
+
result = body.force_encoding("UTF-8")
|
75
|
+
if result.include? '二维码已失效'
|
76
|
+
QQBot::LOGGER.info '二维码已失效,准备重新获取'
|
77
|
+
return unless get_qrcode
|
78
|
+
elsif result.include? 'http'
|
79
|
+
QQBot::LOGGER.info '认证成功'
|
80
|
+
return URI.extract(result).first
|
81
|
+
end
|
82
|
+
else
|
83
|
+
QQBot::LOGGER.info "请求失败,返回码#{code}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def close_qrcode_server
|
89
|
+
if @pid
|
90
|
+
QQBot::LOGGER.info '关闭web服务进程'
|
91
|
+
Process.kill('KILL', @pid)
|
92
|
+
@pid = nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_ptwebqq(url)
|
97
|
+
code, ptwebqq = @api.get_ptwebqq url
|
98
|
+
|
99
|
+
if code == '302'
|
100
|
+
ptwebqq
|
101
|
+
else
|
102
|
+
QQBot::LOGGER.info "请求失败,返回码#{code}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_vfwebqq(ptwebqq)
|
107
|
+
code, body = @api.get_vfwebqq(ptwebqq)
|
108
|
+
|
109
|
+
result = self.class.check_response_json(code, body)
|
110
|
+
result['vfwebqq'] if result
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_psessionid_and_uin(ptwebqq)
|
114
|
+
code, body = @api.get_psessionid_and_uin ptwebqq
|
115
|
+
|
116
|
+
result = self.class.check_response_json(code, body)
|
117
|
+
if result
|
118
|
+
return result['psessionid'], result['uin']
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def login
|
123
|
+
QQBot::LOGGER.info '开始获取二维码'
|
124
|
+
raise QQBot::Error::LoginFailed unless get_qrcode
|
125
|
+
|
126
|
+
QQBot::LOGGER.info '等待扫描二维码'
|
127
|
+
url = verify_qrcode
|
128
|
+
raise QQBot::Error::LoginFailed unless url
|
129
|
+
|
130
|
+
close_qrcode_server
|
131
|
+
|
132
|
+
QQBot::LOGGER.info '开始获取ptwebqq'
|
133
|
+
@ptwebqq = get_ptwebqq url
|
134
|
+
raise QQBot::Error::LoginFailed unless @ptwebqq
|
135
|
+
|
136
|
+
QQBot::LOGGER.info '开始获取vfwebqq'
|
137
|
+
vfwebqq = get_vfwebqq @ptwebqq
|
138
|
+
raise QQBot::Error::LoginFailed unless vfwebqq
|
139
|
+
|
140
|
+
QQBot::LOGGER.info '开始获取psessionid和uin'
|
141
|
+
psessionid, uin = get_psessionid_and_uin @ptwebqq
|
142
|
+
raise QQBot::Error::LoginFailed unless uin && psessionid
|
143
|
+
|
144
|
+
{
|
145
|
+
ptwebqq: @ptwebqq,
|
146
|
+
vfwebqq: vfwebqq,
|
147
|
+
psessionid: psessionid,
|
148
|
+
uin: uin
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def relogin
|
153
|
+
QQBot::LOGGER.info '开始获取vfwebqq'
|
154
|
+
vfwebqq = get_vfwebqq @ptwebqq
|
155
|
+
raise QQBot::Error::LoginFailed unless vfwebqq
|
156
|
+
|
157
|
+
QQBot::LOGGER.info '开始获取psessionid和uin'
|
158
|
+
psessionid, uin = get_psessionid_and_uin @ptwebqq
|
159
|
+
raise QQBot::Error::LoginFailed unless uin && psessionid
|
160
|
+
|
161
|
+
{
|
162
|
+
ptwebqq: @ptwebqq,
|
163
|
+
vfwebqq: vfwebqq,
|
164
|
+
psessionid: psessionid,
|
165
|
+
uin: uin
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def poll
|
170
|
+
loop do
|
171
|
+
code, body = @api.poll
|
172
|
+
result = self.class.check_response_json(code, body)
|
173
|
+
|
174
|
+
if result
|
175
|
+
result.each do |item|
|
176
|
+
message = QQBot::Message.new
|
177
|
+
value = item['value']
|
178
|
+
message.type, message.from_id, message.send_id =
|
179
|
+
case item['poll_type']
|
180
|
+
when 'message' then [0, value['from_uin'], value['from_uin']]
|
181
|
+
when 'group_message' then [1, value['from_uin'], value['send_uin']]
|
182
|
+
when 'discu_message' then [2, value['from_uin'], value['send_uin']]
|
183
|
+
else 3
|
184
|
+
end
|
185
|
+
message.time = value['time']
|
186
|
+
message.content = value['content'][1]
|
187
|
+
|
188
|
+
font = QQBot::Font.new
|
189
|
+
font_json = value['content'][0][1]
|
190
|
+
font.color = font_json['color']
|
191
|
+
font.name = font_json['name']
|
192
|
+
font.size = font_json['size']
|
193
|
+
font.style = font_json['style']
|
194
|
+
message.font = font
|
195
|
+
|
196
|
+
yield message if block_given?
|
197
|
+
end
|
198
|
+
end
|
199
|
+
sleep 1
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def get_group_list
|
204
|
+
code, body = @api.get_group_list
|
205
|
+
result = self.class.check_response_json(code, body)
|
206
|
+
|
207
|
+
if result
|
208
|
+
group_map = {}
|
209
|
+
|
210
|
+
gnamelist = result['gnamelist']
|
211
|
+
gnamelist.each do |item|
|
212
|
+
group = QQBot::Group.new
|
213
|
+
group.name = item['name']
|
214
|
+
group.id = item['gid']
|
215
|
+
group.code = item['code']
|
216
|
+
group_map[group.id] = group
|
217
|
+
end
|
218
|
+
|
219
|
+
gmarklist = result['gmarklist']
|
220
|
+
gmarklist.each do |item|
|
221
|
+
group_map[item['uin']].markname = item['markname']
|
222
|
+
end
|
223
|
+
|
224
|
+
group_map.values
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def get_friend_list_with_category
|
229
|
+
code, body = @api.get_friend_list
|
230
|
+
result = self.class.check_response_json(code, body)
|
231
|
+
|
232
|
+
if result
|
233
|
+
friend_list = self.class.build_friend_list result
|
234
|
+
|
235
|
+
categories = result['categories']
|
236
|
+
has_default_category = false
|
237
|
+
category_list = categories.collect do |item|
|
238
|
+
category = QQBot::Category.new
|
239
|
+
category.name = item['name']
|
240
|
+
category.sort = item['sort']
|
241
|
+
category.id = item['index']
|
242
|
+
category.friends = friend_list.select { |friend| friend.category_id == category.id }
|
243
|
+
has_default_category ||= (category.id == 0)
|
244
|
+
category
|
245
|
+
end
|
246
|
+
|
247
|
+
unless has_default_category
|
248
|
+
category = QQBot::Category.new
|
249
|
+
category.name = '我的好友(默认)'
|
250
|
+
category.sort = 1
|
251
|
+
category.id = 0
|
252
|
+
category.friends = friend_list.select { |friend| friend.category_id == category.id }
|
253
|
+
category_list << category
|
254
|
+
end
|
255
|
+
|
256
|
+
category_list
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def get_friend_list
|
261
|
+
code, body = @api.get_friend_list
|
262
|
+
result = self.class.check_response_json(code, body)
|
263
|
+
|
264
|
+
if result
|
265
|
+
self.class.build_friend_list(result)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.build_friend_list(json)
|
270
|
+
friend_map = {}
|
271
|
+
|
272
|
+
friends = json['friends']
|
273
|
+
friends.each do |item|
|
274
|
+
friend = QQBot::Friend.new
|
275
|
+
friend.id = item['uin']
|
276
|
+
friend.category_id = item['categories']
|
277
|
+
friend_map[friend.id] = friend
|
278
|
+
end
|
279
|
+
|
280
|
+
marknames = json['marknames']
|
281
|
+
marknames.each do |item|
|
282
|
+
friend_map[item['uin']].markname = item['markname']
|
283
|
+
end
|
284
|
+
|
285
|
+
vipinfo = json['vipinfo']
|
286
|
+
vipinfo.each do |item|
|
287
|
+
friend = friend_map[item['u']]
|
288
|
+
friend.is_vip = item['is_vip']
|
289
|
+
friend.vip_level = item['vip_level']
|
290
|
+
end
|
291
|
+
|
292
|
+
info = json['info']
|
293
|
+
info.each do |item|
|
294
|
+
friend_map[item['uin']].nickname = item['nick']
|
295
|
+
end
|
296
|
+
|
297
|
+
friend_map.values
|
298
|
+
end
|
299
|
+
|
300
|
+
def get_discuss_list
|
301
|
+
code, body = @api.get_discuss_list
|
302
|
+
result = self.class.check_response_json(code, body)
|
303
|
+
|
304
|
+
if result
|
305
|
+
dnamelist = result['dnamelist']
|
306
|
+
dnamelist.collect do |item|
|
307
|
+
discuss = QQBot::Discuss.new
|
308
|
+
discuss.name = item['name']
|
309
|
+
discuss.id = item['did']
|
310
|
+
discuss
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def send_to_friend(friend_id, content)
|
316
|
+
code, body = @api.send_to_friend(friend_id, content)
|
317
|
+
self.class.check_send_msg_response(code, body)
|
318
|
+
end
|
319
|
+
|
320
|
+
def send_to_group(group_id, content)
|
321
|
+
code, body = @api.send_to_group(group_id, content)
|
322
|
+
self.class.check_send_msg_response(code, body)
|
323
|
+
end
|
324
|
+
|
325
|
+
def send_to_discuss(discuss_id, content)
|
326
|
+
code, body = @api.send_to_discuss(discuss_id, content)
|
327
|
+
self.class.check_send_msg_response(code, body)
|
328
|
+
end
|
329
|
+
|
330
|
+
def send_to_sess(sess_id, content)
|
331
|
+
code, body = @api.send_to_sess(sess_id, content)
|
332
|
+
self.class.check_send_msg_response(code, body)
|
333
|
+
end
|
334
|
+
|
335
|
+
def get_account_info
|
336
|
+
code, body = @api.get_account_info
|
337
|
+
result = self.class.check_response_json(code, body)
|
338
|
+
|
339
|
+
if result
|
340
|
+
# TODO
|
341
|
+
build_user_info(result)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def get_friend_info(friend_id)
|
346
|
+
code, body = @api.get_friend_info(friend_id)
|
347
|
+
result = self.class.check_response_json(code, body)
|
348
|
+
|
349
|
+
if result
|
350
|
+
# TODO
|
351
|
+
build_user_info(result)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def build_user_info(result)
|
356
|
+
user_info = QQBot::UserInfo.new
|
357
|
+
user_info.phone = result['phone']
|
358
|
+
user_info.occupation = result['occupation']
|
359
|
+
user_info.college = result['college']
|
360
|
+
user_info.id = result['uin']
|
361
|
+
user_info.blood = result['blood']
|
362
|
+
user_info.slogan = result['lnick']
|
363
|
+
user_info.homepage = result['homepage']
|
364
|
+
user_info.vip_info = result['vip_info']
|
365
|
+
user_info.city = result['city']
|
366
|
+
user_info.country = result['country']
|
367
|
+
user_info.province = result['province']
|
368
|
+
user_info.personal = result['personal']
|
369
|
+
user_info.shengxiao = result['shengxiao']
|
370
|
+
user_info.nickname = result['nick']
|
371
|
+
user_info.email = result['email']
|
372
|
+
user_info.account = result['account']
|
373
|
+
user_info.gender = result['gender']
|
374
|
+
user_info.mobile = result['mobile']
|
375
|
+
birthday = QQBot::Birthday.new
|
376
|
+
birthday.year = result['birthday']['year']
|
377
|
+
birthday.month = result['birthday']['month']
|
378
|
+
birthday.day = result['birthday']['day']
|
379
|
+
user_info.birthday = birthday
|
380
|
+
|
381
|
+
user_info
|
382
|
+
end
|
383
|
+
|
384
|
+
def get_recent_list
|
385
|
+
code, body = @api.get_recent_list
|
386
|
+
result = self.class.check_response_json(code, body)
|
387
|
+
|
388
|
+
if result
|
389
|
+
result.collect do |item|
|
390
|
+
recent = QQBot::Recent.new
|
391
|
+
recent.id = item['uin']
|
392
|
+
recent.type = item['type']
|
393
|
+
recent
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def get_qq_by_id(id)
|
399
|
+
code, body = @api.get_qq_by_id(id)
|
400
|
+
result = self.class.check_response_json(code, body)
|
401
|
+
|
402
|
+
if result
|
403
|
+
result['account']
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def get_online_friends
|
408
|
+
code, body = @api.get_online_friends
|
409
|
+
result = self.class.check_response_json(code, body)
|
410
|
+
|
411
|
+
if result
|
412
|
+
result.collect do |item|
|
413
|
+
online = QQBot::Online.new
|
414
|
+
online.id = item['uin']
|
415
|
+
online.client_type = item['client_type']
|
416
|
+
online
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def get_group_info(group_code)
|
422
|
+
code, body = @api.get_group_info(group_code)
|
423
|
+
result = self.class.check_response_json(code, body)
|
424
|
+
|
425
|
+
if result
|
426
|
+
group_info = QQBot::GroupInfo.new
|
427
|
+
ginfo = result['ginfo']
|
428
|
+
group_info.id = ginfo['gid']
|
429
|
+
group_info.create_time = ginfo['createtime']
|
430
|
+
group_info.memo = ginfo['memo']
|
431
|
+
group_info.name = ginfo['name']
|
432
|
+
group_info.owner_id = ginfo['owner']
|
433
|
+
group_info.markname = ginfo['markname']
|
434
|
+
|
435
|
+
member_map = {}
|
436
|
+
|
437
|
+
minfo = result['minfo']
|
438
|
+
minfo.each do |item|
|
439
|
+
member = QQBot::GroupMember.new
|
440
|
+
member.id = item['uin']
|
441
|
+
member.nickname = item['nick']
|
442
|
+
member.gender = item['gender']
|
443
|
+
member.country = item['country']
|
444
|
+
member.city = item['city']
|
445
|
+
member_map[member.id] = member
|
446
|
+
end
|
447
|
+
|
448
|
+
cards = result['cards']
|
449
|
+
cards.each { |item| member_map[item['muin']].markname = item['card'] } if cards
|
450
|
+
|
451
|
+
vipinfo = result['vipinfo']
|
452
|
+
vipinfo.each do |item|
|
453
|
+
member = member_map[item['u']]
|
454
|
+
member.is_vip = item['is_vip']
|
455
|
+
member.vip_level = item['vip_level']
|
456
|
+
end
|
457
|
+
|
458
|
+
stats = result['stats']
|
459
|
+
stats.each do |item|
|
460
|
+
member = member_map[item['uin']]
|
461
|
+
member.client_type = item['client_type']
|
462
|
+
member.status = item['stat']
|
463
|
+
end
|
464
|
+
|
465
|
+
group_info.members = member_map.values
|
466
|
+
|
467
|
+
group_info
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
def get_discuss_info(discuss_id)
|
472
|
+
code, body = @api.get_discuss_info(discuss_id)
|
473
|
+
result = self.class.check_response_json(code, body)
|
474
|
+
|
475
|
+
if result
|
476
|
+
discuss_info = QQBot::DiscussInfo.new
|
477
|
+
info = result['info']
|
478
|
+
discuss_info.id = info['did']
|
479
|
+
discuss_info.name = info['discu_name']
|
480
|
+
|
481
|
+
member_map = {}
|
482
|
+
|
483
|
+
mem_info = result['mem_info']
|
484
|
+
mem_info.each do |item|
|
485
|
+
member = QQBot::DiscussMember.new
|
486
|
+
member.id = item['uin']
|
487
|
+
member.nickname = item['nick']
|
488
|
+
member_map[member.id] = member
|
489
|
+
end
|
490
|
+
|
491
|
+
mem_status = result['mem_status']
|
492
|
+
mem_status.each do |item|
|
493
|
+
member = member_map[item['uin']]
|
494
|
+
member.client_type = item['client_type']
|
495
|
+
member.status = item['status']
|
496
|
+
end
|
497
|
+
|
498
|
+
discuss_info.members = member_map.values
|
499
|
+
|
500
|
+
discuss_info
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|
504
|
+
end
|