本章代码在04/发送图片分支。

由于发送图片消息和前一章说的发送文本消息的 API 不一样,所以我们需要对不同类型的消息进行识别,而 Rust 强大的枚举类型能让我们很容易的实现。

消息类型枚举

有了消息类型枚举,我们在 hook 中判断出不同指令后,就可以使用这个枚举进行标识、处理了。

使用消息类型枚举标识不同的消息

// src/handler/mod.rs

pub async fn hook(
    Json(payload): Json<Update>,
    Extension(state): Extension<AppState>,
) -> Result<String> {
    // ..

    let msg_text = payload.message.text.unwrap_or("".to_string());

    let msg_type = match msg_text.as_str() {
        "/website" => MsgType::Text(command::website()),
        "/logo" => MsgType::Photo(command::logo()),
        _ => MsgType::Text(echo(msg_text.clone())),
    };

    let res = match msg_type {
        MsgType::Text(reply_msg) => {
            bot::send_text_message(&state.bot.token, payload.message.chat.id, reply_msg).await
        }
        MsgType::Photo(reply_msg) => {
            bot::send_photo_message(&state.bot.token, payload.message.chat.id, reply_msg).await
        }
    }
    .map_err(log_error(msg_text));

    // ..
}

对于不同的指令,我们将其映射到不同的消息类型。然后通过消息类型来调用不同的 API,实现消息的发送。

相应的,也需要为图片类型的消息增加 API 调用函数。

调用发送图片消息的 API

// src/bot.rs

pub async fn send_photo_message(token: &str, chat_id: u64, photo: String) -> Result<Response> {
    let data = request::PhotoMessage { chat_id, photo };
    invoke_api(&data, "sendPhoto", token).await
}

这里使用了 request::PhotoMessage,我们还没定义它。

定义 PhotoMessage

// src/types/request.rs

#[derive(Serialize, Debug)]
pub struct PhotoMessage {
    pub chat_id: u64,
    pub photo: String,
}

定义 command::logo()

最后,别忘了定义返回 LOGO 图片的函数:

Telegram 支持多种方式发送图片。我们使用的是直接返回一个有效的图片的 URL,其它方式还有:使用 Telegram 服务器上已存在的图片以及从本地上传。详细信息请参见官方文档。