nodejs版本的Gitalk/Gitment評論自動初始化

原文發表於nodejs版本的Gitalk/Gitment評論自動初始化javascript

前言

今天搭建blog的最後一步,添加評論功能,一番搜索,看中了Gitalk和Gitment,由於Gitment在github上的代碼斷更過久,最終選擇了Gitalk,關於具體安裝和配置,能夠參見下面官網和兩篇文章html

Gitalk官網java

Hexo中Gitalk配置使用教程-多是目前最詳細的教程node

Hexo NexT主題中集成gitalk評論系統git

遇到的問題

Gitalk配置完成後,啓動hexo,打開文章頁面,會出現以下的界面,須要登錄github,完成初始化後才能使用github

image.png

文章這麼一篇一篇的點過去,操做賊麻煩,若是有自動化操做一波,才符合懶人天性,就百度了一下有沒有同道中人,已經解決過了,果真有【這裏】,一頓操做後,只能放棄。web

緣由:npm

  1. 發佈的時候,每次執行這個腳本,都會爲每一個連接 建立一個issue,並無對已經建立的作過濾。
  2. ruby手生,改不動

如此如此,只能本身動手了,nodejs大法。json

解決問題

生成sitemap站點地圖

站點地圖是一種文件,您能夠經過該文件列出您網站上的網頁,從而將您網站內容的組織架構告知Google和其餘搜索引擎。搜索引擎網頁抓取工具會讀取此文件,以便更加智能地抓取您的網站。api

  1. 安裝插件

    在你hexo的根目錄,執行下面兩個命令來安裝針對google和百度的插件

    npm install hexo-generator-sitemap --save
    npm install hexo-generator-baidu-sitemap --save
    複製代碼
  2. 在站點根目錄下的_config.yml添加以下代碼

    # hexo sitemap網站地圖
    sitemap:
      path: sitemap.xml
    
    baidusitemap:
      path: baidusitemap.xml
    複製代碼

    如今在執行hexo generate的時候,在博客根目錄下的public文件夾下面,就會生成sitemap.xml和baidusitemap.xml。

獲取github接口的調用權限

  1. 建立一個access token,點擊連接進入

  2. 點擊Generate new token按鈕

    image.png

  3. 輸入一個描述,爲token添加全部的repo權限,而後點擊最下方的Generate token按鈕,就能夠生成一個新的Token備用

    image.png
    生成的token,在後面使用
    image.png

腳本文件

  1. 安裝依賴包

    在你hexo的根目錄,執行下面的命令

    npm install request --save
    npm install xml-parser --save
    npm install yamljs --save
    npm install cheerio --save
    複製代碼
  2. 建立腳本文件

    在站點根目錄下建立comment.js文件,將下面的代碼粘貼進文件中,而後修改config中的配置項,其中token就是上一步中獲取的值

    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 config = {
        username: "GitHub 用戶名", // GitHub 用戶名
        token: "GitHub Token",  // GitHub Token
        repo: "daihaoxin.github.io",  // 存放 issues的git倉庫
        // sitemap.xml的路徑,commit.js放置在根目錄下,無需修改,其餘狀況自行處理
        sitemapUrl: path.resolve(__dirname, "./public/sitemap.xml"),
        kind: "Gitalk",  // "Gitalk" or "Gitment"
    };
    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": "github-user"
        }
    };
    let requestPostOpt = {
        ...requestGetOpt,
        url:issuesUrl,
        method: "POST",
        form: ""
    };
    
    console.log("開始初始化評論...");
    
    (async function() {
        console.log("開始檢索連接,請稍等...");
        
        try {
            let websiteConfig = YAML.parse(fs.readFileSync(path.resolve(__dirname, "./_config.yml"), "utf8"));
            
            let urls = sitemapXmlReader(config.sitemapUrl);
            console.log(`共檢索到${urls.length}個連接`);
            
            console.log("開始獲取已經初始化的issues:");
            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("開始提交初始化請求, 大約須要40秒...");
                /** * 部署好網站後,直接執行start,新增文章並不會生成評論 * 經測試,最少須要等待40秒,才能夠正確生成, 懷疑跟github的api有關係,沒有找到實錘 */
                setTimeout(async ()=>{
                    let initRet = await notInitIssueLinks.map(async (item) => {
                        let html = await send({ ...requestGetOpt, url: item });
                        let title = cheerio.load(html)("title").text();
                        let pathLabel = url.parse(item).path;
                        let body = `${item}<br><br>${websiteConfig.description}`;
                        let form = JSON.stringify({ body, labels: [config.kind, pathLabel], title });
                        return send({ ...requestPostOpt, form });
                    });
                    console.log(`已完成${initRet.length}個!`);
                    console.log("能夠愉快的發表評論了!");
                },40000);
            } 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);
                }
            });
        });
    }
    複製代碼
  3. 執行腳本

    須要注意的是第一步中的sitemap插件會生成的sitemap.xml會包含所有的界面,包括標籤頁、關於頁等,執行上面的代碼也會對這些頁面生成評論框(也就是issue)

    完成上述操做後,執行下面的命令,就能夠部署站點,並初始化全部的評論了。

    hexo clean
    hexo generate
    hexo deploy
    node ./comment.js
    複製代碼

    也能夠經過在站點根目錄的package.json文件中,新建npm腳本,一個命令搞定清除緩存、生成靜態文件、提交git並生成issue的全部操做。

    "scripts": {
        "start": "hexo clean && hexo s",
        "deploy": "hexo clean && hexo generate && hexo deploy && node ./comment.js"
    }
    複製代碼

    完成文章編寫,或者其餘的更新操做後,直接執行deploy便可。

    npm run deploy
    複製代碼

後記和一些坑

計劃半個小時搞定的,最後花了三四個小時,程序猿評估工做量的水平依然很穩定^_^。

在使用nodejs完成腳本的過程當中,由於找不到在頁面點擊直接登陸github完成的初始化規則,踩了很多坑。

  1. 初版完成的時候,測試發現相同的地址,仍是會生成issue,後來才發現github獲取issues的接口是分頁的,默認返回的30條。在官方文檔能夠找到分頁的設置方式,每頁的最大記錄1000條,因此代碼裏指定了1000。博客文章數超過1000貌似要寫好久好久,就沒有作進一步的處理
  2. 在_config.yml站點網址的時候,使用了http協議,而登錄自動生成規則使用的是https協議,致使過濾手動初始化的判斷一直有問題(一個s引起的血案)。經過去除連接裏的協議,而後比較進行解決,兼容了http和https;
  3. Gitalk在頁面登錄初始化的時候,默認生成的issue label是連接的path,最開始處理的是直接使用連接,與默認規則生成的在一塊兒很不統一,就所有處理爲path
  4. 代碼完成後,測試發現並非每次生成都會成功,也沒有錯誤,測試調試嘗試各類辦法,花了一個多小時,發現部署完成後,最少須要等待40秒,才能夠正確完成issue的初始化, 懷疑跟github的api有關係,沒有找到實錘,知道緣由或者有更好的解決方案能夠在下面留言給我,謝謝
  5. sitemap.xml沒有使用網站部署後的,由於想在部署後,直接執行腳本進行初始化,而deploy命令執行後,經過網絡獲取sitemap.xml不是最新的,具體更新時間沒有規律,全部選擇了讀取本地生成在public下的sitemap.xml獲取最新的連接,確保初始化順利完成。

參考

Gitment/Gitalk自動初始化

自動初始化 Gitalk 和 Gitment 評論

相關文章
相關標籤/搜索