博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
当前端玩起 CoolQ:做个技术文章推送机器人
阅读量:6151 次
发布时间:2019-06-21

本文共 6555 字,大约阅读时间需要 21 分钟。

编者按:好久不见,今天的文章来自创宇前端读者投稿。创宇前端接受读者首发或授权转载的原创技术分享,我们会充分尊重读者的所有权益,并对选用文章作者赠送任选技术书籍聊表心意 :)

背景

在我看来,再牛逼的技术不落到实处永远是纸上谈兵,秉承着 学以致用 的校训。一个字 “干” 就完事了?。

2019 年了,如何将前端知识学以致用呢?️?前段时间 QQ 群里大佬们突然玩起了 CoolQ 机器人,用机器人进行在线陪聊、在线点歌、在线搜图乃至……(你能想到的一切?)

突然脑子里闪过一道光 ⚡️,卧槽牛哔呀,我也要玩!作为一个每天早上醒来都有新轮子的前端,不如搞个技术文章推送吧!

啥是 CoolQ

说实话,在 CoolQ 的官网看了半天,愣是不知道它是个什么玩意!难道你都不介绍一下自己是干哈的嘛,差评。

(编者按:这个有一定的历史原因……)

下面的介绍来自百度百科:

酷Q,是一款基于 Smart 协议功能强大的机器人软件,它可以通过安装插件实现自动审核他人申请入群、自动踢人、自动管理群等自动化操作,还能实现自动群聊、自动聊天,起到活跃群组气氛的重要作用,节省您的宝贵时间。

好牛哔,接下来我只是使用了 CoolQ 消息推送的功能?。

技术文章来源

如果让你来搞,你会怎么办呢?你可能会想到爬虫。可以爬页面,也可以爬接口……这里我用 RSS 来实现。

一部分年轻的朋友可能已经没有听说过 RSS 了,时代的眼泪……你可以在这里读到相关介绍::

然而,并不是所有的网站都提供 RSS 服务,比如说 掘金。在这里安利 ,它替我们获取页面内容并生成 RSS 源,为我们懒人提供了福利。如果里面没有找到你想要的内容,那么很抱歉只能自己手撕代码了

实操

1. 安装 CoolQ

CoolQ 官网只提供 Windows 版本,因此,如果想要装在 Linux 或 macOS 上,官方推荐通过 Docker 安装对应的镜像文件。(9102 年了,如果你还不会 Docker 你就 out 了,有些知识不深可以,但是广一点是没有任何毛病的 ?)

一般我们安装。

如果默认的功能不能满足你的需求,想要自己开发一些好玩新奇的功能,则可以安装。

接下来我们分别介绍这两个版本的安装方式。

普通版安装

1.1. 获取镜像

docker pull coolq/wine-coolq复制代码

1.2. 创建文件夹,用于存放 CoolQ 持久化数据

# 任意路径均可mkdir /root/coolq-data复制代码

1.3. 运行镜像

docker run --name=coolq --rm -p 9000:9000 -v /root/coolq-data:/home/user/coolq coolq/wine-coolq复制代码
  • --name 创建一个容器
  • --rm 这个参数是说容器退出之后随之将其删除。默认情况下,为了排障需求,退出的容器不会立即删除,除非手动 docker rm
  • -p <宿主端口>:<容器端口> -p,是用来映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问
  • -v指定挂载一个本地主机的目录到容器中去

1.4. 启动 CoolQ

打开浏览器 输入

点击 connect 输入 默认密码 MAX8char

输入QQ号及密码(推荐注册小号,以防风险)登录 CoolQ

开发版安装

1.1. 获取镜像

docker pull richardchien/cqhttp:latest复制代码

1.2. 创建文件夹,用于存放 CoolQ 持久化数据

1.3. 运行镜像

docker run -ti --rm --name cqhttp -p 9000:9000 -p 5700:5700 -v /root/coolq-data:/home/user/coolq richardchien/cqhttp复制代码

1.4. 启动 CoolQ

2. 安装MongoDB

略(相信这一定不会难道小天才的你 ?)

3. 撸代码

爬文章

async function crawl(url) { try {   const feed = await parser.parseURL(url);   const items = feed.items.map(({ title, link, guid = link }) => {     title = title.trim();     link = link.trim();     guid = guid.trim();     console.log(title, link);     return { title, link, guid };   });   return items; } catch (err) {   console.log(err); }}复制代码

数据库插入数据

