在 Github Profile Readme 添加自动更新的最新文章列表

最近更新了 Github Profile Readme,添加了自动更新的最新文章列表,效果如下:

实现原理

  • 下载 hexo-info-api 插件,生成 Restful 风格的 API

  • 使用 Github Action 定时获取 API 数据,更新 Github Profile Readme

下载 hexo-info-api 插件

1
2
3
4
5
# npm
npm install hexo-info-api --save

# yarn
yarn add hexo-info-api

配置 hexo-info-api 插件请参考 开箱即用,支持跨域的 hexo 博客 api

此处使用的接口是 getLatest5Posts,返回最新的 5 篇文章,所以需要在配置文件中开启该接口。

编写 Github Action

在项目根目录下创建 .github/workflows 文件夹,新建 update-readme.yml 文件,内容如下:

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
name: Build README

on:
push:
workflow_dispatch:
schedule:
- cron: '0 */3 * * *'

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.10"
- uses: actions/cache@v2
name: Configure pip caching
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install Python dependencies
run: |
python -m pip install -r requirements.txt
- name: Update README
run: |-
python build_readme.py
cat README.md
- name: Commit and push if changed
run: |-
git diff
git config --global user.email "actions@users.noreply.github.com"
git config --global user.name "README-bot"
git add -A
git commit -m "Updated content" || exit 0
git push

其中 build_readme.py 文件内容如下:

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
import httpx
import re
import pathlib

root = pathlib.Path(__file__).parent.resolve()

API_PATH = "" # Your Blog Link /api/getLatest5Posts here.

def get_latest_posts() -> list:
r = httpx.get(API_PATH)
lines = []
for i in r.json()['data']:
lines.append(f"- [{i['title']}]({i['_link']}) - {i['date'].split('T')[0]}")
if i['description'] == "文章描述":
continue
i["description"] = i["description"].replace("<br/>", " ").replace("<br>", " ").replace("<br />", " ")
if len(i['description']) > 50:
i['description'] = i['description'][:50] + "..."
lines.append(f" *{i['description']}*")
return lines

def replace_chunk(content, marker, chunk, inline=False):
r = re.compile(
r"<!\-\- {} starts \-\->.*<!\-\- {} ends \-\->".format(marker, marker),
re.DOTALL,
)
if not inline:
chunk = "\n{}\n".format(chunk)
chunk = "<!-- {} starts -->{}<!-- {} ends -->".format(marker, chunk, marker)
return r.sub(chunk, content)

if __name__ == "__main__":
readme = root / "README.md"
readme_contents = readme.open(encoding='utf-8').read()
latest_posts = "\n\n".join(get_latest_posts())

rewritten = replace_chunk(readme_contents, "latest_posts", latest_posts)
readme.open("w", encoding='utf-8').write(rewritten)

其中 API_PATH 为你的博客链接加上 /api/getLatest5Posts,例如我的博客链接为 https://blog.im0o.top,所以 API_PATHhttps://blog.im0o.top/api/getLatest5Posts

requirements.txt 文件内容如下:

1
httpx==0.23.3

在 Readme 中添加标签

在 Readme 中添加标签 <!-- latest_posts starts --><!-- latest_posts ends -->,用于标记需要替换的内容。

1
2
3
<!-- latest_posts starts -->
这里的内容会被替换为最新文章列表
<!-- latest_posts ends -->

提交代码

每次 push 代码后,Github Action 会自动运行,更新 Readme。

每 3 小时自动运行一次,如果想要更改时间,可以修改 update-readme.yml 文件中的 cron 字段。

参考