Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit f98b024

Browse files
committed
Merge pull request #31 from HalfdogStudio/linux
reviewed by reverland
2 parents 4fcc9f0 + 3d942ea commit f98b024

File tree

5 files changed

+133
-124
lines changed

5 files changed

+133
-124
lines changed

cache.js

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
11
'use strict'
22

33
function cacheContact(modContactList, obj) {
4-
for (var o of modContactList) {
5-
if (o.UserName.startsWith('@@')) { // 群组
4+
modContactList.forEach(o=>{
5+
if (o.UserName.startsWith('@@')) { // 群组直接替换了
6+
// console.log('群缓存更新', o.NickName)
67
obj.groupContact[o.UserName] = {
78
nickName: o.NickName,
89
memberList: o.MemberList,
910
}
1011
} else { // 用户
11-
// 查找与替换
12-
var length = obj.memberList.length
13-
let find = false;
14-
for (let i = 0; i < length; i++) {
15-
let user = obj.memberList[i];
16-
if (user['UserName'] == o.UserName) {
17-
obj.memberList[i] = o;
18-
find = true;
19-
break;
20-
}
21-
}
22-
// 如果没有找到
23-
if (!find) {
12+
// 如果不在缓存中
13+
var index = obj.memberList.findIndex(user=> user['UserName'] == o.UserName);
14+
if (index < 0) {
15+
// console.log('用户缓存推入', o.NickName)
2416
obj.memberList.push(o);
17+
} else {
18+
// console.log('用户缓存替换', o.NickName)
19+
obj.memberList[index] = o;
2520
}
2621
}
27-
}
22+
});
2823
}
2924

25+
26+
3027
module.exports.cacheContact = cacheContact;

index.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,27 @@ var parseRedirectUrl = require('./webwx.js').parseRedirectUrl;
88
var login = require('./webwx.js').login;
99
var getbaseRequest = require('./webwx.js').getbaseRequest;
1010
var webwxinit = require('./webwx.js').webwxinit;
11+
12+
var wechatLogger = require('./logger.js').wechatLogger;
13+
var generateReplys = require('./reply.js').generateReplys;
14+
1115
var getContact = require('./webwx.js').getContact;
1216
var robot = require('./webwx.js').robot;
1317

14-
getUUID.
15-
then(checkAndParseUUID).
16-
then(showQRImage).
17-
then(checkLogin).
18-
then(parseRedirectUrl).
19-
then(login).
20-
then(getbaseRequest).
21-
then(webwxinit).
22-
then(getContact).
23-
then(robot).
24-
catch((e)=>{
18+
getUUID
19+
.then(checkAndParseUUID)
20+
.then(showQRImage)
21+
.then(checkLogin)
22+
.then(parseRedirectUrl)
23+
.then(login)
24+
.then(getbaseRequest)
25+
.then(webwxinit)
26+
.then(getContact)
27+
.then(robot(
28+
[(obj)=>o=>true],
29+
[wechatLogger, generateReplys]
30+
))
31+
.catch((e)=>{
2532
console.error(e);
2633
process.exit(1);
2734
});

logger.js

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,26 @@ function logPrivateMsg(o, obj) {
3535
function handlePrivate(username, replyContent, obj) {
3636
// 如果没找到,请求啊
3737
// 查看Object Array中是否有UserName属性为username的Object
38-
function _has(list, Property, username) {
39-
for (let l of list) {
40-
if (l[Property] == username) {
41-
return true;
42-
}
38+
// FIXME_TEST: find替换
39+
40+
var p = new Promise((resolve, reject)=>{
41+
if (obj.memberList.findIndex(m=>m['UserName']==username) < 0) {
42+
// memberList中不存在
43+
var contactP = _requestUserInfo(username, obj);
44+
} else {
45+
var contactP = Promise.resolve(obj);
4346
}
44-
return false;
45-
}
4647

48+
contactP.then(_logPrivateTextMsg).catch(reject);
4749

48-
var p = new Promise((resolve, reject)=>{
49-
if (!_has(obj.memberList, 'UserName', username)) {
50-
var contactP = new Promise((resolve, reject)=>{
50+
function _logPrivateTextMsg(obj) {
51+
// FIXME_TEST: 用find替换
52+
var m = obj.memberList.find(m=>m.UserName==username);
53+
resolve("[" + m.NickName + "说]" + replyContent);
54+
}
55+
56+
function _requestUserInfo(username, obj) {
57+
return new Promise((resolve, reject)=>{
5158
var postData = {
5259
BaseRequest: obj.BaseRequest,
5360
Count: 1,
@@ -82,19 +89,6 @@ function handlePrivate(username, replyContent, obj) {
8289
resolve(obj);
8390
});
8491
});
85-
} else {
86-
var contactP = Promise.resolve(obj);
87-
}
88-
89-
contactP.then(_logPrivateTextMsg).catch(reject);
90-
91-
function _logPrivateTextMsg(obj) {
92-
for (var i = 0; i < obj.memberList.length; i++) {
93-
if (obj.memberList[i]['UserName'] == username) {
94-
console.log('[' + obj.memberList[i]['NickName'] + ' 说]', replyContent);
95-
return;
96-
}
97-
}
9892
}
9993
});
10094
return p;
@@ -116,7 +110,21 @@ function handleGroup(groupUserName, replyContent, obj) {
116110
}
117111
// 查看是否缓存中有
118112
if (!(groupUserName in obj.groupContact)) {
119-
var contactP = new Promise((resolve, reject)=>{
113+
var contactP = _requestGroupInfo(groupUserName, obj)
114+
} else {
115+
var contactP = Promise.resolve(obj);
116+
}
117+
118+
contactP.then(_logGroupTextMsg);
119+
// 记录群消息函数
120+
function _logGroupTextMsg(obj) {
121+
var groupRealName = obj.groupContact[groupUserName]['nickName'];
122+
var m = obj.groupContact[groupUserName]['memberList'].find(m=>m.UserName==fromUserName)
123+
resolve("[" + groupRealName + "]" + m.NickName + replyContent.replace(fromUserName, '').replace("<br/>", ""));
124+
}
125+
126+
function _requestGroupInfo(groupUserName, obj) {
127+
return new Promise((resolve, reject)=>{
120128
var postData = {
121129
BaseRequest: obj.BaseRequest,
122130
Count: 1,
@@ -153,23 +161,8 @@ function handleGroup(groupUserName, replyContent, obj) {
153161
nickName: groupRealName,
154162
};
155163
resolve(obj);
156-
});
157-
})
158-
} else {
159-
var contactP = Promise.resolve(obj);
160-
}
161-
162-
contactP.then(_logGroupTextMsg);
163-
// 记录群消息函数
164-
function _logGroupTextMsg(obj) {
165-
// 直接更新
166-
for (let m of obj.groupContact[groupUserName]['memberList']) {
167-
if (fromUserName && (fromUserName == m.UserName)) {
168-
var nickName = m.NickName;
169-
var groupRealName = obj.groupContact[groupUserName]['nickName'];
170-
resolve("[" + groupRealName + "]" + nickName + replyContent.replace(fromUserName, '').replace("<br/>", ""));
171-
}
172-
}
164+
}); // request
165+
}); //promise
173166
}
174167
});
175168
return p;

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@
2424
"dependencies": {
2525
"request": "^2.67.0",
2626
"segment": "^0.1.3"
27+
},
28+
"devDependencies": {
29+
"mocha": "^2.3.4"
2730
}
2831
}

webwx.js

Lines changed: 65 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var getUUID = new Promise((resolve, reject)=>{
4242
function checkAndParseUUID(text) {
4343
var result = /window.QRLogin.code = (\d+); window.QRLogin.uuid = "([^"]+)";/.exec(text);
4444
//debug("checkAndParseUUID");
45-
if (result[1] != '200') {
45+
if (!result || result[1] != '200') {
4646
return false;
4747
}
4848
return result[2];
@@ -333,68 +333,77 @@ function synccheck(obj) {
333333
return p;
334334
}
335335

336-
function webwxsync(obj) {
337-
// https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xWam498tVKzNaHLt&skey=@crypt_3bb2969_a8ec83465d303fb83bf7ddcf512c081d&lang=en_US&pass_ticket=YIBmwsusvnbs8l7Z4wtRdBXtslA8JjyHxsy0Fsf3PN8NTiP3fzhjB9rOE%252Fzu6Nur
338-
if (!obj.webwxsync) {
339-
return Promise.resolve(obj);
340-
}
341-
var p = new Promise((resolve, reject) => {
342-
//debug('obj in webwxsync:\n' + inspect(obj));
343-
var BaseRequest = obj.BaseRequest;
344-
var pass_ticket = obj.pass_ticket;
345-
var rr = ~Date.now();
346-
var postData = {
347-
BaseRequest: obj.BaseRequest,
348-
SyncKey: obj.SyncKey
349-
};
350-
var options = {
351-
baseUrl: 'https://wx.qq.com',
352-
uri: `/cgi-bin/mmwebwx-bin/webwxsync?sid=${obj.BaseRequest.Sid}&skey=${obj.BaseRequest.Skey}&lang=en_US&pass_ticket=${pass_ticket}&rr=${rr}`,
353-
method: 'POST',
354-
body: postData,
355-
json: true,
356-
jar: true,
336+
function webwxsync(filters, mappers) {
337+
return (obj)=>{
338+
// https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xWam498tVKzNaHLt&skey=@crypt_3bb2969_a8ec83465d303fb83bf7ddcf512c081d&lang=en_US&pass_ticket=YIBmwsusvnbs8l7Z4wtRdBXtslA8JjyHxsy0Fsf3PN8NTiP3fzhjB9rOE%252Fzu6Nur
339+
if (!obj.webwxsync) {
340+
return Promise.resolve(obj);
357341
}
342+
return new Promise((resolve, reject) => {
343+
//debug('obj in webwxsync:\n' + inspect(obj));
344+
var BaseRequest = obj.BaseRequest;
345+
var pass_ticket = obj.pass_ticket;
346+
var rr = ~Date.now();
347+
var postData = {
348+
BaseRequest: obj.BaseRequest,
349+
SyncKey: obj.SyncKey
350+
};
351+
var options = {
352+
baseUrl: 'https://wx.qq.com',
353+
uri: `/cgi-bin/mmwebwx-bin/webwxsync?sid=${obj.BaseRequest.Sid}&skey=${obj.BaseRequest.Skey}&lang=en_US&pass_ticket=${pass_ticket}&rr=${rr}`,
354+
method: 'POST',
355+
body: postData,
356+
json: true,
357+
jar: true,
358+
}
358359

359-
//debug("options in webwxsync: \n" + inspect(options));
360-
//debug("postData in webwxsync: \n" + inspect(postData));
360+
//debug("options in webwxsync: \n" + inspect(options));
361+
//debug("postData in webwxsync: \n" + inspect(postData));
361362

362-
// 请在评论教我该怎么在循环中优雅地使用Promise。。。
363-
request(options, (error, response, body)=>{
364-
// console.log("websync:" + inspect(obj.SyncKey));
365-
// fs.writeFile('webwxsync.json', JSON.stringify(body));
366-
// 更新 synckey
367-
obj.SyncKey = body.SyncKey;
368-
//debug("in websync body: " + inspect(body))
369-
//FIXME: 队列,非要处理完单次的更新吗?
370-
371-
var replys = body.AddMsgList.
372-
filter(o=>(o.ToUserName === obj.username)). // 过滤不是给我的信息
373-
filter(o=>(SPECIAL_USERS.indexOf(o.FromUserName) < 0)). // 不是特殊用户
374-
filter(o=>true). // 用户定义黑白名单
375-
376-
map(wechatLogger(obj)). // 日志
377-
map(generateReplys(obj)); // 回复
378-
379-
// get all replys resolved 所有回复完成
380-
// FIXME: 不对,如果单个消息回复失败则不该所有该批次更新都失败
381-
// 也许可以对失败回复回复以特殊值undefined
382-
Promise.all(replys).then(()=>{
383-
resolve(obj); // 在回调中控制权交给botSpeak
363+
// 请在评论教我该怎么在循环中优雅地使用Promise。。。
364+
request(options, (error, response, body)=>{
365+
// console.log("websync:" + inspect(obj.SyncKey));
366+
// fs.writeFile('webwxsync.json', JSON.stringify(body));
367+
// 更新 synckey
368+
obj.SyncKey = body.SyncKey;
369+
//debug("in websync body: " + inspect(body))
370+
//FIXME: 队列,非要处理完单次的更新吗?
371+
//FIXME: 将这些filter和map作为参数以类似eventListener注册的方式传入?
372+
373+
var replys = body.AddMsgList // 先是默认filter
374+
.filter(o=>(o.ToUserName === obj.username)) // 过滤不是给我的信息
375+
.filter(o=>(SPECIAL_USERS.indexOf(o.FromUserName) < 0)) // 不是特殊用户
376+
377+
filters.forEach(f=> {
378+
replys=replys.filter(f(obj));
379+
});
380+
381+
mappers.forEach(f=> {
382+
replys=replys.map(f(obj));
383+
});
384+
385+
// get all replys resolved 所有回复完成
386+
// FIXME: 不对,如果单个消息回复失败则不该所有该批次更新都失败
387+
// 也许可以对失败回复回复以特殊值undefined
388+
Promise.all(replys).then(()=>{
389+
resolve(obj); // 在回调中控制权交给botSpeak
390+
});
391+
392+
// 更新联系人如果有的话
393+
cacheContact(body.ModContactList, obj);
384394
});
385-
386-
// 更新联系人如果有的话
387-
cacheContact(body.ModContactList, obj);
388395
});
389-
});
390-
return p;
396+
}
391397
}
392398

393-
function robot(obj) {
394-
synccheck(obj).
395-
then(webwxsync).
396-
then(botSpeak).then(robot).
397-
catch(console.error);
399+
function robot(filters, mappers) {
400+
return (obj) => {
401+
synccheck(obj)
402+
.then(webwxsync(filters, mappers))
403+
.then(botSpeak)
404+
.then(robot(filters, mappers))
405+
.catch(console.error);
406+
}
398407
}
399408

400409
function processExit(code, signal) {

0 commit comments

Comments
 (0)