编者按:很久不见,今天的文章来自创宇前端读者投稿。创宇前端接受读者首发或受权转载的原创技术分享,咱们会充分尊重读者的全部权益,并对选用文章做者赠送任选技术书籍聊表心意 :)javascript
在我看来,再牛逼的技术不落到实处永远是纸上谈兵,秉承着 学以至用
的校训。一个字 “干” 就完事了💪。html
2019 年了,如何将前端知识学以至用呢🤔️?前段时间 QQ 群里大佬们忽然玩起了 CoolQ
机器人,用机器人进行在线陪聊、在线点歌、在线搜图乃至……(你能想到的一切😏)前端
忽然脑子里闪过一道光 ⚡️,卧槽牛哔呀,我也要玩!做为一个天天早上醒来都有新轮子的前端,不如搞个技术文章推送吧!java
说实话,在 CoolQ
的官网看了半天,愣是不知道它是个什么玩意!难道你都不介绍一下本身是干哈的嘛,差评。git
(编者按:这个有必定的历史缘由……)github
下面的介绍来自百度百科:算法
酷Q,是一款基于 Smart 协议功能强大的机器人软件,它能够经过安装插件实现自动审核他人申请入群、自动踢人、自动管理群等自动化操做,还能实现自动群聊、自动聊天,起到活跃群组气氛的重要做用,节省您的宝贵时间。mongodb
好牛哔,接下来我只是使用了 CoolQ
消息推送的功能😳。docker
若是让你来搞,你会怎么办呢?你可能会想到爬虫。能够爬页面,也能够爬接口……这里我用 RSS 来实现。shell
一部分年轻的朋友可能已经没有据说过 RSS 了,时代的眼泪……你能够在这里读到相关介绍::www.runoob.com/rss/rss-int…
然而,并非全部的网站都提供 RSS 服务,好比说 掘金
。在这里安利 RSSHub,它替咱们获取页面内容并生成 RSS 源,为咱们懒人提供了福利。若是里面没有找到你想要的内容,那么很抱歉只能本身手撕代码了
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
打开浏览器 输入 localhost:9000
点击 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
略(相信这必定不会难道小天才的你 😉)
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!
文 / lastSeries
做者也在掘金哦,快关注他吧!
编 / 荧声
本文由创宇前端做者受权发布,版权属于做者,创宇前端出品。 欢迎注明出处转载本文。文章连接:原文连接
想要订阅更多来自知道创宇开发一线的分享,请搜索关注咱们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,咱们会尽量回复。
感谢您的阅读。