1

自动初始化Gitalk评论

 2 years ago
source link: http://edisonxu.com/2018/10/31/gitalk-auto-init.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近重新将博客整理了一下,之前忙的都没有时间取打理。其中一下是用Gitalk更换原来的评论系统。
Gitalk是利用了GithubAPI,将网站的评论转写到Github上指定仓库的Issues里,相当于做了一个代理。风格做的简约漂亮,但每种不足的是每次发表了新博文后,需要自己用管理员账号登陆下评论系统,否则就会:

所以就萌生了写个nodejs代码去代替人工初始化的想法。

Gitalk安装

总体来说,使用还是比较简单的,具体步骤请参阅官网,这里就不再赘述了。重点讲下配置。
首先,是Github上申请OAuth App的配置

然后,是Gitalk的配置

var gitalk = new Gitalk({
clientID: 'xxxxxxxxxxxxxx',
clientSecret: 'xxxxxxxxxxxxxxxx',
repo: 'GitHub repo',
owner: 'GitHub repo owner',
admin: ['GitHub repo owner and collaborators, only these guys can initialize github issues'],
id: md5(window.location.pathname), // Ensure uniqueness and length less than 50
distractionFreeMode: false // Facebook-like distraction free mode
})

这里,重点有三个地方:

  • owenr是Github上的ID。有些人(比如我),登陆时习惯用邮箱,放这里就不行了。一定得是自己的ID!
  • repo,要填的是用来存储评论的Issues所对应的仓库的名字,记住后面不要有.git
  • 配置中的id,是唯一表示当前评论页面的主键。Gitalk用它作为Github Issue的Label,而Github对Label的长度有限制,最多50个字符,所以这里比较好的解决方案是对pathname做MD5,以保证长度和唯一性。
    需要引入md5的js,可以使用JavaScript-MD5.

申请Personal Access Token

GithubAPI对一些接口有调用限制,具体可以查看Rate limiting的解释。对于不同的认证方式,调用限制不同。

Gitalk使用的是Github的OAuth认证,请求时必须要有clientIDclientSecret,这种方式每小时的Rate limiting60。如果只是发表评论,肯定是够了。
而如果要批量创建所有文章对应的Issue来作为这些文章的评论存储,可能就未必够了。

好在Github提供了另一种认证方式——Personal access token,这种方式每小时的限制高达5000次。所以,第一步就是申请这个token。

从Github的Personal access token页面,点击Generate new token

创建完成后,获得一个Token。

我用NodeJs写了个简单的批量刷新工具,是基于网站的sitemap的。如果你的网站没有sitemap,可以自行修改。

npm install sitemapper -S
npm install cheerio -S

NodeJS文件

var request = require('request');
var Sitemapper = require('sitemapper');
var cheerio = require('cheerio');
var crypto = require('crypto');

// 配置信息
const username = "EdisonXu" //github账号,对应Gitalk配置中的owner
const repo_name = "repo" //用于存储Issue的仓库名,对应Gitalk配置中的repo
const token = "xxxxxxxxxxxxxxxxxxxxxxxxxxx" //前面申请的personal access token
const sitemap_url = "http://edisonxu.com/sitemap.xml" // 自己站点的sitemap地址

var base_url = "https://api.github.com/repos/"+ username + "/" + repo_name + "/issues"

var sitemap = new Sitemapper();

sitemap.fetch(sitemap_url)
.then(function (sites) {
sites.sites.forEach(function (site, index) {
if (site.endsWith('404.html')) {
console.log('跳过404')
return
}
request({
url: site,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
}, function (err, resp, bd) {
if (err || resp.statusCode != 200)
return
const $ = cheerio.load(bd);
var title = $('title').text();
var desc = site + "\n\n" + $("meta[name='description']").attr("content");
var path = site.split(".com")[1]
var md5 = crypto.createHash('md5');
var label = md5.update(path).digest('hex')
var options = {
headers: {
'Authorization': 'token '+token,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
'Accept': 'application/json'
},
url: base_url+ "?labels="+"Gitalk," + label,
method: 'GET'
}
// 检查issue是否被初始化过
request(options, function (error, response, body) {
if (error || response.statusCode != 200) {
console.log('检查['+site+']对应评论异常')
return
}
var jbody = JSON.parse(body)
if(jbody.length>0)
return
//创建issue
var request_body = {"title": title, "labels": ["Gitalk", label], "body": desc}
//console.log("创建内容: "+JSON.stringify(request_body));
var create_options = {
headers: {
'Authorization': 'token '+token,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
},
url: base_url,
body: JSON.stringify(request_body),
method: 'POST'
}
request(create_options, function(error, response, body){
if (!error && response.statusCode == 201)
console.log("地址: ["+site+"] Gitalk初始化成功")
})
});
});
});
})
.catch(function (err) {
console.log(err);
});

注意
代码里默认将path做了MD5化,如果你的Gitalk配置里没有使用MD5后的值作为ID,这里要相应修改!

Gulp调用

我的博客是Hexo+Gulp,所以我把Gitalk初始化也做到了Gulp里,这样每次写完文章压缩、发布、初始化评论一条龙。用法比较简单:

var $ = require('gulp-load-plugins')();
gulp.task('init-gitalk', ['deploy'], $.shell.task('node init_gitalk.js'));

最后将init-gitalk的task自己加到你的gulp任务序列去就好了。
由于我博客的配置文件里已经有了username和sitemap地址,另外gitalk配置和上门代码的配置也有部分重复,所以我又添加了读取配置的功能,有需要的自行挑选。

npm install js-yaml -S

配置文件中增加

gitalk:
githubId: xxx
repo: xxxxxxxxxx
owner: xxxxxxxxxxxxx
token: xxxxxxxxxxxxxx
var yml = require('js-yaml');
var fs = require('fs');

//读取配置文件
var file = process.cwd()+"\\_config.yml";
var config = yml.safeLoad(fs.readFileSync(file, 'utf8'))

const username = config.gitalk.githubId
const repo_name = config.gitalk.repo
const token = config.gitalk.token
const sitemap_url = config.url+"/"+config.sitemap.path

至此,Gitalk自动初始化就完成了,再也不要手动初始化了。NodeJS非我之长,所以写不出”信达雅”,只保证能用,起个抛砖引玉的效果。

如果您觉得文章不错,可以请我喝一杯咖啡!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK