diff --git a/cache.js b/cache.js
index fbd4fb3..8389650 100644
--- a/cache.js
+++ b/cache.js
@@ -1,30 +1,27 @@
'use strict'
function cacheContact(modContactList, obj) {
- for (var o of modContactList) {
- if (o.UserName.startsWith('@@')) { // 群组
+ modContactList.forEach(o=>{
+ if (o.UserName.startsWith('@@')) { // 群组直接替换了
+ // console.log('群缓存更新', o.NickName)
obj.groupContact[o.UserName] = {
nickName: o.NickName,
memberList: o.MemberList,
}
} else { // 用户
- // 查找与替换
- var length = obj.memberList.length
- let find = false;
- for (let i = 0; i < length; i++) {
- let user = obj.memberList[i];
- if (user['UserName'] == o.UserName) {
- obj.memberList[i] = o;
- find = true;
- break;
- }
- }
- // 如果没有找到
- if (!find) {
+ // 如果不在缓存中
+ var index = obj.memberList.findIndex(user=> user['UserName'] == o.UserName);
+ if (index < 0) {
+ // console.log('用户缓存推入', o.NickName)
obj.memberList.push(o);
+ } else {
+ // console.log('用户缓存替换', o.NickName)
+ obj.memberList[index] = o;
}
}
- }
+ });
}
+
+
module.exports.cacheContact = cacheContact;
diff --git a/index.js b/index.js
index 4dac1ae..f0f20cc 100644
--- a/index.js
+++ b/index.js
@@ -8,20 +8,27 @@ var parseRedirectUrl = require('./webwx.js').parseRedirectUrl;
var login = require('./webwx.js').login;
var getbaseRequest = require('./webwx.js').getbaseRequest;
var webwxinit = require('./webwx.js').webwxinit;
+
+var wechatLogger = require('./logger.js').wechatLogger;
+var generateReplys = require('./reply.js').generateReplys;
+
var getContact = require('./webwx.js').getContact;
var robot = require('./webwx.js').robot;
-getUUID.
- then(checkAndParseUUID).
- then(showQRImage).
- then(checkLogin).
- then(parseRedirectUrl).
- then(login).
- then(getbaseRequest).
- then(webwxinit).
- then(getContact).
- then(robot).
- catch((e)=>{
+getUUID
+ .then(checkAndParseUUID)
+ .then(showQRImage)
+ .then(checkLogin)
+ .then(parseRedirectUrl)
+ .then(login)
+ .then(getbaseRequest)
+ .then(webwxinit)
+ .then(getContact)
+ .then(robot(
+ [(obj)=>o=>true],
+ [wechatLogger, generateReplys]
+ ))
+ .catch((e)=>{
console.error(e);
process.exit(1);
});
diff --git a/logger.js b/logger.js
index b085afe..d2a481d 100644
--- a/logger.js
+++ b/logger.js
@@ -35,19 +35,26 @@ function logPrivateMsg(o, obj) {
function handlePrivate(username, replyContent, obj) {
// 如果没找到,请求啊
// 查看Object Array中是否有UserName属性为username的Object
- function _has(list, Property, username) {
- for (let l of list) {
- if (l[Property] == username) {
- return true;
- }
+ // FIXME_TEST: find替换
+
+ var p = new Promise((resolve, reject)=>{
+ if (obj.memberList.findIndex(m=>m['UserName']==username) < 0) {
+ // memberList中不存在
+ var contactP = _requestUserInfo(username, obj);
+ } else {
+ var contactP = Promise.resolve(obj);
}
- return false;
- }
+ contactP.then(_logPrivateTextMsg).catch(reject);
- var p = new Promise((resolve, reject)=>{
- if (!_has(obj.memberList, 'UserName', username)) {
- var contactP = new Promise((resolve, reject)=>{
+ function _logPrivateTextMsg(obj) {
+ // FIXME_TEST: 用find替换
+ var m = obj.memberList.find(m=>m.UserName==username);
+ resolve("[" + m.NickName + "说]" + replyContent);
+ }
+
+ function _requestUserInfo(username, obj) {
+ return new Promise((resolve, reject)=>{
var postData = {
BaseRequest: obj.BaseRequest,
Count: 1,
@@ -82,19 +89,6 @@ function handlePrivate(username, replyContent, obj) {
resolve(obj);
});
});
- } else {
- var contactP = Promise.resolve(obj);
- }
-
- contactP.then(_logPrivateTextMsg).catch(reject);
-
- function _logPrivateTextMsg(obj) {
- for (var i = 0; i < obj.memberList.length; i++) {
- if (obj.memberList[i]['UserName'] == username) {
- console.log('[' + obj.memberList[i]['NickName'] + ' 说]', replyContent);
- return;
- }
- }
}
});
return p;
@@ -116,7 +110,21 @@ function handleGroup(groupUserName, replyContent, obj) {
}
// 查看是否缓存中有
if (!(groupUserName in obj.groupContact)) {
- var contactP = new Promise((resolve, reject)=>{
+ var contactP = _requestGroupInfo(groupUserName, obj)
+ } else {
+ var contactP = Promise.resolve(obj);
+ }
+
+ contactP.then(_logGroupTextMsg);
+ // 记录群消息函数
+ function _logGroupTextMsg(obj) {
+ var groupRealName = obj.groupContact[groupUserName]['nickName'];
+ var m = obj.groupContact[groupUserName]['memberList'].find(m=>m.UserName==fromUserName)
+ resolve("[" + groupRealName + "]" + m.NickName + replyContent.replace(fromUserName, '').replace("
", ""));
+ }
+
+ function _requestGroupInfo(groupUserName, obj) {
+ return new Promise((resolve, reject)=>{
var postData = {
BaseRequest: obj.BaseRequest,
Count: 1,
@@ -153,23 +161,8 @@ function handleGroup(groupUserName, replyContent, obj) {
nickName: groupRealName,
};
resolve(obj);
- });
- })
- } else {
- var contactP = Promise.resolve(obj);
- }
-
- contactP.then(_logGroupTextMsg);
- // 记录群消息函数
- function _logGroupTextMsg(obj) {
- // 直接更新
- for (let m of obj.groupContact[groupUserName]['memberList']) {
- if (fromUserName && (fromUserName == m.UserName)) {
- var nickName = m.NickName;
- var groupRealName = obj.groupContact[groupUserName]['nickName'];
- resolve("[" + groupRealName + "]" + nickName + replyContent.replace(fromUserName, '').replace("
", ""));
- }
- }
+ }); // request
+ }); //promise
}
});
return p;
diff --git a/package.json b/package.json
index 2fc1dbd..7d5e4ba 100644
--- a/package.json
+++ b/package.json
@@ -24,5 +24,8 @@
"dependencies": {
"request": "^2.67.0",
"segment": "^0.1.3"
+ },
+ "devDependencies": {
+ "mocha": "^2.3.4"
}
}
diff --git a/webwx.js b/webwx.js
index 2e8b83a..9a3edea 100644
--- a/webwx.js
+++ b/webwx.js
@@ -42,7 +42,7 @@ var getUUID = new Promise((resolve, reject)=>{
function checkAndParseUUID(text) {
var result = /window.QRLogin.code = (\d+); window.QRLogin.uuid = "([^"]+)";/.exec(text);
//debug("checkAndParseUUID");
- if (result[1] != '200') {
+ if (!result || result[1] != '200') {
return false;
}
return result[2];
@@ -333,68 +333,77 @@ function synccheck(obj) {
return p;
}
-function webwxsync(obj) {
- // https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xWam498tVKzNaHLt&skey=@crypt_3bb2969_a8ec83465d303fb83bf7ddcf512c081d&lang=en_US&pass_ticket=YIBmwsusvnbs8l7Z4wtRdBXtslA8JjyHxsy0Fsf3PN8NTiP3fzhjB9rOE%252Fzu6Nur
- if (!obj.webwxsync) {
- return Promise.resolve(obj);
- }
- var p = new Promise((resolve, reject) => {
- //debug('obj in webwxsync:\n' + inspect(obj));
- var BaseRequest = obj.BaseRequest;
- var pass_ticket = obj.pass_ticket;
- var rr = ~Date.now();
- var postData = {
- BaseRequest: obj.BaseRequest,
- SyncKey: obj.SyncKey
- };
- var options = {
- baseUrl: 'https://wx.qq.com',
- uri: `/cgi-bin/mmwebwx-bin/webwxsync?sid=${obj.BaseRequest.Sid}&skey=${obj.BaseRequest.Skey}&lang=en_US&pass_ticket=${pass_ticket}&rr=${rr}`,
- method: 'POST',
- body: postData,
- json: true,
- jar: true,
+function webwxsync(filters, mappers) {
+ return (obj)=>{
+ // https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=xWam498tVKzNaHLt&skey=@crypt_3bb2969_a8ec83465d303fb83bf7ddcf512c081d&lang=en_US&pass_ticket=YIBmwsusvnbs8l7Z4wtRdBXtslA8JjyHxsy0Fsf3PN8NTiP3fzhjB9rOE%252Fzu6Nur
+ if (!obj.webwxsync) {
+ return Promise.resolve(obj);
}
+ return new Promise((resolve, reject) => {
+ //debug('obj in webwxsync:\n' + inspect(obj));
+ var BaseRequest = obj.BaseRequest;
+ var pass_ticket = obj.pass_ticket;
+ var rr = ~Date.now();
+ var postData = {
+ BaseRequest: obj.BaseRequest,
+ SyncKey: obj.SyncKey
+ };
+ var options = {
+ baseUrl: 'https://wx.qq.com',
+ uri: `/cgi-bin/mmwebwx-bin/webwxsync?sid=${obj.BaseRequest.Sid}&skey=${obj.BaseRequest.Skey}&lang=en_US&pass_ticket=${pass_ticket}&rr=${rr}`,
+ method: 'POST',
+ body: postData,
+ json: true,
+ jar: true,
+ }
- //debug("options in webwxsync: \n" + inspect(options));
- //debug("postData in webwxsync: \n" + inspect(postData));
+ //debug("options in webwxsync: \n" + inspect(options));
+ //debug("postData in webwxsync: \n" + inspect(postData));
- // 请在评论教我该怎么在循环中优雅地使用Promise。。。
- request(options, (error, response, body)=>{
- // console.log("websync:" + inspect(obj.SyncKey));
- // fs.writeFile('webwxsync.json', JSON.stringify(body));
- // 更新 synckey
- obj.SyncKey = body.SyncKey;
- //debug("in websync body: " + inspect(body))
- //FIXME: 队列,非要处理完单次的更新吗?
-
- var replys = body.AddMsgList.
- filter(o=>(o.ToUserName === obj.username)). // 过滤不是给我的信息
- filter(o=>(SPECIAL_USERS.indexOf(o.FromUserName) < 0)). // 不是特殊用户
- filter(o=>true). // 用户定义黑白名单
-
- map(wechatLogger(obj)). // 日志
- map(generateReplys(obj)); // 回复
-
- // get all replys resolved 所有回复完成
- // FIXME: 不对,如果单个消息回复失败则不该所有该批次更新都失败
- // 也许可以对失败回复回复以特殊值undefined
- Promise.all(replys).then(()=>{
- resolve(obj); // 在回调中控制权交给botSpeak
+ // 请在评论教我该怎么在循环中优雅地使用Promise。。。
+ request(options, (error, response, body)=>{
+ // console.log("websync:" + inspect(obj.SyncKey));
+ // fs.writeFile('webwxsync.json', JSON.stringify(body));
+ // 更新 synckey
+ obj.SyncKey = body.SyncKey;
+ //debug("in websync body: " + inspect(body))
+ //FIXME: 队列,非要处理完单次的更新吗?
+ //FIXME: 将这些filter和map作为参数以类似eventListener注册的方式传入?
+
+ var replys = body.AddMsgList // 先是默认filter
+ .filter(o=>(o.ToUserName === obj.username)) // 过滤不是给我的信息
+ .filter(o=>(SPECIAL_USERS.indexOf(o.FromUserName) < 0)) // 不是特殊用户
+
+ filters.forEach(f=> {
+ replys=replys.filter(f(obj));
+ });
+
+ mappers.forEach(f=> {
+ replys=replys.map(f(obj));
+ });
+
+ // get all replys resolved 所有回复完成
+ // FIXME: 不对,如果单个消息回复失败则不该所有该批次更新都失败
+ // 也许可以对失败回复回复以特殊值undefined
+ Promise.all(replys).then(()=>{
+ resolve(obj); // 在回调中控制权交给botSpeak
+ });
+
+ // 更新联系人如果有的话
+ cacheContact(body.ModContactList, obj);
});
-
- // 更新联系人如果有的话
- cacheContact(body.ModContactList, obj);
});
- });
- return p;
+ }
}
-function robot(obj) {
- synccheck(obj).
- then(webwxsync).
- then(botSpeak).then(robot).
- catch(console.error);
+function robot(filters, mappers) {
+ return (obj) => {
+ synccheck(obj)
+ .then(webwxsync(filters, mappers))
+ .then(botSpeak)
+ .then(robot(filters, mappers))
+ .catch(console.error);
+ }
}
function processExit(code, signal) {