Loading

Firefly 友链自助申请自动化

5546 字
28 分钟
Firefly 友链自助申请自动化

Firefly 友链自助申请自动化#

这篇文章把我这次在 Firefly 里落地的“友链自助申请”方案完整拆开讲一遍。

目标很简单:

  1. 访客不需要私聊站长,直接在 GitHub 仓库里点一个 Issue 模板。
  2. 填完网站名称、网站链接、友链页面 URL 等信息后,GitHub Actions 自动开始校验。
  3. 系统会自动检查对方站点是否真的加了本站友链。
  4. 校验通过后,自动把友链写入 src/config/friendsConfig.ts
  5. 自动格式化、自动提交、自动推送,并在 Issue 里回评结果。

如果你也想在自己的博客里做一套类似的“自助申请友链”系统,这篇文章可以直接照着抄。


一、最终效果是什么#

这套方案上线后,整个流程会变成这样:

  1. 用户打开 GitHub 仓库里的“申请友链” Issue 模板。
  2. 填写以下信息:
    • 网站名称
    • 网站链接
    • 友链页面 URL
    • 网站描述
    • 网站头像 URL
  3. 用户提交 Issue。
  4. GitHub Actions 监听到 issues.opened 事件后自动运行。
  5. 工作流先给 Issue 打上“验证中”标签。
  6. 脚本使用 Playwright 访问对方填写的友链页面。
  7. 校验两件事:
    • 这个页面能不能正常打开
    • 页面里有没有本站的回链
  8. 如果校验失败:
    • 在 Issue 里自动评论失败原因
    • 给 Issue 打上 needs-update
  9. 如果校验成功:
    • 自动更新 src/config/friendsConfig.ts
    • 自动运行 Biome 格式化
    • 自动提交到仓库
    • 自动推送到默认分支
    • 在 Issue 里评论“已添加成功”
    • 自动关闭 Issue

评论重新验证也支持:

  1. 如果申请者后来修好了友链页面,只需要回复这个 Issue。
  2. Workflow 会监听 issue_comment.created
  3. 但只有 Issue 作者本人 的评论才会触发重新验证,避免别人乱刷。

二、这套系统的核心原理#

这套自动化其实不是“一个脚本干完所有事”,而是四层拼起来的:

1. GitHub Issue 模板负责收集表单#

你不需要自己写前端表单,也不需要数据库。

GitHub 自带的 Issue Forms 就能帮你把申请信息收上来。
用户填完表单后,GitHub 会把内容渲染成一段结构化文本,放进 Issue body。

我们后面的脚本做的事情,本质上就是:

  • 读取 context.payload.issue.body
  • 从里面解析出“网站名称 / 网站链接 / 友链页面 URL / 描述 / 头像”

所以第一层原理很朴素:

GitHub Issue 不是单纯的“提问题”,它也可以被当成一个零后端表单系统。


2. GitHub Actions 负责事件驱动#

第二层是 GitHub Actions。

它的职责不是写业务逻辑,而是:

  • 监听事件
  • 准备运行环境
  • 安装依赖
  • 调用真正的处理脚本

这里我们监听两个事件:

on:
issues:
types: [opened, reopened]
issue_comment:
types: [created]

这意味着:

  • 新建 Issue 时自动跑一次
  • 重新打开 Issue 时自动跑一次
  • 在 Issue 下面评论时也会跑一次

但后面脚本里会再做一层筛选,只允许作者自己的评论触发重新验证。


3. actions/github-script 负责把 GitHub 上下文交给本地脚本#

很多人会把全部逻辑都塞进 YAML 里的 script: |,但这样很容易炸:

  • YAML 缩进难维护
  • JS 代码太长可读性差
  • 混入 # 注释时容易直接变成语法错误
  • 编码和引号很容易出坑

所以这次的做法是:

  1. Workflow 里只保留一个很短的入口。
  2. 真实逻辑放到独立文件 .github/scripts/process-friend-request.cjs

现在入口只有这一小段:

- name: Process friend request
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const path = require('node:path');
const handler = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/process-friend-request.cjs'));
await handler({ github, context, core });

这段代码只做一件事:

