呀!(o^^o) 使用 CronJob 同步 GitHub 用户的活动
GitHub:https://github.com/wibus-wee/github-event-discord-listener (欢迎 Star 🌟!)
事情的起因
是这样的,我和 @荆棘 大佬创建了一个新的 Discord 服务器,另外一个大佬说了一个有点意思的东西:同步用户活动,在翻找 GitHub 无果后,我只好自己手写了
想法原理
GitHub 原本是有一个 Webhook 功能的,可以在特定的事件发生时,向指定的 URL 发送一个 HTTP 请求。但是我们需要监听用户活动,第一:我们不可能要每一个用户去配置一个 Webhook,这很明显不可行,并且有可能 private 仓库的活动也会被传播,第二:用户活动的更新反馈是无法被 GitHub 主动触发的。
结合上面的问题,我只好暂时使用 cronjob 来定时向 GitHub 发送请求,获取用户活动, 获取活动有个 API:https://api.github.com/users/${username}/events/public 拿他就完事儿了!
为了实践万物皆可 js的理论,加上我很懒的问题,就使用 node v18 的 fetch 特性来做请求好了。
Coding 部分
正好,GitHub Action 支持 schedule
字段,我们把它设置为 15min 好了
name: "Event Checker"
on:
push:
branches:
- main
schedule:
- cron: "*/15 * * * *" # every 15 minutes
workflow_dispatch:
如果你并不希望 push 的时候被触发,那就删掉这个字段就好了。
如何发出最新的活动?
我目前的想法是利用文件储存最新的活动id
,根据微略的计算,我发现新的 Event ID 都恒大于旧的 Event ID,那我只需要保存最新的 Event ID 比对即可
但不是什么都要广播的,我们只决定广播
Issues
,PR
,Star (Watch)
活动那么这个所谓的 “最新”的 Event ID 也应该只是这三个活动当中的最新活动ID,而不是全部的最新活动 ID
为了不想装 node_modules 我全部选择原生的库(fs, fetch),这样就可以很容易被调用了。
const jsonFile = require('./latest.id.json');
const subscribersFile = require('./subscribers.json');
先导入两个文件,一个是最新ID的保存,另一个是订阅用户的username储存,他们大致像是这样的:
// latest.id.json
{"jsun969":"24954043300","wibus-wee":"24969877605",}
// subscribers.json
[ "wibus-wee", "jsun969", ]
这样导入的就是一个 Object,我们也不需要使用 JSON.parse()
等方法了
为了方便发送信息,我们直接定一个产生出 body 的方法
const body = (content, username) => {
return {
content,
username: `[GitHub] ${username}` || "GitHub",
avatar_url: username ? `https://github.com/${username}.png` : "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
}
}
不但是 content,还使用了 GitHub User 上传的头像,这样发出来或许会更形象一点呼呼呼
由于写得匆忙,我也来不及想那个好那个不行了,我直接就用 forEach 获取一下每一个 username 之后立即发送讯息,并且保存好最新的ID(如果有的话)
usernames.forEach(async function (username) {
// ...
})
但需要注意的是,我们前面讲了不是什么都要广播的,“最新”的 Event ID 也应该只是这三个活动当中的最新活动ID,而不是全部的最新活动 ID,我选择继续跑这个数组,利用 switch-case
判断 type,如果他是 IssuesEvent
, PullRequestEvent
, WatchEvent
中的任意一种,就将这次活动的id存入进去,以及把内容 return 出来,如果不是,就return个空的值。
代码中,我对某些变量定义使用了 var,实际上我并不建议使用 var,这是一个将近被弃用的关键词了,我们只有在特殊情况才会用到它,至于这个地方...
可能算吧
最后 filter
方法将空的内容过滤一下就好了,接着用 fs.writeFile
写下文件就 ok 👌 了. 不过最好用 sort 排序一下,取最大的值存入进去(最新的)
欢迎来到 GitHub 给我 Star 一个!