惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
有赞技术团队
有赞技术团队
www.infosecurity-magazine.com
www.infosecurity-magazine.com
大猫的无限游戏
大猫的无限游戏
爱范儿
爱范儿
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threatpost
V
Visual Studio Blog
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - Franky
人人都是产品经理
人人都是产品经理
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Cloudflare Blog
N
News and Events Feed by Topic
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
AWS News Blog
AWS News Blog
S
SegmentFault 最新的问题
T
Tailwind CSS Blog
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Spread Privacy
Spread Privacy
J
Java Code Geeks
博客园 - 聂微东
T
Tor Project blog
宝玉的分享
宝玉的分享
博客园 - 叶小钗
Webroot Blog
Webroot Blog
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Heimdal Security Blog
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
MongoDB | Blog
MongoDB | Blog
I
InfoQ
Security Latest
Security Latest
Martin Fowler
Martin Fowler
Hacker News: Ask HN
Hacker News: Ask HN
P
Privacy International News Feed
C
CERT Recently Published Vulnerability Notes
Latest news
Latest news
雷峰网
雷峰网
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cisco Blogs
H
Help Net Security
L
LINUX DO - 最新话题
L
LINUX DO - 热门话题

二丫讲梵

学习周刊-总第258期-2026年第15周 学习周刊-总第257期-2026年第14周 学习周刊-总第256期-2026年第13周 学习周刊-总第255期-2026年第12周 学习周刊-总第254期-2026年第11周 学习周刊-总第253期-2026年第10周 临时插播一条羊毛,免费领取450元大模型API代金券 学习周刊-总第252期-2026年第09周 学习周刊-总第251期-2026年第08周 学习周刊-总第250期-2026年第07周 学习周刊-总第249期-2026年第06周 诚邀评论,聊聊你所知欲知的我 学习周刊-总第248期-2026年第05周 我的QQ动态之2015年 我的QQ动态之2014年 我的QQ动态之2013年 我的QQ动态之2012年 我的QQ动态-2010-2011年 我的QQ动态-创栏小叙 学习周刊-总第247期-2026年第04周 Nexus社区版权益阉割--一文告诉你有哪些版本可以选择 学习周刊-总第246期-2026年第03周 学习周刊-总第245期-2026年第02周 学习周刊-总第244期-2026年第01周 学习周刊-总第243期-2025年第52周 学习周刊-总第242期-2025年第51周 开源项目ZenOps:带你领略禅意运维 学习周刊-总第241期-2025年第50周 用京东金融,享负债人生 学习周刊-总第240期-2025年第49周 学习周刊-总第239期-2025年第48周 整理我在静态服务透明代理上的极致求索之路,最后一个你绝想不到 学习周刊-总第238期-2025年第47周 我们输了,但收获颇多 太多了,太多了 学习周刊-总第237期-2025年第46周 学习周刊-总第236期-2025年第45周 学习周刊-总第235期-2025年第44周 二五年国庆二三事 学习周刊-总第234期-2025年第43周 学习周刊-总第233期-2025年第42周 学习周刊-总第232期-2025年第41周 学习周刊-总第231期-2025年第40周 学习周刊-总第230期-2025年第39周 西湖毅行 2025年开源世界逸闻三则 学习周刊-总第229期-2025年第38周 手抄《与妻书》 CNB开发与构建基于docker-cache缓存复用的配置实践心得 学习周刊-总第228期-2025年第37周 父亲善行录 学习周刊-总第227期-2025年第36周 带你认识我之看看我的高中同学录(其二) 学习周刊-总第226期-2025年第35周 带你认识我之看看我的高中同学录(其一) 认识神级MCP工具系列--用anyquery和数据库交互 学习周刊-总第225期-2025年第34周 学习周刊-总第224期-2025年第33周 学习周刊-总第223期-2025年第32周 学习周刊-总第222期-2025年第31周 学习周刊-总第221期-2025年第30周 CNB云原生开发环境届的瑞士军刀,详解qifei项目 vuepress-vdoing主题配置自建不蒜子统计 学习周刊-总第220期-2025年第29周 写在博客发表文章1000篇的节点 从claude cli的体验聊聊最大的敌人是我们自己的成见 学习周刊-总第219期-2025年第28周 学习周刊-总第218期-2025年第27周 学习周刊-总第217期-2025年第26周 理论正确,事实错误 学习周刊-总第216期-2025年第25周 学习周刊-总第215期-2025年第24周 学习周刊-总第214期-2025年第23周 学习周刊-总第213期-2025年第22周 学习周刊-总第212期-2025年第21周 从赵心童世锦赛夺冠聊聊我的斯诺克情缘 学习周刊-总第211期-2025年第20周 记录二五年五一之短暂回归家庭 学习周刊-总第210期-2025年第19周 学习周刊-总第209期-2025年第18周 学习周刊-总第208期-2025年第17周 Go开发实践之Gin框架将前端的dist目录embed到二进制 学习周刊-总第207期-2025年第16周 近期关于cobra库的一些实践心得总结 学习周刊-总第206期-2025年第15周 我的嗜好--嗑瓜子 记大宝参加幼儿园组织的清明烈士陵园扫墓活动 学习周刊-总第205期-2025年第14周 学习周刊-总第204期-2025年第13周 前端开发小笔记--在数组中给字段添加值与删除字段的操作 学习周刊-总第203期-2025年第12周 人生实苦,何以自渡 学习周刊-总第202期-2025年第11周 近期发现的一些优秀的工具提名(一) 学习周刊-总第201期-2025年第10周 学习周刊-总第200期-2025年第09周 记一次女友喝醉使我忍术破功 爱情风波--一次分手又复合的经历 学习周刊-总第199期-2025年第08周 整理我的信息源
Vuepress配置评论插件为Artalk
二丫讲梵 · 2022-11-28 · via 二丫讲梵