githubcontext 这些 GitHub Runtime 对象传给仓库里的本地脚本。

于是业务逻辑就从“YAML 内联脚本”变成了“普通 Node.js 文件”,维护体验会好很多。


4. Playwright 负责做浏览器级校验#

为什么不用 fetch 直接请求页面?

因为友链页面场景更适合浏览器级校验:

  • 有些站点会跳转
  • 有些内容是客户端渲染出来的
  • 有些友链列表在真实 DOM 渲染后才出现
  • 只看 HTML 源码不一定能确认页面最终长什么样

所以这里用了 Playwright:

const { chromium } = require("playwright");

校验逻辑分成两步:

  1. 用浏览器打开对方提供的友链页面
  2. 检查页面内容和页面上的所有链接里,是否出现本站域名或本站名称

也就是说它不是纯字符串比较,而是近似模拟了一个真实用户打开页面之后看到的结果。


三、当前实现依赖哪些文件#

如果你要在自己的项目里复刻这套系统,主要会改下面这些文件。

1. .github/ISSUE_TEMPLATE/friend-request.yml#

作用:定义“申请友链”表单。

这个文件负责告诉 GitHub:

  • 模板标题是什么
  • 默认标签是什么
  • 需要用户填写哪些字段

你至少要保留这些字段:

  • 网站名称
  • 网站链接
  • 友链页面 URL

描述和头像可以设为可选。


作用:定义自动化工作流。

它主要负责:

  • 监听 Issue / 评论事件
  • 安装 Node.js
  • 安装 pnpm
  • 安装项目依赖
  • 安装 Playwright Chromium
  • 调用处理脚本

这个文件是系统的“总开关”。


3. .github/scripts/process-friend-request.cjs#

作用:真正的核心业务逻辑。

它做了几乎所有关键工作:

  • 解析 Issue 内容
  • 校验 URL
  • 使用 Playwright 检查友链页
  • 解析现有 friendsConfig.ts
  • 生成新的友链对象
  • 写回配置文件
  • 运行 Biome 格式化
  • Git 提交与推送
  • 在 Issue 里评论成功/失败
  • 打标签和关闭 Issue

可以把它理解成这套系统的“应用层”。


4. src/config/friendsConfig.ts#

作用:真正保存友链数据。

这个仓库不是写入 JSON,而是直接更新 TypeScript 配置文件里的数组:

export const friendsConfig: FriendLink[] = [
{
title: "站点名",
imgurl: "头像地址",
desc: "描述",
siteurl: "https://example.com/",
tags: ["Blog"],
weight: 10,
enabled: true,
issue_id: 123,
},
];

所以自动化脚本必须知道这个文件的格式,并按它的结构生成内容。


5. .github/workflows/biome.yml#

作用:保证自动写入后的文件仍然符合代码格式规范。

这一步非常重要,因为如果脚本写入的内容格式不稳定,CI 会红,自动化虽然成功写入了数据,但 PR / 提交质量检查会挂掉。


四、完整执行链路#

这里按一次“用户申请友链”的真实时间顺序讲。

第 1 步:用户提交申请#

用户点击 GitHub Issue 模板,生成一条“友链申请” Issue。

Issue body 里会包含类似下面的结构:

### 网站名称
My Blog
### 网站链接
https://example.com
### 友链页面 URL
https://example.com/friends
### 网站描述
记录技术与生活
### 网站头像 URL
https://example.com/avatar.png

这一步不需要额外后端,GitHub 自己就帮你把数据存下来了。


第 2 步:Workflow 被触发#

.github/workflows/friend-link-checker.yml 被触发。

它会在 Ubuntu Runner 上做这些准备工作:

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: pnpm/action-setup@v4
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps chromium

这几步分别解决:

  • 拉代码
  • 提供 Node 环境
  • 提供 pnpm
  • 安装仓库依赖
  • 安装 Playwright 所需浏览器

第 3 步:脚本判断这是不是友链申请#

process-friend-request.cjs 里,脚本首先读取:

  • context.eventName
  • context.payload.action
  • context.payload.issue.body

然后判断:

const isFriendRequest = body.includes("### 网站名称") && body.includes("### 网站链接");

