概览
LogShare API 用于把 Minecraft/Hytale 日志文件上传到平台,并在之后读取文件内容、获取 Codex 结构化分析或删除日志。所有接口都通过 HTTPS 访问,当前版本为 v1。
| 项目 | 说明 |
|---|---|
| Base URL | https://api.logshare.cn |
| API 版本 | 当前稳定版本,所有接口路径都以 /v1 开头。 |
| 请求格式 | 上传接口支持 application/json 和 application/x-www-form-urlencoded;读取和删除接口使用标准 HTTP 方法。 |
| 响应格式 | 单文件 raw 接口返回 text/plain;多文件 raw 接口返回 JSON 文件列表;其余接口均返回 JSON。 |
| 认证 | 上传和读取接口不需要认证;删除日志时必须携带上传时返回的 Bearer token。 |
| 日志 ID | 每次上传成功后生成,由 7 位字母和数字组成。 |
| 默认保留时间 | 默认至少保留 7 天。expires 是逻辑过期时间,实际删除可能因 TTL 回收延迟;仅访问日志元信息不会续期。 |
- 成功响应使用
{ success: true, message, ... },错误响应使用{ success: false, error, code }。客户端应先判断 HTTP 状态码,再读取 success 和 error 字段。 - 请求体支持
br/gzip/deflate压缩,最多 5 层;服务端响应优先 Brotli,可发送Accept-Encoding: br, gzip。 GET /v1/log/{id}不会续期。raw / insights 的任意成功读取(包括多文件时返回文件列表)都会延长日志的保留时间。
接入流程
每次上传会创建一条日志记录,这条记录可以包含一个或多个文件。客户端接入时,建议按照下面的顺序处理:
- 上传文件。 使用
POST /v1/log,把本次要分享的日志文件放入files数组。旧客户端也可以继续提交content字段,服务端会把它映射为latest.log。上传成功后,响应会返回日志 ID、分享地址、主文件原文地址、删除 token 和文件列表。请立即保存 token,它只在这次响应中返回一次。 - 获取文件列表。 使用
GET /v1/log/{id}获取日志元信息和文件列表。该接口不会续期,适合在打开日志页面时使用。 - 让用户选择文件。 如果响应中的
requiresFileSelection为 true,说明这次上传包含多个文件。客户端应展示files列表,让用户选择要查看的文件,而不是自行假定某个文件是主日志。 - 读取或分析文件。 使用文件对象中的
name作为 filename,请求/v1/raw/{id}/{filename}读取原文,或请求/v1/insights/{id}/{filename}获取 Codex 分析。
id 会指向已有日志, deduplicated 为 true。此时返回的 token 是本次请求新生成的,并未写入存储,不能用于删除已有日志;删除凭证仍然属于第一次上传该内容的客户端。 快速开始
# 1. 上传文件列表
curl -X POST https://api.logshare.cn/v1/log \
-H 'Content-Type: application/json' \
-d '{
"files": [
{"name": "latest.log", "content": "<游戏主日志>"},
{"name": "crash-reports/crash-01.txt", "content": "<崩溃报告>"}
],
"source": "fcl/1.2.0",
"metadata": [
{"key": "version", "value": "1.21.9", "label": "Minecraft 版本"}
]
}'
# 2. 获取文件列表
curl https://api.logshare.cn/v1/log/sAbCdEf
# 3. 选择文件后读取或分析
curl https://api.logshare.cn/v1/raw/sAbCdEf/latest.log
curl https://api.logshare.cn/v1/insights/sAbCdEf/latest.log
# 4. 删除日志
curl -X DELETE https://api.logshare.cn/v1/log/sAbCdEf \
-H 'Authorization: Bearer <token>' 如果客户端只上传单个文件,也可以继续使用旧版 content 字段:服务端会把它映射为 latest.log,响应结构与 files 上传一致。
端点总览
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /v1/log | 上传一个或多个日志文件(也兼容旧版单文件 content),创建日志记录,并返回日志 ID、分享地址、删除 token 和文件列表。 |
| GET | /v1/log/{id} | 获取日志的元信息、公开 metadata 和文件列表。 |
| GET | /v1/raw/{id} | 读取日志原文。当同一个 ID 下只有一个文件时直接返回文本;存在多个文件时返回文件列表,客户端需要先选择文件。 |
| GET | /v1/raw/{id}/{filename} | 读取指定文件的原文。文件名可以包含子路径。 |
| GET | /v1/insights/{id} | 获取 Codex 分析。当同一个 ID 下只有一个文件时直接返回分析结果;存在多个文件时返回文件列表。 |
| GET | /v1/insights/{id}/{filename} | 对指定文件执行 Codex 分析,并返回结构化结果。 |
| DELETE | /v1/log/{id} | 删除一个或多个日志。需要上传时返回的删除 token。 |
| GET | /v1/limits | 获取当前上传限制,包括文件数、总大小、请求体大小和保留时间。 |
| GET | / | 返回当前可用的端点列表,可用于健康检查或能力发现。 |
/v1/log上传日志
该接口用于上传一个或多个日志文件。新客户端应把文件放入 files 数组;旧版单文件字段 content 仍然可用,服务端会把它映射为主文件(优先 latest.log,重名时使用 main.log、latest (2).log 等名称),已对接旧接口的客户端不需要修改。这个主文件同样占用文件数配额并计入总大小。每次上传会创建一条日志记录;平台会对每个文件单独执行脱敏,并在识别为 Minecraft 日志时执行 SpinYarn 反混淆。Codex 全文分析不会在上传时执行,而是在之后请求某个文件的分析接口时按需执行。
Content-Type: 上传接口支持 application/json 和 application/x-www-form-urlencoded 两种请求格式。推荐使用 JSON,便于同时提交文件、metadata 和 source。如果 Content-Type 缺失或不是上述两种,服务端会按 urlencoded 尝试解析。
Content-Encoding: 如果请求体较大,可以使用 br / gzip / x-gzip / deflate 压缩请求体,最多支持 5 层编码;每一层解压后的输出都不能超过 32 MiB。gzip、x-gzip 和 deflate 由 PHP 内置 zlib 支持,br 需要服务端安装 ext-brotli,缺少扩展时返回 501。服务端返回响应时会优先使用 Brotli 压缩,客户端可以发送 Accept-Encoding: br, gzip。
请求字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| files | array<FileInput> | 否* | 日志文件数组,每个元素是一个 FileInput 对象。一次最多上传 200 个文件;所有文件展开后的总大小不能超过 20 MiB。与 content 至少提供一个。 |
| content | string | 否* | 旧版单文件字段。非空时会映射为主文件(优先 latest.log,重名时使用 main.log、latest (2).log 等);与 files 同时提交时作为主文件。它同样占用文件数配额并计入总大小。 |
| metadata | array<MetadataEntry> | 否 | 可选。结构化元数据数组,最多 100 条。服务端会使用日志识别结果补充 version 和 loader;如果客户端提交了同名 key,则以客户端值为准。 |
| source | string | 否 | 可选。来源标识,最长 64 字节。推荐使用「启动器标识/版本号」格式,例如 fcl/1.2.0。省略时服务端会尝试从 User-Agent 推断启动器来源,无法识别时记为「未指定」。该字段也会参与内容去重。 |
files 和 content 至少提供一个。两者同时提供时, content 作为主文件:服务端优先使用 latest.log,如果该名称已被 files 占用,则依次尝试 main.log、 latest (2).log 等名称。
FileInput
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 必填。文件名或相对路径,例如 latest.log 或 crash-reports/crash-01.txt。最长 512 字节,超长会返回 400。如果文件名以 .zip 结尾,服务端会把 content 当作 ZIP 压缩包并展开。 |
| content | string | 是 | 必填。文件内容。普通日志直接传文本;ZIP 文件传压缩包字节内容。 |
MetadataEntry
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| key | string | 是 | 必填。元数据键,去除首尾空白后不能为空;超过 64 个字符会截断。 |
| value | string | number | boolean | object | 是 | 必填。元数据值。字符串超过 1024 个字符会截断;数组、对象会先 JSON 序列化,再按同样长度截断,公开接口返回的是 JSON 字符串。value 为 null 的条目会被丢弃。 |
| label | string | 否 | 可选。展示名称,超过 128 个字符会截断。 |
| visible | boolean | 否 | 可选。是否在公开元信息接口中返回,默认 true。设置为 false 后,GET /v1/log/{id} 不会返回该条目。 |
服务端会用日志识别结果补写 version / loader 元数据;客户端提交同名 key 时以客户端值为准。重复 key 以首次出现为准。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| success | boolean | 请求是否成功。 |
| message | string | 服务端返回的结果说明。 |
| id | string | 本次创建的日志 ID。如果命中内容去重,该 ID 指向已有日志。 |
| url | string | 可以直接分享给用户的页面地址。 |
| filesUrl | string | 该日志的文件列表接口地址。 |
| raw | string | 主文件原文地址。单文件日志指向 /v1/raw/{id};多文件日志如果上传时提供了 content,则指向 content 映射出的主文件,否则指向按文件名排序后的第一个文件。 |
| token | string | 删除该日志所需的凭证。只在本次上传响应中返回一次,请立即保存。 |
| deduplicated | boolean | 是否命中内容去重。为 true 时,本次响应中的 token 不能用于删除已有日志。 |
| fileCount | number | 本次日志包含的文件数量。 |
| requiresFileSelection | boolean | 是否需要在多个文件中选择。文件数大于 1 时为 true。 |
| files | array<FileObject> | 文件列表,每个元素是一个 FileObject。 |
FileObject
| 字段 | 类型 | 说明 |
|---|---|---|
| name | string | 文件名或相对路径。后续读取或分析该文件时,需要把这个值作为 filename 参数。 |
| size | number | 文件字节数,仅用于展示,不参与上传限制。 |
| lines | number | 文件行数,按换行符计算,仅用于展示,不参与上传限制。 |
| raw | string | 该文件的原文接口地址。 |
| insights | string | 该文件的 Codex 分析接口地址。 |
{
"success": true,
"message": "Log submitted successfully",
"id": "sAbCdEf",
"url": "https://logshare.cn/sAbCdEf",
"filesUrl": "https://api.logshare.cn/v1/log/sAbCdEf",
"raw": "https://api.logshare.cn/v1/raw/sAbCdEf/latest.log",
"token": "3f9c1a7d...",
"deduplicated": false,
"fileCount": 2,
"requiresFileSelection": true,
"files": [
{
"name": "latest.log",
"size": 2048,
"lines": 40,
"raw": "https://api.logshare.cn/v1/raw/sAbCdEf/latest.log",
"insights": "https://api.logshare.cn/v1/insights/sAbCdEf/latest.log"
},
{
"name": "crash-reports/crash-01.txt",
"size": 2048,
"lines": 80,
"raw": "https://api.logshare.cn/v1/raw/sAbCdEf/crash-reports/crash-01.txt",
"insights": "https://api.logshare.cn/v1/insights/sAbCdEf/crash-reports/crash-01.txt"
}
]
}- 如果文件是 ZIP 压缩包,服务端会展开压缩包并保留内部相对路径。展开后的每个文件都会单独脱敏和反混淆。同名文件会自动改名为
name (2).ext、name (3).ext,避免覆盖。 - 一次上传最多包含 200 个文件;所有文件展开后的总大小不能超过 20 MiB。旧版 content 映射出的主文件也计入这两个限制。单个文件本身没有大小或行数限制;ZIP 压缩包自身大小不计入 20 MiB,但原始 ZIP 字节仍受 32 MiB 请求体限制。
- 文件名最长 512 字节,超过会返回 400。文件名中的子路径需要按路径段做 URL 编码,服务端只按存储名称精确匹配。
- 如果同时提交了 content 和 files,content 会作为主文件,响应中的 raw 指向该文件;files 中的其余文件仍会出现在 files 列表。
- 上传接口会返回删除 token。请把它保存在安全的位置;服务端不保存明文 token,丢失后无法找回。
/v1/log/{id}日志元信息
该接口用于获取一条日志的元信息、公开 metadata 和文件列表。上传成功后,客户端通常应先获取一次元信息,确认日志包含哪些文件,以及是否需要让用户选择文件。
如果响应中的 requiresFileSelection 为 true,说明这条日志包含多个文件。客户端应展示 files 列表,让用户选择要查看的文件。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 日志 ID,由 7 位字母和数字组成。 |
| fileCount | number | 该日志包含的文件数量。 |
| requiresFileSelection | boolean | 是否需要在多个文件中选择。文件数大于 1 时为 true。 |
| size | number | 所有文件合计的字节数。 |
| lines | number | 所有文件合计的行数。 |
| created | number | 日志创建或最近一次续期的时间,Unix 秒。 |
| expires | number | 逻辑过期时间,值为 created + storageTime,Unix 秒。实际删除可能因 TTL 回收延迟而晚于这个时间。 |
| metadata | array<MetadataEntry> | 公开元数据数组。visible=false 的条目不会出现在这个字段中;数组/对象类型的 value 会以 JSON 字符串返回。 |
| source | string | 上传时提交的来源标识;省略时可能由服务端从 User-Agent 推断,无法识别时为「未指定」。 |
| filesUrl | string | 该日志的文件列表接口地址。 |
| raw | string | 单文件日志指向 /v1/raw/{id};多文件日志指向按文件名排序后的第一个文件的 raw 地址,不保证是上传时 content 映射出的主文件。 |
| files | array<FileObject> | 文件列表。每个元素包含文件名、大小、行数以及该文件的 raw/insights 地址。 |
该接口不会续期。raw / insights 的任意成功读取(包括多文件时返回文件列表)都会重新计算过期时间;仅仅打开元信息页面不会延长日志的保留时间。
多文件响应中的 raw 指向按文件名排序后的第一个文件,不保证是上传时 content 映射出的主文件。如果客户端依赖主文件,请使用上传响应的 raw,或 files 中对应文件的 URL。
{
"success": true,
"message": "Log metadata retrieved successfully",
"id": "sAbCdEf",
"fileCount": 2,
"requiresFileSelection": true,
"size": 4096,
"lines": 120,
"created": 1755200000,
"expires": 1755804800,
"metadata": [],
"source": "fcl/1.2.0",
"filesUrl": "https://api.logshare.cn/v1/log/sAbCdEf",
"raw": "https://api.logshare.cn/v1/raw/sAbCdEf/latest.log",
"files": [
{
"name": "latest.log",
"size": 2048,
"lines": 40,
"raw": "https://api.logshare.cn/v1/raw/sAbCdEf/latest.log",
"insights": "https://api.logshare.cn/v1/insights/sAbCdEf/latest.log"
},
{
"name": "crash-reports/crash-01.txt",
"size": 2048,
"lines": 80,
"raw": "https://api.logshare.cn/v1/raw/sAbCdEf/crash-reports/crash-01.txt",
"insights": "https://api.logshare.cn/v1/insights/sAbCdEf/crash-reports/crash-01.txt"
}
]
}读取文件
读取文件时,需要先判断日志是否包含多个文件。单文件日志可以直接读取;多文件日志必须先获取文件列表,并使用文件名请求指定文件。
/v1/raw/{id} 当同一个 ID 下只有一个文件时,该接口会直接返回 text/plain 正文。如果该 ID 下存在多个文件,接口不会自动选择文件,而是返回文件列表;客户端需要先让用户选择文件,再使用带 filename 的接口。
/v1/raw/{id}/{filename} 该接口用于读取指定文件的原文。filename 必须与文件列表中的 name 完全一致。如果文件名包含子路径,例如 crash-reports/crash-01.txt,需要对每个路径段进行 URL 编码,但保留斜杠分隔符。服务端只按数据库中的文件名精确匹配,不会把它当作文件系统路径。
读取成功时返回 200 text/plain; charset=utf-8;文件不存在时返回 404。读取成功会续期日志的保留时间。
curl 'https://api.logshare.cn/v1/raw/sAbCdEf/crash-reports/crash-01.txt'分析文件
Codex 分析按文件执行。上传时不会立即分析全文,只有在请求某个文件的分析接口时才会执行。
/v1/insights/{id} 当同一个 ID 下只有一个文件时,该接口会直接返回该文件的 Codex 分析 JSON;如果该 ID 下存在多个文件,接口会返回文件列表,客户端需要先让用户选择文件,再请求 /v1/insights/{id}/{filename} 获取指定文件的分析结果。
/v1/insights/{id}/{filename}响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | Codex 识别出的日志类型标识,例如 vanilla/server。 |
| name | string | 日志类型名称。 |
| type | string | 日志类别,例如 Server Log 或 Crash Report。 |
| version | string | 识别出的 Minecraft 版本。 |
| title | string | 分析标题。部分日志类型可能不返回这个字段。 |
| analysis.problems | array<Problem> | 检测到的问题列表。每个问题包含问题描述、出现次数和解决建议。 |
| analysis.information | array<Information> | 提取到的环境与版本信息列表。每条信息包含标签、值和出现次数。 |
| message | string | 问题描述。 |
| counter | number | 该问题在文件中出现的次数。 |
| solutions | array<{ message: string }> | 解决建议列表。每个建议是一个对象,message 字段为建议内容。 |
| message | string | 信息文本。 |
| counter | number | 该信息出现的次数。 |
| label | string | 信息标签,例如 Minecraft version。 |
| value | string | 信息值。 |
{
"id": "vanilla/server",
"name": "Vanilla",
"type": "Server Log",
"version": "1.21.9",
"title": "Vanilla 1.21.9 Server Log",
"analysis": {
"problems": [
{
"message": "Could not load chunk",
"counter": 3,
"solutions": [
{ "message": "检查世界存档完整性并恢复备份" }
]
}
],
"information": [
{
"message": "Minecraft version: 1.21.9",
"counter": 1,
"label": "Minecraft version",
"value": "1.21.9"
}
]
}
}分析结果会按文件内容哈希缓存在服务端进程内。相同内容的文件重复请求时会直接返回缓存结果,不会重复执行 Codex。缓存有容量上限,服务重启后失效。
/v1/log/{id}删除日志
该接口用于删除日志。删除时需要上传时返回的 token;服务端只保存 token 的哈希值,因此 token 丢失后无法找回。请求头中需要携带 Authorization: Bearer <token>。
路径中的 {id} 可以是一个日志 ID,也可以是多个用逗号分隔的日志 ID,例如 DELETE /v1/log/id1,id2。服务端会逐个校验日志是否存在,以及 token 是否匹配。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| success | boolean | 请求是否成功。只要至少有一个日志删除成功,这个字段就是 true。 |
| message | string | 服务端返回的结果说明。 |
| deleted | string[] | 删除成功的日志 ID 列表。 |
| failed | array<{ id, message, code }> | 删除失败的日志列表。每个元素包含 id、message 和 code。 |
| total | number | 本次请求包含的日志总数。 |
| deletedCount | number | 删除成功的日志数量。 |
| failedCount | number | 删除失败的日志数量。 |
{
"success": true,
"message": "Log deletion completed",
"deleted": ["sAbCdEf"],
"failed": [],
"total": 1,
"deletedCount": 1,
"failedCount": 0
}- 如果所有 ID 都删除失败,接口返回 400,failed 数组会列出每个 ID 的失败原因和状态码。
- 如果只有部分 ID 删除成功,接口返回 200,失败项仍然会出现在 failed 数组中。
- 缺少 Authorization 请求头时返回 401;token 与日志不匹配时返回 403。
/v1/limits上传限制
该接口返回当前部署的上传限制。客户端应在选择文件或上传前读取这些值,避免提交明显超过限制的内容。
| 字段 | 类型 | 说明 |
|---|---|---|
| storageTime | number | 日志保留时间,单位为秒。默认 604800 秒,即至少保留 7 天;expires 是逻辑过期时间,实际删除可能延迟。 |
| maxFiles | number | 一次上传允许包含的最大文件数。旧版 content 映射出的主文件也计入这个配额。 |
| maxTotalBytes | number | 所有文件展开后的总字节数上限。ZIP 压缩包自身大小不计入,但原始 ZIP 字节仍受 maxRequestBodyBytes 限制。 |
| maxRequestBodyBytes | number | 请求体(原始和解压后)的最大字节数。多层 Content-Encoding 会逐层解压,每一层输出都不能超过这个值。 |
{
"storageTime": 604800,
"maxFiles": 200,
"maxTotalBytes": 20971520,
"maxRequestBodyBytes": 33554432
}当前版本只返回上述四个字段。如果某个实例仍返回 maxLength / maxLines,说明它尚未升级到当前版本;客户端应以四个字段为准,并处理旧实例的差异。
平台在边缘层进行限流:nginx limit_req 按 IP 30 r/s(burst 60),OpenLiteWaf 再叠加 10 秒窗口 240 次的 CC 限流。触发 CC 限流时返回 429,并带有 Retry-After 响应头;触发 nginx limit_req 时返回 503。
错误与状态码
所有错误响应都使用相同的 JSON 结构。调用方应先检查 HTTP 状态码,再读取 error 字段;不要只依赖 message 字段,因为部分错误可能只返回 error。
{
"success": false,
"error": "错误描述",
"code": 400
}| 状态码 | 说明 |
|---|---|
| 200 | 请求成功。多文件日志返回文件列表时也使用 200。 |
| 400 | 请求参数错误、必填字段缺失、内容为空或文件名校验失败。 |
| 401 | 删除请求缺少 Authorization: Bearer token。 |
| 403 | 删除 token 不匹配,或客户端 IP 已被封禁。 |
| 404 | 指定的日志或文件不存在。 |
| 405 | 当前路径不支持该 HTTP 方法。 |
| 413 | 请求体、文件数量或文件总大小超过限制;边缘 nginx 的 210 MB 请求体上限也返回 413。 |
| 415 | 请求使用了不支持的 Content-Encoding。Content-Type 缺失或未知时会按 urlencoded 尝试解析,不返回 415。 |
| 429 | 触发了 WAF CC 限流。响应会带 Retry-After 头,客户端应等待后重试。 |
| 500 | 服务端内部错误。 |
| 501 | 服务端未安装 Brotli 扩展,无法解压 br 请求体。 |
| 503 | 触发了 nginx limit_req 限流。 |
根端点 GET / 返回当前部署支持的端点列表。它不需要认证,适合用于健康检查或确认服务能力。
{
"success": true,
"message": "LogShare API",
"endpoints": [
"POST /v1/log",
"GET /v1/log/{id}",
"GET /v1/raw/{id}",
"GET /v1/raw/{id}/{filename}",
"GET /v1/insights/{id}",
"GET /v1/insights/{id}/{filename}",
"DELETE /v1/log/{id}",
"GET /v1/limits"
]
}SDK
v3.1.0我们提供 JavaScript、PHP、Java 和 C#/.NET 四个 SDK。它们封装了上传、文件列表、读取、分析和删除接口,方法命名基本一致。下载后直接引入即可使用。JavaScript SDK 支持浏览器和 Node.js 18+;PHP 需要 7.4+;Java 需要 11+;.NET 需要 6+。
浏览器与 Node.js 18+,零依赖
cURL 封装,PHP 7.4+
java.net.http,Java 11+
System.Text.Json,.NET 6+
| 方法 | 说明 |
|---|---|
| submit(files, options) | 上传文件列表,返回日志对象 |
| getMeta(id) | 获取日志元信息与文件列表,用于确定文件名以及是否需要让用户选择文件。 |
| getRaw(id) | 读取单文件日志原文。仅当该日志只有一个文件时使用;多文件请使用 getRawFile。 |
| getRawFile(id, filename) | 读取指定文件原文;filename 使用文件列表中的 name。 |
| getInsights(id) | 分析单文件日志。仅当该日志只有一个文件时使用;多文件请使用 getInsightsFile。 |
| getInsightsFile(id, filename) | 分析指定文件;filename 使用文件列表中的 name。 |
| getLimits() | 获取上传限制 |
| delete(id, token) | 删除一个或多个日志 |
JavaScript、PHP 和 Java 使用 camelCase 方法名;.NET 使用 PascalCase,并在异步方法后加 Async 后缀。四个 SDK 返回的数据结构与本文档一致;raw 文件接口返回字符串。
import { LogShareSDK } from './mclogs.js'
const sdk = new LogShareSDK()
const result = await sdk.submit([
{ name: 'latest.log', content: logText },
{ name: 'crash-reports/crash-01.txt', content: crashText }
], {
source: 'fcl/1.2.0',
metadata: [{ key: 'version', value: '1.21.9', label: 'Minecraft 版本' }]
})
const meta = await sdk.getMeta(result.id)
const file = meta.files[0].name
const raw = await sdk.getRawFile(result.id, file)
const analysis = await sdk.getInsightsFile(result.id, file)