Synapse 事件举报管理 Admin API 完全指南:查询、详情与删除 Reported Events
2026/9/23 14:58:35 网站建设 项目流程
  • 后端
  • 即时通讯

【免费下载链接】synapse

Synapse: Matrix homeserver written in Python/Twisted.

项目地址:https://gitcode.com/gh_mirrors/sy/synapse
点击查看免费下载

本文基于 Synapse(Matrix homeserver,Python/Twisted 实现)官方管理接口文档,系统讲解/_synapse/admin/v1/event_reports系列三个端点:举报列表分页查询、单条举报详情查看、以及举报记录删除。读者读完将掌握如何用access_token调用 Admin API 审计与处置用户举报,理解每个 URL 参数、返回字段的语义与默认值,并能结合源码理解其分页与过滤实现原理。

背景:什么是 Event Report

在 Matrix 生态中,客户端可以通过m.report消息(对应的服务端接口为POST /_matrix/client/v3/rooms/{roomId}/report/{eventId})对房间内的某条事件进行举报,附带一个reason(举报理由)与一个score(严重程度评分,-100 表示“最具冒犯性”,0 表示“无害”)。这些举报记录会被持久化到 Synapse 数据库的event_reports表中,供服务器管理员通过管理 API 审计和处理。

从数据库 schema 可以看到该表的原始结构(synapse/storage/schema/main/delta/32/reports.sql):

CREATE TABLE event_reports( id BIGINT NOT NULL PRIMARY KEY, received_ts BIGINT NOT NULL, room_id TEXT NOT NULL, event_id TEXT NOT NULL, user_id TEXT NOT NULL, reason TEXT, content TEXT );

其中content字段以 JSON 形式保存了举报请求中的scorereason等附加内容;reason单独成列用于索引与过滤。管理员 API 返回结果时,会将该 JSON 反序列化,拆出scorereason两个字段返回。

权限与认证前提

使用本节全部接口都必须提供服务器管理员账号的access_token(通过Authorization: Bearer <token>请求头携带),否则请求会被拒绝。关于 Admin API 的认证方式与管理员账号配置,参见 Admin API 使用说明。

从源码实现(synapse/rest/admin/event_reports.py)看,每个处理器在业务逻辑前都会调用:

await assert_requester_is_admin(self._auth, request)

测试用例也验证了两种失败场景(tests/rest/admin/test_event_reports.py):

  • 未携带 token 调用GET /_synapse/admin/v1/event_reports:返回401errcodeMISSING_TOKENtest_no_auth);
  • 普通(非管理员)用户调用:返回403errcodeFORBIDDENtest_requester_is_no_admin)。

一、列出事件举报(GET /_synapse/admin/v1/event_reports)

该接口返回本服务器已知的所有事件举报记录,支持分页、排序方向与按用户/房间过滤。

请求

GET /_synapse/admin/v1/event_reports?from=0&limit=10

URL 参数

参数类型必填默认值说明
limitinteger100本次调用返回的最大条数,用于分页
frominteger0结果偏移量。应视为不透明值,只应使用上一次调用返回的next_token,不应手工指定其他值
dirstringb举报记录的排序方向:b(backwards)为最新的在前,f(forwards)为最旧的在前
user_idstring过滤条件,只返回user_id(举报人)包含该值的记录
room_idstring过滤条件,只返回room_id包含该值的记录

源码(synapse/rest/admin/event_reports.py)中对参数的解析与校验如下:

start = parse_integer(request, "from", default=0) limit = parse_integer(request, "limit", default=100) direction = parse_enum(request, "dir", Direction, Direction.BACKWARDS) user_id = parse_string(request, "user_id") room_id = parse_string(request, "room_id") if start < 0: raise SynapseError(HTTPStatus.BAD_REQUEST, "The start parameter must be a positive integer.", errcode=Codes.INVALID_PARAM) if limit < 0: raise SynapseError(HTTPStatus.BAD_REQUEST, "The limit parameter must be a positive integer.", errcode=Codes.INVALID_PARAM)

因此若传入负数的fromlimit,接口会返回400M_INVALID_PARAM

响应示例