如果不是友链申请,直接跳过。

这样做的好处是:

  • 这个 workflow 可以挂在 issues 事件上
  • 但不会误处理其他普通 Issue

第 4 步:打“验证中”标签#

如果是新建或重新打开的 Issue,先打一个标签:

await github.rest.issues.addLabels({
owner,
repo,
issue_number: issueNumber,
labels: ["验证中"]
});

这一步主要是用户体验优化。

访客一看标签,就知道系统已经开始处理,不需要站长人工回复“我看到了”。


第 5 步:解析 Issue 表单#

解析逻辑在 parseIssueBody(body)

这个函数做了两件事:

  1. 按 Markdown 标题识别字段
  2. 容忍一些不同写法

它会兼容这些字段名称:

  • 网站名称 / 名称 / 站点名称
  • 网站链接 / 站点链接 / 链接 / 网址 / 地址
  • 友链页面 / 友链地址
  • 网站描述 / 描述 / 简介
  • 网站头像 / 头像 / 图标
  • 网站标签 / 标签 / 分类

这样做的意义是:

  • 模板稍微改字,不至于整套系统失效
  • 用户手动编辑 Issue 内容时,也更不容易把解析搞崩

解析结束后会得到一个统一结构:

{
site_name,
site_url,
friend_page_url,
site_desc,
site_avatar,
site_tag
}

第 6 步:先校验 URL 合法性#

在真正访问网站前,脚本先用 new URL() 规范化地址:

function normalizeUrl(value) {
try {
return new URL(value.trim()).toString();
} catch {
return "";
}
}

如果用户填了无效 URL,就直接回评,不继续往后跑。

这样能省掉很多无意义的浏览器启动和网络请求。


第 7 步:用 Playwright 校验友链页面#

validateFriendPage(pageUrl) 是整个流程最关键的函数之一。

它主要做四件事:

1. 启动无头 Chromium#

const browser = await chromium.launch({
headless: true,
args: ["--no-sandbox"]
});

2. 打开用户提供的友链页#

response = await page.goto(pageUrl, {
waitUntil: "domcontentloaded",
timeout: 12000
});

3. 做失败重试#

脚本不是只试一次,而是会重试 3 次,中间等待 2 秒。

这样能降低这类波动造成的误判:

  • 短时网络抖动
  • 对方站点首包慢
  • CDN 临时超时

4. 检查是否存在本站回链#

脚本会同时抓:

  • 页面 HTML 内容
  • 页面所有 a[href] 链接

然后统一转成小写,检查其中是否包含:

  • 本站域名
  • 本站名称

当前配置里是:

const SITE_INFO = {
name: "fqzlr",
url: "https://fqzlr.com/",
avatar: "...",
desc: "..."
};

于是脚本会重点寻找:

  • fqzlr.com
  • fqzlr

如果没找到,就说明“对方站点没有把你的友链真正挂上去”,申请不会通过。


第 8 步:失败时怎么处理#

如果友链页打不开,或者没找到本站回链,脚本不会静默失败,而是自动在 Issue 里评论。

失败时会分成两类文案:

页面不可访问#

会提示:

  • 用户填写的友链页 URL
  • 实际访问后的 URL
  • HTTP 状态码
  • 错误信息

页面可访问,但没找到本站友链#

会提示:

  • 没找到友链
  • 请先在对方站点添加本站信息
  • 附上本站名称、链接、头像、描述

同时还会给 Issue 打上:

needs-update

这样用户只要修完,再回评论,就能重新触发验证。


第 9 步:通过后如何写入 friendsConfig.ts#

通过验证后,系统会进入“写配置”阶段。

这一步主要由三个函数完成:

  • parseFriendsConfig(content)
  • renderFriend(friend, indent)
  • updateFriendsConfig(repoRoot, data, issueId)

为什么不是直接 JSON.parse#

因为这个文件是 TypeScript,不是纯 JSON。

它长这样:

export const friendsConfig: FriendLink[] = [
{
title: "xxx",
imgurl: "xxx",
desc: "xxx",
siteurl: "xxx",
tags: ["Blog"],
weight: 10,
enabled: true,
issue_id: 1,
},
];

