LoginSignup
8

【Rust・LINEBot】line-bot-sdk-rust が無かったから作ってみた。

Last updated at Posted at 2021-02-28

2023.12.04 追記

line-openapi の公開により、OpenAPIベースのライブラリに更新しました。

はじめに

Rustに入門し、早1週間。

Rustの色々な機能やシステムが有能すぎることに気付く。
そして、LINEBotの公式SDKにRustがないことに気付く。

ということで、練習がてらに line-bot-sdk-rust 作りました。

GitHub

Crate

Documentation

LINEBotを動かすための準備

基本的に、rocketactix-web といったFWを用いて動かします。

LINEBotのためのアカウントの作成方法はこちら
【初心者向け】LINEBOTを作るためのLINE公式アカウント作成・設定

Channel secret Channel access token (long-lived) の値を保存してください。

動かしてみよう

Rustのフレームワーク rocket を使用して行きます。

とりあえず、cargo new

$ cargo new rust-linebot

Cargo.toml に以下を追記。

Cargo.toml
[dependencies]
line-bot-sdk-rust = { version = "0.1", features = ["rocket_support"] }
rocket = "0.4"
dotenv = "0.15.0"

.env ファイルを作成

.env
LINE_CHANNEL_RECRET="取得した Channel secret"
LINE_CHANNEL_ACCESS_TOKEN="取得した Channel access token (long-lived)"

main.rs にコードを書いてく。( EchoBot )
送られた文字をそのまま返すBotです。

src/main.rs
#![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 を設定します。

LINE

メッセージを送信してみる。

LINE

返ってきた。

rocketngrok はこんな感じ。

  • 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ください。。。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8