本章继续完善我们的机器人。收到用户的/logo指令,我们需要把我们的 LOGO 图片发送给用户。让我们来看看如何让 Telegram 机器人发送图片信息。

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

消息类型枚举

// src/types/mod.rs

pub enum MsgType {
    Text(String),
    Photo(String),
}

有了消息类型枚举,我们在 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

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

定义 PhotoMessage

// src/types/request.rs

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

定义 command::logo()

// src/handler/command.rs

pub fn logo() -> String {
    "https://axum.rs/static/img/logo.png".to_string()
}

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