注意几点:

  • 属性名没加引号
  • 带类型标注
  • 可能带注释
  • 不是合法 JSON

所以脚本不能这样写:

JSON.parse(match[1]);

这也是之前自动化里一个会继续引发报错的坑。

当前实现怎么做#

现在的实现是:

  1. 用正则先截出 friendsConfig 数组主体
  2. 再把每个对象块拆出来
  3. 分别抽取:
    • title
    • imgurl
    • desc
    • siteurl
    • tags
    • weight
    • enabled
    • issue_id
  4. 构造成 JS 对象数组
  5. 再渲染回 TypeScript 字面量

这是一种“结构感知但不依赖 TS AST”的轻量实现。

优点是简单、无额外编译依赖。
缺点是如果你未来把 friendsConfig.ts 改成完全不同的格式,正则也得跟着改。


第 10 步:新增还是覆盖,怎么判断#

脚本会根据 siteurl 判断这是不是已存在的友链:

const existingIndex = friends.findIndex(
(friend) => trimTrailingSlash(friend.siteurl) === normalizedUrl
);

这里做了去尾斜杠处理:

  • https://example.com
  • https://example.com/

会被视为同一个站点。

如果已存在:

  • 覆盖旧项

如果不存在:

  • push 新项

这样可以避免重复添加同一个网站。


第 11 步:为什么写完后还要再跑 Biome#

这是这次修复里非常关键的一步。

自动脚本虽然能写出结构正确的 TS,但不一定和仓库的 Biome 格式完全一致。
结果就是:

  • 友链添加成功了
  • biome ci ./srcFile content differs from formatting output

为了解决这个问题,我在脚本里加了一层:

formatFriendsConfig(repoRoot);

它会调用仓库自己的 Biome 可执行文件:

node_modules/.bin/biome

然后执行:

Terminal window
biome format --write src/config/friendsConfig.ts

这样自动生成的提交就会和仓库 CI 的格式要求一致。

这是把“写入成功”升级成“写入成功且能过 CI”的关键。


第 12 步:自动提交与推送#

通过验证并写入配置后,脚本会自动执行 Git 流程:

git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add src/config/friendsConfig.ts
git commit -m "🤝 更新友链: 站点名"
git pull --rebase origin <default-branch>
git push origin HEAD:<default-branch>

这里有两个值得注意的点。

1. 为什么先 pull --rebase#

因为仓库有可能在 workflow 运行期间又被其他人提交了新内容。
如果直接 push,很容易出现:

! [rejected] master -> master (fetch first)

pull --rebase 可以降低这种失败概率。

2. 为什么不是强推#

自动化流程里不应该默认 --force
因为它是服务流程,不是人工兜底流程。强推会增加误覆盖风险。


第 13 步:评论成功结果并关闭 Issue#

自动提交成功后,脚本还会回到 GitHub 上收尾:

  1. 评论“已成功添加友链”
  2. 移除“验证中”
  3. 移除 needs-update
  4. 关闭 Issue

关闭时使用的是:

await github.rest.issues.update({
owner,
repo,
issue_number: issueNumber,
state: "closed",
state_reason: "completed"
});

这里要注意:

  • state 必须是 "closed"
  • 不能写成 "completed"

completedstate_reason,不是 state

这也是这次修复里顺手纠正的一个 API 用法问题。


五、这次真正需要改哪些代码#

如果你也要照着搭一套,最少要改下面这些地方。

1. 修改 Issue 模板#

文件:

.github/ISSUE_TEMPLATE/friend-request.yml

你要根据自己的站点信息调整:

  • 模板标题
  • 默认标签
  • 表单字段
  • “请先添加本站友链”的提示文案

如果你站点不是博客,还可以加更多字段,比如:

  • RSS 链接
  • 站点分类
  • 站长昵称
  • 是否接受头像热链

2. 修改站点常量#

文件:

.github/scripts/process-friend-request.cjs

重点修改这里:

const SITE_INFO = {
name: "fqzlr",
url: "https://fqzlr.com/",
avatar: "https://q1.qlogo.cn/g?b=qq&nk=20447289&s=640",
desc: "坐而言不如起而行."
};

