hexo使用Artalk评论系统

  前些日子逛 GitHub 时发现一个比较满足强迫症要求的评论系统 Artalk,功能完善且带有支持自托管的后台,恰逢 LeanCloud 政策变更, 忍受了 LeanCloud 好几年的资源与其他限制, 终于这次,我准备休掉它换 Artalk 了, 毕竟自建博客本就是为了不受到各种平台的限制。
  从关于页面可以看出, Alliot’s blog 已经有很长很长一段时间没有折腾过博客了, 本站所用的 NexT 主题也是多年以前自己魔改过很多的 5.1.0 版本,早已偏离了上游仓库十万百千里, 同时因为魔改了挺多,又懒得折腾升级新的版本, 因此无法直接使用 Artalk 文档中提到的插件方式安装。这里只能直接进行修改,在这过程中踩了一些坑, 这里稍微记录一遇到同样问题的朋友参考(或许没我这么懒而强迫症的)。

后端配置

  后端安装跟着官方文档 docker-compose 一把梭基本是没有什么部署上的问题的,只是在配置上需要注意一些地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 可信域名, 必须匹配,否则会报CSRF
trusted_domains:
- "https://artalk.iots.vip" # artalk 后端地址
- "https://www.iots.vip" # 博客地址
- "http://www.iots.vip"
- "http://localhost:4000" # 供本地调试地址
- "http://127.0.0.1:4000"


# 默认站点名
site_default: "blog"

# 管理员账户
admin_users:
- name: "xxx"
email: "xxx@xxx.com"

# 密码支持 bcrypt 或 md5 加密
# 如admin加密后的32位md5为: 21232f297a57a5a743894a0e4a801fc3,则如下字段因添加(md5)前缀:
password: "(md5)21232f297a57a5a743894a0e4a801fc"

  如果需要 Nginx 反向代理, 这里提供一份 Nginx 配置参考:

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
server {
listen 443 ssl http2;
server_name artalk.xxx.com;
access_log access_artalk.log;

#新增ssl配置---开始:
ssl_certificate xxx.crt; #证书公钥文件路径
ssl_certificate_key xxx.key; #证书私钥文件路径
ssl_session_timeout 5m; #5分钟session会话保持
ssl_session_cache shared:MozSSL:10m;
ssl_dhparam cert_file/dhparam;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_stapling on;
ssl_stapling_verify on;
#新增ssl配置---结束:

proxy_max_temp_file_size 0;
client_max_body_size 128M;


location / {
proxy_pass http://localhost:23366;

# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}

location =/robots.txt {
default_type text/html;
add_header Content-Type "text/plain; charset=UTF-8";
return 200 "User-Agent: *\nDisallow: /*";
}
}

# http 301 -> https
server {
listen 80;
server_name artalk.xxx.com;
return 301 https://artalk.xxx.com$request_uri;
}

前端配置

  这里只是提供适用于适用于 Alliot’s blog 当前版本 NexT 主题的配置, 其他主题未经官方适配的主题或许可以参考一下(我前端超烂…见笑了):

  首先是资源引用,以及实例化 artalk。 themes/next/layout/_scripts/third-party/comments.swig 实例化的时候需要注意,如果你有评论是从 valine 导入的话, page_key 这里需要改一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% if theme.artalk.enable and theme.artalk.server %}

<link href="https://unpkg.com/artalk@2.3.4/dist/Artalk.css" rel="stylesheet">
<script src="https://unpkg.com/artalk@2.3.4/dist/Artalk.js"></script>

<script>
// 获取相对路径, 如果直接用官方文档说的不指定 pageKey,则会出现 about 等页面评论无法正常加载的情况
// 因为page_key的缺省值location.pathname 会在 /about/ 后添加 index.html 后缀
// 而hexo的about等页面实际上的 URL 是不包含这个后缀的,所以会导致 key 无法对应上,评论导入后为空。
const url = '/' + "{{ page.permalink }}".split('/').slice(3).join('/');

var artalk = new Artalk({
el: '#artalkComments',
server: '{{ theme.artalk.server }}',
pageKey: url,
site: '{{ theme.artalk.site }}'
})

</script>

{% endif %}

  然后我们在评论位置添加这个元素, themes/next/layout/_partials/comments.swig:

1
2
3
4
{% elseif theme.artalk.enable and theme.artalk.server %}
<div id="artalkComments"></div>
{% include '../_scripts/third-party/comments.swig' %}

  再然后,为了添加首页文章评论数的效果,我采用了比较笨的一个方法去请求后端获取评论数量(粗略的看了一下文档好像并没有提供,因此构造请求来拿一下…), themes/next/layout/_macro/post.swig header 标签内添加:

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
{% if theme.artalk.enable and theme.artalk.server %}
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="{{ url_for(post.path) }}#artalkComments" itemprop="discussionUrl">
<span id="{{ post.path }}" class="post-comments-count" data-xid="{{ url_for(post.path) }}" itemprop="commentCount">loading..</span>
</a>
</span>
<script>
var formdata = new FormData();
formdata.append("site_name", "{{ theme.artalk.site }}");
formdata.append("page_key", "{{ url_for(post.path) }}");
formdata.append("limit", "1");

var requestOptions = {
method: 'POST',
body: formdata,
};
//console.log("{{ url_for(post.path) }}")

fetch("{{ theme.artalk.server }}/api/get", requestOptions)
.then(response => response.text())
.then(result => {
const count = JSON.parse(result).data.total
document.getElementById('{{ post.path }}').innerText = count
})
.catch(error => console.log('error', error));
</script>
{% endif %}

最后,主题配置文件 themes/next/_config.yml 添加:

1
2
3
4
artalk:
enable: true
site: 'blog'
server: 'https://artalk.xxx.com' # 记住不要加 / 结束

导入valine评论到Artalk

  跟随 Artalk 官方文档从 LeanCloud 导出 Comment Class 后,邮件收到的是 jsonl 格式,我们需要将其转为 json 格式:

1
2
# 首先打开 jsonl 文件删除首行的注释后,执行如下shell命令,注意valine.jsonl替换为实际的文件名 
sed '1s/^/[/; $!s/$/,/; $s/$/]/' valine.jsonl > artalk.json

这样再通过数据行囊 将其格式转换,并导入到 Artalk。
  导入的时候,需要提供 “目标站点名”, “目标站点 URL”,我这里目标站点为 “blog”, URL 为 “https://www.iots.vip", 导入后会发现一个问题,由于我们前面前端使用的 page_key 为相对路径, 但是 Artalk 的导入功能在写入数据的时候又默认会拼接 “目标站点 URL” 进 page_key 字段,这样就会导致旧的评论无法在文章页面中展示,我们需要手动将数据库中的 comments 表中的 page_key 改成相对路径。这样导入的评论就能正常展示了(感觉应该算是一个 BUG,已经跟作者提了)。
  连接数据库执行如下 SQL(如果你用的是 sqlite,那么直接用 navicat 打开它就行啦):

1
update `comments` set page_key=REPLACE(page_key, 'https://www.iots.vip/', '/');

结语

  工作后已经很少有心情去折腾博客了,比较双手抱着砖头,失去了太多的热情。这次改评论系统过程中的处理的方法又丑又笨,但就如罗老师说的————又不是不能用(逃