Last active
December 28, 2022 13:51
-
-
Save geektutu/f379d87767787979507a0e4a20da64ba to your computer and use it in GitHub Desktop.
模仿disqus的 SEE ALSO ON <blog> 功能,为静态博客添加“显示本站其他文章评论”的功能。 https://geektutu.com/post/blog-experience-7.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Generate Comments JSON Data | |
*/ | |
const https = require('https'); | |
const fs = require('fs'); | |
const github = { | |
client_id: '<your-client-id>', | |
client_secret: '<your-client-secret>', | |
repo: '<your-github-repo>', | |
owner: '<your-github-name>' | |
} | |
const PREFIX = `/repos/${github.owner}/${github.repo}/` | |
const AUTH = `&client_id=${github.client_id}&client_secret=${github.client_secret}` | |
const PAGING = '&sort=created&direction=desc&per_page=100' | |
class Comments { | |
constructor() { | |
this.comments = [] | |
this.issueMap = [] | |
this.obj = {} | |
} | |
deltaDate(old) { | |
let hours = (Date.now() - new Date(old)) / 1000 / 3600 | |
let years = Math.floor(hours / 24 / 365) | |
if (years) { | |
return `${years}年前` | |
} | |
let months = Math.floor(hours / 24 / 30) | |
if (months) { | |
return `${months}月前` | |
} | |
let days = Math.floor(hours / 24) | |
if (days) { | |
return `${days}天前` | |
} | |
hours = Math.floor(hours) | |
return `${hours}小时前` | |
} | |
async parse() { | |
this.comments = await this.get(`issues/comments?${PAGING}`) | |
console.log(`comments.length: ${this.comments.length}`) | |
await this.writeComments() | |
} | |
async fetchIssue(issueUrl) { | |
let issueApi = issueUrl.slice(issueUrl.indexOf(PREFIX) + PREFIX.length) | |
if (!this.issueMap[issueApi]) { | |
let issue = await this.get(issueApi + '?') | |
if (!issue.labels.find(label => label.name === 'Gitalk')) { | |
return | |
} | |
issue.post = issue.labels.find(label => label.name.startsWith("/")).name | |
issue.title = issue.title.split('|')[0].trim() | |
this.issueMap[issueApi] = issue | |
} | |
return this.issueMap[issueApi] | |
} | |
async writeComments() { | |
let simpleComments = {} | |
for (const comment of this.comments) { | |
let issue = await this.fetchIssue(comment.issue_url) | |
if (!issue) { | |
continue | |
} | |
if (issue.user.login === comment.user.login) { | |
continue | |
} | |
if (simpleComments[issue.post]) { | |
continue | |
} | |
simpleComments[issue.post] = { | |
title: issue.title, | |
url: issue.post, | |
count: issue.comments, | |
user: comment.user.login, | |
icon: comment.user.avatar_url, | |
date: this.deltaDate(comment.created_at), | |
body: comment.body.replace(/</g, " ").replace(/>/g, " ").replace(/\s+/g, " ").trim() | |
} | |
} | |
let obj = Object.keys(simpleComments).map(key => simpleComments[key]) | |
fs.writeFileSync("comments.json", JSON.stringify(obj), { encoding: 'utf-8' }); | |
console.log(`write ${obj.length} success!`) | |
} | |
get(api) { | |
let options = { | |
hostname: 'api.github.com', | |
path: `${PREFIX}${api}${AUTH}`, | |
headers: { 'User-Agent': 'Node Https Client' } | |
}; | |
console.log(`GET ${options.path}`) | |
return new Promise((resolve, reject) => { | |
const req = https.get(options, (res) => { | |
let data = ''; | |
res.on('data', (chunk) => data += chunk); | |
res.on('end', () => resolve(JSON.parse(data))); | |
}); | |
req.on('error', (e) => reject(e)); | |
req.end(); | |
}); | |
} | |
} | |
(async () => { | |
client = new Comments() | |
await client.parse() | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="gitalk-related"></div> | |
<style> | |
#gitalk-related.dis-wrapper { | |
font-size: 14px; | |
margin: 70px 0; | |
overflow: hidden; | |
padding-bottom: 10px; | |
} | |
#gitalk-related * { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
text-decoration: none; | |
transform: none; | |
-webkit-transform: none; | |
} | |
#gitalk-related .dis-divide { | |
border-top: 2px solid #e7e9ee; | |
width: 100%; | |
float: left; | |
padding: 5px 10px; | |
margin-top: 20px; | |
text-align: center; | |
} | |
#gitalk-related .dis-item { | |
width: 50%; | |
float: left; | |
padding: 0px 10px; | |
margin-top: 20px; | |
height: 108px; | |
overflow: hidden; | |
} | |
#gitalk-related .dis-item-title { | |
font-size: 16px; | |
color: #6190e8; | |
font-weight: 500; | |
max-height: 3em; | |
line-height: 1.5; | |
overflow: hidden; | |
} | |
#gitalk-related .dis-item-des { | |
font-size: 0.85em; | |
} | |
#gitalk-related .dis-divide a, | |
#gitalk-related .dis-item-des, | |
#gitalk-related .dis-item-user { | |
color: rgba(30, 55, 70, .4); | |
} | |
#gitalk-related .dis-item-img { | |
width: 30px; | |
height: 30px; | |
margin-top: 3px; | |
} | |
#gitalk-related .dis-item-content { | |
display: flex; | |
} | |
#gitalk-related .dis-item-content>p { | |
padding-left: 10px; | |
color: #333; | |
line-height: 1.4em; | |
max-height: 4.2em; | |
overflow: hidden; | |
} | |
</style> | |
<script> | |
window.addEventListener('load', function () { | |
function render(comments) { | |
var template = '<a href="${comment.url}?utm_source=gitalk" class="dis-item-url"><h3 class="dis-item-title">${comment.title}</h3>' + | |
'<p class="dis-item-des">${comment.count} 评论 ● ${comment.date}</p>' + | |
'<div class="dis-item-content"><img class="dis-item-img" src="${comment.icon}" alt="icon"><p><b><span class="dis-item-user">${comment.user}</span></b> —— ${comment.body}</p></div>' + | |
'</a>' | |
var wrapper = get('#gitalk-related'); | |
comments = shuffle(comments); | |
comments.slice(0, 4).forEach(function (c) { | |
var div = document.createElement('div'); | |
div.classList.add('dis-item'); | |
div.innerHTML = template.replace("${comment.url}", c.url) | |
.replace("${comment.title}", c.title) | |
.replace("${comment.count}", c.count) | |
.replace("${comment.date}", c.date) | |
.replace("${comment.icon}", c.icon) | |
.replace("${comment.user}", c.user) | |
.replace("${comment.body}", c.body) | |
wrapper.appendChild(div) | |
}) | |
var p = document.createElement('p') | |
p.innerHTML = '<a href="https://geektutu.com/post/blog-experience-7.html">Gitalk Plus</a>'; | |
p.classList.add('dis-divide'); | |
wrapper.appendChild(p); | |
wrapper.classList.add('dis-wrapper') | |
} | |
function shuffle(a) { | |
for (var i = a.length - 1; i > 0; i--) { | |
var j = Math.floor(Math.random() * (i + 1)); | |
[a[i], a[j]] = [a[j], a[i]]; | |
} | |
return a; | |
} | |
function get(str) { return document.querySelector(str) } | |
fetch('/comments.json').then(function (r) { return r.json() }).then(render).catch(function (e) { }) | |
}) | |
</script> |
report 一个bug:
github 的 获取 issues/comments api 会将 PR 的 comments 也获取出来,我在运行时发生了错误,发现是将这个 PR 给带出来了: hutusi/hutusi.github.com#56
issue.post = issue.labels.find(label => label.name.startsWith("/")).name
这段如果找不到 / 开头的 label 会抛异常。
@hutusi Fixed, thanks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
效果