前注:本文同时收录在 artalk 官方文档的推荐当中:https://artalk.js.org/guide/extras.html#artalk-v2 (opens new window)

# 前言

把博客平台迁移到 vuepress 以来,之前折腾过好几次评论系统,大多是依赖第三方作为后端存储,导致要么是加载速度不理想,要么是配置费劲儿,于是,我终于下决心,自建评论系统。

目前国内比较知名的有两个前端评论系统:

一开始我是走 twikoo 的配置流程进行配置,配置到最后,发现这个系统原本依赖云开发系统,对于自建非常不友好,于是立马放弃,恰逢 vdoing 群里有群友说自己折腾了 artalk 系统的插件集成,经过一番了解,准备转战 Artalk。

# 安装

安装 artalk 也非常简单,该系统提供了 go 语言版本的,作者也继承好了镜像,提供了容器部署的方案,于是,我使用 docker-compose 进行启动,配置信息如下:

version: "3.5"
services:
  artalk:
    container_name: artalk-go
    image: artalk/artalk-go
    restart: always
    ports:
      - 8070:23366
    volumes:
      - ./data:/data

1
2
3
4
5
6
7
8
9
10

执行如下命令启动服务:

服务启动之后,可以先给 artalk 创建一个管理员账号:

docker exec -it artalk-go artalk admin

1

创建完管理员账号,等会儿配置了访问域名,就能登陆了。

启动完成之后,会在服务器监听 8070 端口,此时给这个服务配置一个域名,配置信息如下:

$cat /etc/nginx/vhost/comment.eryajf.net.conf

