# 外部 API

本页说明 DLC 管理器当前已实现的外部 API。

API 同时支持：
- 客户端
- 服务端

## 启用 API

在 `config.dc` 或 `config-server.dc` 中配置 `[api]`：

```dc
[api]
apiEnabled = true
apiPort = 10086
apiToken = "your_token_here"
```

字段说明：
- `apiEnabled`：是否启用 API 服务
- `apiPort`：API 端口，默认 `10086`
- `apiToken`：鉴权用 Bearer Token

## 鉴权

所有接口都需要：

```http
Authorization: Bearer <apiToken>
```

如果 `apiToken` 为空，所有请求都会被拒绝。

## 通用规则

- 基础路径：`/api`
- 返回格式：

成功：

```json
{
  "ok": true,
  "data": {}
}
```

失败：

```json
{
  "ok": false,
  "error": {
    "code": "not_found",
    "message": "Unknown API route."
  }
}
```

- 支持 `OPTIONS` 预检
- 已启用 CORS，`Access-Control-Allow-Origin: *`

## 基础接口

### `GET /api/ping`

健康检查。

返回字段：
- `service`
- `running`
- `mode`

### `GET /api/version`

返回 `DLC/info/version.dc` 的当前版本信息。

返回字段：
- `base`
- `dlc`
- `rollback_from`
- `changelog_shown`
- `label`

### `GET /api/state`

返回 API 与运行时状态摘要。

返回字段：
- `serverRunning`
- `dedicatedServer`
- `totalItems`
- `enabledItems`
- `counts`

### `GET /api/dlc/list`

返回按类型分组的 DLC 列表。

每个条目可能包含：
- `id`
- `identifier`
- `name`
- `type`
- `enabled`
- `baselineEnabled`
- `pending`
- `hidden`
- `configType`
- `alarm`
- `allowEnableByAll`
- `appliedTarget`
- `sourcePath`
- `sourcePaths`
- `displayNames`
- `tips`
- `dependencies`
- `conflicts`

### `GET /api/dlc/pending`

返回当前待应用的 DLC 改动。

返回字段：
- `count`
- `items`
  - `id`
  - `identifier`
  - `name`
  - `type`
  - `enabled`
  - `baselineEnabled`
  - `pending`

## DLC 根目录 / 配置文件接口

### `GET /api/dlc/root/list`

列出 DLC 根目录下可编辑的 `.dc` 文件。

当前可访问范围限制为：
- `<DLC>/info/**/*.dc`
- `<DLC>/remote/**/*.dc`
- `<DLC>/required/**/*.dc`
- `<DLC>/preset/**/*.dc`
- `<DLC>/update/**/*.dc`
- `<DLC>/notice.dc`

返回字段：
- `rootCount`
- `roots`
  - `rootIndex`
  - `rootPath`
  - `files`
    - `name`
    - `path`
    - `type`
    - `supported`

### `POST /api/dc/detect-type`

根据路径/文件名/内容识别配置类型。

请求体：

```json
{
  "name": "example.dc",
  "path": "remote/example.dc",
  "content": "..."
}
```

返回字段：
- `type`
- `supported`

### `POST /api/dc/validate`

校验 dc 配置内容。

请求体：

```json
{
  "type": "remote",
  "content": "..."
}
```

返回字段：
- `type`
- `supported`
- `valid`
- `issues`

Issue 字段：
- `severity`
- `source`
- `field`
- `message`

### `POST /api/dc/read`

从 DLC 工作区读取指定 dc 文件。

请求体：

```json
{
  "path": "remote/example.dc",
  "rootIndex": 0
}
```

返回字段：
- `name`
- `path`
- `rootIndex`
- `type`
- `supported`
- `content`

### `POST /api/dc/write`

向 DLC 工作区写入 dc 文件。

请求体：

```json
{
  "path": "remote/example.dc",
  "rootIndex": 0,
  "type": "remote",
  "content": "..."
}
```

说明：
- 对当前支持的配置类型，写入前会先尝试解析。
- 工作区之外的路径会被拒绝。

返回字段：
- `name`
- `path`
- `rootIndex`
- `type`
- `supported`
- `written`

### `POST /api/notice/content`

请求体：

```json
{
  "url": "https://example.com/notice.md"
}
```

返回字段：
- `url`
- `content`

## 文件接口

### `POST /api/file/add`

请求体：

```json
{
  "path": "mods/example.jar",
  "content": "..."
}
```

或：

```json
{
  "path": "config/example.txt",
  "contentBase64": "SGVsbG8="
}
```

或：

```json
{
  "path": "mods/example.jar",
  "source": "downloads/example.jar"
}
```

创建目录：

```json
{
  "path": "tmp/example",
  "directory": true
}
```

返回字段：
- `path`
- `created`
- `directory`

### `POST /api/file/del`

请求体：

```json
{
  "path": "mods/example.jar"
}
```

返回字段：
- `path`
- `deleted`

### `POST /api/file/mv`

请求体：

```json
{
  "from": "mods/example.jar",
  "to": "mods/example-disabled.jar"
}
```

返回字段：
- `from`
- `to`
- `moved`

### `POST /api/file/rename`

请求体：