这是整个校验逻辑里“本站信息”的唯一可信来源。

它会影响:

  • 是否判断回链存在
  • 失败时给用户展示的本站友链信息

3. 修改友链数据文件路径#

如果你的友链配置不在当前路径,需要改这里:

const FRIENDS_CONFIG_RELATIVE_PATH = "src/config/friendsConfig.ts";

如果你用的是:

  • friends.json
  • data/friends.ts
  • src/content/friends.yaml

那解析和写入逻辑也要跟着改。


4. 修改配置文件字段映射#

当前脚本写入的是这个结构:

{
title,
imgurl,
desc,
siteurl,
tags,
weight,
enabled,
issue_id
}

如果你的项目使用的是别的字段,比如:

  • name
  • url
  • avatar
  • description

那就要同步调整:

  • parseFriendsConfig
  • renderFriend
  • updateFriendsConfig

这三个函数。


5. 修改 Workflow 权限#

当前 workflow 需要:

permissions:
contents: write
issues: write

原因是:

  • contents: write 用来提交代码
  • issues: write 用来评论、打标签、关闭 Issue

如果权限不够,会表现成:

  • 能跑脚本
  • 但不能回评
  • 或者不能 push

6. 确保依赖安装方式和仓库一致#

这次还修了一组很典型的 CI 坑。

pnpm/action-setup 版本冲突#

如果你的 package.json 已经有:

"packageManager": "pnpm@9.14.4"

那么 workflow 里不要再写:

with:
version: 9

否则会出现:

Multiple versions of pnpm specified

Biome 命令找不到#

不要依赖“全局有 biome 命令”。

更稳的方式是:

pnpm install --frozen-lockfile
pnpm exec biome ci ./src --reporter=github

这样 CI 使用的一定是仓库锁定的 Biome 版本。


六、为什么我把长逻辑挪出了 YAML#

这是这次改动里最值得保留的一个经验。

一开始如果把全部逻辑都写在:

script: |
...

里面,会有这些真实问题:

  1. 代码太长,维护困难
  2. YAML 和 JS 的双层语法混在一起,调试痛苦
  3. 混入 # 注释时会直接触发 SyntaxError
  4. 编码、引号、缩进很容易造成“看起来没问题,运行就炸”

所以我最后采用的是:

  • Workflow 里只保留短入口
  • 真正逻辑写进 .cjs 文件

这也是我给所有 GitHub Actions 复杂逻辑的建议:

YAML 负责调度,脚本文件负责业务。

不要让 YAML 同时承担“编排器”和“应用层代码容器”的职责。


七、这一套方案有哪些限制#

这套实现已经够实用,但它不是没有边界。

1. friendsConfig.ts 解析依赖当前格式#

现在是用正则和对象块拆分来处理 TS 配置。

所以如果你未来把友链配置改成:

  • 嵌套更深
  • 动态表达式更多
  • 多行模板字符串
  • 复杂注释结构

那解析函数需要一起升级。

更稳的长期方案有两个:

  1. 改成单独的 JSON / YAML 数据文件
  2. 用 TypeScript AST 或 Babel AST 解析

2. Playwright 校验是“近似真实浏览器”,但不是 100% 万能#

比如:

  • 站点有地区限制
  • 站点会拦 GitHub Actions Runner IP
  • 页面需要登录
  • 友链列表要滚动或点击后才出现

这些情况下仍可能误判。

如果你的网站遇到这种场景,可以进一步增强:

  • 增加自定义等待策略
  • 支持指定 CSS 选择器
  • 支持截图附件
  • 把失败截图上传到 Issue 评论

3. 自动 push 依赖仓库分支策略#

如果你的默认分支启用了非常严格的限制,比如:

  • 不允许 GitHub Actions 写入
  • 必须走 PR 合并
  • 强制签名提交

那么脚本里的“直接提交并推送”就需要改造。

你可以改成:

  1. 自动创建分支
  2. 自动提交到新分支
  3. 自动开 PR

这样会更适合协作型仓库。


八、如果你要从零搭建,推荐照这个顺序做#