{ "event_reports": [ { "event_id": "$bNUFCwGzWca1meCGkjp-zwslF-GfVcXukvRLI1_FaVY", "id": 2, "reason": "foo", "score": -100, "received_ts": 1570897107409, "canonical_alias": "#alias1:matrix.org", "room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org", "name": "Matrix HQ", "sender": "@foobar:matrix.org", "user_id": "@foo:matrix.org" }, { "event_id": "$3IcdZsDaN_En-S1DF4EMCy3v4gNRKeOJs8W5qTOKj4I", "id": 3, "reason": "bar", "score": -100, "received_ts": 1598889612059, "canonical_alias": "#alias2:matrix.org", "room_id": "!eGvUQuTCkHGVwNMOjv:matrix.org", "name": "Your room name here", "sender": "@foobar:matrix.org", "user_id": "@bar:matrix.org" } ], "next_token": 2, "total": 4 }

响应字段

字段类型说明
idinteger举报记录的 ID
received_tsinteger举报提交时间,Unix 时间戳(毫秒)
room_idstring被举报事件所在房间的 ID
namestring房间名称
event_idstring被举报事件的 ID
user_idstring举报人(撰写举报理由的用户)的用户 ID
reasonstring举报人填写的理由,可能为空字符串或null
scoreinteger举报严重程度评分:-100 为“最具冒犯性”,0 为“无害”,可能为null
senderstring被举报原始事件发送者的用户 ID
canonical_aliasstring房间的规范别名,未设置时为null
next_tokeninteger分页游标,见下文分页说明
totalinteger与查询条件(user_idroom_id)匹配的举报总数

分页机制

判断响应中是否含next_token

  • 若存在next_token,将from设为该值再次调用本端点,即可取得下一页数据;
  • 若响应中没有next_token,说明没有更多举报可翻页了。

从源码可见next_token的生成规则(synapse/rest/admin/event_reports.py):

ret = {"event_reports": event_reports, "total": total} if (start + limit) < total: ret["next_token"] = start + len(event_reports)

即:当from + limit仍小于总数total时,next_token = from + 本次实际返回条数;否则不返回该字段。

过滤与排序的底层实现

分页与过滤最终由存储层 synapse/storage/databases/main/room.py 的get_event_reports_paginate完成,其 SQL 行为值得注意:

  • user_idroom_id过滤采用LIKE '%' || 参数 || '%'子串匹配(如er.user_id LIKE ?er.room_id LIKE ?),所以传部分 ID 也能命中;
  • dir=b时按received_ts DESC排序(最新在前),dir=f时按received_ts ASC排序(最旧在前);
  • 使用LIMIT ? OFFSET ?实现分页;
  • 查询会对event_reports(别名erLEFT JOIN events获取发送者sender,并JOIN room_stats_state获取房间namecanonical_alias。源码注释特别说明,即使不使用room_stats_state的列,也必须 JOIN 它,因为 JOIN 会影响返回的行数(例如房间状态缺失、房间可能已被删除的情况),从而保证“总数统计查询”与“结果查询”一致;
  • content字段经db_to_json反序列化后取出scorereason;若某行 JSON 解析失败,会记录错误日志并跳过该行(Unable to parse json from event_reports)。

二、查看单条举报详情(GET /_synapse/admin/v1/event_reports/<report_id>)

该接口返回指定举报记录的完整信息,包括被举报事件的原始 JSON。

请求

GET /_synapse/admin/v1/event_reports/<report_id>

URL 参数

参数类型说明
report_idstring事件举报记录的 ID(数据库主键)

源码中对report_id的校验逻辑(synapse/rest/admin/event_reports.py):必须是能解析为非负整数的字符串,否则返回400+M_INVALID_PARAM;若数据库中没有该 ID,则返回404NotFoundError("Event report not found"))。

响应示例

{ "event_id": "$bNUFCwGzWca1meCGkjp-zwslF-GfVcXukvRLI1_FaVY", "event_json": { "auth_events": [ "$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M", "$oggsNXxzPFRE3y53SUNd7nsj69-QzKv03a1RucHu-ws" ], "content": { "body": "matrix.org: This Week in Matrix", "format": "org.matrix.custom.html", "formatted_body": "<strong>matrix.org</strong>:<br><a href=\"https://matrix.org/blog/\"><strong>This Week in Matrix</strong></a>", "msgtype": "m.notice" }, "depth": 546, "hashes": { "sha256": "xK1//xnmvHJIOvbgXlkI8eEqdvoMmihVDJ9J4SNlsAw" }, "origin": "matrix.org", "origin_server_ts": 1592291711430, "prev_events": [ "$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M" ], "prev_state": [], "room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org", "sender": "@foobar:matrix.org", "signatures": { "matrix.org": { "ed25519:a_JaEG": "cs+OUKW/iHx5pEidbWxh0UiNNHwe46Ai9LwNz+Ah16aWDNszVIe2gaAcVZfvNsBhakQTew51tlKmL2kspXk/Dg" } }, "type": "m.room.message", "unsigned": { "age_ts": 1592291711430 } }, "id": <report_id>, "reason": "foo", "score": -100, "received_ts": 1570897107409, "canonical_alias": "#alias1:matrix.org", "room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org", "name": "Matrix HQ", "sender": "@foobar:matrix.org", "user_id": "@foo:matrix.org" }