async function insert(db, { title, link, guid }) { const collection = db.collection(collectionName); // Insert some documents try {   await collection.updateOne(     {       guid     },     {       $set: { title, link, guid },       $setOnInsert: { status: 0 }     },     {       upsert: true     }   ); } catch (err) {   console.log(err); }}复制代码

数据库查找数据

status 0: 未推送 1: 已推送

async function find(db) { const collection = db.collection(collectionName); // Find some documents try {   return await collection     .find({       status: 0     })     .toArray(); } catch (err) {   console.log(err); }}复制代码

推送消息

group_id 群号

const request = require('superagent');async function send(message) { return await request   .post('http://0.0.0.0:5700/send_group_msg')   .send({ group_id: XXX, message })   .set('Accept', 'application/json');}复制代码

数据爬取及存储代码整合

const MongoClient = require('mongodb').MongoClient;const Parser = require('rss-parser');const parser = new Parser();const url = 'mongodb://localhost:27017';const dbName = 'robot'; // 数据库名const collectionName = 'juejin'; // 集合名(表名)const pullList = ['https://rsshub.app/juejin/category/frontend'];// 插入async function insert(db, { title, link, guid }) { const collection = db.collection(collectionName); // Insert some documents try {   await collection.updateOne(     {       guid     },     {       $set: { title, link, guid },       $setOnInsert: { status: 0 }     },     {       upsert: true     }   ); } catch (err) {   console.log(err); }}// 爬虫async function crawl(url) { try {   const feed = await parser.parseURL(url);   const items = feed.items.map(({ title, link, guid = link }) => {     title = title.trim();     link = link.trim();     guid = guid.trim();     console.log(title, link);     return { title, link, guid };   });   return items; } catch (err) {   console.log(err); }}(async () => { // Create a new MongoClient const client = new MongoClient(url); try {   // Use connect method to connect to the Server   await client.connect();   console.log('Connected successfully to server');   const db = client.db(dbName);   const promises = pullList.map((value) => {     return (async () => {       const items = await crawl(value);       const insertPromises = items.map((item) => {         return insert(db, item);       });       await Promise.all(insertPromises);     })();   });   await Promise.all(promises).then(() => {     client.close();   }); } catch (err) {   console.log(err.stack); }})();复制代码

数据推送及查找代码整合

为了保障代码的运行记得修的修改为自己的 QQ 群号(以下仅以发送群组消息为例,具体的也可以是发送私信,讨论组消息)

const MongoClient = require('mongodb').MongoClient;const request = require('superagent');const url = 'mongodb://localhost:27017';const dbName = 'robot'; // 数据库名const collectionName = 'juejin'; // 集合名(表名)// 查找async function find(db) { const collection = db.collection(collectionName); // Find some documents try {   return await collection     .find({       status: 0     })     .toArray(); } catch (err) {   console.log(err); }}// 更新async function update(db, { guid }) { const collection = db.collection(collectionName); // Update some documents try {   await collection.updateOne(     {       guid     },     {       $set: { status: 1 }     }   ); } catch (err) {   console.log(err); }}// 推送 群组async function send(message) { return await request   .post('http://0.0.0.0:5700/send_group_msg')   .send({ group_id: XXX, message }) // 记得修改哟?   .set('Accept', 'application/json');}(async () => { // Create a new MongoClient const client = new MongoClient(url); try {   // Use connect method to connect to the Server   await client.connect();   console.log('Connected successfully to server');   const db = client.db(dbName);   const docs = await find(db);   console.log(docs);   let message = '';   message = docs.reduce((acu, { title, link }, index) => {     return `${acu}${title} ${link}${index === docs.length - 1 ? '' : '\n'}`;   }, message);   const { text } = await send(message);   const { status, retcode } = JSON.parse(text);   if (status === 'ok' && retcode === 0) {     const promises = docs.map((value) => {       return update(db, value);     });     await Promise.all(promises);   } else {     console.log(status, retcode);   }   client.close(); } catch (err) {   console.log(err.stack); }})();复制代码

展望

以上只是对于 CoolQ 的简单应用,最近还有一个 饿了么外卖推送 的想法,就是根据商家的满减优惠计算出 最优套餐,但是碍于算法的问题,暂时卡在了这一块。如果你还有什么其他想法欢迎一起交流~

最后,送诸位一句 大胆假设,小心求证,人人都是科学家?,欢迎晒出你的 idea!


文 /

作者也在掘金哦,快关注他吧!

编 /

本文由创宇前端作者授权发布,版权属于作者,创宇前端出品。 欢迎注明出处转载本文。文章链接:原文链接

想要订阅更多来自知道创宇开发一线的分享,请搜索关注我们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,我们会尽可能回复。

感谢您的阅读。

你可能感兴趣的文章
2017-2018-1 20165313 《信息安全系统设计基础》第八周学习总结
查看>>
《代码敲不队》第四次作业:项目需求调研与分析
查看>>
菜鸡互啄队—— 团队合作
查看>>
HttpWebRequest的GetResponse或GetRequestStream偶尔超时 + 总结各种超时死掉的可能和相应的解决办法...
查看>>
SparseArray
查看>>
第二章
查看>>
android背景选择器selector用法汇总
查看>>
[转]Paul Adams:为社交设计
查看>>
showdialog弹出窗口刷新问题
查看>>
java
查看>>
Vue.js连接后台数据jsp页面  ̄▽ ̄
查看>>
关于程序的单元测试
查看>>
mysql内存优化
查看>>
都市求生日记第一篇
查看>>
Java集合---HashMap源码剖析
查看>>
SQL优化技巧
查看>>
thead 固定,tbody 超出滚动(附带改变滚动条样式)
查看>>
Dijkstra算法
查看>>
css 动画 和 响应式布局和兼容性
查看>>
csrf 跨站请求伪造相关以及django的中间件
查看>>