LoginSignup
10
2

More than 3 years have passed since last update.

LINEBOTで会話のステータス(文脈)管理(セッション管理?)

Posted at

やりたいこと

会話のステータス(文脈)のようなものをサーバー側に持たせておいて(Webアプリのセッションみたいな感じ?)、それによって応答が変わるようなLINEBOTを作りたい。

イメージとしてはこんな感じ。
image.png

自然言語解析とか、DeepLearningとか、RNNとか、雑談BOTとか、そういった高度な話ではありません。

実現方法

ユーザーIDをkey、保存すべき値を集めたクラスをvalueにしたmapを作成することにしました。

その他、メッセージに応答する箇所の実装はsample-spring-boot-kitchensinkを参考にしました(replyTextメソッド)。
言語はJavaです。

実はもっと王道の方法(≒ライブラリ、フレームワーク)がある、ということがあれば是非教えてください。

ステータスを保存するクラス

Status.java
public class Status {

    private String context = "0";//ステータス
    private String place = "";//場所

    public String getContext() {
        return context;
    }
    public void setContext(String context) {
        this.context = context;
    }

    public String getPlace() {
        return place;
    }
    public void setPlace(String place) {
        this.place = place;
    }

}

マップ

PseudoSession.java
public class PseudoSession {

    private static Map<String,Status> statusMap = new HashMap<>();

    public static Status getStatus(String userId) {
        return PseudoSession.statusMap.get(userId);
    }

    public static void putStatus(String userId, Status status) {
        PseudoSession.statusMap.put(userId, status);
    }

    public static String readContext(String userId) {
        return PseudoSession.statusMap.get(userId).getContext();
    }

    public static String readPlace(String userId) {
        return PseudoSession.statusMap.get(userId).getPlace();
    }

    public static void updateContext(String userId, String context) {
        Status newStatus = PseudoSession.statusMap.get(userId);
        newStatus.setContext(context);
        PseudoSession.statusMap.put(userId, newStatus);
    }

    public static void updatePlace(String userId, String place) {
        Status newStatus = PseudoSession.statusMap.get(userId);
        newStatus.setPlace(place);
        PseudoSession.statusMap.put(userId, newStatus);
    }

}

メインの処理

Controller.java
    private void handleTextContent(String replyToken, Event event, TextMessageContent content)
            throws Exception {
        final String text = content.getText();
        final String userId = event.getSource().getUserId();

        //初めてアクセスするユーザーの場合、mapに値を入れる
        if (Objects.isNull(PseudoSession.getStatus(userId))) {
            PseudoSession.putStatus(userId, new Status());
        }

        if(PseudoSession.readContext(userId).equals("0")) {

            if (text.equals("天気教えて")) {
                this.replyText(replyToken,"どこの天気?");
                PseudoSession.updateContext(userId,"1");
            } else {
                this.replyText(replyToken,"「天気教えて」って入力してみて!");
            }

        }else if (PseudoSession.readContext(userId).equals("1")) {

            if (!("富山".equals(text))&&!("石川".equals(text))) {
                this.replyText(replyToken,"富山か石川しか分からないんだ");
            } else {
                this.replyText(replyToken,"いつの天気?");
                PseudoSession.updatePlace(userId,text);
                PseudoSession.updateContext(userId,"2");
            }

        }else if (PseudoSession.readContext(userId).equals("2")) {

            if (!("今日".equals(text))&&!("明日".equals(text))) {
                this.replyText(
                        replyToken,"今日か明日しか分からないんだ");
            } else {
                String answer = text + "の"
                        + PseudoSession.readPlace(userId) + "の"
                        + "天気は晴れです。";
                this.replyText(replyToken,answer);
                PseudoSession.updatePlace(userId,"");
                PseudoSession.updateContext(userId,"0");
            }
        }
    }

結果

image.png

10
2
0

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
10
2