响应字段

与列表接口相比,单条详情返回了额外的event_json字段:

字段类型说明
idinteger举报记录 ID
received_tsinteger举报提交时间(Unix 毫秒时间戳)
room_idstring被举报事件所在房间 ID
namestring房间名称
event_idstring被举报事件 ID
user_idstring举报人用户 ID
reasonstring举报理由,可能为空
scoreinteger举报评分:-100 最严重,0 无害
senderstring被举报事件发送者用户 ID
canonical_aliasstring房间规范别名,未设置时为null
event_jsonobject被举报原始事件的完整 JSON(含contenttypesenderorigin_server_tssignatureshashesauth_eventsprev_events等事件原始字段)

event_json的作用是让管理员无需另查事件详情,即可直接看到被举报内容的原始内容(如消息正文、格式化后的 HTML、消息类型等),便于判断举报是否成立。

存储层实现(synapse/storage/databases/main/room.py 的get_event_report)中,该接口额外JOIN event_json ON event_json.event_id = er.event_id,并把事件原始 JSON 以event_json键返回。

三、删除单条举报记录(DELETE /_synapse/admin/v1/event_reports/<report_id>)

该接口用于删除指定举报记录。删除成功后响应体为空 JSON 对象({})。

请求

DELETE /_synapse/admin/v1/event_reports/<report_id>

URL 参数

参数类型说明
report_idstring要删除的事件举报记录 ID

成功响应

请求成功后返回 HTTP200,响应体为:

{}

失败场景

  • report_id无法解析为非负整数:返回400+M_INVALID_PARAM
  • report_id不存在:返回404NotFoundError("Event report not found"))。

存储层delete_event_report(synapse/storage/databases/main/room.py)通过simple_delete_oneevent_reports表删除对应id的行;当记录不存在时捕获StoreError返回False,由 REST 层转换为404

实战示例:用 curl 完成一次举报审计

以下是结合上述三个端点的完整 curl 调用示例($TOKEN为管理员access_token):

# 1. 列出前 10 条举报(最新的在前) curl -H "Authorization: Bearer $TOKEN" \ "https://your-server.example/_synapse/admin/v1/event_reports?from=0&limit=10" # 2. 按举报人过滤 curl -H "Authorization: Bearer $TOKEN" \ "https://your-server.example/_synapse/admin/v1/event_reports?user_id=@foo:matrix.org" # 3. 按房间过滤并按最旧在前排序 curl -H "Authorization: Bearer $TOKEN" \ "https://your-server.example/_synapse/admin/v1/event_reports?room_id=!ERAgBpSOcCCuTJqQPk:matrix.org&dir=f" # 4. 查看单条举报详情(含被举报事件原始 JSON) curl -H "Authorization: Bearer $TOKEN" \ "https://your-server.example/_synapse/admin/v1/event_reports/2" # 5. 删除某条举报记录 curl -X DELETE -H "Authorization: Bearer $TOKEN" \ "https://your-server.example/_synapse/admin/v1/event_reports/2"

相关实现文件索引

  • REST 接口实现:synapse/rest/admin/event_reports.py
  • 存储层查询与删除逻辑:synapse/storage/databases/main/room.py(get_event_reportget_event_reports_paginatedelete_event_report
  • 数据库表结构:synapse/storage/schema/main/delta/32/reports.sql
  • 测试用例:tests/rest/admin/test_event_reports.py
  • 客户端侧举报接口(产生举报数据的来源):synapse/rest/client/report_event.py
  • 后端
  • 即时通讯

【免费下载链接】synapse

Synapse: Matrix homeserver written in Python/Twisted.

项目地址:https://gitcode.com/gh_mirrors/sy/synapse
点击查看免费下载

相关推荐

上一篇:Spring AI终极指南:如何用Java构建智能AI应用的完整教程
下一篇:UVR 5.6 安装指南:从 0 到跑通第一首歌

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询