如果你不是在改现有项目,而是从零上手,我推荐按下面顺序来。

第 1 步:先确定友链数据存储格式#

先决定你最终要写入哪里:

  • JSON
  • YAML
  • TS 配置文件

这一步会直接决定后面脚本复杂度。

如果想最省事,我建议优先 JSON 或 YAML。
如果你已经有成熟的 TS 配置结构,也可以像 Firefly 这样继续沿用。


第 2 步:先把 Issue 模板做好#

不要一上来就写脚本。
先确保用户提交的内容结构稳定。

因为自动化流程的第一输入,其实就是 Issue body。


第 3 步:先做“只解析不写入”#

先写一个最小脚本,只做:

  1. 读取 Issue 内容
  2. 解析字段
  3. 在日志里打印结果

这样先确认字段提取没问题,再往后接浏览器校验和写文件。


第 4 步:接入 Playwright 校验#

等字段解析稳定后,再加:

  • URL 检查
  • 页面是否可访问
  • 页面里是否包含本站回链

不要一开始把所有事情混在一块写,不然后期很难排错。


第 5 步:最后再接 Git 提交#

真正危险的是自动提交阶段。
我建议把“解析”和“校验”完全确认稳定后,再开放:

  • 写文件
  • git add
  • git commit
  • git push

否则一开始就自动 push,调试时很容易把仓库历史搞脏。


九、这次踩过的坑,顺手给你避掉#

这里把这次实际遇到的问题总结一下。

1. actions/github-script 里的 JS 不是 Shell#

script: | 里面只能写 JS,不能混进:

# 注释

这种 Shell 风格注释。
否则会直接触发:

SyntaxError: Invalid or unexpected token

2. TS 配置文件不能直接 JSON.parse#

friendsConfig.ts 是 TypeScript 对象字面量,不是 JSON。

只要你文件里有:

  • 类型标注
  • 非引号属性名
  • 注释

它就不可能直接被 JSON.parse


3. 自动写入后的文件必须再格式化#

脚本“能写进去”不等于“能过 CI”。

格式化是必须的,不是锦上添花。


4. pnpm/action-setuppackageManager 不能双重声明版本#

如果 package.json 已经写了:

"packageManager": "pnpm@9.14.4"

workflow 里就不要重复写 version


5. Cloudflare 机器人会检查 wrangler.jsonc 的 Worker 名称#

如果你的项目名已经改成 firefly,但 wrangler.jsonc 里还是:

"name": "fuwari"

Cloudflare 的机器人 PR 会持续提醒你更新。

所以这次也顺手把:

"name": "fuwari"

改成了:

"name": "firefly"

十、我对这套方案的建议#

如果你只是个人博客,这套方案已经够用,而且很优雅:

  • 没有数据库
  • 没有后端服务
  • 没有额外部署成本
  • 审核门槛低
  • 自动化程度高

它利用的其实都是 GitHub 现成能力:

  • Issue Forms
  • Actions
  • github-script
  • 仓库写权限

再加上一个 Playwright,就能拼出相当完整的业务闭环。

如果你以后还想继续增强,我建议优先加这几项:

  1. 失败时自动截图并贴到评论
  2. 自动创建 PR,而不是直接推默认分支
  3. 将友链数据迁移到单独的 JSON / YAML 文件
  4. 支持白名单域名 / 黑名单域名
  5. 支持自动去重、自动排序、自动补充默认头像

十一、本文对应的关键文件清单#

方便你对照仓库直接看:

  • .github/ISSUE_TEMPLATE/friend-request.yml
  • .github/workflows/friend-link-checker.yml
  • .github/scripts/process-friend-request.cjs
  • src/config/friendsConfig.ts
  • .github/workflows/biome.yml
  • wrangler.jsonc

十二、结语#

这套“友链自助申请”方案本质上是把 GitHub 当成了一个轻量业务平台来用:

  • 用 Issue 表单承接输入
  • 用 Actions 承接流程
  • 用脚本承接业务判断
  • 用仓库文件承接数据落地

没有后端,也能把流程做完整。
对个人博客和轻量站点来说,这种思路非常值。

