写给学弟:怎样用编程督促晚间打卡
免责声明:本文是作者闲暇之余,出于学习目的而作,仅供学习与讨论,严禁用于违法违规用途,违者后果自负
写在前面
自从学校要求每天打卡后,班干部就忙碌起来了
这些人力一定程度上是浪费,让我们看一下,班干部做的事是很固定的
- 打卡开始时刻一条消息,提醒大家今天打卡
- 打卡临近结束时候进入后台查看有谁没有打卡,在群里提醒特定的人
- 不断重复过程2,直至全员打卡或打卡时间结束
我们今天要做的就是用程序代替这一番行为
仅仅想使用
程序效果
设定了一个被通知人(例如班长),和一个被通知 QQ 群(你的班群)
准备服务器并安装环境
如果没有可以在这里按需求购买,最便宜的1核1G也可以满足需求,推荐 Ubuntu 系统镜像
安装 node 环境,提供一个 Ubuntu 下 安装 node 教程
如果你在服务器输入 node -v
和 npm -v
有版本输出即可
准备好 qmsg 机器人
打开 qmsg 酱官网,注册登录
进入管理台,选择一个机器人
在下方添加被通知 QQ 号和被通知 QQ 群,使用被通知 QQ 号加他为好友并把他拉进 QQ 群
将 QQ 群设置为可被根据群号搜索
在文档页面进行 QQ 群消息推送权限的申请,然后等待申请通过(需要 24h 左右),只有申请通过后才可以向 QQ 群推送消息
检查系统时间是否正确
注册一个 gitee 账号
demo 地址:https://gitee.com/vvv4230/hebut-night-clock-in-demo
服务器执行 git clone git@gitee.com:vvv4230/hebut-night-clock-in-demo.git
此时执行 ls, 你应该可以看到一个名为 hebut-night-clock-in-demo 的文件夹
使用 pwd
查看当前目录路径,记住详细路径
安装依赖
cd hebut-night-clock-in-demo
npm i --registry=https://registry.npmmirror.com
学习使用 nano / vi / vim
编辑文件,将工程下 config.json 中配置项改为你自己的
{
"QMSGKey": "axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0", // qmsg 账号的key
"username": "188888", // 有查看未打卡人数权限的账号
"password": "password", // 账号对应的密码
"search": "计182", // 班级
"group": "12345678", // 被通知的 QQ 群
"qq": "4230722" // 被通知人的 QQ
}
此时让我们测试一下,在项目根目录下执行 node app.js
,你应该可以在 QQ 上收到对应通知了
下面是最后一步了,在cron 表达式生成生成你需要的 cron 时间表达式,他可以用来表示一些周期性时间
执行 crontab -e
,填入对应表达式
例如我填入了
30 22 * * * node /home/ubuntu/hebut-night-clock-in-demo/app.js
00 23 * * * node /home/ubuntu/hebut-night-clock-in-demo/app.js
表示在 30 22 * * *
(每天 22:30)执行 node /home/ubuntu/hebut-night-clock-in-demo/app.js
命令
和在 00 23 * * *
(每天 23:00)执行 node /home/ubuntu/hebut-night-clock-in-demo/app.js
命令
/home/ubuntu
路径即为 pwd
命令查询到的 hebut-night-clock-in-demo 文件夹所在的路径
好的,配置完成~
如果有兴趣,你可以再完成下面两件事:
- 完善错误处理
- 按照 qmsg 文档,在提示信息中加入 @ 对应同学的操作
好奇原理
把大象装进冰箱分为几步
- 从疫情防控小程序后端接口获取未打卡数据
- 将未打卡人员名单推送到 QQ 群
- 设置定时任务在特定时间点执行我们的程序
获取未打卡数据
接口抓取
疫情防控小程序没有提供对外服务,所以为了达到目的,我们需要 hack 一下
这里用反编译微信小程序和抓包软件配合,细节在此不表,分析获得接口:
baseURL:https://yqfw.hebut.edu.cn/api/
登录接口(JWT)
POST /logins
Headers: Referer、User-Agent、code
body:
{
"data": "[隐去]",
"code": "[隐去]"
}
data 和 code 生成逻辑如下
const blueTower = require('./blue-tower')
const loginModel = {
username: '188888',
password: 'password'
}
const code = blueTower.getUUID();
const data = blueTower.encrypts(JSON.stringify(loginModel), code);
Response 中可以拿到 token
查询未打卡人员
GET /hm/stats/night/user/list
query: date=${date}&dayStu=9&leave=9&inFlag=9&fillFlag=&fillType=&type=1&search=${search}&pageNum=${pageNum}
Headers: Referer、User-Agent、token
具体参数含义没有全部分析,我们只需要知道 date
、search
、pageNum
分别代表欲查询数据的日期、关键字、分页页数属性
Response 中可以拿到 list 和 count,再以此计算去请求所有分页获得完整列表
吐槽一下:这个分页查询接口有严重 bug,不同页存在重复数据,同时也就有可能无法获取准确全量数据(即使是在疫情防控小程序中)
程序编写
简单说就是我们让我们的程序去模拟疫情防控小程序的登录和查询未打卡人员的相关请求
推送到 QQ 群
消息推送方式
- 邮件、短信
- 应用(企业微信、飞书、钉钉)的官方推送接口
- 对于无官方接口应用(QQ、微信)的第三方灰色推送服务(酷Q机器人、晨风机器人、server 酱、qmsg 酱)
qmsg 酱使用
打开qmsg 酱官网,注册登录,确保你的欲通知人(群)加了推送机器人为好友,如果是推送消息到群,需要提供群号经过 qmsg 的审核
webhook 调用示例
function send2Group(group, msg) {
return axios.post(`https://qmsg.zendee.cn/group/${QMSGKey}`, qs.stringify({
msg,
qq: group
}))
}
设置为定时任务
方式一:在 Linux 服务器上,使用 cron 设置定时执行任务,cron 表达式生成
方式二:云厂商的云函数执行方式
写在最后
如果有兴趣,你可以再完成下面两件事:
- 完善错误处理
- 按照 qmsg 文档,在提示信息中加入 @ 对应同学的操作
更建议自己动手从头实现一番,编程语言不限