server {
    listen 80;
    listen 443 ssl;
    server_name comment.eryajf.net;

    ssl_certificate /etc/nginx/ssl/comment.eryajf.net.pem;
    ssl_certificate_key /etc/nginx/ssl/comment.eryajf.net.key;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_set_header Host $host;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_pass http://127.0.0.1:8070;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

然后访问 comment.eryajf.net 能够进入到管理后台,使用刚刚创建的管理员账号信息进行登陆。

# 配置服务端

artalk 的配置文件在 data 目录下,你可以通过修改配置文件根据自己的需求进行调整,也可以在管理后台的页面上进行配置,尽管两种方式都不够美好,不过花点时间了解下这些配置,就能够很快完成自己的配置了。

下边是我使用的配置信息,其中部分信息做了脱敏:

# 服务器地址
host: "0.0.0.0"
# 服务器端口
port: 23366
# 加密密钥
app_key: "eryajf"
# 调试模式
debug: false
# 时间区域
timezone: "Asia/Shanghai"
# 默认站点名
site_default: "二丫讲梵"
# 登陆有效时长 (单位:秒)
login_timeout: 259200
# 数据库
db:
  # 数据库类型 ["sqlite", "mysql", "pgsql", "mssql"]
  type: "sqlite"
  # 数据库文件 (仅 SQLite 数据库需填写)
  file: "./data/artalk-go.db"
  # 数据库名称
  name: "artalk"
  # 数据库地址
  host: "localhost"
  # 数据库端口
  port: 3306
  # 数据库账户
  user: "root"
  # 数据库密码
  password: ""
  # 编码格式
  charset: "utf8mb4"
  # 表前缀 (例如:"atk_")
  table_prefix: ""
# 日志
log:
  # 启用日志
  enabled: true
  # 日志文件路径
  filename: "./data/artalk-go.log"
# 缓存
cache:
  # 缓存类型 ["redis", "memcache", "builtin"]
  type: "builtin"
  # 缓存过期时间 (单位:分钟)
  expires: 30
  # 缓存启动预热 (程序启动时预热缓存)
  warm_up: false
  # 缓存服务器地址 (例如:"localhost:6379")
  server: ""
  # Redis 配置
  redis:
    # 连接方式 ["tcp", "unix"]
    network: "tcp"
    # 用户名
    username: ""
    # 密码
    password: ""
    # 数据库编号 (例如使用零号数据库填写 0)
    db: 0
# 可信域名
trusted_domains:
  - https://wiki.eryajf.net
  - http://localhost:8080
  - https://eryajf.github.io
  - https://www.eryajf.net
  - https://eryajf.net
# SSL
ssl:
  # 启用 SSL
  enabled: false
  # 证书文件路径
  cert_path: ""
  # 密钥文件路径
  key_path: ""
# 管理员账户
admin_users:
  - name: "eryajf"
    email: "xxxxxxxxxx"
    password: "xxxxxxxxxx" # 支持 bcrypt 或 md5 加密,如:"(md5)50c21190c6e4e5418c6a90d2b5031119"
    badge_name: "管理员"
    badge_color: "#FF6C00"
# 评论审核
moderator:
  # 默认待审 (发表新评论需要后台人工审核后才能显示)
  pending_default: 1
  # API 请求错误时拦截 (关闭此项当请求错误时让评论放行)
  api_fail_block: 1
  # Akismet Key
  # (Akismet 反垃圾服务,https://akismet.com)
  akismet_key: ""
  # 腾讯云文本内容安全
  # (https://cloud.tencent.com/document/product/1124/64508)
  tencent:
    enabled: false
    secret_id: ""
    secret_key: ""
    region: "ap-guangzhou"
  # 阿里云内容安全
  # (https://help.aliyun.com/document_detail/28417.html)
  aliyun:
    enabled: false
    access_key_id: ""
    access_key_secret: ""
    region: "cn-shanghai"
  # 关键词过滤 (本地离线词库)
  keywords:
    enabled: false
    # 匹配成功设为待审状态
    pending: false
    # 词库文件 (支持多个词库文件)
    files:
      - "./data/词库_1.txt"
    # 词库文件内容分割符 (例如填写 "\n" 文件中一行一个关键词)
    file_sep: "\n"
    # 替换字符
    replac_to: "x"
# 验证码
captcha:
  # 启用验证码
  enabled: true
  # 总是需要验证码
  always: false
  # 激活验证码所需操作次数
  action_limit: 3
  # 重置操作计数器超时 (单位:s, 设为 -1 不重置)
  action_reset: 60
  # Geetest 极验 (https://www.geetest.com)
  geetest:
    enabled: false
    captcha_id: ""
    captcha_key: ""
# 邮件通知
email:
  # 启用邮件通知
  enabled: 1
  # 发送方式 ["smtp", "ali_dm", "sendmail"]
  send_type: "smtp"
  # 发信人昵称
  send_name: "{{reply_nick}}"
  # 发信人地址
  send_addr: "eryajf@163.com"
  # 邮件标题
  mail_subject: "[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复"
  # 邮件模板文件 (填入文件路径使用自定义模板)
  mail_tpl: "default"
  # SMTP 发送 (启用请将发送方式设为 "smtp")
  smtp:
    # 发件地址
    host: "smtp.163.com"
    # 发件端口
    port: 465
    # 用户名
    username: "eryajf@163.com"
    # 密码
    password: "xxxxxxxxxxx"
  # 阿里云邮件推送
  # (启用请将发送方式设为 "ali_dm";参考:https://help.aliyun.com/document_detail/29444.html)
  ali_dm:
    access_key_id: ""
    access_key_secret: ""
    account_name: "noreply@example.com"
# 图片上传
img_upload:
  # 启用图片上传
  enabled: 0
  # 图片存放路径
  path: "./data/artalk-img/"
  # 图片大小限制 (单位:MB)
  max_size: 5
  # 图片链接基础路径 (默认为 "/static/images/")
  public_path: null
  # Upgit 配置
  # (使用 Upgit 将图片上传到 GitHub 或图床:https://github.com/pluveto/upgit)
  upgit:
    # 启用 Upgit
    enabled: false
    # 命令行参数
    exec: "./upgit -c <upgit配置文件路径> -t /artalk-img"
    # 上传后删除本地的图片
    del_local: true
# 多元推送
admin_notify:
  # 通知模版 (填入文件路径使用自定义模板)
  notify_tpl: "default"
  # 嘈杂模式
  noise_mode: false
  # 邮件通知管理员
  email:
    # 开启 (当使用其他推送方式时,可以关闭管理员邮件通知)
    enabled: 0
    # 邮件标题 (发送给管理员的邮件标题)
    mail_subject: "[{{site_name}}] 您的文章「{{page_title}}」有新回复"
  # Telegram
  telegram:
    enabled: false
    api_token: ""
    receivers:
      - 7777777
  # Bark
  bark:
    enabled: false
    server: "http://day.app/xxxxxxx/"
  # 飞书
  lark:
    enabled: false
    webhook_url: ""
  # WebHook
  webhook:
    enabled: false
    url: ""
  # 钉钉
  ding_talk:
    enabled: 1
    token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    secret: "wiki"
  # Slack
  slack:
    enabled: false
    oauth_token: ""
    receivers:
      - "CHANNEL_ID"
  # LINE
  line:
    enabled: false
    channel_secret: ""
    channel_access_token: ""
    receivers:
      - "USER_ID_1"
      - "GROUP_ID_1"
# 前端配置
frontend:
  # 评论框占位文字
  placeholder: "请正确填写邮箱以便接收回复通知,如需添加图片,请通过第三方图床引用图片,评论支持Markdown语法"
  # 无评论显示文字
  noComment: "「此时无声胜有声」"
  # 发送按钮文字
  sendBtn: "提交"
  # 评论框旅行
  editorTravel: 1
  # 暗黑模式
  darkMode: false
  # 表情包
  emoticons: "https://cdn.jsdelivr.net/gh/eryajf/emotion_generate/dist/artalk.json"
  # 投票按钮
  vote: true
  # 反对按钮
  voteDown: false
  # 用户 UA 徽标
  uaBadge: true
  # 评论排序功能
  listSort: true
  # 页面 PV 绑定元素
  pvEl: "#ArtalkPV"
  # 评论数绑定元素
  countEl: "#ArtalkCount"
  # 编辑器实时预览功能
  preview: true
  # 平铺模式 ["auto", true, false]
  flatMode: "auto"
  # 最大嵌套层数
  nestMax: 10
  # 嵌套评论排序规则 ["DATE_ASC", "DATE_DESC", "VOTE_UP_DESC"]
  nestSort: DATE_ASC
  # 头像
  gravatar:
    # Gravatar 镜像地址
    mirror: "https://cravatar.cn/avatar/"
    # 默认头像
    default: "mp"
  # 评论分页
  pagination:
    # 每页评论数
    pageSize: 20
    # 加载更多模式 (关闭则使用分页条)
    readMore: true
    # 滚动加载
    autoLoad: true
  # 内容限高
  heightLimit:
    # 评论内容限高 (单位:px)
    content: 300
    # 子评论区域限高 (单位:px)
    children: 400
  # 请求超时 (单位:毫秒)
  reqTimeout: 15000
  # 版本检测
  versionCheck: true

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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288

因为官方文档写的很详细,这里就不多赘述了。

补充:配置文件中使用的表情包,来自于项目emotion_generate (opens new window),是我维护的一个拥有丰富表情包的集合,此集合永久有效(除非 github 或者 jsdelivr 崩了),你可以直接在自己的配置文件中使用。

# 配置页面端

页面端,通过如下插件来完成配置:

# 安装

npm install --save vuepress-plugin-vdoing-comment --registry=https://registry.npmmirror.com

1

# 配置

在自己的 vdoing 工程项目中,插件配置文件中 docs/.vuepress/config/plugins.js 添加如下配置:

module.exports = {
  plugins: [
    [
      "vuepress-plugin-vdoing-comment",
      {
        choosen: "artalk",
        options: {
          server: "https://comment.eryajf.net", // (必填)
          site: "二丫讲梵", // (必填)
          // disableEmotion: false, // 是否禁用表情(可选)
          // disablePicture: true, // 是否禁用图片(可选)
          // disablePreview: false // 是否禁用预览(可选)
        },
      },
    ],
  ],
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

目前这个插件中的禁用图片参数在我这里测试没有生效,如果你想禁用评论区上传图片,可以通过下边 css 中的方案对图片按钮进行隐藏。

然后在自定义 css 文件 docs/.vuepress/styles/palette.styl 最后添加如下内容进行优化:

// artalk 评论框 适配暗黑模式
.theme-mode-dark #vuepress-plugin-vdoing-comment {
  --at-color-bg: --bodyBg;
  color: #ffffff;
  --at-color-font: #ffffff;
  --at-color-bg-transl: --bodyBg;
  --at-color-bg-grey: #373a40;
}
.theme-mode-dark
  #vuepress-plugin-vdoing-comment
  .atk-editor-plug-emoticons
  > .atk-grp-switcher
  > span:hover,
.atk-editor-plug-emoticons > .atk-grp-switcher > span.active {
  background: var(--at-color-bg-grey);
}
.theme-mode-dark
  #vuepress-plugin-vdoing-comment
  .atk-editor-plug-emoticons
  > .atk-grp-switcher {
  background: var(--at-color-bg-grey);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

然后可以先在本地 yarn dev 启动调试一下看看效果,没问题之后,再发布到远端即可。

看下我这里配置好之后的效果:

# 迁移

将评论系统配置为 artalk 之后,加载速度方面完全没了问题,现在需要做的一件事儿就是将原来的评论做一个迁移。

artalk 官方文档中介绍的迁移很详细,也提供了迁移工具,但我在这个过程中也踩了一些坑,这里做一下过程记录。

我原来评论系统依托于 Vssue,数据存放在 GitHub Issue,想要拿到这些数据并不难,官方文档中给到的说明如下:

Artran 格式定义:每一条评论数据 (Object) 称为 Artran,多条评数据论组成一个 Artrans (Array 类型)

{
  "id": "123",
  "rid": "233",
  "content": "Hello Artalk",
  "ua": "ArtalkGo/6.6",
  "ip": "233.233.233.233",
  "created_at": "2021-10-28 20:50:15 +0800 +0800",
  "updated_at": "2021-10-28 20:50:15 +0800 +0800",
  "is_collapsed": "false",
  "is_pending": "false",
  "vote_up": "666",
  "vote_down": "0",
  "nick": "qwqcode",
  "email": "qwqcode@github.com",
  "link": "https://qwqaq.com",
  "password": "",
  "badge_name": "管理员",
  "badge_color": "#FF716D",
  "page_key": "https://artalk.js.org/guide/transfer.html",
  "page_title": "数据迁移",
  "page_admin_only": "false",
  "site_name": "Artalk",
  "site_urls": "http://localhost:3000/demo/,https://artalk.js.org"
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

简单来说,如上内容就是一条评论的详情,如果想要导入多条,就用一个数组包裹。

只是,这里有必要对其中几个字段做一个说明:

  • rid:表示这是哪条评论的回复,如果这是第一条评论,则 rid 为 0,如果是回复 ID 为 1 的评论,则 rid 为 1。
  • page_key:这的确是评论所属的标识页面,但可能是哪里的配置原因,我发现我这里获取到的 page_key 不带主域名,这也是我迁移过程中踩得一个坑。

我的建议是,评论系统配置好之后,最好先在自己的博客评论一条,然后把这条数据查出来,看看详情:

INSERT INTO "main"."comments" ("id", "created_at", "updated_at", "deleted_at", "content", "page_key", "site_name", "user_id", "ua", "ip", "rid", "is_collapsed", "is_pending", "is_pinned", "vote_up", "vote_down") VALUES (1, '2022-11-24 22:32:59.597873282+08:00', '2022-11-24 22:52:19.954473963+08:00', NULL, '今天,终于决定把评论系统也改为自建,兜兜转转,不如自建,无论图床还是评论系统。以后大家可以愉快地进行评论啦🎉', '/about/', '二丫讲梵', 2, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36', '182.119.128.2', 0, 0, 0, 0, 1, 0);

1

根据如上情况,我的脚本内容如下:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/google/go-github/v47/github"
	"golang.org/x/oauth2"
)

var (
	client      *github.Client
	GtihubToken string = "ghp_7xxxxxxxxxxxxxxxxxxxxxxxxx"
)

func init() {
	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: GtihubToken},
	)
	tc := oauth2.NewClient(ctx, ts)

	client = github.NewClient(tc)
}

type ArtalkComment struct {
	ID            string `json:"id"`
	Rid           string `json:"rid"`
	Content       string `json:"content"`
	Ua            string `json:"ua"`
	IP            string `json:"ip"`
	CreatedAt     string `json:"created_at"`
	UpdatedAt     string `json:"updated_at"`
	IsCollapsed   string `json:"is_collapsed"`
	IsPending     string `json:"is_pending"`
	VoteUp        string `json:"vote_up"`
	VoteDown      string `json:"vote_down"`
	Nick          string `json:"nick"`
	Email         string `json:"email"`
	Link          string `json:"link"`
	Password      string `json:"password"`
	BadgeName     string `json:"badge_name"`
	BadgeColor    string `json:"badge_color"`
	PageKey       string `json:"page_key"`
	PageTitle     string `json:"page_title"`
	PageAdminOnly string `json:"page_admin_only"`
	SiteName      string `json:"site_name"`
	SiteUrls      string `json:"site_urls"`
}

func main() {
	githubUser := "eryajf"
	githubRepo := "eryajf.github.io"

	issues, err := GetAllIssue(githubUser, githubRepo)
	if err != nil {
		fmt.Println(err)
	}
	var artalks []ArtalkComment
	for _, repo := range issues {
		if *repo.Comments > 0 {
			comments, err := GetAllComment(githubUser, githubRepo, repo.GetNumber())
			if err != nil {
				fmt.Printf("get all comments failed: %v\n", err)
			}
			for _, comment := range comments {

				user, err := GetUser(comment.User.GetLogin())
				if err != nil {
					fmt.Printf("get user failed: %v\n", err)
				}
				var email string
				if user.GetEmail() == "" {
					email = "empyt@github.com"
				} else {
					email = user.GetEmail()
				}

				artalks = append(artalks, ArtalkComment{
					ID:            fmt.Sprintf("%v", repo.GetNumber()),
					Rid:           "0",
					Content:       comment.GetBody(),
					Ua:            "",
					IP:            "",
					CreatedAt:     comment.GetCreatedAt().String(),
					UpdatedAt:     comment.GetUpdatedAt().String(),
					IsCollapsed:   "false",
					IsPending:     "false",
					VoteUp:        "0", // 赞成
					VoteDown:      "0",
					Nick:          comment.User.GetLogin(),   // 评论者的昵称
					Email:         email,                     // 评论者的邮箱
					Link:          comment.User.GetHTMLURL(), // 评论者的网站
					Password:      "",
					BadgeName:     "",
					BadgeColor:    "",
					PageKey:       strings.Split(repo.GetBody(), "https://wiki.eryajf.net")[1], // 页面的url,只取域名后的uri
					PageTitle:     "数据迁移",
					PageAdminOnly: "false",
					SiteName:      "二丫讲梵",
					SiteUrls:      "https://comment.eryajf.net",
				})
			}
		}
	}
	str, err := json.Marshal(artalks)
	if err != nil {
		fmt.Printf("marshal failed: %v\n", err)
	}
	fmt.Println(string(str))
}

// 获取用户信息
func GetUser(name string) (*github.User, error) {
	ctx := context.Background()
	user, _, err := client.Users.Get(ctx, name)
	if err != nil {
		fmt.Printf("get user info failed: %v\n", err)
	}
	return user, nil
}

// 获取仓库所有的issue
func GetAllIssue(owner, repoName string) ([]*github.Issue, error) {
	ctx := context.Background()
	opt := &github.IssueListByRepoOptions{
		State:       "open",
		Labels:      []string{"Vssue"},
		ListOptions: github.ListOptions{PerPage: 10},
	}
	// get all pages of results
	var allIssues []*github.Issue
	for {
		repos, resp, err := client.Issues.ListByRepo(ctx, owner, repoName, opt)
		if err != nil {
			return nil, err
		}
		allIssues = append(allIssues, repos...)
		if resp.NextPage == 0 {
			break
		}
		opt.Page = resp.NextPage
	}
	return allIssues, nil
}

// 获取对应issue的所有对话
func GetAllComment(owner, repoName string, number int) ([]*github.IssueComment, error) {
	ctx := context.Background()
	opt := &github.IssueListCommentsOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}
	// get all pages of results
	var allRepos []*github.IssueComment
	for {
		repos, resp, err := client.Issues.ListComments(ctx, owner, repoName, number, opt)
		if err != nil {
			return nil, err
		}
		allRepos = append(allRepos, repos...)
		if resp.NextPage == 0 {
			break
		}
		opt.Page = resp.NextPage
	}
	return allRepos, nil
}

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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