如果你正在做自己的博客系统,或者想把原本人工处理的流程逐步自动化,我很推荐从这种“基于 Git 仓库自身能力”的方案开始搭。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
Firefly 友链自助申请自动化
https://fqzlr.com/posts/blog/friend-link-auto-apply-guide/
作者
fqzlr
发布于
2026-04-27
许可协议
CC BY-NC-SA 4.0

评论区

看板娘
公告
欢迎 关于我的介绍

欢迎来到我的博客。

查看详情
音乐
封面

音乐

暂未播放

0:00
0:00
暂无歌词
标签
# Firefly 6 # Markdown 5 # 友链 2 # 文章示例 2 # 图床 1 # IP优选 1 # 环境安装 1 # Windows 1 # 博客搭建 1 # Git 1 # 自助申请 1 # Astro 1 # 博客优化 1 # Playwright 1 # 自动化 1 # Obsidian 1 # astro 1 # Mizuki 1 # Blogging 1 # Customization 1 # Test 1 # Encryption 1 # Example 1 # Video 1 # MDX 1 # 演示 1 # 示例 1 # 博客 1 # Mermaid 1 # PlantUML 1
目录

隐私政策

更新日期: 2026/5/19
生效日期: 2026/5/19

导言#

MmzMing的知识库 是一款由 MmzMing(以下简称“我们”)提供的产品。您在使用我们的服务时,我们可能会收集和使用您的相关信息。我们希望通过本《隐私政策》向您说明,在使用我们的服务时,我们如何收集、使用、储存和分享这些信息,以及我们为您提供的访问、更新、控制和保护这些信息的方式。

本《隐私政策》与您所使用的 MmzMing的知识库 服务息息相关,希望您仔细阅读,在需要时,按照本《隐私政策》的指引,作出您认为适当的选择。本《隐私政策》中涉及的相关技术词汇,我们尽量以简明扼要的表述,并提供进一步说明的链接,以便您的理解。

您使用或继续使用我们的服务,即意味着同意我们按照本《隐私政策》收集、使用、储存和分享您的相关信息。

如对本《隐私政策》或相关事宜有任何问题,请通过 784774835@qq.com 与我们联系。

1. 我们收集的信息#

我们或我们的第三方合作伙伴提供服务时,可能会收集、储存和使用下列与您有关的信息。如果您不提供相关信息,可能无法注册成为我们的用户或无法享受我们提供的某些服务,或者无法达到相关服务拟达到的效果。

  • 个人信息:您在注册账户或使用我们的服务时,向我们提供的相关个人信息,例如电话号码、电子邮件等。
  • 日志信息:指您使用我们的服务时,系统可能通过 cookies、标识符及相关技术收集的信息,包括您的 设备信息浏览信息点击信息,并将该等信息储存为日志信息,为您提供个性化的用户体验、保障服务安全。您可以通过浏览器设置拒绝或管理 cookie、标识符或相关技术的使用。
  • 位置信息:指您开启设备定位功能并使用我们基于位置提供的相关服务时,收集的有关您位置的信息,包括:
    • 您通过具有定位功能的移动设备使用我们的服务时,通过 GPS 或 WiFi 等方式收集的您的地理位置信息;
    • 您可以通过关闭定位功能,停止对您的地理位置信息的收集。

2. 信息的存储#

2.1 信息存储的方式和期限#

我们会通过安全的方式存储您的信息,包括本地存储(例如利用 APP 进行数据缓存)、数据库和服务器日志。

一般情况下,我们只会在为实现服务目的所必需的时间内或法律法规规定的条件下存储您的个人信息。

2.2 信息存储的地域#

我们会按照法律法规规定,将境内收集的用户个人信息存储于中国境内。

目前我们不会跨境传输或存储您的个人信息。将来如需跨境传输或存储的,我们会向您告知信息出境的目的、接收方、安全保证措施和安全风险,并征得您的同意。

2.3 产品或服务停止运营时的通知#

当我们的产品或服务发生停止运营的情况时,我们将以推送通知、公告等形式通知您,并在合理期限内删除您的个人信息或进行匿名化处理,法律法规另有规定的除外。

3. 信息安全#

