就在昨天进入Valine 评论后台发现没有自己域名的调用在10月1号就会停止服务,我也没有那个需求要专门给自己的博客买一个域名,所以换了一个评论插件gitalk
说道为什么需要自动化
原因是Gitalk配置完成后,启动hexo,打开文章页面,需要登陆github,完成初始化后才能使用,并且是每一篇没有初始化的文章都需要,虽然你如果登录了点开文章就会自动创建,但是每一篇新文章都需要点进去,博客少还好但是多了就不好搞了,所以这个自动初始化很有必要,gitakl怎么加入博客这个官网 就有例子,照着做就行了,网上也很多比如这个 ,自动初始化的我找了下都是什么py或者其他自动化语言写的,我这用的node搞了一个
gitalk setting
实现gitalk 自动为文章生成评论栏
第一步 获取github接口的调用权限
- 创建一个access token,点击链接进入
- 点击
Generate new token
- 添加所有的repo权限 在repo前面打勾勾 然后点击最下方的
Generate token
绿色按钮,就可以生成一个新的Token
备用
生成sitemap站点地图
站点地图是一种文件,您可以通过该文件列出您网站上的网页,从而将您网站内容的组织架构告知Google和其他搜索引擎。搜索引擎网页抓取工具会读取此文件,以便更加智能地抓取您的网站
安装插件
这里我们用这个来获取文章的路径数量信息 在你hexo的根目录,执行下面两个命令来安装针对google和百度的插件
1 2
| npm install hexo-generator-sitemap --save npm install hexo-generator-baidu-sitemap --save
|
在站点根目录下的_config.yml添加如下代码
1 2 3 4 5 6
| sitemap: path: sitemap.xml
baidusitemap: path: baidusitemap.xml
|
到这一步 执行hexo generate的时候,在博客根目录下的public文件夹下面,就会生成sitemap.xml和baidusitemap.xml
More info: Server
脚本文件编写
安装依赖包
在你hexo的根目录,执行下面的命令 分别是一些 请求插件,
1 2 3 4
| npm install request --save npm install xml-parser --save npm install yamljs --save npm install cheerio --save
|
创建脚本文件
在站点根目录下创建comment.js
文件,将下面的代码粘贴进文件中,然后修改config
中的配置项,其中token
就是上一步中获取的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
const request = require("request"); const fs = require("fs"); const path = require("path"); const url = require("url"); const xmlParser = require("xml-parser"); const YAML = require("yamljs"); const cheerio = require("cheerio"); const crypto = require('crypto');
const config = { username: "YuThree", token: "xxxxxxxxxxxxxxxxxxxxxxxx", repo: "yuthreeComment", sitemapUrl: path.resolve(__dirname, "./public/sitemap.xml"), kind: "Gitalk", }; let issuesUrl = `https://api.github.com/repos/${config.username}/${config.repo}/issues?access_token=${config.token}`;
let requestGetOpt = { url: `${issuesUrl}&page=1&per_page=1000`, json: true, headers: { "user-agent": "YuThree" } }; let requestPostOpt = { ...requestGetOpt, url:issuesUrl, method: "POST", form: "" }; console.log("开始初始化评论...");
(async function() { console.log("开始检索链接,请稍等..."); try { let urls = sitemapXmlReader(config.sitemapUrl); console.log(`共检索到${urls.length}个链接`); console.log(urls) console.log("开始获取已经初始化的issues:"); console.log('请求连接为---'+issuesUrl) let issues = await send(requestGetOpt); console.log(`已经存在${issues.length}个issues`); let notinitissuelinks = urls.filter((link) => { return !issues.find((item) => { link = removeProtocol(link); return item.body.includes(link); }); }); if (notinitissuelinks.length > 0) { console.log(`本次有${notinitissuelinks.length}个链接需要初始化issue:`); console.log(notinitissuelinks); console.log("开始提交初始化请求, 大约需要2秒..."); setTimeout(async ()=>{ let initRet = await notinitissuelinks.map(async (item) => { let html = await send({ ...requestGetOpt, url: item }); let $ = cheerio.load(html) let title = $("title").first().text(); let pathLabel = md5Sign(url.parse(item).path); let body = `地址:${item}<br><br>简介:${$('#more').prev().text()}`; let form = JSON.stringify({ body, labels: [config.kind, pathLabel], title, client_id:config.client_id, client_secret:config.client_secret}); return send({ ...requestPostOpt, form }); }); console.log(`已完成${initRet.length}个!`); console.log("可以愉快的发表评论了!"); },2000); } else { console.log("本次发布无新增页面,无需初始化issue!!"); } } catch (e) { console.log(`初始化issue出错,错误如下:`); console.log(e); } finally { } })();
function sitemapXmlReader(file) { let data = fs.readFileSync(file, "utf8"); let sitemap = xmlParser(data); return sitemap.root.children.map(function (url) { let loc = url.children.filter(function (item) { return item.name === "loc"; })[0]; return loc.content; }); }
function removeProtocol(url) { return url.substr(url.indexOf(":")); }
function send(options) { return new Promise(function (resolve, reject) { request(options, function (error, response, body) { if (!error) { resolve(body); } else { reject(error); } }); }); } function md5Sign(data) { var md5 = crypto.createHash('md5').update(data).digest('hex'); return md5; }
|
- 执行脚本
需要注意的是第二步中的sitemap插件会生成的sitemap.xml会包含全部的界面,包括标签页、关于页等,执行上面的代码也会对这些页面生成评论框(也就是一条issue)
完成上述操作后,执行下面的命令,就可以部署站点,并初始化所有的评论了。
1 2 3 4
| hexo clean hexo generate hexo deploy node ./comment.js
|
也可以通过在站点根目录的package.json
文件中,新建npm
脚本,一个命令搞定清除缓存、生成静态文件、提交git并生成issue的所有操作。
1 2 3 4
| "scripts": { "start": "hexo clean && hexo s", "build": "hexo clean && hexo generate && hexo deploy && node ./comment.js" }
|
之后完成文章编写,或者其他的更新操作后,直接执行build即可
后记
- 最开始的gittoken 获取后复制出来 他会带一个空格,也可能是我的复制姿势不对,导致开始的连接返回值不对,是个小坑
- Gitalk在页面登陆初始化的时候,默认生成的issue label是链接的path,生成的时候用的path为了满足issue的label不超过50个字符所以都用md5加密了一下,这里就要注意里面的path与这里的path必须一致
参考
Gitment/Gitalk自动初始化
自动初始化 Gitalk 和 Gitment 评论
nodejs版本的Gitalk/Gitment评论自动初始化
封面
Matt Hardy