如果你也想通过这个脚本来生成你的评论数据,可以适当调整其中的信息,如果有不了解的,可以在评论区与我交流。

当我运行完脚本之后,就获得了对应评论数据的一个大数组,将这个数组写入到一个名为 art.json.artrans(注意:后缀必须为这个,这是官方识别的格式。)的文件中,然后来到管理后台,通过页面进行导入,在控制中心 ==> 设置 ==> 迁移中:

最后点击导入,可以看到成功导入的数据条数。

当数据导入成功,就可以到文章页面上看对应的评论信息了,此时数据还有一些小问题,需要进行修复,因为我这边数据量比较小,因此选择了手动修复。

需要修复的是 rid 这个字段,需要根据原来各条评论的对应关系来维护 rid 这个字段。

我的操作步骤是:先把数据文件下载到本地,然后使用 Navicat 打开,对数据进行修复,修复完毕之后,再把数据上传到服务器的数据目录下,然后重启 artalk-go 服务端即可。

比如我的关于页面的评论信息如下: https://github.com/eryajf/eryajf.github.io/issues/152 (opens new window) ,关于页面的 URI 为 /about/,执行如下查询:

$ SELECT id,content,rid FROM comments  WHERE "page_key"='/about/' ORDER BY created_at ASC;

1

然后参照 GitHub 中 issue 的内容关系,来手动修复 rid 字段的值。

经过一番艰辛的探索,总算是把原来的评论数据迁移到新的系统中了。