[docs/zh] update zh docs: synced to 98c4cae + fix typo (#3884)

* [docs/zh] update zh docs: synced to 98c4cae8

* fix typo

* sync the support matrix in README

* update mkdocs.yml: add new article
This commit is contained in:
CDN 2025-03-10 09:24:37 +00:00 committed by GitHub
parent 252a17a691
commit 3db5bfa0f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1176 additions and 693 deletions

View file

@ -45,7 +45,7 @@ If desired, update the GoToSocial Docker image tag to the version of GtS you wan
* `X.Y.Z`: release tag. This points to a specific, stable, release of GoToSocial.
!!! tip
Both the `latest` and `snapshot` tags are moving tags, whereas the `vX.Y.Z` tags are immutable. The result of pulling a moving tag might change from day to day. `latest` on one system might not be the same `latest` on a different system. It's recommended to use the `X.Y.Z` tags instead so you always know exactly which version of GoToSocial you're running. The list of releases can be found [right here](https://github.com/superseriousbusiness/gotosocial/releases), with the newest release at the top.
Both the `latest` and `snapshot` tags are moving tags, whereas the `X.Y.Z` tags are immutable. The result of pulling a moving tag might change from day to day. `latest` on one system might not be the same `latest` on a different system. It's recommended to use the `X.Y.Z` tags instead so you always know exactly which version of GoToSocial you're running. The list of releases can be found [right here](https://github.com/superseriousbusiness/gotosocial/releases), with the newest release at the top.
### Host

View file

@ -46,13 +46,15 @@
## 注册限制
为了避免注册积压过多使管理员和版主不堪重负GoToSocial 将待处理注册积压限制为 20 个账户。一旦积压中有 20 个账户等待管理员或版主处理,新注册将不能通过表单提交
为了避免积压的注册申请超出管理员和版主的处理能力GoToSocial 默认将待处理注册积压限制为 20 个账号。一旦待处理队列中有 20 个账号等待管理员或版主处理,将不再通过表单接受新注册申请
如果过去 24 小时内已批准 10 个或以上新账户注册,新的注册也将不能通过表单提交,以避免实例规模快速扩张超出管理能力。
默认情况下,如果在过去 24 小时内已批准的注册账号数达到或超过 10 个,新注册也将不再通过表单接受,以避免实例规模快速扩张超出管理能力。
在这两种情况下,申请人将看到一条错误信息,解释无法提交表单的原因,并邀请他们稍后再试。
在这两种情况下,申请者将看到一条错误信息,说明无法提交表单的原因,并邀请他们稍后再试。
为了防止垃圾账户GoToSocial 的账户注册**始终**需要管理员手动批准,并且申请人**始终**需确认其电子邮件地址后才能登录和发布贴文。
每日注册的上限及待处理注册队列的大小可以通过 `accounts-registration-daily-limit``accounts-registration-backlog-limit` 这两个变量进行配置或完全禁用。更多信息请参见 [账户配置](../configuration/accounts.md)。
为了防止垃圾账户GoToSocial 的账户注册**始终**需要管理员手动审批,并且申请人**始终**需确认其电子邮件地址后才能登录和发布贴文。
## 通过邀请注册

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,24 @@ accounts-registration-open: false
# 默认: true
accounts-reason-required: true
# 整数值。表示24小时内允许的最大已批准注册账号数量超出此数量将关闭新账号注册。
#
# 一般情况下,保持默认值相当于将你的实例限制为每天最多新增 10 个账号。
#
# 将此数值设置为 0 或更低将移除限制。
#
# 默认10
accounts-registration-daily-limit: 10
# 整数值。表示待审核队列中允许的最大新账号注册数量,超出此数量将关闭新账号注册。
#
# 这可以用来对注册队列进行“节流”,从而防止实例管理员不堪重负。
#
# 将此数值设置为 0 或更低将移除限制。
#
# 默认20
accounts-registration-backlog-limit: 20
# 布尔值。允许此实例上的账户为其个人资料页面和贴文设置自定义 CSS。
# 启用此设置将允许账户通过 /user 设置页面上传自定义 CSS
# 然后这些 CSS 将在账户的个人资料和贴文的网页视图中呈现。

View file

@ -155,4 +155,15 @@ instance-subscriptions-process-every: "24h"
# 选项: ["", "zero", "serve", "baffle"]
# 默认: ""
instance-stats-mode: ""
# 布尔值。此变量控制本地账户是否可以使用 /api/v1/statuses 的 scheduled_at 参数将帖文设为过去的日期。
# 此变量不影响将在未来定时发布的帖文(目前尚未实现),
# 也无法阻止外站账户为其发布的帖文设置过去的日期。
#
# 如果设置为 true所有本站账户都可以新增历史帖文。
# 如果设置为 false将禁止新增历史帖文并在调用相关端点时返回错误。
#
# 选项: [true, false]
# 默认值: true
instance-allow-backdating-statuses: true
```

View file

@ -0,0 +1,679 @@
# 互动规则
GoToSocial 在帖文中使用 `interactionPolicy` 属性向外站实例描述:对于任意给定的帖文,本站服务器允许处理和存储哪些类型的互动及其条件。
`interactionPolicy` 及相关对象和属性的 `@context` 文档位于 `https://gotosocial.org/ns`
!!! danger 警告
互动规则旨在限制帖文作者不希望看到的回复以及其它可能对用户造成有害影响的互动(例如,来自“回复狂”的互动)。
然而,这一技术方案远未足以解决此问题,因为在用户最初的希望设定的回复范围之外,仍存在许多“常规途径之外”的分发或回复方式。
例如,用户可能会创建一个具有非常严格的互动规则的帖文,但发现其他软件和实例并不遵守这一规则,其他实例上的用户可能正在他们各自实例的范围讨论这个帖文并回复。原帖文作者所在的实例会自动将这些作者不希望出现的互动从视图中丢弃,但外站实例可能仍会显示它们。
再举一个例子:有人可能会看到一个规定“任何人都不能回复”的帖文,但他截屏了该帖文,然后在自己的新帖文中发布该截屏,并提及原帖作者。另外,用户也可能发布链接到该帖文的 URL并以提及形式标记原帖作者。在这种情况下他们通过创建一个新帖文有效地“回复”了原来的帖文。
考虑到上述情形GoToSocial 只能提供一种尽最大努力、部分解决问题的技术方案,该方案之外的情形更多是关乎社交行为和边界问题。
## 概览
`interactionPolicy` 是附加在类似帖文的 `Object`(例如 `Note`、`Article`、`Question` 等)上的一个对象属性,其格式如下:
```json
{
"@context": [
"https://gotosocial.org/ns",
[...]
],
[...],
"interactionPolicy": {
"canLike": {
"always": [ "零个或多个总是允许此操作的 URI" ],
"approvalRequired": [ "零个或多个需要批准才能执行此操作的 URI" ]
},
"canReply": {
"always": [ "零个或多个总是允许此操作的 URI" ],
"approvalRequired": [ "零个或多个需要批准才能执行此操作的 URI" ]
},
"canAnnounce": {
"always": [ "零个或多个总是允许此操作的 URI" ],
"approvalRequired": [ "零个或多个需要批准才能执行此操作的 URI" ]
}
},
[...]
}
```
`interactionPolicy` 对象中:
- `canLike` 是一个子规则,用于表明哪些对象(或集合)被允许以帖文 URI 作为 `Like``object` 来创建一个点赞活动。
- `canReply` 是一个子规则,用于表明哪些对象(或集合)被允许以将 `inReplyTo` 设置为该帖文的 URI/ID 来创建一个回复帖文。
- `canAnnounce` 是一个子规则,用于表明哪些对象(或集合)被允许以帖文 URI/ID 作为 `Announce``object` 来创建一个转发活动。
另外:
- `always` 表示 ActivityPub URI/ID 中的 `Actor` 或者 `Actor` 集合,它们被允许在不需要帖文作者手动批准的情况下创建并分发针对帖文的互动。
- `approvalRequired` 表示 ActivityPub URI/ID 中的 `Actor` 或者 `Actor` 集合,它们被允许创建针对帖文的互动,但应当等待帖文作者手动批准后再进行分发(详见[请求、获取和验证批准](#请求获取和验证批准))。
`always``approvalRequired` 中,合法的 URI 项目包括:
- 特殊的 ActivityStreams 公共 URI `https://www.w3.org/ns/activitystreams#Public`
- 帖文创建者的 `Following` 和/或 `Followers` 集合的 URI
- 单个行为体的 URI
例如:
```json
[
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/someone/followers",
"https://example.org/users/someone/following",
"https://example.org/users/someone_else",
"https://somewhere.else.example.org/users/someone_on_a_different_instance"
]
```
!!! info "注意"
请注意,根据 JSON-LD 规范,`always` 与 `approvalRequired` 的值可以是单个字符串,也可以是字符串数组。也就是说,以下几种写法都是合法的:
- 单个字符串:`"always": "https://example.org/users/someone"`
- 单一条目数组:`"always": [ "https://example.org/users/someone" ]`
- 多个条目的数组:`"always": [ "https://example.org/users/someone", "https://example.org/users/someone_else" ]`
## 指定“没有人”
要指定除作者之外**没有人**可以对帖文进行互动(而作者始终是被允许互动),实现者应将 `always` 数组设置为**仅包含帖文的作者 URI**,而 `approvalRequired` 则可以不包含、设为 `null` 或者留空。
例如,下面的 `canLike` 值表示除帖文作者以外,**没有人**可以对该帖文执行点赞操作:
```json
"canLike": {
"always": "帖文作者的ActivityPub URI"
},
```
再举一个例子。对于下面这条由 `https://example.org/users/someone` 发布的帖文,它的 `interactionPolicy` 表明任何人都可以点赞该帖文,但只有作者本人可以回复或转发:
```json
{
"@context": [
"https://gotosocial.org/ns",
[...]
],
[...],
"interactionPolicy": {
"canLike": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canReply": {
"always": "https://example.org/users/someone"
},
"canAnnounce": {
"always": "https://example.org/users/someone"
}
},
[...]
}
```
!!! note "注意"
为了防止恶意行为GoToSocial 即使在规则中指定“没有人”时,也会对谁能否进行互动做隐含假设,详见[隐含假设](#隐含假设)。
## 冲突 / 重复的值
如果一个用户既存在于某个集合 URI 中,又以单个行为体 URI 的形式被明确指定,则**更为具体**的值将优先采用。
例如:
```json
[...],
"canReply": {
"always": "https://example.org/users/someone",
"approvalRequired": "https://www.w3.org/ns/activitystreams#Public"
},
[...]
```
在这里,`@someone@example.org` 出现在 `always` 中,同时又实际包含在 `approvalRequired` 中的特殊公共集合里。此时,由于 `always` 中的值更明确,他们总是可以回复。
另一个例子:
```json
[...],
"canReply": {
"always": "https://www.w3.org/ns/activitystreams#Public",
"approvalRequired": "https://example.org/users/someone"
},
[...]
```
这里,`@someone@example.org` 出现在 `approvalRequired` 中,但也实际存在于 `always` 中的特殊公共集合里。在这种情况下,所有人都可以在不需要批准的情况下回复,但 `@someone@example.org` **除外**,它需要批准。
如果相同的 URI 同时存在于 `always``approvalRequired` 中,则**权限较高的**(即出现在 `always` 中的)值将会优先。
## 默认的 `interactionPolicy`
当帖文中完全没有包含 `interactionPolicy` 属性,或者 `interactionPolicy` 键存在但其值为 `null``{}` 时,实现者可以假定该帖文具有下面隐含的、默认的 `interactionPolicy`
```json
{
"@context": [
"https://gotosocial.org/ns",
[...]
],
[...],
"interactionPolicy": {
"canLike": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canReply": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canAnnounce": {
"always": "https://www.w3.org/ns/activitystreams#Public"
}
},
[...]
}
```
默认情况下各子规则中没有任何 `approvalRequired` 属性,也就是说 `approvalRequired` 的默认值为空数组。
该默认 `interactionPolicy` 旨在反映撰写时所有版本低于 v0.17.0 的 GoToSocial 以及其他 ActivityPub 服务器软件实际采用的互动规则。也就是说,这正是那些不支持互动规则的服务器*已默认假定*的互动权限。
!!! info "行为体只能与他们有权查看的帖文进行互动"
请注意,即使对帖文假定了默认 `interactionPolicy`,帖文的**可见性**仍需通过查看 `to`、`cc` 及/或 `audience` 属性来确认,以确保那些无权*查看*帖文的行为体也无法*互动*。例如,如果一条帖文仅面向粉丝,并且假定了默认 `interactionPolicy`,那么不关注帖文作者的人仍然*不能*看到或者互动该帖文。
!!! tip "提示"
与其他 ActivityPub 实现规范类似,实现者通常仍希望对针对帖文的转发(`Announce`)操作做限制,当帖文仅粉丝可见时,仅允许作者本人进行相关操作。
## 各子规则的默认值
当某个互动规则仅被*部分*定义(例如,仅设置了 `canReply`,而没有设置 `canLike``canAnnounce` 键)时,实现者应对 `interactionPolicy` 对象中未定义的每个子规则做如下假定。
!!! tip "未来的扩展可能具有不同默认值"
请注意,**下述列表并非详尽无遗**,未来对 `interactionPolicy` 的扩展可能希望为其他类型的互动定义**不同的默认值**。
### `canLike`
如果 `interactionPolicy` 中缺失 `canLike`,或 `canLike` 的值为 `null``{}`,则实现者应假定:
```json
"canLike": {
"always": "https://www.w3.org/ns/activitystreams#Public"
}
```
换言之,默认情况下**任何能看到帖文的人都可以对其点赞**。
### `canReply`
如果 `interactionPolicy` 中缺失 `canReply`,或 `canReply` 的值为 `null``{}`,则实现者应假定:
```json
"canReply": {
"always": "https://www.w3.org/ns/activitystreams#Public"
}
```
换言之,默认情况下**任何能看到帖文的人都可以回复**。
### `canAnnounce`
如果 `interactionPolicy` 中缺失 `canAnnounce`,或 `canAnnounce` 的值为 `null``{}`,则实现者应假定:
```json
"canAnnounce": {
"always": "https://www.w3.org/ns/activitystreams#Public"
}
```
换言之,默认情况下**任何能看到帖文的人都可以转发**。
## 描述子规则是否需要验证
在本文撰写时,并非所有服务器都已经实现了互动规则,因此有必要提供一种方法,使实现者可以表明他们**既知道又会执行**下文[互动验证](#互动验证)部分中描述的互动规则。
这种参与互动规则的描述方式,要求服务器在外发帖文时显式设置 `interactionPolicy` 及其子规则,而不依赖于上述默认值。
也就是说,**一个实例通过在帖文上设置 `interactionPolicy.*`即可向其它实例表明其会对每个显式设置的子规则进行互动验证。**
这意味着,如果服务端自己实现了互动规则控制,并希望其他服务端遵循,则应总是显式设置 `interactionPolicy` 上其已实现的所有子规则,即使这些值与隐含默认值没有区别。
例如,如果一个服务器理解并希望强制执行 `canLike`、`canReply` 和 `canAnnounce` 子规则(正如 GoToSocial 的情况),那么他们应当在外发帖文时显式为这些子规则赋值,即使这些值与隐含默认值相同。这让外站服务器知道本站服务器会执行规则,并了解如何处理每个子规则的相应 `Reject``Accept` 消息。
另一个例子:如果某个服务器只实现了 `canReply` 的互动子规则,而没有实现 `canLike``canAnnounce`,那么他们应总是设置 `interactionPolicy.canReply`,并将另外两个子规则排除在 `interactionPolicy` 外,以表明他们无法理解或执行它们。
这种通过键的存在与否来表明参与互动规则的方式,就是为了让大部分未设置 `interactionPolicy` 的服务器(因为它们尚未实现该功能)无需更改行为。已实现互动规则的服务器则可以通过帖文上没有 `interactionPolicy` 键这一特征了解到原始服务器不支持互动规则,并作出相应处理。
## 隐含假设
出于常识性的安全考虑GoToSocial 做出并始终应用两条关于互动规则的隐含假设。
### 1. 被提及和被回复的行为体总是可以回复
无论帖文的可见性和 `interactionPolicy` 如何,被提及或者被帖文回复中的行为体**总是**可以无需批准即对该帖进行回复,**除非**提及或回复它们的帖文本身正处于待批准状态。
这样设计是为了防止潜在的骚扰者在滥用帖文时提及某人,从而使被提及的用户无从回复。
因此在发出互动规则时GoToSocial **总是**会将被提及的用户 URI 加入 `canReply.always` 数组中,除非这些用户已经被 ActivityStreams 的特殊公共 URI 所覆盖。
同样在执行接收到的互动规则时GoToSocial 会**始终**将行为体当作已出现在 `canReply.always` 数组中,即使实际数据中没有包含他们的 URI。
### 2. 行为体始终可以对自己的帖文进行任何形式的互动
**其次**,行为体**始终**应该能够对自己的帖文进行回复、点赞和转发boost而无需批准**除非**该帖文本身正处于待批准状态。
因此在发出互动规则时GoToSocial **总是**会将帖文作者的 URI 加入到 `canLike.always`、`canReply.always` 和 `canAnnounce.always` 数组中,**除非**这些 URI 已经被 ActivityStreams 的特殊公共 URI 所涵盖。
同样在执行接收到的互动规则时GoToSocial 会**始终**将帖文作者视作出现在每个 `always` 字段中,即使实际数据中不存在。
## 示例
这里给出了一些有关互动规则允许用户操作的示例。
### 1. 限制讨论范围
在下面的示例中,用户 `@the_mighty_zork` 希望与用户 `@booblover6969``@hodor` 开启一段讨论。
为了防止讨论被其他人插话而偏离Ta 希望帖文的回复(除这三位参与者外)必须经过 `@the_mighty_zork` 的批准才能生效。
此外Ta 希望只允许自己的粉丝以及这三位讨论参与者转发announce他们的帖文。
然而,任何人都可以对 `@the_mighty_zork` 的帖文进行点赞。
这可以通过为一篇可见行为“公开”的帖文设置如下 `interactionPolicy` 来实现:
```json
{
"@context": [
"https://gotosocial.org/ns",
[...]
],
[...],
"interactionPolicy": {
"canLike": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canReply": {
"always": [
"https://example.org/users/the_mighty_zork",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
],
"approvalRequired": "https://www.w3.org/ns/activitystreams#Public"
},
"canAnnounce": {
"always": [
"https://example.org/users/the_mighty_zork",
"https://example.org/users/the_mighty_zork/followers",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
]
}
},
[...]
}
```
### 2. 单人长篇讨论串
在这个示例中,用户 `@the_mighty_zork` 想要写一段长篇讨论。
他们不介意别人转发和点赞讨论串中的帖文,但不想收到任何回复,因为他们没有精力去管理讨论;他们只是想发发牢骚。
这可以通过在讨论串中的每个帖文都设置如下 `interactionPolicy` 实现:
```json
{
"@context": [
"https://gotosocial.org/ns",
[...]
],
[...],
"interactionPolicy": {
"canLike": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canReply": {
"always": "https://example.org/users/the_mighty_zork"
},
"canAnnounce": {
"always": "https://www.w3.org/ns/activitystreams#Public"
}
},
[...]
}
```
在这里,任何人都允许点赞或转发,但除了 `@the_mighty_zork` 自己以外,没人允许回复。
### 3. 完全开放
在这个示例中,`@the_mighty_zork` 希望发表一条完全开放的帖文,以便任何能看到它的人都可以回复、转发或点赞:
```json
{
"@context": [
"https://gotosocial.org/ns",
[...]
],
[...],
"interactionPolicy": {
"canLike": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canReply": {
"always": "https://www.w3.org/ns/activitystreams#Public"
},
"canAnnounce": {
"always": "https://www.w3.org/ns/activitystreams#Public"
}
},
[...]
}
```
## 后续回复/扩大范围
讨论中的每条后续回复都有其各自的互动规则,由创建该回复的用户设定。换言之,整个*讨论串*或*主题*并不由单一的 `interactionPolicy` 控制,每个帖文作者可以为其后续帖文设置不同的规则。
不幸的是,这意味着即使设置了 `interactionPolicy`,讨论串的范围有时也会无意中超出第一帖作者的预期。
例如,在上面的[示例 1 - 限制讨论范围](#1-限制讨论范围)中,`@the_mighty_zork` 在首个帖文中设置了如下 `canReply.always` 值:
```json
[
"https://example.org/users/the_mighty_zork",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
]
```
而在随后的某个回复中,可能因疏忽或刻意为之,`@booblover6969` 将 `canReply.always` 值设置为:
```json
[
"https://www.w3.org/ns/activitystreams#Public"
]
```
此举扩大了讨论范围,因为现在任何人都可以回复 `@booblover6969` 的帖文,并可能在回复中提及 `@the_mighty_zork`
为了避免这种情况,建议外站实例防止用户扩大讨论范围(具体的实现机制有待确定)。
同时,实例也应把任何处于待批准状态的帖文(包含互动)也视作待批准状态。
换言之,实例应将所有处于待批准状态的上级帖文之下的互动也标记为待批准状态,不论该待批准的上级帖文的互动规则是否允许那些互动。
这样可以避免以下情况:某人回复一个帖文,即便他们的回复正待批准,但随后他们可对自己的回复继续回复,从而利用自身作为作者的[隐含允许回复的权限](#隐含假设)使其回复被标记为允许。
## 互动验证
[互动规则](#互动规则)部分描述了互动规则的格式、假定默认值以及相关假设。
本节描述互动规则的执行和验证,即设置互动规则的服务端如何发送批准或拒绝消息,以回应请求/待批准的互动,以及外站服务器如何证明互动者已获得互动对象对互动目标帖文的批准。
### 请求、获取和验证批准
当某个行为体的 URI 存在于某种互动类型的 `approvalRequired` 数组中,**或者**需要通过验证其在某集合中的存在(参见[验证在粉丝或关注集合中的存在](#验证在粉丝或关注集合中的存在)),在行为体希望对某条受互动规则限制的帖文请求批准互动时,服务端实现应当执行以下步骤:
1. 按常规构造该互动 `Activity`(例如 `Like`、`Create`,或 `Announce`)。
2. 按常规将该 `Activity``to``cc` 指定为预期的活动接收方。
3. 仅将该 `Activity``POST` 方式发送至互动目标帖文作者的 `Inbox`(或 `sharedInbox`)。
4. **此时不要再对该 Activity 执行进一步分发**
在此阶段,该互动可视为*待批准*状态,不应显示在被互动帖文的回复或点赞等集合中。
它可以以“互动待批准”的模式显示给发送该互动的用户,但理想情况下不应显示给与该用户同一实例的其他用户。
从这一点开始,可能出现以下三种情况之一:
#### 拒绝
在这种情况下,互动目标帖文的作者所在的服务器将会发送一个 `Reject` 类型的 `Activity`,其 `object` 属性为待批准互动的 URI/ID。
例如,下面这个 JSON 对象拒绝了 `@someone@somewhere.else.example.org` 试图回复 `@post_author@example.org` 帖文的请求:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/reject/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"type": "Reject"
}
```
若发生这种情况,`@someone@somewhere.else.example.org`(以及其所在实例)应将该互动视为已被拒绝。实例应将其内部存储(例如数据库)中的对应活动删除,或以其他方式标记为已拒绝,并且不再进一步分发或重试该互动。服务器可能希望通知互动发起者他们的互动已被拒绝。
#### 无应答
在这种情况下,被互动帖文的作者既没有返回 `Reject` 也没有返回 `Accept` 类型的 `Activity`。在这种情况下,该互动将无限期地处于“待批准”状态。实现者可以考虑实现某种清理机制,将达到一定时间而依然处于待批准状态的发送或待批准互动视为已失效或被拒绝,然后以之前提到的方式移除。
#### 接受
在这种情况下,互动目标帖文的作者会发送一个 `Accept` 类型的 `Activity`,其 `object` 属性为待批准互动的 URI/ID同时其 `result` 属性中包含一个可解引用的批准对象 URI详见[批准对象](#批准对象))。
例如,下面这个 JSON 对象接受了 `@someone@somewhere.else.example.org` 试图回复 `@post_author@example.org` 帖文的请求:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"cc": [
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/post_author/followers"
],
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/accept/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"result": "https://example.org/users/post_author/reply_approvals/01JMMGABRDNA9G9BDNYJR7TC8D",
"type": "Accept"
}
```
若发生这种情况,`@someone@somewhere.else.example.org`(以及其所在实例)应将该互动视为已获得被互动者的批准/接受。
此时,`somewhere.else.example.org` 应再次分发该互动,但有以下区别:
1. 这次需要在发送的 `Create` 活动中包含 `Accept` 消息中给出的 `result` 的 URI/ID并将其放入 `approvedBy` 字段中。
2. 这次将该互动分发给 `to`、`cc` 等所有目标收件人。
!!! note "注意"
虽然不是严格必须,但在上例中,行为体 `https://example.org/users/post_author` 不仅将 `Accept` 消息的接收方设为互动发起者 `https://somewhere.else.example.org/users/someone`,还额外包含了他们的粉丝集合(以及隐含地包含了公共地址)。这使得其他服务器上的 `https://example.org/users/post_author` 的粉丝,也可以标记该互动为已接受,并在不必解引用 `approvedBy` URI 的情况下,将该互动与被互动帖文一同展示。
### 批准对象
批准对象是基本 ActivityStreams 对象的扩展,其类型可以是 `LikeApproval`、`ReplyApproval` 或 `AnnounceApproval`。每种类型对应一个特定互动类型的批准。
例如,`LikeApproval`
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://gotosocial.org/ns"
],
"attributedTo": "https://example.org/users/post_author",
"id": "https://example.org/users/post_author/approvals/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/likes/01JMPKG79EAH0NB04BHEM9D20N",
"target": "https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT",
"type": "LikeApproval"
}
```
`ReplyApproval`
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://gotosocial.org/ns"
],
"attributedTo": "https://example.org/users/post_author",
"id": "https://example.org/users/post_author/approvals/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"target": "https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT",
"type": "ReplyApproval"
}
```
`AnnounceApproval`
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://gotosocial.org/ns"
],
"attributedTo": "https://example.org/users/post_author",
"id": "https://example.org/users/post_author/approvals/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/boosts/01JMPKG79EAH0NB04BHEM9D20N",
"target": "https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT",
"type": "AnnounceApproval"
}
```
在一个批准对象中:
- `attributedTo`:应为发出 `Accept` 消息的行为体,也即互动对象。
- `object`:应为进行互动的 `Like`、`Announce` 或帖文类别的 `Object`
- `target`(可选):如果包含,应为被互动的帖文类别的 `Object`
!!! info "批准对象应当可以被解引用"
根据验证机制(参见[验证 `approvedBy`](#验证-approvedby)),各实例应确保对批准对象 URI 的解引用返回合法的 ActivityPub 响应。否则,外站实例在分发帖文时可能会受限。
### `approvedBy`
`approvedBy` 是附加在 `Like`、`Announce` 活动中,以及任何被视为“帖文”(例如 `Note`、`Article` 等)的对象上的额外属性。
`approvedBy` 表示该互动(或回复对象)已获得目标帖文作者的批准/接受,从而现在可以分发给预期的受众。
`approvedBy` 的值应为在 `Accept` 消息中发送的 `result` URI/ID该 URI 指向一个可解引用的批准对象。
例如,下面这个 `Announce` 活动通过存在 `approvedBy` 表明其已被 `@post_author@example.org` 接受:
```json
{
"actor": "https://somewhere.else.example.org/users/someone",
"to": [
"https://somewhere.else.example.org/users/someone/followers"
],
"cc": [
"https://example.org/users/post_author"
],
"id": "https://somewhere.else.example.org/users/someone/activities/announce/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://example.org/users/post_author/statuses/01J17ZZFK6W82K9MJ9SYQ33Y3D",
"approvedBy": "https://example.org/users/post_author/reply_approvals/01JMMGABRDNA9G9BDNYJR7TC8D",
"type": "Announce"
}
```
#### 验证 `approvedBy`
当接收到带有 `approvedBy` 值的活动或帖文对象时,外站实例应:
1. 验证 `approvedBy` URI 的主机名/域名与被互动帖文作者的主机名/域名一致。
2. 解引用 `approvedBy` URI/ID 以获得批准对象(见[批准对象](#approval-objects))。
3. 检查批准对象的类型,确保其正确,即例如一个 `Announce` 消息的 `approvedBy` URI 应指向 `AnnounceApproval`,而不是 `ReplyApproval``LikeApproval`
4. 检查批准对象中的 `attributedTo` 值是否与进行互动的行为体的 URI/ID 一致。
5. 检查批准对象中的 `object` 值是否与互动 `Activity` 或对象的 `id` 一致。
如果批准对象无法解引用,或者未通过上述有效性检查,则应将该互动视为无效并丢弃。
!!! warning "警告"
GoToSocial 版本 0.17.x 和 0.18.x 没有包含指向批准对象的 `result`,而是直接在 `approvedBy` 中发送了 `Accept` 的 URI/ID。
GoToSocial 版本 0.18.x 部分地向批准对象类型提供了向前兼容,因为它可以对解引用得到的 `Accept` 或批准对象进行验证,同时仍在 `approvedBy` 字段中发送 `Accept` 的 URI。
GoToSocial 版本 0.19.x 及更高版本将按照本文档所述发送指向批准对象的 `approvedBy`,而不是发送 `Accept` 的 URI。
### 验证在粉丝或关注集合中的存在
如果一个行为体(通过 `Like`、`inReplyTo` 或 `Announce`)对一个对象进行互动,而其权限依赖于其出现在 `interactionPolicy``always` 字段里 Followers 或 Following 集合,则其服务器**仍应等待**目标行为体的服务器发出 `Accept` 消息后,再将该互动以带有 `approvedBy` 属性(值为批准 URI/ID的形式广泛分发。
这是为了防止第三方服务器需要以某种方式验证进行互动的行为体是否存在于被互动行为体的粉丝或关注集合中。让目标服务器来做验证,并信任其隐式批准互动的行为体存在于相应集合中会更简单。
同理,当接收到一个行为体的互动,且其权限与 `always` 属性中关注或粉丝集合中的某一项匹配时,被互动行为体所在的服务器应**总是**确保尽快发送 `Accept` 消息,以便发起互动行为体所在的服务器可以带上适当的批准证明分发该互动。
这一过程应该绕过正常的"待批准"阶段,也就是说,被互动行为体所在的服务器无需通知被互动行为体有待处理的交互,并等待行为体接受或拒绝,因为行为体实际上已经明确同意这些交互。在 GoToSocial 的代码库中,这一过程称为“预先批准”。
### 可选行为
本节描述了在发送 `Accept``Reject` 消息时实现者*可能*使用、以及在接收时应考虑的可选行为。
#### 总是发送 `Accept` 消息
实现者可能希望:即使根据所在 `always` 数组,互动行为已被默认或显式允许,也要向外站互动者发送一个 `Accept` 消息。当接收到这样的 `Accept` 时,实现者可能仍希望更新其互动记录,将 `approvedBy` URI 更新为指向批准对象。这在以后处理撤回TODO时可能会有所帮助。
#### 类型提示:`Accept` 和 `Reject` 的内联 `object` 属性
如果需要,实现者可以部分展开/内联 `Accept``Reject` 消息的 `object` 属性,以向外站服务器提示即将被接受或拒绝的互动类型。当以这种方式内联时,`object` 中至少必须定义 `type``id`。例如:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"cc": [
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/post_author/followers"
],
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/reject/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": {
"type": "Note",
"id": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
[...]
},
"result": "https://example.org/users/post_author/approvals/01JMPS01E54DG9JCF2ZK3JDMXE",
"type": "Accept"
}
```
#### 在 `Accept``Reject` 消息中设定 `target` 属性
如果需要,实现者可以在发出的 `Accept``Reject` 消息中设置 `target` 属性,其值为互动目标帖文的 `id`,以便外站服务器更容易理解所接受或拒绝的互动的形状和关联性。
例如,下面这个 JSON 对象接受了 `@someone@somewhere.else.example.org` 试图回复 id 为 `https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT` 的帖文的互动:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"cc": [
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/post_author/followers"
],
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/reject/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"target": "https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT",
"result": "https://example.org/users/post_author/approvals/01JMPS01E54DG9JCF2ZK3JDMXE",
"type": "Accept"
}
```
如果需要,`target` 属性也可部分展开/内联以提示互动目标帖文的类型。在内联时,`target` 至少必须定义 `type``id`。例如:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"cc": [
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/post_author/followers"
],
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/reject/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"target": {
"type": "Note",
"id": "https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT"
[ ... ]
},
"result": "https://example.org/users/post_author/approvals/01JMPS01E54DG9JCF2ZK3JDMXE",
"type": "Accept"
}
```

View file

@ -217,527 +217,9 @@ GoToSocial 在解析传入的 `Object` 时使用 `content` 和 `contentMap` 属
## 互动规则
GoToSocial 使用 `interactionPolicy` 属性告知外站给定帖文允许的互动类型(有前提)
GoToSocial 在帖文中使用 `interactionPolicy` 属性,以向外站实例描述对于任何给定的帖子,哪些类型的互动在条件允许的情况下可以被原始服务器处理和存储
!!! danger "危险"
互动规则旨在限制用户贴文上用户不希望的回复和其他互动的有害影响(例如,“回复家(reply guys)” —— 不请自来地发表冒失回复的人)。
然而,这远远不能满足这一目的,因为仍然有许多“额外”方式可以分发或回复贴文,进而超出用户的初衷或意图。
例如,用户可能创建一个附有非常严格互动规则的贴文,却发现其他服务器软件不尊重该规则,而其他实例上的用户从他们的实例视角进行讨论并回复该贴文。原始发布者的实例将自动从视图中删除这些用户不想要的互动,但外站实例可能仍会显示它们。
另一个例子:有人可能会看到一个指定没人可以回复的贴文,但截屏该贴文,将截屏作为新帖文发布,并将提及原作者或只是附上原贴文的 URL。在这种情况下他们成功通过新创建的贴文串来达到“回复”该贴文的目的。
无论好坏GoToSocial 只能为这一部分问题提供尽最大努力的部分技术解决方案,这更多的是一个社会行为和边界的问题。
### 概述
`interactionPolicy` 是贴文类 `Object`(如 `Note`、`Article`、`Question` 等)附带的一个属性,其格式如下:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [ "始终可进行此操作的零个或多个 URI" ],
"approvalRequired": [ "需要批准才能进行此操作的零个或多个 URI" ]
},
"canReply": {
"always": [ "始终可进行此操作的零个或多个 URI" ],
"approvalRequired": [ "需要批准才能进行此操作的零个或多个 URI" ]
},
"canAnnounce": {
"always": [ "始终可进行此操作的零个或多个 URI" ],
"approvalRequired": [ "需要批准才能进行此操作的零个或多个 URI" ]
}
},
[...]
}
```
在此对象中:
- `canLike` 指定可创建 `Like` 并将帖文 URI 作为 `Like``Object` 的人。
- `canReply` 指定可创建 `inReplyTo` 设置为帖文 URI 的帖文的人。
- `canAnnounce` 指定可创建 `Announce` 并将帖文 URI 作为 `Announce``Object` 的人。
并且:
- `always` 是一个 ActivityPub URI/ID 的 `Actor``Actor``Collection`,无需 `Accept` 即可进行互动分发到其粉丝。
- `approvalRequired` 是一个 ActivityPub URI/ID 的 `Actor``Actor``Collection`,可以互动,但在将互动分发给其粉丝之前需要获得 `Accept`
`always``approvalRequired` 的有效 URI 条目包括 magic ActivityStreams 公共 URI `https://www.w3.org/ns/activitystreams#Public`,贴文创建者的 `Following` 和/或 `Followers` 集合的 URI以及个人请求体的 URI。例如
```json
[
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/someone/followers",
"https://example.org/users/someone/following",
"https://example.org/users/someone_else",
"https://somewhere.else.example.org/users/someone_on_a_different_instance"
]
```
### 指定无人能进行的操作
!!! note "注意"
即使规则指定无人可互动GoToSocial 仍做出默认假设。参见[默认假设](#默认假设)。
空数组或缺少/空的键表示无人能进行此互动。
例如,以下 `canLike` 指定无人能 `Like` 该贴文:
```json
"canLike": {
"always": [],
"approvalRequired": []
},
```
类似的,`canLike` 值为 `null` 也表示无人能 `Like` 该帖:
```json
"canLike": null
```
```json
"canLike": {
"always": null,
"approvalRequired": null
}
```
缺失的 `canLike` 值同样表达了相同的意思:
```json
{
[...],
"interactionPolicy": {
"canReply": {
"always": [ "始终可进行此操作的零个或多个 URI" ],
"approvalRequired": [ "需要批准才能进行此操作的零个或多个 URI" ]
},
"canAnnounce": {
"always": [ "始终可进行此操作的零个或多个 URI" ],
"approvalRequired": [ "需要批准才能进行此操作的零个或多个 URI" ]
}
},
[...]
}
```
### 冲突/重复值
在用户位于集合 URI 中, 且也通过 URI 被显式指定的情况下,**更具体的值**优先。
例如:
```json
[...],
"canReply": {
"always": [
"https://example.org/users/someone"
],
"approvalRequired": [
"https://www.w3.org/ns/activitystreams#Public"
]
},
[...]
```
在此情形下,`@someone@example.org` 位于 `always` 数组中,并且也存在于 `approvalRequired` 数组中的 magic ActivityStreams 公共集合中。在这种情况下,他们可以始终回复,因为 `always` 值更为明确。
另一个例子:
```json
[...],
"canReply": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": [
"https://example.org/users/someone"
]
},
[...]
```
在此,`@someone@example.org` 位于 `approvalRequired` 数组中,但也隐含地存在于 `always` 数组中的 magic ActivityStreams 公共集合中。在这种情况下,除了 `@someone@example.org` 需要批准外,其他人都可以无需批准进行回复。
在相同 URI 存在于 `always``approvalRequired` 两者中时,**最高级别的权限**优先(即 `always` 中的 URI 优先于 `approvalRequired` 中的相同 URI
### 默认假设
GoToSocial 对 `interactionPolicy` 做出若干默认假设。
**首先**,无论贴文的可见性和 `interactionPolicy` 如何,被[提及](#提及)或回复的用户应**始终**能够回复该贴而无需批准,**除非**提及或回复他们的贴文本身正在等待批准。
这是为了防止潜在的骚扰者在辱骂贴文中提及某人,并不给被提及的用户任何回复的机会。
因此当发送互动规则时GoToSocial 始终将提及用户的 URI 添加到 `canReply.always` 数组中,除非它们已被 magic ActivityStreams 公共 URI 覆盖。
同样,在执行接收到的互动规则时,即使用户 URI 不存在于 `canReply.always` 数组中GoToSocial 也将被提及用户的 URI 视作已存在。
**其次**,用户应**始终**能够回复自己的贴文,点赞自己的贴文,并转发自己的贴文而无需批准,**除非**该贴文本身正在等待批准。
因此当发送互动规则时GoToSocial 始终将贴文作者的 URI 添加到 `canLike.always`、`canReply.always` 和 `canAnnounce.always` 数组中,除非它们已被 magic ActivityStreams 公共 URI 覆盖。
同样,在执行接收到的互动规则时,即使贴文作者 URI 不存在于这些 `always` 数组中GoToSocial 也始终将贴文作者 URI 视为已存在。
### 默认值
当贴文上没有 `interactionPolicy` 属性时GoToSocial 会根据贴文可见级别和发帖作者为该帖假定默认的 `interactionPolicy`
对于 `@someone@example.org` 的**公开**或**未列出**贴文,默认 `interactionPolicy` 为:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
}
},
[...]
}
```
对于 `@someone@example.org` 的**仅限粉丝**贴文,假定的 `interactionPolicy` 为:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://example.org/users/someone",
"https://example.org/users/someone/followers",
[...提及的用户的 URI...]
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/someone",
"https://example.org/users/someone/followers",
[...提及的用户的 URI...]
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://example.org/users/someone"
],
"approvalRequired": []
}
},
[...]
}
```
对于 `@someone@example.org` 的**私信**贴文,假定的 `interactionPolicy` 为:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://example.org/users/someone",
[...提及的用户的 URI...]
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/someone",
[...提及的用户的 URI...]
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://example.org/users/someone"
],
"approvalRequired": []
}
},
[...]
}
```
### 示例 1 - 限制对话范围
在此示例中,用户 `@the_mighty_zork` 想开始与用户 `@booblover6969``@hodor` 之间的对话。
为了避免讨论被他人打断,他们希望来自三名参与者以外的用户的回复仅在获得 `@the_mighty_zork` 批准后才被允许。
此外,他们希望将贴文转发/`Announce` 的权利限制为仅限于他们自己的粉丝和三个对话参与者。
然而,任何人都可以 `Like` `@the_mighty_zork` 的贴文。
这可以通过以下 `interactionPolicy` 来实现,它附加在可见性为公开的帖文上:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/the_mighty_zork",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
],
"approvalRequired": [
"https://www.w3.org/ns/activitystreams#Public"
]
},
"canAnnounce": {
"always": [
"https://example.org/users/the_mighty_zork",
"https://example.org/users/the_mighty_zork/followers",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
],
"approvalRequired": []
}
},
[...]
}
```
### 示例 2 - 长独白贴文串
在此示例中,用户 `@the_mighty_zork` 想写一个长篇独白。
他们不介意别人转发和点赞贴文,但不想收到任何回复,因为他们没有精力去管理讨论;他们只是想通过发泄自己的想法去表达自我。
这可以通过在贴文串中的每个贴文上设置以下 `interactionPolicy` 来实现:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/the_mighty_zork"
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
}
},
[...]
}
```
在这里,任何人都可以点赞或转发,但无人能够回复(除了 `@the_mighty_zork` 自己)。
### 示例 3 - 完全开放
在此示例中,`@the_mighty_zork` 想写一篇完全开放的贴文,任何能看到此帖的人都可以进行回复、转发或点赞(即解锁和公开贴文默认行为):
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
}
},
[...]
}
```
### 请求、获得和验证批准
当用户的 URI 在需要获得批准的互动的 `approvalRequired` 数组中时,如果他们希望获得批准以分发互动,应该执行以下步骤:
1. 像往常一样撰写互动 `Activity`(即 `Like`、`Create` (回复)或 `Announce`)。
2. 像往常一样将 `Activity``to``cc` 地址设为预期的收件人。
3. 将 `Activity` **仅**发送到要互动帖的作者的 `Inbox`(或 `sharedInbox`)。
4. **此时不要进一步分发 `Activity`**
此时,互动可视为等待批准,并不应该显示在被互动的贴文的回复或点赞集合等中。
可以向发送互动的用户显示“互动待批准”状态,但理想情况下不应该向与该用户共享实例的其他用户显示。
从这里开始,可能会出现以下三种情况之一:
#### 拒绝
在这种情况下,互动目标贴文的作者发回一个 `Reject` `Activity`,该活动的 `Object` 属性带有待拒绝互动活动的 URI/ID。
例如,以下 JSON 对象 `Reject``@someone@somewhere.else.example.org` 回复 `@post_author@example.org` 贴文的尝试:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/reject/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"type": "Reject"
}
```
如果发生这种情况,`@someone@somewhere.else.example.org`(及其实例)应视交互为被拒绝。该实例应从其内部存储(即数据库)中删除该活动,或以其他方式表明它已被拒绝,并且不应进一步分发该 `Activity` 或重试该交互。
#### 无响应
在这种情况下,正在互动的贴文的作者从不发送 `Reject``Accept` `Activity`。在这种情况下,交互被视为永久“待处理”。实例可能希望实现某种清理功能,达到一定时间期限的已发送且待处理交互应被视为过期,然后按照上述方式被处理为 `Rejected` 并删除。
#### 接受
在这种情况下,正在互动的贴文的作者发回一个`Accept` `Activity`,该活动的 `Object` 属性带有待批准互动活动的 URI/ID。
例如,以下 JSON 对象 `Accept``@someone@somewhere.else.example.org` 回复 `@post_author@example.org` 贴文的尝试:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/post_author",
"cc": [
"https://www.w3.org/ns/activitystreams#Public",
"https://example.org/users/post_author/followers"
],
"to": "https://somewhere.else.example.org/users/someone",
"id": "https://example.org/users/post_author/activities/accept/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://somewhere.else.example.org/users/someone/statuses/01J17XY2VXGMNNPH1XR7BG2524",
"type": "Accept"
}
```
如果发生这种情况,`@someone@somewhere.else.example.org`(及其实例)应视为交互已被批准/接受。然后,该实例可以自由地将此交互 `Activity` 分发给所有由 `to`、`cc` 等目标的接收者,并附加属性 `approvedBy`
### 验证在粉丝/关注中是否存在
如果一个 `Actor` 在其互动规则的 `always` 字段中因为存在于 `Followers``Following` 集合中而被允许进行交互(例如 `Like`、`inReplyTo` 或 `Announce`),则其服务器仍应等待来自目标帐户服务器的 `Accept`,然后才更广泛地分发交互,并将 `approvedBy` 属性设置为 `Accept` 的 URI。
这样可以防止第三方服务器被迫以某种方式验证互动的 `Actor` 是否存在于接收互动的用户的 `Followers``Following` 集合中。让目标服务器进行验证,并采信其 `Accept` ,将其视为交互 `Actor` 存在于相关集合中的证明,更为简单。
同样,当接收到一个具有匹配 `Following``Followers` 集合的 `Actor` 的互动请求时,接收互动的 `Actor` 的服务器应确保尽快发送出 `Accept`,以便交互 `Actor` 服务器可以带着适当的接受证明发送出 `Activity`
这个过程应绕过通常的“待批准”阶段,因此没有必要通知 `Actor` 待批准的交互,因为他们已明确同意。在 GoToSocial 代码库中,这被称为“预批准”。
### `approvedBy`
`approvedBy` 是一个附加属性,添加到 `Like``Announce` 活动以及任何被视为“贴文”的 `Object`(如 `Note`、`Article`)中。
`approvedBy` 的存在表明贴文的作者接受了由 `Activity` 作为目标或由 `Object` 所回复的互动,并现在可以分发给其预期观众。
`approvedBy` 的值应为创建 `Accept` `Activity` 的接收交互贴文作者的 URI。
例如,以下 `Announce` `Activity``approvedBy` 表示它已被 `@post_author@example.org` `Accept`
```json
{
"actor": "https://somewhere.else.example.org/users/someone",
"to": [
"https://somewhere.else.example.org/users/someone/followers"
],
"cc": [
"https://example.org/users/post_author"
],
"id": "https://somewhere.else.example.org/users/someone/activities/announce/01J0K2YXP9QCT5BE1JWQSAM3B6",
"object": "https://example.org/users/post_author/statuses/01J17ZZFK6W82K9MJ9SYQ33Y3D",
"approvedBy": "https://example.org/users/post_author/activities/accept/01J18043HGECBDZQPT09CP6F2X",
"type": "Announce"
}
```
接收到一个带有 `approvedBy` 值的 `Activity` 时,外站实例应解引用字段的 URI 值以获取 `Accept` `Activity`
然后,他们应验证 `Accept` `Activity``object` 值是否等于交互 `Activity``Object``id`,并验证 `actor` 值是否等于接收交互的贴文的作者。
此外,他们应确保解引用的 `Accept` 的 URL 域名等于接收交互贴文的作者的 URL 域名。
如果无法解引用 `Accept` 或未通过有效性检查,则交互应被视为无效并丢弃。
由于这种验证机制,实例应确保他们对涉及 `interactionPolicy``Accept` URI 的解引用响应提供一个有效的 ActivityPub 对象。如果不这样做,他们会无意中限制外站实例分发其贴文的能力。
### 后续回复/范围扩展
对话中的每个后续回复将有其自己的互动规则,由创建回复的用户选择。换句话说,整个*对话*或*贴文串*并不由一个 `interactionPolicy` 控制,而是贴文串中的每个后续贴文可以由贴文作者设置不同的规则。
不幸的是,这意味着即使有 `interactionPolicy`,贴文串的范围也可能不小心超出第一个贴文作者的意图。
例如,在上述[示例 1](#示例-1---限制对话范围)中,`@the_mighty_zork` 在第一个贴文中指定了 `canReply.always` 值为
```json
[
"https://example.org/users/the_mighty_zork",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
]
```
在后续回复中,`@booblover6969` 无意或有意地将 `canReply.always` 值设为:
```json
[
"https://www.w3.org/ns/activitystreams#Public"
]
```
这扩大了对话的范围,因为现在任何人都可以回复 `@booblover6969` 的贴文,并可能也在该回复中标记 `@the_mighty_zork`
为了避免这个问题,建议外站实例防止用户能够扩大范围(具体机制待定)。
同时,实例应将任何与仍处于待批准状态的贴文或贴文类似的 `Object` 的交互视作待批准。
换句话说,只要某条贴文处于待批准状态,实例应将该贴文下的所有互动标记为待批准,无论此贴文的互动规则通常允许什么。
这可避免有用户回复贴文,且在回复尚未得到批准的情况下继续回复*他们自己的回复*并将其标记为允许(作为贴文回复的作者,他们默认拥有对贴文回复的[回复权限](#默认假设))。
有关更多详细信息,请参阅单独的 [互动规则](./interaction_policy.md) 文档。
## 投票

View file

@ -42,10 +42,10 @@ nano docker-compose.yaml
* `latest`:默认值。这指向最新的稳定版本的 GoToSocial。
* `snapshot`:指向当前在主分支上的代码。不保证稳定,可能经常出错。谨慎使用。
* `vX.Y.Z`:发布标签。这指向 GoToSocial 的特定、稳定的版本。
* `X.Y.Z`:发布标签。这指向 GoToSocial 的特定、稳定的版本。
!!! tip "提示"
`latest``snapshot` 标签是动态标签,而 `vX.Y.Z` 标签是固定的。拉取动态标签的结果可能每天都会变化。同一系统上的 `latest` 可能与不同系统上的 `latest` 不同。建议使用 `vX.Y.Z` 标签,以便你始终确切知道运行的是 GoToSocial 的哪个版本。发布列表可以在[这里](https://github.com/superseriousbusiness/gotosocial/releases)找到,最新的发布在顶部。
`latest``snapshot` 标签是动态标签,而 `X.Y.Z` 标签是固定的。拉取动态标签的结果可能每天都会变化。同一系统上的 `latest` 可能与不同系统上的 `latest` 不同。建议使用 `X.Y.Z` 标签,以便你始终确切知道运行的是 GoToSocial 的哪个版本。发布列表可以在[这里](https://github.com/superseriousbusiness/gotosocial/releases)找到,最新的发布在顶部。
### 主机

View file

@ -30,6 +30,7 @@ nav:
- "user_guide/password_management.md"
- "user_guide/rss.md"
- "user_guide/migration.md"
- "user_guide/importing_posts.md"
- "开始部署":
- "getting_started/index.md"
- "getting_started/releases.md"
@ -104,6 +105,7 @@ nav:
- "federation/ratelimiting.md"
- "federation/actors.md"
- "federation/posts.md"
- "federation/interaction_policy.md"
- "federation/moderation.md"
- "federation/glossary.md"
- "客户端 API 文档":

View file

@ -43,7 +43,8 @@ GoToSocial 是一个用 Golang 编写的 [ActivityPub](https://activitypub.rocks
- [已知问题](#已知问题)
- [安装 GoToSocial](#安装-gotosocial)
- [支持的平台](#支持的平台)
- [FreeBSD](#freebsd)
- [64位](#64位)
- [BSD系](#bsd系)
- [32位](#32位)
- [OpenBSD](#openbsd)
- [稳定版本](#稳定版本)
@ -276,19 +277,34 @@ GoToSocial 支持 [OpenID Connect (OIDC)](https://openid.net/connect/) 身份提
以下是 GoToSocial 当前针对不同平台的支持状态(如果某个平台未列出,则表示我们尚未检查,因此我们不清楚):
| 操作系统 | 架构 | 支持程度 | 二进制文件 | Docker 容器 |
| ------- | --------------------- | ---------------------------------- | ---------- | --------------- |
| Linux | x86-64/AMD64 (64位) | 🟢 完全支持 | 是 | 是 |
| Linux | Armv8/ARM64 (64位) | 🟢 完全支持 | 是 | 是 |
| FreeBSD | x86-64/AMD64 (64位) | 🟢 完全支持<sup>[1](#freebsd)</sup> | 是 | 否 |
| Linux | x86-32/i386 (32位) | 🟡 部分支持<sup>[2](#32-bit)</sup> | 是 | 是 |
| Linux | Armv7/ARM32 (32位) | 🟡 部分支持<sup>[2](#32-bit)</sup> | 是 | 是 |
| Linux | Armv6/ARM32 (32位) | 🟡 部分支持<sup>[2](#32-bit)</sup> | 是 | 是 |
| OpenBSD | 任何架构 | 🔴 不支持<sup>[3](#openbsd)</sup> | 否 | 否 |
| FreeBSD | Armv8/ARM64 (64位) | 🟢 完全支持<sup>[1](#freebsd)</sup> | 是 | 否 |
| NetBSD | x86-64/AMD64 (64位) | 🟢 完全支持<sup>[1](#netbsd)</sup> | 是 | 否 |
| NetBSD | Armv8/ARM64 (64位) | 🟢 完全支持<sup>[1](#netbsd)</sup> | 是 | 否 |
| Linux | x86-32/i386 (32位) | 🟡 部分支持<sup>[2](#32位)</sup> | 是 | 是 |
| Linux | Armv7/ARM32 (32位) | 🟡 部分支持<sup>[2](#32位)</sup> | 是 | 是 |
| Linux | Armv6/ARM32 (32位) | 🟡 部分支持<sup>[2](#32位)</sup> | 是 | 是 |
| OpenBSD | Any | 🔴 不支持<sup>[3](#openbsd)</sup> | 否 | 否 |
#### FreeBSD
#### 64位
大多数情况下可用,只是在 WASM SQLite 上有一些问题;在 FreeBSD 上安装时请仔细查看发行说明。如果使用 Postgres则不应出现问题。
64位平台需要以下(现在很常见的)CPU指令:
- x86-64需要SSE4.1(用于媒体解码和WASM SQLite)
- Armv8需要ARM64大型系统扩展(ARM64 Large System Extensions)(特别是在使用WASM SQLite时)
如果没有这些指令,性能将会受到影响。在这些情况下,您可以尝试使用完全**不受支持、实验性的**[nowasm](https://docs.gotosocial.org/en/latest/advanced/builds/nowasm/)标签自行构建二进制文件。
#### BSD系
大部分可以正常工作,只是使用WASM SQLite时需要[注意几个事项](https://github.com/ncruces/go-sqlite3/wiki/Support-matrix);在NetBSD或FreeBSD上安装时请仔细查看发行说明。如果使用Postgres运行,您应该不会有任何问题。
#### 32位
@ -300,7 +316,7 @@ GtS 在像 i386 或 Armv6/v7 这样的 32 位系统上表现不佳,这主要
#### OpenBSD
由于性能问题(空闲时的高内存占用,在处理媒体时崩溃),此系统被标记为不支持。
由于性能问题(不支持 WASM 编译器,空闲时的高内存占用,在处理媒体时崩溃),此系统被标记为不支持。
虽然我们不支持在 OpenBSD 上运行 GtS但你可以尝试使用完全**不受支持、实验性**的 [nowasm](https://docs.gotosocial.org/zh-cn/latest/advanced/builds/nowasm/) 标签自行构建二进制文件。
@ -421,6 +437,7 @@ GoToSocial 使用以下开源库、框架和工具,在此声明并致谢 💕
- [superseriousbusiness/exif-terminator](https://codeberg.org/superseriousbusiness/exif-terminator); EXIF 数据擦除。 [GNU AGPL v3 许可证](https://spdx.org/licenses/AGPL-3.0-or-later.html)。
- [superseriousbusiness/httpsig](https://codeberg.org/superseriousbusiness/httpsig) 从 [go-fed/httpsig](https://github.com/go-fed/httpsig) 派生; 安全 HTTP 签名库。 [BSD-3-Clause 许可证](https://spdx.org/licenses/BSD-3-Clause.html)。
- [superseriousbusiness/oauth2](https://codeberg.org/superseriousbusiness/oauth2) 从 [go-oauth2/oauth2](https://github.com/go-oauth2/oauth2) 派生; OAuth 服务器框架和令牌处理。 [MIT 许可证](https://spdx.org/licenses/MIT.html)。
- [temoto/robotstxt](https://github.com/temoto/robotstxt); robots.txt 解析。 [MIT 许可证](https://spdx.org/licenses/MIT.html)。
- [tdewolff/minify](https://github.com/tdewolff/minify); Markdown 帖文的 HTML 压缩。 [MIT 许可证](https://spdx.org/licenses/MIT.html)。
- [uber-go/automaxprocs](https://github.com/uber-go/automaxprocs); GOMAXPROCS 自动化。 [MIT 许可证](https://spdx.org/licenses/MIT.html)。
- [ulule/limiter](https://github.com/ulule/limiter); http 流量限制中间件。 [MIT 许可证](https://spdx.org/licenses/MIT.html)。

View file

@ -0,0 +1,42 @@
# 从以前的实例导入帖文
从 v0.18.0 版本开始GoToSocial 可以导入你在之前实例中的帖文存档。
!!! tip "注意"
此过程会为你之前的帖文创建一个 *副本*。截至 2025 年初Fediverse 中部署的 ActivityPub 还没有提供 *迁移* 帖文的方法,也还不能使现有帖文在新位置上可被检索。如果你之前的实例停止运营,则原始帖文也会消失——但你依然会保留此处被导入的副本。
## 你可以导入的内容
- 你的独立帖文
- 你对自己帖文的回复
- 这些帖文的原始创建日期
- 随附在这些帖文中的媒体(照片、音频、视频)
- 帖文中使用的表情符号(前提是这些表情符号已经在你的实例上提供)
导入帖文的过程是有意减少打扰的:导入的帖文不会被推送到你在外站实例中的粉丝,不会插入到你实例的时间线上,也不会为订阅你的新帖文的用户生成通知。这意味着你可以导入大量帖文而不会打扰到粉丝。不过,一旦帖文导入后,你依然可以像对待其他帖文那样进行转发或分享其的链接。
## 你无法导入的内容
- 对其他账户的回复
- 对其他账户的提及
- 转发(无论是对你自己的帖文的转发还是对其他账户的帖文的转发)
- 其他账户对你帖文进行点赞或转发的记录
- 带有投票的帖文
- 日期在 Unix 纪元1970 年 1 月 1 日)或之前的帖文
这些对其他账户互动的限制是出于礼貌的设计考虑:允许在导入的旧帖文中回复他人可能会引发混淆(例如“嘿,我记得这段对话,但不是和这个账户进行的”)。此外,如果你导入了大量对某人连续对话的回复,然后再转发它们,使得这些内容在对方的实例上可见,可能会导致该用户在原对话结束多年后收到大量提及或待处理提及通知。出于类似的原因,重放点赞或转发记录将不可避免地带来信息骚扰的问题。
## 如何导入你的帖文
当前,该过程需要借助利用 GTS API 的第三方工具。未来,我们可能会将此功能整合到 GoToSocial 内部:请关注 [issue #2](https://github.com/superseriousbusiness/gotosocial/issues/2) 以获取最新动态。
[`slurp`](https://github.com/VyrCossont/slurp)(由 GTS 开发者 Vyr Cossont 开发)可以导入来自 [Mastodon 归档](https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-mastodon-archive) 和 [Pixelfed 归档](https://github.com/VyrCossont/slurp?tab=readme-ov-file#importing-a-pixelfed-archive) 的帖文。请查阅 `slurp` 的文档、[Mastodon 关于导出数据的说明](https://docs.joinmastodon.org/user/moving/#export) 以及 Jeff Sikes 的文章 [“使用 Slurp 将 Pixelfed 帖文导入 GoToSocial”](https://box464.com/posts/gotosocial-slurp/) 以了解更多细节。你需要熟悉命令行基础,并提前安装 Git 和 Go 编译器。
!!! warning "警告"
如果你从 Pixelfed 导入,请注意 Pixelfed 归档中不包含你的照片,因此在导入时,你原来的实例和账户必须仍然可用。
## 开发者
你可以通过向 POST /v1/statuses/create 发送带有 scheduled_at 参数的请求来使用 GoToSocial 的日期回溯功能。如果设置了该参数且该日期位于 *过去*该帖文将被视为对旧帖文的导入scheduled_at 参数的日期将用于设置帖文的创建日期和 ID。GoToSocial 使用 [ULID](https://github.com/ulid/spec) 作为 ID且这些 ID 可以通过字典序排序来按时间排序。)此外,该帖文不会被推送给粉丝、插入时间线,也不会触发通知。创建既往帖文的导入时,返回类型与正常发布帖文时的返回类型相同,均为一个 status 对象。
由于此过程使用的是 GTS API原始帖文不必为 ActivityPub 活动,其来源可以是博客、 Cohost、Bluesky、Usenet 等平台。

View file

@ -25,7 +25,7 @@ GoToSocial 支持使用 `Move` 活动进行账号迁移。
迁移你的账号将从你当前账号向粉丝发送一条消息,指示他们关注目标账号。根据你的粉丝使用的服务器软件,他们可能会自动向目标账号发送关注请求,并取消关注你当前账号。
目前,**只有你的粉丝会转移到新账号**。其他如关注列表、贴文、媒体、书签、点赞、屏蔽等不会转移。
目前,**只有你的粉丝会转移到新账号**。其他如关注列表、媒体、书签、点赞、屏蔽等不会转移。作为一个独立的操作,你可以[导入你的帖文](./importing_posts.md)。
一旦你的账号迁移完成,你当前的(旧的)账号的网页视图将显示已迁移的信息,以及迁移的目标账号。

View file

@ -266,3 +266,26 @@ markdown 设置表示你的贴文应被按 Markdown 格式解析,这是一种
!!! info "附注"
由于各种原因,通过导入不可能一定会重新创建上传的 CSV 文件中的每个条目。例如,假设你试图导入包含 `example_account` 的关注 CSV`example_account` 的实例已下线,或者它们的实例封禁了你的实例,或你的实例封禁了它们的实例等。在这种情况下,将无法创建对 `example_account` 的关注。
!!! warning "警告"
CSV 格式的隐藏列表数据不包含失效日期,因此临时隐藏在导出(和导入)时会被视为永久隐藏。
## 访问令牌
在访问令牌部分,你可以查看和撤销被你授权访问你的账户和/或代表你执行操作的应用所拥有的 [OAuth 访问令牌](https://www.oauth.com/oauth2-servers/access-tokens/)。
![访问令牌页面。](../public/user-settings-access-tokens.png)
如果你曾多次使用同一应用登录,或者在多个设备或浏览器中登录,你可能会看到多个具有相同应用名称的令牌。这是正常现象!例如,假设你使用 Pinafore 分别在手机和笔记本电脑浏览器上登录,你可能会看到两个由 Pinafore 所拥有的不同令牌。
你可以点击某个令牌下方的“使令牌失效”按钮来使该令牌失效。这会将该令牌从数据库中移除。使用该令牌访问你账户的应用随后将不再被授权访问相关信息,因此你需要重新注销和/或重新使用该应用进行登录。
退出某个应用并不一定会将令牌从 GoToSocial 数据库中移除,所以之前很久使用过的应用可能遗留有旧令牌。因此,建议经常检查和撤销那些从未使用过或长时间未使用的令牌;这是一个良好的安全惯例——只保留你需要的令牌,而且点击那个大红按钮也很有趣。
!!! danger "风险提示"
如果你发现了任何来自于你不认识或不记得曾授权过的应用的令牌,请撤销它们,并考虑尽快更改您的密码。
!!! note "附注"
令牌的“最后使用”时间是近似值,可能存在正负一小时的误差。