本帖算是 尝试用浏览器查看论坛 RSS 订阅 的延续。在那个帖子中我介绍了 RSSHub,里面也提供了订阅 GitHub Notifications 的 feed。但是,由于获取数据需要使用 GitHub Access Token,可能是出于安全考虑,因而只有本地部署 RSSHub 的选项。这样一来呢,每次开机都必须要自启动 Docker。像我这样 GitHub 没什么新通知也根本不用 Docker 的人,也不太可能为了接 RSS 安个软件。此外,GitHub 也有邮件通知的设置,但有时也不是每个通知都想要邮件。这时,就可以用到类似本帖的订阅方式。
虽然我觉得有这个需求的人都能自己写,不过写都写了就发一下吧。这里用 DataviewJS 实现。
241209: 更新了通知距离当前时间的计算方式。顺带一提之前修复了获取不到首发帖子的问题。
240125: PR 的 comments api url 路径不是 +/comments 的格式,还是得分情况讨论。已修。
DataviewJS 代码
const token = '你的 Token'
const conf = {
method: 'GET',
headers: {
'Accept': 'application/vnd.github+json',
'Authorization': `Bearer ${token}`,
},
}
const fetchUrl = async (url, conf)=> {
try {
const res = await fetch(url, conf)
if (!res.ok) throw new Error(res.status)
return await res.json()
} catch (err) {
console.error(err.message)
throw err // 重新抛出错误以便处理
}
}
const dateDiff = (t1, t2)=> {
if (t1 > t2) return;
else {
const minutes = (t2 - t1) / 6e4
const hours = minutes / 60
const days = hours / 24
const weeks = days / 7
const half_trunc = (num)=> Math.trunc(num * 2) / 2
if (weeks > 4) return '很久';
else if (weeks >= 1) return `${half_trunc(weeks)} 周前`;
else if (days >= 1) return `${half_trunc(days)} 天前`;
else if (hours >= 1) return `${half_trunc(hours)} 时前`;
else return `${Math.trunc(minutes)} 分前`
}
}
const icon = '<font color="#1f6feb">☼</font>'
const getDial = (time1, time2, curr)=> {
const t1 = new Date(time1)
const t2 = new Date(time2)
const diff = dateDiff(t2, curr)
return (t1 > t2) ? icon : diff
}
const pickLatest = new class {
main = async ({type, url}, conf)=> {
const getOPost = async ()=> await fetchUrl(url, conf)
let cmtUrl, oPost
if (type == 'PullRequest') {
oPost = await getOPost()
cmtUrl = oPost.comments_url
}
else cmtUrl = `${url}/comments`
const cmts = await fetchUrl(cmtUrl, conf)
// Original Post is not considered as a comment.
const post = cmts[0] ? cmts.pop() : (oPost || await getOPost())
return this.formPost(post)
}
limit = 420
formPost = ({body, html_url, user})=> {
const lines = this.trimTrailing(body.split('\r\n'))
const parag = lines.join('\n')
const _body = (parag.length > this.limit)
? parag.slice(0, this.limit) + '\n-<more>'
: parag
return {
body: '````markdown\n' + _body + '\n````', html_url,
user: ` ${user.login}`,
}
}
trimTrailing = (arr)=> {
let index = arr.length - 1
while (index > 0 && arr[index] === '') index--
return arr.slice(0, index + 1)
}
}
const curr = new Date()
const liveUrl = `https://api.github.com/notifications?${curr.getTime()}`
const threads = await fetchUrl(liveUrl, conf), data = []
for (const thread of threads) {
const { last_read_at, updated_at, subject } = thread
const { title } = subject
const dial = getDial(last_read_at, updated_at, curr)
if (!subject.url) {
const link = `[${dial}](https://github.com/notifications)`
data.push(`${thread.reason.toUpperCase()} ${link} ${title}`)
}
else {
const latest = await pickLatest.main(subject, conf)
const link = `[${dial}](<${latest.html_url}>)`
data.push(`${latest.user} ${link} ${title}\n\n${latest.body}`)
}
}
dv.paragraph(data.join('\n\n')||'🎉 No further', {cls: 'gitbox'})
申请 Token 大致步骤
地址:https://github.com/settings/tokens
,或点击头像 - Settings - 左侧滑到底部 Developer settings - Personal access tokens - Tokens (classic)。
Generate new token 继续设置:
Select scopes 向下滑,无其他需求只勾选 notifications 即可。
效果,无新消息时:
GitHub 的 API 只会获取到未读状态的信息。这里我手动将状态设置为未读来进行测试:
原始通知
如何设置为未读
→
类型依次为 ci_activity、PullRequest、Issue 和 Discussion。