2023.12.04 追記
line-openapi
の公開により、OpenAPIベースのライブラリに更新しました。
はじめに
Rustに入門し、早1週間。
Rustの色々な機能やシステムが有能すぎることに気付く。
そして、LINEBotの公式SDKにRustがないことに気付く。
ということで、練習がてらに line-bot-sdk-rust 作りました。
GitHub
Crate
Documentation
LINEBotを動かすための準備
基本的に、rocket
や actix-web
といったFWを用いて動かします。
LINEBotのためのアカウントの作成方法はこちら
【初心者向け】LINEBOTを作るためのLINE公式アカウント作成・設定
Channel secret
と Channel access token (long-lived)
の値を保存してください。
動かしてみよう
Rustのフレームワーク rocket
を使用して行きます。
とりあえず、cargo new
$ cargo new rust-linebot
Cargo.toml
に以下を追記。
[dependencies]
line-bot-sdk-rust = { version = "0.1", features = ["rocket_support"] }
rocket = "0.4"
dotenv = "0.15.0"
.env
ファイルを作成
LINE_CHANNEL_RECRET="取得した Channel secret"
LINE_CHANNEL_ACCESS_TOKEN="取得した Channel access token (long-lived)"
main.rs
にコードを書いてく。( EchoBot )
送られた文字をそのまま返すBotです。
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
extern crate line_bot_sdk_rust as line;
use dotenv::dotenv;
use std::env;
use rocket::http::Status;
use line::bot::LineBot;
use line::events::messages::MessageType as EventMessageType;
use line::events::{EventType, Events};
use line::messages::{SendMessageType, TextMessage};
use line::support::rocket_support::{Body, Signature};
#[post("/callback", data = "<body>")]
fn callback(signature: Signature, body: Body) -> Status {
// Get channel secret and access token by environment variable
let channel_secret: &str =
&env::var("LINE_CHANNEL_RECRET").expect("Failed getting LINE_CHANNEL_RECRET");
let access_token: &str =
&env::var("LINE_CHANNEL_ACCESS_TOKEN").expect("Failed getting LINE_CHANNEL_ACCESS_TOKEN");
// LineBot
let bot = LineBot::new(channel_secret, access_token);
// Request body parse
let result: Result<Events, &'static str> =
bot.parse_event_request(&signature.key, &body.string);
// Success parsing
if let Ok(res) = result {
for event in res.events {
// MessageEvent only
if let EventType::MessageEvent(message_event) = event.r#type {
// TextMessageEvent only
if let EventMessageType::TextMessage(text_message) = message_event.message.r#type {
// Create TextMessage
let message = SendMessageType::TextMessage(TextMessage {
text: text_message.text,
emojis: None,
});
// Reply message with reply_token
let _res = bot.reply_message(&message_event.reply_token, vec![message]);
}
}
}
return Status::new(200, "OK");
}
// Failed parsing
else if let Err(msg) = result {
return Status::new(500, msg);
}
Status::new(500, "Internal Server Error")
}
fn main() {
dotenv().ok();
rocket::ignite().mount("/", routes![callback]).launch();
}
そして実行。
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.55s
Running `target/debug/rust-linebot`
🔧 Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: 16
=> secret key: generated
=> limits: forms = 32KiB
=> keep-alive: 5s
=> read timeout: 5s
=> write timeout: 5s
=> tls: disabled
🛰 Mounting /:
=> POST /callback (callback)
🚀 Rocket has launched from http://localhost:8000
ローカルサーバーが起動したので、LINEBotのWebhookに設定する。
ローカルで建てたサーバーを一時的に外部に公開できる ngrok を使用します。
(ngrok の設定は調べてください。)
8000
ポートを指定して起動します(一応、リージョンは ap
)。
$ ngrok http 8000 --region=ap
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Account ななといつ (Plan: Free)
Version 2.3.35
Region Asia Pacific (ap)
Web Interface http://127.0.0.1:4040
Forwarding http://cc41bcab451d.ap.ngrok.io -> http://localhost:8000
Forwarding https://cc41bcab451d.ap.ngrok.io -> http://localhost:8000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
https
のURLをwebhookに設定します。
エンドポイントは /callback
なので、
https://cc41bcab451d.ap.ngrok.io/callback
を設定します。
メッセージを送信してみる。
返ってきた。
rocket
と ngrok
はこんな感じ。
- rocket
POST /callback application/json; charset=utf-8:
=> Matched: POST /callback (callback)
=> Outcome: Success
=> Response succeeded.
- ngrok
HTTP Requests
-------------
POST /callback 200 OK
ちゃんと、200
のレスポンスを返してる。
おっけい。
書いたコードは一応、ここに置いてあります。
https://github.com/nanato12/rust-linebot
最後に
正直、実装できてない部分があります。
issue 建ててあるので、もし良かったら実装してみてください。
あと、Rust初心者なので、
- ここの書き方きめえよ!
- ここもっといい書き方がある!
- Rustの良いところ活かせてない!
とかあればPRください。。。