2022年8月22日星期一

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
{% 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
{% 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/', '/');

结语

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

https://www.iots.vip/post/hexo-artalk-comment.html

2022年8月20日星期六

hugo github action|vecel 部署后文章更新时间异常修复

hugo 博客搭建好后,陆陆续续发现一些问题。大都成功进行了处理。

其中一个最头大的问题就是:文章更新时间异常。

文章更新时间异常
文章更新时间,本地和远程部署的不同,远程通过 github action|vecel 部署,远程部署后的时间不对,会把所有文章时间都更为最新。

每次更新文章后,本地显示所有文章更新时间正常,没有修改的还是保留旧的更新日期,而通过 github action|vecel 自动部署后,所有文章更新时间都会改为最新此次更新时间,那些此次没有做修改的文章也一并全部更新。

注意,不是发表时间,发表时间没有问题。

https://s2.loli.net/2022/08/16/Mt2EKIVY5ai8zmv.png
本地端
https://s2.loli.net/2022/08/16/jgeDwLyHtzUpFY4.png
远程部署后

这个 bug,花费了我很多时间精力才找到原因,终于解决了这个问题。

解决这个问题,我们先说 hugo 博客的几个时间字段说起。

hugo 全局配置文件为 config.toml/yaml/json

在 hugo 中日期(时间)是非常重要的字段,hugo 的官方配置文档 configuration(https://gohugo.io/getting-started/configuration/#configure-dates) 提供一个配置日期的 section [frontmatter]

1
2
3
4
5
6
7
[frontmatter]

  # 左边意为,变量 .Date 将会被赋值为右边数组中最先找到的的日期值
  date = ['date', 'publishDate', 'lastmod'] 
  expiryDate = ['expiryDate']
  lastmod = [':git', 'lastmod', 'date', 'publishDate']
  publishDate = ['publishDate', 'date']
  • publishDate: 变量,发表日期
  • expiryDate:变量,有效期
  • lastmod:变量,最后修改日期
  • :git:git 文件提交修改时间

这是官方列举的字段和基本配置,不过说明不是很详细。

这里说明一下,= 左边的是变量,右边中括号的是变量值,需要在对应模板里添加后才生效。

这里我们只探讨最后更新时间 lastmod

一般主题里的配置方式是这样:

1
2
[frontmatter]
  lastmod = [":git", ":fileModTime", "lastmod", ":defalut"]
  • :git:git 文件提交修改时间
  • :fileModTime:文件修改时间
  • lastmod:文章里 lastmod 字段
  • :defalut:默认时间

这里 lastmod 变量获取,以 git 文件提交修改时间,文件修改时间这样排,文章里 "lastmod“字段可不加,这样是没问题的。

我的博客就是以此配置为准,本地运行时,更新时间显示正常


  1. 如果要加”lastmod“字段,在创建文章模板里添加以下一行。添加”lastmod",有个好处就是可自由修改这个字段的时间。

hugo 默认位置为 archetypes/default.md 或者主题下目录下 xx主题/archetypes/posts.md,主题目录下如果有增加模板,创建时会以主题目录下的模板来创建。

1
lastmod: {{ .Date }}
  1. 然后再去 config.toml/yaml/json

调整这里顺序即可:

1
2
[frontmatter]
  lastmod = [":git", "lastmod", ":fileModTime", ":defalut"]

好了,按以上配置,本地运行时,更新时间显示正常,这没有任何问题。

问题来了,通过 GitHub action 部署后(我的 verccel 从 GitHub 直接同步过去),就出现问题了,每次一提交更新,会把所有文章时间都更为最新。

本地端没问题,说明问题就出在 GitHub action 部署过程了。

补充提示一下,有一个坑 : GitHub action 的 Schedule 运行不准时

GitHub action 上的默认配置时间有个坑,设定的 schedule 是 UCT 时间的 08:00,比北京时间快 8 个小时。因此运行环境要改为北京时间。

解决方法:

.github/workflows/xx.yml

yml 文件中添加 2 行设置当前环境时区

1
2
3
4
5
6
name: Hugo build and deploy
on:
	push:

env:
	TZ: Asia/Shanghai # 设置当前环境时区

config.toml/yaml/json

1
2
#获取git信息
enableGitInfo = true  #设为true

建构前新增以下配置,主要是 quotePath,默认情况下,文件名包含中文时,git 会使用引号吧文件名括起来,这会导致 action 中无法读取:GitInfo 变量,所以要设置 Disable quotePath[^1]

1
2
3
4
5
6
- name: Git Configuration
        run: |
          git config --global core.quotePath false
          git config --global core.autocrlf false
          git config --global core.safecrlf true
          git config --global core.ignorecase false

使用 checkout 的话 fetch-depth 需要设为 0,depth 默认是为 1,默认只拉取分支最近一次 commit,可能会导致一些文章的 GitInfo 变量无法获取,设为 0 代表拉去所有分支所有提交。

1
2
	uses: actions/checkout@v2
		  fetch-depth: 0   #设为0

以下是我最终的 yml 配置文件

参考:

# Github Action 自动修改文章的更新日期

# [BUG] 目录所有文章 - 最近更新,本地与远程打包不同,数据不对