最近实现了一个树洞(匿名发秘密的一个主页)。nodejs写的。
总体结构是这样的:HAND负责接收数据,数据来源有微信,留言板和站内信。FOOT负责处理数据,图片的话就上传相册,文字就发布状态,这两者都会记录由日志进行记录。至于过滤器是对数据到达FOOT之前进行过滤或者加工。
HAND和FOOT我分别写一个:
HAND中微信这个功能模块主要由wechat这个组件完成,通过npm install wechat安装,wechat相当于一个微信客户端。
需要配置的是申请微信公共主页时要设置token和接收消息的地址。这个wechat相当于一个微信客户端,消息被推到指定的地址。
配置好token和消息接受地址后(我这里token是hollowZJUT,地址是http://jinqi.xxx.biz/wechat),增加相应的自定回复就完成了消息的接收。这是代码:
var wechatListen=function(){
app.use(urlpath, wechat(token, wechat.text(function (message, req, res, next) {
res.reply(dftReply);
console.log('username:'+message.FromUserName);
var description='「微信'+ (token || 'hollowZJUT') + '」';
callbackFn(HandType,messageType,message.Content+description);
}).image(function (message, req, res, next) {
res.reply(dftReply);
console.log('username:'+message.FromUserName);
savePicture(message.PicUrl);
}).location(function (message, req, res, next) {
console.log(message);
res.reply(dftNotsupport);
}).voice(function (message, req, res, next) {
console.log(message);
res.reply(dftNotsupport);
}).link(function (message, req, res, next) {
console.log(message);
res.reply(dftNotsupport);
}).event(function (message, req, res, next) {
console.log(message);
res.reply(dftNotsupport);
})));
}
下面写FOOT中文字信息的处理。
这里的处理方式有发布状态,删除留言,描述照片,回复状态。但是处理方式是一致的,首先根据文字消息的类型构造相应的post结构。然后统一推到一个队列中进行发送。
发送失败的话会尝试3次,超多3次就丢弃这个消息,一般都是一次发送成功的。下面是部分代码:
/**
* 对外接收消息的接口
* @param handid
* @param messageid
* @param message
*/
this.accept=function(handid,messageid,message){
var msgblock;
if(messageid === msgType.textType){
msgblock=buildOneStateBlock(message);
}else if(messageid === msgType.deleteGossip){
msgblock=buildOneDelGossipBlock(message);
}else if(messageid === msgType.stateReply){
msgblock=buildOneStateReplyBlock(message);
}else if(messageid === msgType.userReply){
msgblock=buildOneUserReplyBlock(message);
}else if(messageid === msgType.imgDespt){
msgblock=buildOneImgDesptBlock(message);
}else{
return;
}
postList.push(msgblock);
}
除此之后,文字消息这个模块还承担另一个任务,就是检查cookie是否失效,失效就通知中介。因为人人的cookie每天凌晨就失效,所以这个功能必须有。
/**
* 尝试cookie是否有效
*/
var refreshCookieExpire=function(){
//console.log('stepCookieLogin');
var uname={};
Step(
function(){
var url='http://notify.renren.com/wpi/getonlinecount.do';
Request.get(url,LoginInfo.Cookie,null,uname,'txt',this);
},
function(){
try{
var tmpJson=JSON.parse(uname.Content.trim());
if(tmpJson.hostid){
unamePage.expireTimes=0;
//unamePage.expireTimes++;//for test
}else{
console.log('renren Cookie expire a Time!');
unamePage.expireTimes++;
}
}catch(e){
console.log('renren Cookie expire a Time!');
unamePage.expireTimes++;
}
if(unamePage.expireTimes >= unamePage.maxExpireTime){
console.log('renren Cookie expired!');
//cookie失效,重启程序
callbackFn(FootType,ctrlType,{
info:'cookieExpire',
suggestAction:'restart'
});
}
setTimeout(refreshCookieExpire,refreshCookieExpireTime*1000);
}
);
};
至于第三部分过滤器主要是过滤一些色情词汇。通过正则和字符串进行过滤。
这个就只讲整体的结构了,其他细节的实现我准备另外写几篇。太懒了,想写有懒得写。