# 数据采集原理

Canonical page: https://phishdestroy.github.io/TgWitness/zh/docs/reference/collection/

观察范围、实时更新、复核、附件、用户操作以及“缺口”的含义，逐条记录。

TgWitness 记录已连接的 Telegram 账户所观察到的内容。该日志保存 这些观察结果、其时间顺序以及随附的上下文信息。它不会 根据缺失的消息或账户处于连接状态的情况，推断出未被观察到的操作。

## 从登录到日志

流程图 · 授权用户账户 → 选择可访问的群组和频道; 选择可访问的群组和频道 → 保存事件和附件设置; 保存事件和附件设置 → 开始监控; 开始监控 → 接收来自活跃客户端的更新; 接收来自活跃客户端的更新 → 应用来源与事件政策; 应用来源与事件政策 → 追加一份经过签名的观察记录; 追加一份经过签名的观察记录 → 查看或导出日志; 追加一份经过签名的观察记录 → 处理队列中的任何附件; 处理队列中的任何附件 → 附上下载结果 · 授权用户账户 · 选择可访问的群组和频道 · 保存事件和附件设置 · 开始监控 · 接收来自活跃客户端的更新 · 应用来源与事件政策 · 追加一份经过签名的观察记录 · 查看或导出日志 · 处理队列中的任何附件 · 附上下载结果

**图表转为文本**

1. 授权用户账户 → 选择可访问的群组和频道
2. 选择可访问的群组和频道 → 保存事件和附件设置
3. 保存事件和附件设置 → 开始监控
4. 开始监控 → 接收来自活跃客户端的更新
5. 接收来自活跃客户端的更新 → 应用来源与事件政策
6. 应用来源与事件政策 → 追加一份经过签名的观察记录
7. 追加一份经过签名的观察记录 → 查看或导出日志
8. 追加一份经过签名的观察记录 → 处理队列中的任何附件
9. 处理队列中的任何附件 → 附上下载结果

授权、访问数据源、运行中的采集器以及完整交付是 三个不同的问题。登录成功并不意味着可以访问所有群组。 传输连接成功并不意味着所有相关更新都已送达。

## 监控范围：选定的聊天群组、某个文件夹或整个账户

来源 → **监控范围**决定了工作区将记录哪些聊天记录。

| 模式 | 记录 | 新聊天记录 |
| --- | --- | --- |
| 选定聊天（默认） | 仅限您手动添加的聊天记录 | 绝不自动添加 |
| Telegram 文件夹 | 该账户某文件夹中的聊天记录：包含按名称列出的聊天记录，加上该文件夹的分类（联系人、非联系人、群组、频道、机器人），减去被排除的聊天记录，以及（如果文件夹有此说明）已归档的聊天记录 | 匹配的聊天记录一经激活即被添加；您在 Telegram 中添加到文件夹的聊天记录将在一小时内被捕获 |
| 完整账户 | 该账户所见的所有聊天记录 | 每当出现首次更新时，新的聊天、群组、私聊或机器人都会被立即添加进来 |

- **消息来源类型**（频道、群组、私聊、机器人）可进一步细化文件夹和 整个账户模式。所选聊天可为任意类型，包括私聊和机器人。
- **被排除的聊天室**在任何模式下均不会被记录。在文件夹模式和整个账户模式下， 对源聊天室执行*“排除*”或*“移除”*操作会将其加入此列表，因此范围设置不会再次将其纳入。 若手动再次选择该聊天（在“来源”或“聊天”中），则将其从列表中移除。该列表 最多可容纳 5,000 个聊天；超过此限时*，“移除”操作*将被拒绝，但可选择暂停该聊天。
- **自身操作**（默认开启）：该账户发送的消息、其编辑操作以及 回复键盘的按键操作。关闭后，将跳过外发消息和编辑操作。
- 切换到某个文件夹或整个账户时会要求确认：这些模式会记录 私人聊天和第三方消息，仅应用于专用账户。 确认操作及每次范围变更都会生成经过`scope.changed`签名的记录。
- 通过范围添加的聊天记录将显示为标记为*“auto*”的来源，记录格式为 `scope.applied` （在开始时及每小时）或 `source.discovered`（监控期间的新聊天）。切换回 选定的聊天记录将暂停所有自动添加的来源。