```json
{
  "path": "mods/example.jar",
  "name": "example-disabled.jar"
}
```

返回字段：
- `from`
- `to`
- `renamed`

### `POST /api/file/upload`

向游戏工作区内目标路径上传原始二进制文件内容。

参数：
- `path`：上传后的目标保存路径，位于游戏目录内，例如 `mods/example.jar` 或 `config/example.txt`

请求体：
- 原始二进制 body

支持的目标路径来源：
- 查询参数 `path`
- 请求头 `X-Dlc-Path`

返回字段：
- `path`
- `uploaded`
- `size`

## DLC 应用接口

### `POST /api/dlc/enable`

请求体：

```json
{
  "id": "mod:...|a.jar"
}
```

或：

```json
{
  "ids": ["mod:...|a.jar", "unknown:...|b.zip"]
}
```

也支持直接传 `identifier`：

```json
{
  "identifier": "example_mod"
}
```

```json
{
  "identifiers": ["example_mod", "example_pack"]
}
```

返回字段：
- `enabled`
- `changes`
- `linkedChanges`
- `unknownIds`
- `unknownIdentifiers`

### `POST /api/dlc/disable`

请求体：

```json
{
  "id": "mod:...|a.jar"
}
```

或：

```json
{
  "ids": ["mod:...|a.jar", "unknown:...|b.zip"]
}
```

也支持直接传 `identifier`：

```json
{
  "identifier": "example_mod"
}
```

```json
{
  "identifiers": ["example_mod", "example_pack"]
}
```

返回字段：
- `enabled`
- `changes`
- `linkedChanges`
- `unknownIds`
- `unknownIdentifiers`

### `POST /api/dlc/apply`

只应用当前已经处于待应用状态的 DLC 改动。

请求体：

```json
{
  "mode": "restart"
}
```

支持的 `mode`：
- `restart`
- `reload`

返回字段：
- `mode`
- `changedCount`
- `requiresRestart`
- `hotReloaded`
- `appliedChanges`
- `messages`

## Remote 接口

### `GET /api/remote/list`

返回当前缺失的 remote 条目。

可选请求头：

```http
X-Dlc-Lang: zh_cn
```

### `POST /api/remote/download`

立即下载当前所有缺失的 remote 条目。

返回字段：
- `success`
- `downloaded`
- `error`

### `POST /api/remote/download/start`

启动指定 key 的 remote 下载任务。

请求体：

```json
{
  "keys": ["remote:key1", "remote:key2"],
  "lang": "zh_cn"
}
```

返回字段：
- `status`

### `GET /api/remote/download/status`

返回当前 remote 下载任务状态。

可选请求头：

```http
X-Dlc-Lang: zh_cn
```

## Required 接口

### `GET /api/required/list`

返回 required 资源条目列表。

可选请求头：

```http
X-Dlc-Lang: zh_cn
```

### `POST /api/required/download/start`

启动指定 id 的 required 下载任务。

请求体：

```json
{
  "ids": ["id_a", "id_b"],
  "lang": "zh_cn"
}
```

返回字段：
- `status`

### `GET /api/required/download/status`

返回当前 required 下载任务状态。

可选请求头：

```http
X-Dlc-Lang: zh_cn
```

### `POST /api/required/download/cancel`

取消当前 required 下载任务。

返回字段：
- `canceled`

### `POST /api/required/uninstall`

卸载指定 required 资源。

请求体：

```json
{
  "ids": ["id_a", "id_b"]
}
```

返回字段：
- `removed`

### `POST /api/required/apply`

按 id 应用指定 required 资源。

请求体：

```json
{
  "ids": ["id_a", "id_b"]
}
```

返回字段：
- `applied`

## Update 接口

### `GET /api/update/state`

返回当前更新状态与回滚历史。

返回字段：
- `rollbackFrom`
- `rolledBack`
- `history`

### `GET /api/update/list`

返回当前可应用的更新包列表。

返回字段：
- `hasUpdates`
- `updates`

每个更新条目可能包含：
- `name`
- `platform`
- `base`
- `base_new`
- `dlc`
- `dlc_new`
- `hidden`
- `changelog`

### `POST /api/update/apply`

应用更新。

若不传版本对，则默认应用当前检测到的整条更新链。

请求体：

```json
{
  "baseOld": "1.0.0",
  "dlcOld": "1.0.0",
  "baseNew": "1.0.1",
  "dlcNew": "1.0.2"
}
```

返回字段：
- `success`
- `missing`
- `message`
- `missingPaths`
- `addedRequired`
- `addedRemote`

### `POST /api/update/rollback`

回滚到目标版本。

请求体：

```json
{
  "target": "1.0.0+1.0.0"
}
```

返回字段：
- `success`
- `message`
- `version`

### `POST /api/update/import`

从游戏目录内已有 zip 导入更新包。

请求体：

```json
{
  "path": "downloads/example-update.zip"
}
```

返回字段：
- `success`
- `path`

### `POST /api/update/import-url`

从 URL 下载更新包后再导入。

请求体：

```json
{
  "url": "https://example.com/update.zip",
  "fileName": "update.zip"
}
```

返回字段：
- `success`
- `message`
- `downloadedPath`
