# 消息发送

> For the complete documentation index, see [llms.txt](https://simbot.forte.love/v4/llms.txt).

在 KOOK 组件中，主要有两种发送消息的方式。

> **Warning:**
> 文档可能有所疏漏或存在一些待更新的内容。如有需要，欢迎前往[社群](https://simbot.forte.love/communities.html) 交流讨论、寻求帮助~

1. 直接构建并使用 API 发送消息。这是最原始的消息发送方式。

2.

在使用 simbot 核心库时，配合使用 消息元素 `Message.Element` 发送消息。

本章将主要介绍第 1 种方式: 使用 API 发送消息。而与 消息元素 相关的内容可前往参考 [消息元素](component-kook-message-element.html)。

## 使用 API

KOOK API 中用于发送消息的 API 主要就是 向子频道发送消息 和 向用户发送私聊消息。 它们的 API 封装分别为：

* `SendChannelMessageApi`: [发送频道聊天消息](https://developer.kookapp.cn/doc/http/message#发送频道聊天消息)

* `SendDirectMessageApi`: [发送私信聊天消息](https://developer.kookapp.cn/doc/http/direct-message#发送私信聊天消息)

> **Note:**
> 它们可以在 [API定义列表](component-kook-api-list.html) 中找到。

这两个 API 的用法非常接近，但仍有两个区别需要先记住：

SendChannelMessageApi
: 面向频道消息。 支持 `quote`、`nonce`、`tempTargetId`，并在 `4.2.0` 起支持 `templateId`。

SendDirectMessageApi
: 面向私聊消息。 可通过 `targetId` 或 `chatCode` 两条路径构建请求。

下面以 `SendChannelMessageApi` 为主说明。

### 仅在API模块使用

当你不依赖其他模块，仅依赖 API 模块 `simbot-component-kook-api` 时， 你可以使用比较贴合原始的方式直接使用 API。

Kotlin:

```KOTLIN
val client = HttpClient()
val authorization = "Bot xxxxx"

val api = SendChannelMessageApi.create(
    targetId = "1234567890",
    content = "Hello KOOK"
)

val result = api.requestData(client, authorization)
```

Java:

```JAVA
var client = ApiRequests.createHttpClient();
var authorization = "Bot xxxxx";

var api = SendChannelMessageApi.create(
        null,
        "1234567890",
        "Hello KOOK"
);

ApiRequests.requestDataAsync(api, client, authorization)
        .thenAccept(result -> {
            // 发送成功
        });
```

```JAVA
var client = ApiRequests.createHttpClient();
var authorization = "Bot xxxxx";

var api = SendChannelMessageApi.create(
        null,
        "1234567890",
        "Hello KOOK"
);

var result = ApiRequests.requestDataBlocking(
        api,
        client,
        authorization
);
```

```JAVA
var client = ApiRequests.createHttpClient();
var authorization = "Bot xxxxx";

var api = SendChannelMessageApi.create(
        null,
        "1234567890",
        "Hello KOOK"
);

ApiRequests.requestDataReserve(api, client, authorization)
        .transform(SuspendReserves.mono())
        .block();
```

### 在标准库中使用

当你依赖使用 标准库模块 `simbot-component-kook-stdlib` 时， 标准库提供的 `Bot` 中基本已经包含了请求 API 所需要的基本信息， 因此其会提供一些扩展/辅助方法来简化你的请求逻辑。

Kotlin:

```KOTLIN
val bot: Bot = ...

val api = SendChannelMessageApi.create(
    targetId = "1234567890",
    content = "Hello KOOK"
)

val result = api.requestDataBy(bot)
```

Java:

```JAVA
Bot bot = ...;

var api = SendChannelMessageApi.create(
        null,
        "1234567890",
        "Hello KOOK"
);

BotRequests.requestDataByAsync(api, bot)
        .thenAccept(result -> {
            // 发送成功
        });
```

```JAVA
Bot bot = ...;

var api = SendChannelMessageApi.create(
        null,
        "1234567890",
        "Hello KOOK"
);

var result = BotRequests.requestDataByBlocking(api, bot);
```

```JAVA
Bot bot = ...;

var api = SendChannelMessageApi.create(
        null,
        "1234567890",
        "Hello KOOK"
);

BotRequests.requestDataByReserve(api, bot)
        .transform(SuspendReserves.mono())
        .block();
```

### 在组件库配合simbot4核心库时使用

> **Warning:**
> 虽然在使用组件库配合simbot4核心库时，我们更建议你使用 消息元素 ( 可参考 [消息元素](component-kook-message-element.html) )，而不是直接使用原始的API类型发送消息，但凡事都有例外。
>
>
>
> 如果你明确确定此时必须要使用原始的API请求，继续阅读即可。

在 `simbot-component-kook-core` 中有两种常见做法：

* 继续使用原始 API：`KookBot.requestData(api)`、`api.requestDataBy(bot)`

* 直接使用对象上的发送能力：`KookChatCapableChannel.send(...)`、`KookUserChat.send(...)`

后者通常更贴近 simbot 的使用方式。

Kotlin:

```KOTLIN
suspend fun send(channel: KookChatCapableChannel) {
    channel.send("hello from kook core")
    channel.send("reply message", quote = null, tempTargetId = null)
}
```

Java:

```JAVA
KookChatCapableChannel channel = ...;

channel.sendAsync("hello from kook core")
        .thenAccept(receipt -> { });
```

```JAVA
KookChatCapableChannel channel = ...;

var receipt = channel.sendBlocking("hello from kook core");
```

```JAVA
KookChatCapableChannel channel = ...;

channel.sendReserve("hello from kook core")
        .transform(SuspendReserves.mono())
        .subscribe(receipt -> { });
```

如果你只是需要把 `KookBot` 当作 stdlib 的 Bot 使用，也可以直接拿到 `sourceBot`：

Kotlin:

```KOTLIN
val kookBot: KookBot = ...
val bot = kookBot.sourceBot // 得到标准库的 Bot
```

Java:

```JAVA
KookBot kookBot = ...;
Bot bot = kookBot.getSourceBot(); // 得到标准库的 Bot
```

> **Tip:**
> 如果你的目标只是“正常发一条消息”， 更推荐优先使用 simbot 的消息元素与 `send` / `reply` 能力； 直接操作原始 API 更适合：
>
>
>
> * 需要用到平台专属字段
>
> * 需要发送模板消息、卡片消息等原始结构
>
> * 正在编写更底层封装