以下情况不适用：

- **秘密聊天**在两台设备之间采用端到端加密，无论在何种模式下， 均不会被 TgWitness 获取。
- **当 TgWitness 未运行时，不会进行任何记录。**重启后，它会向 Telegram 查询遗漏的更新并重新检查聊天记录，但在长时间 中断后，Telegram 无法返回所有数据。报告和 `verify.py` 会将此类时段显示为数据缺口（参见[覆盖范围](https://phishdestroy.github.io/TgWitness/zh/docs/reference/evidence/#coverage-continuity-gaps-and-unobserved-ids)）。
- 初始仅列出前 1,000 个对话（限制值可在**“参数”**中查看）；较早的 聊天记录将在下次激活时被添加。已添加聊天的早期历史记录不会被获取——如有需要，请 创建历史记录快照或导出完整聊天记录。
- 不会应用那些随时变化的文件夹条件（如静音、已读）：此类聊天 仍会受到监控。
- 在另一款应用中点击的**内联（回调）机器人按钮**对第二个 会话不可见；机器人的回复或编辑会被记录下来。回复键盘按键操作会作为外发 消息发送，并标记为 `button_press`。
- 聊天量越大，请求就越多。Telegram 会因消息量被其视为 过高而限制账号，这也是使用专用账号的又一个理由。

## 范围与事件选择

每个工作区都有其独立的来源。TgWitness 不会加入群组、接受 邀请，也不会自动枚举所有成员。来源必须是 该账户已可访问的。 启动时，收集器会将选定的数据源 与该账户可见的对话进行比对；除非 **在“参数 → 从账户列表读取的聊天**”中另有规定，否则将检查前 1,000 个对话。 未找到的数据源将被标记为**“访问未确认**”，不会被视为已将您移除。

| 设置 | 收集 | 禁用时的效果 |
| --- | --- | --- |
| 新消息 | 普通已发送消息 | 后续的编辑/删除操作可能无法与先前捕获的文本进行比对。 |
| 编辑 | 已交付编辑后的消息版本 | 中间的更改不会在后续过程中被重建。 |
| 删除操作 | 范围限定删除通知与非范围限定账户级通知 | 删除通知不会被添加到日志中。 |
| 反应 | 已交付的反应快照 | 不添加单独的反应更新。 |
| 会员 | 已发送会员服务消息和参与者更新 | 这些会员观察内容未被纳入。 |

设置适用于工作区中所有选定的消息源。保存表单以应用 更改；更改将通过带签名的“更改前”和“更改后”值进行记录。禁用某类别 不会删除之前的记录。重新启用该类别也不会补录遗漏的更新。

操作记录及其他群组服务事件与这些 开关设置相互独立。当会员服务功能启用时，会员服务消息仍会生成消息记录， 即使普通的新消息捕获功能已被禁用。捕获的 Telegram 对象保留嵌入的元数据；开关设置并非信息遮蔽规则。

**私人聊天和普通群组中的删除操作**会以消息 ID 的形式出现，而不包含聊天信息。 这些聊天共享一个账户级别的消息 ID 序列，因此当带有该 ID 的消息 此前已被保存时，其所属聊天即可确定：删除操作将记录在该聊天中， `chat_resolution` 解释了具体原理。 从未被保存的ID将作为**范围未定的删除**记录，其 来源明确标注为未知；收集器不会进行推测。Telegram从不透露是谁删除了 某条消息；当被删除的消息由该账户发送时，记录中会注明 （`deleted_message_was_outgoing`），但不会指名删除者。

## 自主操作

被监控账户发送的消息标记为 `outgoing`。关于外发 消息的编辑说明指出：在私聊和群聊中，仅消息作者可进行编辑；而频道 帖子则可由其他管理员编辑。 当一条发送的消息重复了该聊天中 最新保存的回复键盘上的按钮文本时，该消息会带有`button_press`标记，并附有指向 该键盘记录的链接。

“排除自身操作”的原则同样适用于后台重新检查和自动生成的新聊天记录。 被跳过的发送消息会向前推移重新检查的位置，从而避免阻塞后续收到的 消息。明确的面板操作以及手动请求的历史快照仍会被记录下来。

## 调查模式：加入团队并与机器人对话

**“来源 → 观察范围 → 调查模式**”为专用 账户配置观察范围，该账户将加入团队聊天群、启动机器人并向其发送消息：涵盖整个账户、所有 来源类型、自身操作，以及每个出现的聊天群或机器人的资料及其最近 200条可见消息。 检查表单并点击**“保存范围**”；切换至整个 账户时，系统会要求进行常规确认。

- **按钮。**消息下方的按钮将与该消息一同保留，并在**“聊天”**界面中显示：链接、网页 应用、登录链接、待复制的文本、回调数据、内联查询、请求电话 号码或位置的信息。 链接以文本形式显示，且绝不会由面板自动打开。当机器人 仅更改按钮内容（例如生成新的支付链接）时，这即被视为消息的新版本，无论 是实时更新还是重新检查的结果。
- **新聊天和机器人。**在“文件夹”和“整个账户”模式下，**当新的聊天或机器人 出现时**，系统会在其出现后立即进行保存：

  - 其作为`source.profile`记录的概况：机器人描述和命令、用户、群组或频道的“关于”文本 、成员、关联聊天以及Telegram返回邀请链接时的 邀请链接；
  - 将其最新的可见消息（最多 1,000 条）作为标记为 `new_chat` 的历史快照： 刚加入的团队聊天中的早期消息，或观察者注意到该聊天之前 机器人所说的话。已实时保存的消息不会重复记录。

  启用该模式时，列表中已存在的聊天记录将被添加，但不包含快照。 FloodWait 会暂停此操作，并在之后恢复；失败情况会被记录，而 聊天的实时记录将继续进行。 - **按需保存配置文件。在“聊天”→“配置文件”中选择“保存配置文件”可**保存当前 任何来源的配置文件；最新配置文件将显示在消息上方。 - **不可见。**在其他 Telegram 应用中点击的内联（回调）按钮、机器人对此类点击作出的弹出窗口或 链接，以及在其他应用中使用的邀请链接，均不会传至 TgWitness。但机器人随后发送或编辑的内容会被记录下来。

### 面板操作指南

**“聊天”功能**现已包含一个迷你客户端，该客户端使用所选工作区的 Telegram 账户：

- 编写一条纯文本消息，或在已保存的消息下方选择**“回复”**。即使范围不包括外发更新，系统生成的外发 消息仍会被记录下来。
- 点击当前回调或文本按钮下方的**“Press”按钮**。服务器将再次获取 该消息，若键盘输入内容与保存版本不符，则拒绝该操作。 回调收据保留 Telegram 的弹出文本、提醒标记和 URL；回复内容也会显示 在对话下方。URL 仍为可选中文本，不会自动打开。
- 展开“**打开 Telegram 链接**”，输入 `@username`、公共 `https://t.me/name` 链接、 `https://t.me/+invite` / `joinchat/invite`，或带有 `?start=parameter` 的机器人链接，然后点击 **“保存预览**”。在加入之前，原始链接和 Telegram 的预览都会被签名。 **加入/打开并观察**：随后加入群组/频道或打开用户/机器人，将 该聊天添加为已启用的数据源，并向机器人发送`/start`（包括其启动参数）。 等待管理员批准的加入请求将记录为“待处理”，而非“成员身份”。

开启“**开始监视**”功能，可实时捕获收到的回复。当 监视处于暂停状态时，面板操作仍可正常进行，但此时仅保证其直接响应会被保存。 当监视正在运行时，新添加的来源将使用已配置的配置文件/历史记录导入设置。 当某个来源处于暂停状态时，请在**“来源**”中启用该来源，然后再发送消息或点击其按钮。

`interaction.preview`、`interaction.requested` 和 `interaction.result` 是证据导出中包含的普通签名 日志事件。请求会标识账户、消息/按钮 或预览记录，以及观察程序是否正在运行。收据可区分成功、 拒绝、待批准和未知结果。中断的请求可能已到达 Telegram：在执行新操作前请检查聊天记录。 重用请求 ID 可检索其 已保存的收据，而无需重复操作，包括重启后。当当前页面会话中同一操作收到模棱两可的响应时，面板会保留该 ID。 当操作成功后刷新视图失败时，面板也会保留该 ID：收据 仍保持可见，再次点击即可检索。 回调和加入 RPC 仅允许一次 尝试；可重试的读取操作将保留其配置的重试策略。立即切换聊天 会立即清除草稿和回复目标，并禁用发送功能，直到新对话加载完毕。

此迷你客户端支持文本和回调按钮。Web 应用、登录/手机号/位置请求、 支付、内联查询和附件仍需 Telegram 客户端；其保存的按钮 元数据仍可见。新控件使用英文文本。

## 重新核对分级

重新检查功能会再次向 Telegram 查询遗漏的消息、编辑记录以及 Telegram 不再返回的消息。 标有星号的来源为**优先**来源，默认每 15 分钟重新检查一次； 所有其他来源每 6 小时重新检查一次。选定的聊天群组初始为优先来源，通过 文件夹或整个账户添加的聊天群组则为常规来源。 每次循环最多重新检查 30 个来源， 其余来源将等待下一分钟；重新连接后，优先级来源将优先处理。这两个 时间间隔均在“来源 → 记录设置 → 重新检查”中设置（0 表示关闭该层级），并 记录为 `recheck.changed`。

遗漏的消息将从上次处理停止的位置开始补全，每次处理最多补全 **“参数 → 每次重新检查的新消息数**”（默认值为 1,000）条。 因此，在长时间暂停后， 重新检查会填补整个缺口，即使比该缺口更新的实时消息已被 优先保存。仍在补全数据中的聊天将在下一分钟再次被重新检查，而非 等待其层级间隔结束；`recheck.completed` 将显示为 `continues_after`，直至补全完成。

比较内容包括消息文本、实体、键盘输入（包括删除操作）以及附件 内容/标识。 仅更改文件访问哈希值或文件引用并不构成 编辑，Telegram 自动生成的内容也不构成编辑：链接预览加载、故事浏览量、该账户解锁的付费 媒体、发票收据等。聊天记录中保存的每个版本都链接到其完整的日志记录，包括媒体元数据。

## 消息历史记录与来源归属

假设采集器先观察到“10:00 开会”，随后看到“11:00 开会”， 接着收到一条删除通知。它会将这三条不同的观察结果追加到日志中： 原始文本保留，编辑后的内容作为独立版本保存，而通知则记录了 已观察到删除操作。

如果数据采集是在首个版本消失后才开始的，则该文本将无法获取。 如果在离线期间发生了多次编辑，则仅能保存后续观察到的 版本。删除通知无法恢复从未被捕获的内容。

消息发送者并不一定就是编辑者。Telegram通常不会 提供删除消息的用户身份或确切的删除时间。未知行为者 仍无法被识别。反应快照和参与者更新仅包含 Telegram向该账户显示的计数和身份信息。

序列号表示观察顺序。采集器的 UTC 时间戳即为其 本地时间；若提供 Telegram 源时间戳，则将其单独存储。 两者均非独立的可信时间戳。

## 历史快照

快照功能会从已启用的消息源中请求最新的可见消息，每次请求最多 500条。结果被标记为“历史观测记录”。这些记录可能与 实时捕获内容重叠，而重复的观测记录将作为独立条目保存。

快照遵循附件政策，但与实时事件切换机制相互独立。 它们不会还原已删除的消息或遗漏的中间版本。您可以在 暂停状态下请求生成快照；其中排队的任何附件将等待观察开始 且下载进程运行后才进行处理。

## 附件处理

附件下载默认开启，当可用磁盘空间低于 1 GiB 时会暂停。收集器会将 消息监控和下载任务一并提交。该任务保留原始媒体 描述符和大小策略，因此后续编辑过的附件不会被悄然替换。

下载操作在消息捕获后执行。下载完成后将生成一个包含 SHA-256 哈希值和字节数的 `media.saved` 记录。被跳过、失败、重试和中断的 任务将产生不同的结果。任务被加入队列并不证明文件已被完整保留。 已完成的文件还必须与原始观察到的附件 描述符中的字节数相匹配。较短或意外较长的响应不会被记录为已保存的媒体文件。

**各类别均**设有存储限制：照片、视频、GIF 和动画、圆形视频消息、 语音消息、音乐和音频、贴纸以及文件。 每种类型均可单独关闭，并设有 1 至 2,000 MiB 的独立大小限制；新工作区初始设置为：照片 20 MiB、 视频 100 MiB、文件、音频及圆形视频 50 MiB、语音和 GIF 20 MiB，以及 5 MiB 用于贴纸。*最大文件大小*会一次性设定所有类型。在 按类型设置限制之前保存的策略，仍保持其针对每种类型的单一限制。关闭某种类别会生成一个 `media.skipped` 记录；未知大小或超大文件不会被下载。 大文件的 下载速率至少为 256 KiB/s。任务在系统重启后仍会保留，但过期的引用、丢失的 访问权限或已删除的文件仍可能导致无法恢复。现有任务将保留与其一同保存的 策略。

## 暂停、锁定、断开连接和重启

| 动作或状态 | 效果 |
| --- | --- |
| 切换工作区 | 更改面板视图；其他收集器的状态保持不变。 |
| 锁定面板或关闭标签页 | 保持服务器和监控功能持续运行。 |
| 暂停观察 | 停止该收集器并保留队列中的附件处理工作。 |
| 禁用一个消息源 | 停止未来的范围捕获；在此期间，与其相关的队列中的媒体任务将处于等待状态。 |
| 移除来源 | 系统会将其作为消息源忽略并删除相关用户资料；已保存的记录仍保留在仅追加的日志中。待处理的附件将被记录为失败（`source_removed`）。在文件夹模式和整个账户模式下，这些内容同样会被排除在外。 |
| 更改连接路径 | 需要暂停，关闭旧客户端，并取消未完成的登录。 |
| 停止 Python 进程 | 停止所有工作区；离线期间不会进行任何监控。 |
| 主动观察后重启 | 尝试使用已保存的会话恢复已保存的范围。手动暂停将清除该意图。 |

该采集器会记录检测到的断开连接、重试、错误、启动/停止以及 心跳信号。短暂的中断可能会被周期性的连通性检查忽略。 重启后，系统将从保存的更新位置请求遗漏的更新，并 定期重新检查已监控的聊天记录；详见[证据格式](https://phishdestroy.github.io/TgWitness/zh/docs/reference/evidence/#durable-collection-and-process-receipts-02)。快照仅提供上下文信息； 它并不能证明数据缺口已得到修复。

## 账户隔离与验证

每个工作区都有独立的日志、授权、签名密钥、策略和队列。 只有其活跃客户端才能提交实时观察记录。被拒绝、待处理、 被取代以及连接测试状态的客户端均无法将实时更新写入其日志。 不同账户可以观察同一个群组，但各自的日志仍保持独立。

每个事件都包含前一个哈希值和一个 Ed25519 签名。导出内容涵盖 整个工作区日志，并通过固定序列号进行标识。面板过滤器不会过滤 导出内容；在导出准备期间，数据收集可能仍会超出其边界继续进行。

**“验证日志”**功能会通过显示的 边界检查事件链和签名。当工作区发生变化时，其结果将被清空，面板会标识 检查后新增的记录。ZIP导出功能还会对收集的媒体文件进行验证。

有效的签名是基于可信密钥来验证数据的完整性，而非基于 Telegram 的来源或内容的真实性。请独立保留指纹和检查点。有关信任和交付要求，请参阅 [证据模型](https://phishdestroy.github.io/TgWitness/zh/docs/reference/evidence/)、[日常操作](https://phishdestroy.github.io/TgWitness/zh/docs/reference/operations/)以及 [实时接纳流程](https://github.com/phishdestroy/TgWitness/blob/main/docs/internal/LIVE_ACCEPTANCE.md)。
