今天我们要让之前的程序能跟 Chat Bot 连动。
直接从程序中 POST 过去啊,难道还要透过 Worker?
对没错,不用,我们可以直接从程序中处理。
让我们回顾一下我们的 checker
函式:
async function checker(courses) {
// 一样,确认子页面存在再操作
await page.waitForSelector("#stfseldListDo");
const child_page = await (await page.$("#stfseldListDo")).contentFrame();
// 用无穷回圈重复执行,直到想停止时手动结束程序
while (true) {
// 遍历每个课程,检查是否有可加选的课程
for (let i = 0; i < courses.length; i++) {
// 在子页面中注入程序确认课程人数状态,後方是带入的查询参数
const data = await child_page.evaluate(injection.getInfo, courses[i].code, courses[i].class, courses[i].type, courses[i].form);
courses[i].seats = data.限修人数 - data.已分发人数;
}
// 印出所有可加选课程
console.log(
"---\n" +
courses
.filter((course) => course.seats > 0)
.map((course) => `${course.name} 还有 ${course.seats} 个空位`)
.join("\n")
);
// 冷却时间,避免瘫痪系统
await child_page.waitForTimeout(30 * 1000);
}
}
我们这里会一直印出有空位的课以及空多少位置。
但你总不希望一直被讯息骚扰吧?所以我们会在位置发生变动时再发送讯息。
我们需要先加上 node-fetch
Package:
npm i node-fetch@2
然後引入:
const fetch = require("node-fetch");
就是传讯息的函式:
async function send(msg) {
// 发送讯息
await fetch(`https://api.telegram.org/bot${process.env.TOKEN}/sendMessage`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ chat_id: +process.env.CHAT_ID, parse_mode: "MarkdownV2", text: msg }),
});
}
这里我们用环境变数来储存 TOKEN 及 CHAT_ID。(当然你也可以一起放到 config 里面)
至於 CHAT_ID 要怎麽取得?你就在 Bot 上写个回传 Chat_ID 的东西就好啦。
// Bot
if (text === "id") {
await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
method: "POST",
headers: { "Content-Type": "application/json" },
// 回覆 Chat ID
body: JSON.stringify({ chat_id, parse_mode: "MarkdownV2", text: chat_id.toString() }),
});
}
async function checker(courses) {
// 一样,确认子页面存在再操作
await page.waitForSelector("#stfseldListDo");
const child_page = await (await page.$("#stfseldListDo")).contentFrame();
// 这里多了个储存空位状态的东西
const seats = {};
// 用无穷回圈重复执行,直到想停止时手动结束程序
while (true) {
// 遍历每个课程,检查是否有可加选的课程
for (let i = 0; i < courses.length; i++) {
// 在子页面中注入程序确认课程人数状态,後方是带入的查询参数
const data = await child_page.evaluate(injection.getInfo, courses[i].code, courses[i].class, courses[i].type, courses[i].form);
courses[i].seats = data.限修人数 - data.已分发人数;
}
// 空位数有变化再放进来
const changed = {};
courses
.forEach((course) => {
if (seats[course.name] !== course.seats) {
// 空位数有变化
changed[course.name] = course.seats;
seats[course.name] = course.seats; // 更新空位数
}
});
// 如果有空位数有变化,传送讯息
if (Object.keys(changed).length > 0) {
// 只发送有位置的讯息,可以发送 Markdown 格式的讯息
let msg = Object.entries(changed)
.map(([name, seats]) => (seats ? `${name} 目前有 **${seats}** 个空位` : ""))
.filter((x) => !!x)
.join("\n");
// 没有 await 的必要,因为不影响
send(msg);
}
// 冷却时间,避免瘫痪系统
await child_page.waitForTimeout(30 * 1000);
}
}
我们用一个 changed 来确认空位数是否有变化。
有变化的话,再传讯息。
完成!
以 10/04 20:00 ~ 10/05 20:00 文章观看数增加值排名
+230
JS 07 - 原型方法:欲达则必速
+155
Day 18:数据蒐集、资料视觉化、数据分析
+134
Day20 Android - Retrofit(Get)
+133
[Day30] 完结洒花❀ 看完赛心得顺便用Python画 3D 渐层花朵!
+133
【Day 20】Google Apps Script - API 篇回顾整理
+132
Day 1 无限手套 AWS 版:掌控一切的 5 + 1 云端必学主题
+122
[面试][资料库]如何解决高并发情境的商品秒杀问题
+120
[Day2] 抓取每日收盘价
+117
Day 23【Tokens' Owner】FUN SIDE PROJECT
+112
从零开始的8-bit迷宫探险【Level 27】神助攻-老弟帮我配个音效
<<: Dialog 关闭後更新 Grid 资料 / 显示储存的图档 - day20
>>: 第一个 HOC (Higher-Order Components)( Day21 )
附codepen网址: https://codepen.io/pwbzvqja/pen/GRWNV...
D3js 动画事件小技巧 用途 在d3世界中,如果想使用起来不是透过事件驱动或是外部驱动,而是想要产...
接着来讲讲泛型的部分.... 简单来说泛型就是传入值、传回值不固定的情况下这时候就可以使用泛型......
from Unsplash 写了三十天的技术文章,最後一篇想谈谈「职涯发展」,毕竟这才是非本科转职...
现在死亡後有了两个选项,一个重新开始游戏,一个是回到标题,目前只有一个场景,所以第一步快速制作一个开...