編者按:很久不見,今天的文章來自創宇前端讀者投稿。創宇前端接受讀者首發或受權轉載的原創技術分享,咱們會充分尊重讀者的全部權益,並對選用文章做者贈送任選技術書籍聊表心意 :)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)。歡迎留言討論,咱們會盡量回復。
感謝您的閱讀。