背景:2月1日我们实验室的qq群引入了一个聊天机器人,可实现签到,打劫,玩游戏(如24点,猜字谜等)等的功能,签到,打劫成功,游戏胜利(如24点回答正确)可获得积分,寒假时未曾关注群所以开学时自己毫无积分,而其他同学都已为富一方,尤其是某学长积分竟达十万之巨,(签到一次100左右,24点回答正确100),遂疑惑,问之,学长曰:无他,刷分耳。于是在4月9日,参考了下学长的思路(http://www.zhangzaizai.com/2017/02/08/xiaozi-helper/),便开始试着开发一个刷分的辅助。

技术:我的后端平台是nodejs,其他框架不是学得很深所以用最底层的http模块来发送post请求。用明文传输信息的smartqq来作为post的接受端。

步骤

了解只需发送两种post请求,一是代表发送信息的send_qun_msg2,可以看到在F12下post信息十分详细,那么在nodejs中照本宣科即可。

var http = require('http');

exports.post= function(contents) {var options ={

host:"d1.web2.qq.com",

method:"POST",

path:"/channel/send_qun_msg2",

headers: {'Host': 'd1.web2.qq.com','User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0','Accept': '*/*','Accept-Language': 'en-US,en;q=0.5','Content-Type': 'application/x-www-form-urlencoded','Referer': 'https://d1.web2.qq.com/cfproxy.html?v=20151105001&callback=1','Content-Length': contents.length,'Cookie': '',/*出于安全考虑隐去cookie*/

'Connection': 'keep-alive'}

};var req = http.request(options, function(res) {});

req.write(contents);

req.end();

};

我为了操作方便把它封装在了模块中。

然而这看似简单的代码实际上出过很大的问题,这是我已经整理过得代码,但是在初期我的content并不是外部的参数,而是自己定义的一个JSON(如下

var rr ={"group_uin": 4111913875,"content": "[\"开始24点\",[\"font\",{\"name\":\"宋体\",\"size\":10,\"style\":[0,0,0],\"color\":\"000000\"}]]","face": 210,"clientid": 53156849,/*出于安全考虑隐去真实数字,换以同长数字*/

"msg_id": 62220001,"psessionid": ""/*出于安全考虑隐去psessionid*/};

),但是传输老失败,后来询问学长,发现实际传输的内容并不是直接JSON,而需要经过URLencode加密,于是我调用了nodejs自带的encodeURI函数把上述加密后传输(),后即成功

var contents2 = encodeURI('r=' + JSON.stringify(rr));

但马上我就碰到了另一个问题,我的响应是一堆乱码,虽然给群里发送消息并不需要考虑响应,但是我post的方式肯定是一样的,也就意味着我接受群里消息时也是一顿乱码,就更别谈处理了。这个问题大概花了我两天时间,一开始怀疑是charset,utf-8的问题,于是在请求头里各种改(比如request.setCharacterEncoding("utf-8")),但是并没有用,又怀疑smartqq用的根本不是utf-8,一查是的(如下图)

然后继续想,这期间查阅了不少网站,比如(http://blog.csdn.net/zsr_251/article/details/49993911)于是猜测问题在buffer的拼接上,几经周折尝试各种方法(如

var buf=Buffer.concat(chunks,size);var str=iconv.decode(buf,'utf-8');

)还是不行。

最后打算对于请求头信息一个一个分析发现了这个

'Accept-Encoding': 'gzip, deflate, br',

于是寻求相关信息,发现(http://www.jb51.net/article/61721.htm)这个网站,尝试着解压了下响应体,如

zlib.unzip(body, function(err, buffer) {

console.log(buffer.toString());

})

6. 然后就ok了,当屏幕上出现send ok时心情还是蛮激动的,然后十分兴奋的告诉学长,只听学长一声“你可以发请求头要求它不做gzip压缩的”,遂删去Accept-Encoding。发送消息至此就算成功了。在此向某个被我拿来做实验的群说声抱歉,我不是故意水的。。

接下来是接受消息。

在smartqq上接受消息的原理是不断post poll2当有人发给你消息时post就会响应,响应内容即为接受内容。那么模拟它即可。

此post跟上述的并没有太大的不同,但是要注意option的path要变了,以及content-length固定不变,option的代码如下,

var options ={

host:"d1.web2.qq.com",

method:"POST",

path:"/channel/poll2",/*注意此处*/headers: {'Host': 'd1.web2.qq.com','User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0','Accept': '*/*','Accept-Language': 'en-US,en;q=0.5','Content-Type': 'application/x-www-form-urlencoded','Referer': 'https://d1.web2.qq.com/cfproxy.html?v=20151105001&callback=1','Content-Length': '395',/*我认为由于参数不同你们的不一定是395,自己抓包即可获得长度*/

'Cookie': '',/*出于安全考虑隐去cookie*/

'Connection': 'keep-alive'}

};

重点在于对响应的处理。当我输入“开始24点”后小紫(机器人)会返回这样一段话:"24点开始!数字(共有6种解法):8, 8, 8, 5将以上数字加减乘除(+,-,*,/)得出24,并列出算式即可。如发送:24点 (4-2)*12/1",当我回答正确后会返回:"很强悍!算式正确。增加100积分当前数字(共有20种解法):9, 9, 3, 5将以上数字加减乘除(+,-,*,/)得出24,并列出算式即可。如发送:24点 (4-2)*12/1",我要做的是正确获取四个数字并避免其他信息干扰,同时不能在没获得信息,即没人互动时程序整个挂掉(会返回一个HTML网页),还要根据4个数字计算得出正确的字符串。

从24点算法开始,我在(http://www.99cankao.com/numbers/24game.php)网页上直接找到了计算24点的代码(如下图)

,把输入的交互改成参数传入,并把返回值改成字符串后就可以直接用了,我把它封装在了calc模块中方便调用,代码如下。

functiontdisoper(f0, f1, f2, f3) {this[0] =f0;this[1] =f1;this[2] =f2;this[3] =f3;

}

disoper= new tdisoper("-", "+", "/", "*");functionoper(f, m, n) {if (f === 3) return (m *n);if (f === 2) return (m /n);if (f === 1) return (parseFloat(m) +parseFloat(n));if (f === 0) return (m -n);

}functiontb(i1, i2, i4, i8) {this[1] =i1;this[2] =i2;this[4] =i4;this[8] =i8;

}functionvalid(a,b,c,d) {var result = '';

n= 1;

b= newtb(a, b, c, d);

k= 0;var output = "";for (i1 = 1; i1 <= 8; i1 *= 2)for (i2 = 1; i2 <= 8; i2 *= 2)for (i3 = 1; i3 <= 8; i3 *= 2)for (i4 = 1; i4 <= 8; i4 *= 2) {if ((i1 | i2 | i3 | i4) !== 0xf) continue;for (f1 = 0; f1 <= 3; f1++)for (f2 = 0; f2 <= 3; f2++)for (f3 = 0; f3 <= 3; f3++) {

m=oper(f3, oper(f2, oper(f1, b[i1], b[i2]), b[i3]), b[i4]);if (Math.abs(m - 24) < 1e-5) {

result= result + "((" + b[i1] + disoper[f1] + b[i2] + ")" + disoper[f2] + b[i3] + ")" + disoper[f3] +b[i4];if ((n !== 0) && (++k >= n)) returnresult;

}

m=oper(f1, b[i1], oper(f3, oper(f2, b[i2], b[i3]), b[i4]));if (Math.abs(m - 24) < 1e-5) {

result= result + b[i1] + disoper[f1] + "((" + b[i2] + disoper[f2] + b[i3] + ")" + disoper[f3] + b[i4] + ")";if ((n !== 0) && (++k >= n)) returnresult;

}

m=oper(f3, oper(f1, b[i1], oper(f2, b[i2], b[i3])), b[i4]);if (Math.abs(m - 24) < 1e-5) {

result= result + "(" + b[i1] + disoper[f1] + "(" + b[i2] + disoper[f2] + b[i3] + "))" + disoper[f3] +b[i4];if ((n !== 0) && (++k >= n)) returnresult;

}

m=oper(f1, b[i1], oper(f2, b[i2], oper(f3, b[i3], b[i4])));if (Math.abs(m - 24) < 1e-5) {

result= result + b[i1] + disoper[f1] + "(" + b[i2] + disoper[f2] + "(" + b[i3] + disoper[f3] + b[i4] + "))";if ((n !== 0) && (++k >= n)) returnresult;

}

m=oper(f2, oper(f1, b[i1], b[i2]), oper(f3, b[i3], b[i4]));if (Math.abs(m - 24) < 1e-5) {

result= result + "(" + b[i1] + disoper[f1] + b[i2] + ")" + disoper[f2] + "(" + b[i3] + disoper[f3] + b[i4] + ")";if ((n !== 0) && (++k >= n)) returnresult;

}

}

}returnresult;

exports.cal= function(a,b,c,d){returnvalid(a,b,c,d);

};

处理响应体并发送,代码如下,注释基本解释清楚,如有疑问欢迎提问。

var req = http.request(options, function(res) {

res.on('data', function(body) {if (body.toString().search('') === -1) {/*此处是为了避免长时间未收到数据导致程序直接崩溃*/

varstr;

str= JSON.parse(body.toString());/*解析响应体为JSON格式*/console.log("接受消息 " + str.result[0].value.content);/*获得接受内容*/

if (str.result[0].value.send_uin === 8888888/*此处出于安全考虑。。*/) {var usethen;/*含有关键4个数字的字符串*/

if (str.result[0].value.content.length >= 6)/*避免无关信息干扰*/usethen= str.result[0].value.content[5];if (usethen!==undefined) {var use = usethen.match(/\u89e3[^\n]*\u4ee5/g);/*利用正则表达式获取从'解'到'以'的字符串*/

varnumber;if (use!==undefined)

number= use[0].match(/[0-9]/g); /*利用正则获取4个重要数字*/console.log("获得数字" +number);if (number !==undefined) {var result = calc.cal(number[0], number[1], number[2], number[3]);

console.log("得到结果" +result);var reg = /["][^\n]*[",]/;

rr.content= rr.content.replace('开始24点', "24点 " + result);/*rr就是上面的rr*/contents2= encodeURI('r=' +JSON.stringify(rr));

contents2= contents2.replace('+', '%2b');/*为什么有这四个,我要放在下面讲*/contents2= contents2.replace('+', '%2b');

contents2= contents2.replace('+', '%2b');

contents2= contents2.replace('+', '%2b');

post.post(contents2);

}

}

}

}

});

res.on('err', function(err) {

console.log(err);

})

});

req.write(contents);

req.end();

为什么我要写四个contents = contents.replace('+','%2b')呢,因为encodeURI函数不会转换加号等特殊字符,导致我发送出去的字符串一直没有加号,这里又卡了我一下。如有更好的方法,希望有大神教与我。

最后是轮询发送poll2的问题,我一开始一直有error显示write after end,后来发现是我没有给req重新赋值,相当于请求结束后继续write自然有错,于是把赋值写在了轮询中。

至此,程序编的差不多了,作为并不熟练的noder,自然是有很多瑕疵,也希望有大神能够指出。

smartqq java撤回_基于nodejs的http模块通过smartqq实现自动收发qq消息的程序相关推荐

  1. smartqq java撤回_基于SmartQQ协议的QQ自动回复机器人-1

    1. 软件安装:[myeclipse6.0 + maven2] 0. https://blog.csdn.net/zgmzyr/article/details/6886440 1. https://b ...

  2. 【java毕业设计】基于javaEE+SSH+SQL Server的学生信息管理系统设计与实现(毕业论文+程序源码)——学生信息管理系统

    基于javaEE+SSH+SQL Server的学生信息管理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+SSH+SQL Server的学生信息管理系统设计与实现,文章 ...

  3. 【java毕业设计】基于javaEE+SSM+MySql的个人博客系统设计与实现(毕业论文+程序源码)——个人博客系统

    基于javaEE+SSM+MySql的个人博客系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+SSM+MySql的个人博客系统设计与实现,文章末尾附有本毕业设计的论文和源 ...

  4. 【java毕业设计】基于javaEE+SSH+SqlServer的企业车辆管理系统设计与实现(毕业论文+程序源码)——车辆管理系统

    基于javaEE+SSH+SqlServer的企业车辆管理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+SSH+SqlServer的企业车辆管理系统设计与实现,文章末尾 ...

  5. 【java毕业设计】基于Spring Boot+mysql的线上教学平台系统设计与实现(程序源码)-线上教学平台

    基于Spring Boot+mysql的线上教学平台系统设计与实现(程序源码+毕业论文) 大家好,今天给大家介绍基于Spring Boot+mysql的线上教学平台系统设计与实现,本论文只截取部分文章 ...

  6. 【java毕业设计】基于javaEE+原生Servlet+MySql的企业财务管理系统设计与实现(毕业论文+程序源码)——企业财务管理系统

    基于javaEE+原生Servlet+MySql的企业财务管理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+原生Servlet+MySql的企业财务管理系统设计与实现, ...

  7. 【java毕业设计】基于javaEE+SSH+mysql的百货中心供应链管理系统设计与实现(毕业论文+程序源码)——供应链管理系统

    基于javaEE+SSH+mysql的百货中心供应链管理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+SSH+mysql的百货中心供应链管理系统设计与实现,文章末尾附有 ...

  8. 【java毕业设计】基于javaEE+Spring的新闻发布及管理系统设计与实现(毕业论文+程序源码)——新闻发布及管理系统

    基于javaEE+Spring的新闻发布及管理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+Spring的新闻发布及管理系统设计与实现,文章末尾附有本毕业设计的论文和源 ...

  9. 【java毕业设计】基于javaEE+原生Servlet+jsp的人力资源管理系统设计与实现(毕业论文+程序源码)——人力资源管理系统

    基于javaEE+原生Servlet+jsp的人力资源管理系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于javaEE+原生Servlet+jsp的人力资源管理系统设计与实现,文章末尾 ...

最新文章

  1. iOS - iOS 适配
  2. 利用JSP内置的Application对象实现的网站引用计数
  3. [转]IIS 允许/禁止 目录浏览
  4. springboot---整合redis
  5. RabbbitMq Return 消息机制
  6. 重修 mongoDB 系列(一) 配置环境
  7. 苹果发明超薄触摸显示技术:iPhone 12系列有望首发搭载
  8. python中io中的+模式_Python的高级特性,模块和IO操作
  9. 仓库货位卡标识牌_仓库应如何规划?
  10. 链家网页爬虫_R爬虫小白入门:Rvest爬链家网+分析(一)
  11. JVM学习04-垃圾回收概念与算法
  12. 【Git/Github学习笔记】Git分支管理(一)
  13. 安装ANSYS19.0的正确方法(附下载)
  14. mysql学生管理系统背景_MySql学习之路1 背景介绍
  15. c语言编程创意表白,C语言和图形界面编程打造——浪漫的表白程序
  16. 软考_高级《系统分析师》考试大纲
  17. Mono 的执行流程
  18. 关于ViewPager.PageTransformer的一些理解
  19. uniapp 微信小程序 map自定义气泡customCallout
  20. FRM 5.3业绩衡量比率

热门文章

  1. 封装的适配器 adapter
  2. 浅谈Junit测试中反射和Jmock的应用
  3. 网络爱好者必知的国内十大知名Linux系统版本
  4. CMMI入门 - 由来与思路
  5. 详解python 3下文本文件的编解码
  6. LINQ中的动态排序
  7. .Net开源工作流Roadflow的使用与集成
  8. sql server 2008学习8 sql server存储和索引结构
  9. Android开发四 开发第一个Android应用
  10. 阿里云可以外链mysql_案例详细说明阿里云下设置MySQL远程连接步骤