我们使用各种安全技术和程序,以防信息的丢失、不当使用、未经授权阅览或披露。例如,在某些服务中,我们将利用加密技术(例如 SSL)来保护您提供的个人信息。但请您理解,由于技术的限制以及可能存在的各种恶意手段,在互联网行业,即便竭尽所能加强安全措施,也不可能始终保证信息百分之百的安全。您需要了解,您接入我们的服务所用的系统和通讯网络,有可能因我们可控范围外的因素而出现问题。

4. 我们如何使用信息#

我们可能将在向您提供服务的过程之中所收集的信息用作下列用途:

  • 向您提供服务;
  • 在我们提供服务时,用于身份验证、客户服务、安全防范、诈骗监测、存档和备份用途,确保我们向您提供的产品和服务的安全性;
  • 帮助我们设计新服务,改善我们现有服务;
  • 使我们更加了解您如何接入和使用我们的服务,从而针对性地回应您的个性化需求,例如语言设定、位置设定、个性化的帮助服务和指示,或对您和其他用户作出其他方面的回应;
  • 向您提供与您更加相关的广告以替代普遍投放的广告;
  • 评估我们服务中的广告和其他促销及推广活动的效果,并加以改善;
  • 软件认证或管理软件升级;
  • 让您参与有关我们产品和服务的调查。

5. 信息共享#

目前,我们不会主动共享或转让您的个人信息至第三方,如存在其他共享或转让您的个人信息或您需要我们将您的个人信息共享或转让至第三方情形时,我们会直接或确认第三方征得您对上述行为的明示同意。

为了投放广告,评估、优化广告投放效果等目的,我们需要向广告主及其代理商等第三方合作伙伴共享您的部分数据,要求其严格遵守我们关于数据隐私保护的措施与要求,包括但不限于根据数据保护协议、承诺书及相关数据处理政策进行处理,避免识别出个人身份,保障隐私安全。

我们不会向合作伙伴分享可用于识别您个人身份的信息(例如您的姓名或电子邮件地址),除非您明确授权。

我们不会对外公开披露所收集的个人信息,如必须公开披露时,我们会向您告知此次公开披露的目的、披露信息的类型及可能涉及的敏感信息,并征得您的明示同意。

随着我们业务的持续发展,我们有可能进行合并、收购、资产转让等交易,我们将告知您相关情形,按照法律法规及不低于本《隐私政策》所要求的标准继续保护或要求新的控制者继续保护您的个人信息。

另外,根据相关法律法规及国家标准,以下情形中,我们可能会共享、转让、公开披露个人信息无需事先征得您的授权同意:

  • 与国家安全、国防安全直接相关的;
  • 与公共安全、公共卫生、重大公共利益直接相关的;
  • 犯罪侦查、起诉、审判和判决执行等直接相关的;
  • 出于维护个人信息主体或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
  • 个人信息主体自行向社会公众公开个人信息的;
  • 从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。

6. 您的权利#

在您使用我们的服务期间,我们可能会视产品具体情况为您提供相应的操作设置,以便您可以查询、删除、更正或撤回您的相关个人信息,您可参考相应的具体指引进行操作。此外,我们还设置了投诉举报渠道,您的意见将会得到及时的处理。如果您无法通过上述途径和方式行使您的个人信息主体权利,您可以通过本《隐私政策》中提供的联系方式提出您的请求,我们会按照法律法规的规定予以反馈。

当您决定不再使用我们的产品或服务时,可以申请注销账户。注销账户后,除法律法规另有规定外,我们将删除或匿名化处理您的个人信息。

7. 变更#

我们可能适时修订本《隐私政策》的条款。当变更发生时,我们会在版本更新时向您提示新的《隐私政策》,并向您说明生效日期。请您仔细阅读变更后的《隐私政策》内容,若您继续使用我们的服务,即表示您同意我们按照更新后的《隐私政策》处理您的个人信息。

8. 未成年人保护#

我们鼓励父母或监护人指导未满十八岁的未成年人使用我们的服务。我们建议未成年人鼓励他们的父母或监护人阅读本《隐私政策》,并建议未成年人在提交的个人信息之前寻求父母或监护人的同意和指导。