飲みに誘いにくい人が使う、飲みお誘いLINE Botの「用途に合わせた宛先設定部分」

#リモートが続いてふさぎ込んでしまう人を救いたい
　コロナの影響でリモートでお仕事をすることが増えて、
　よほどオープンにぐいぐい誘える人でない限り、人を飲みに誘うのも気がひけてしまう。（私もその一人です）
　今、会社に入った新人の子たちなど、顔も知らない社員の人がいっぱいいる。__なかなかつながりが広がらない__のが課題です。
　だけど飲みたい。___（言わずもがな対策は必須で）___
　
　__そんなときに会社の人たちを飲みに誘うサービスをLINE Botで作っています。__
　その１機能がこれです。まだDBへの接続などはやってなくて出し分けの部分のみ。

　<img width="400px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737206/bcfc25db-e480-51f3-e02a-06b6afb12d00.gif">

 

　なんでLINE Botを使ったかというと、
　シャイな人でも使えて、利点として__大体の人が使っている。どこでもメッセージを送れる。__
　といったところがあります。

　LINEということもあり、ユーザはメッセージやボタンで操作していくことになるので、
　__操作感の確認__をしようと思い、○○したら××が返ってきて、そのあとどういうアクションをとるかなど、
　アクションの設計について作ったものをヒアリングしています。
　
#操作感を後輩（若い子）にヒアリング聞いてみた
　■操作感
　　・LINEであるのはよい、__導入しやすい__。__メッセージも簡潔で使いやすい__と思う。
　　・自分が__登録した名前が出るのも安心感__がある。誰とも知らない人と飲むよりよい。
　　・今、1グループの人数をある限られた数にしているが、人数を__言い出しっぺの人が決められる__ようにするとよいと思う。

　■操作感というより企画の部分
　　・自分だと__1人目になるのは恥ずかしい__かもしれない。Bot内に含まれる人の多さがちょっと気になる。
　　・1年目の子が使うのはいいと思う。1年目の子が1人目であれば、2人目で続いて自分（先輩たち）も使いたい。

　■フィードバックを受けた改善活動　
　　・人数を決められるようにする機能は後々追加していくことにしよう。
　　　コロナが終わるまでは4人が上限としたいので、今回の開発範囲に入れるかは検討。
　　　
　　・1人目になるのが恥ずかしい。
　　　⇒目立つのが苦手なのが多い日本人の見られる傾向。
　　　　誰かが言ってくれたら乗っかりたいという流れ。
　　　　言い出しっぺになることが多い人に、
　　　　「そろそろ行く？」みたいなメッセージを送って、
　　　　1人目になる機会を増やすか、
　　　　なかなか言い出しっぺにならない人の1人目になる意識を盛り上げていく施策は必要かも。




#作っている機能
　__募集__（登録）こんな人が飲み行くって言ってるよ！と伝えるようにBotの友達皆に「__Broad__」で連絡
　__集まった連絡__ 　既定の人数集まったら、集まったメンバーをBotの友達皆に「__Broad__」で連絡
　__キャンセル__　いけなくなった時の機能。
　　　　　　　一緒に飲みに行く人たちだけでいいので、そのデータをとってきて「__Multicast__」で配信
　__連絡__　　　　お店や集合時間の連絡に使用。
　　　　　　　一緒に飲みに行く人たちだけでいいので、そのデータをとってきて「__Multicast__」で配信
　__他、想定にないメッセージ__　送ってきた人にちゃんと書き方を守ってもらうように「__Reply__」で返信

#構成
　基本的にユーザの操作はLINEで完結させる予定です。
　DBを通さない状態（固定データ）で出し分け出来るところまで作っています。
　<img width="600px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737206/4b4c7473-6627-c5b4-81cb-497cf8f9fa73.png">

#環境
　Node.js
　LINE Messaging API
　Cloud Functions　諸事情でサーバレスの方がやりやすかったため。

#ソース（動くけどまだ作りきってない）
アクセストークンなどは環境変数にしています。


```javascript
'use strict';

// LINESDKのライブラリをインポート
const line = require('@line/bot-sdk');

// コンフィグ
const config = {
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET,
};

const client = new line.Client(config);

// １グループに入る最大人数を定義
const GROUP_MEMBER_LIMIT = 4;

// LINEサーバーからWebhookがあると「サーバー部分」から以下の "handleEvent" という関数が呼び出されます
async function handleEvent(event) {
    console.log(event);
    var message = 'Please push text message.';
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }

    // レスポンスの関数を実行します
    return responseFunction(event);

}

// ユーザのメッセージに対してどう返すかを定義
const responseFunction = async (event) => {
    // 送られてくるイベントがテキストメッセージであれば下記の対応
    if (event.type === 'message' && event.message.type === 'text') {
        
        // 想定しているメッセージ形式であるかチェック


        // 送られてきたメッセージを分解
        const message_arr = event.message.text.split("　");
        console.log(message_arr[0]);
        console.log(message_arr[1]);

        let pushText = '';
        // 飲みに行きたい人が出たときの処理　チャンネル全体に告知
        if (check_go(message_arr[0])) {
            console.log("飲みに行きたいってさ");
            // 名前の抽出
            const user_name = message_arr[1];
            let member_count = 0;            


            // すでに今日飲みに行きたい人に自分が入っているか確認。入っていたら入ってますと連絡して終了。

            // 現在の登録人数を確認　今日の最初の登録かの確認に使用
            
            // 一番数字が大きい今日のグループNoとメンバーNoを取得

            // １グループに入る最大人数と同じであれば、新規グループを作ってメンバー1人目として登録、そうでなければ追加登録



            //後で書き換えする処理
            if(user_name === "ちょめお"){
                member_count = 1;
            }else if(user_name === "ちょめすけ"){
                member_count = 2;
            }else if(user_name === "ちょめこ"){
                member_count = 3;
            }else{
                member_count = 4;
            }
            pushText = "飲みに行きたい人" + member_count + "人目　" + user_name;



            if(member_count === GROUP_MEMBER_LIMIT){
                // 最後に登録した人が所属するグループに入っている名前を取得して格納

                let user_name_list = ["ちょめお","ちょめすけ","ちょめこ","ちょむちょむ"];

                pushText += "　グループの飲みに行くメンバーは、"
                // 同じグループの人数分ループ
                for(var i = 0 ; i <= user_name_list.length - 1 ; i++ ){
                    pushText += user_name_list[i] + "さん、";
                }
                pushText += "です！張り切っていきましょう！"
            }

            // チャンネルに登録されている方たちに連絡
            return client.broadcast({
                type: "text",
                text: pushText
            }).then(data => console.log(data))
            .catch(e => console.log(e))
        

        // キャンセル者が出たときのメッセージ　同じグループの人に届ける
        }else if(check_cancel(message_arr[0])){
            console.log("キャンセルしたい");
            try{
                       
                // すでに今日飲みに行きたい人に自分が入っているか確認。入ってなかったら登録されてませんと連絡して終了。
                

                // 出席者リストからキャンセル者を削除する　DELか、削除フラグを使うか考えどころ


                // キャンセル連絡をした人の名前をセット
                const user_name = message_arr[1];            
                // 誰がキャンセルしたかグループの人に連絡する用のメッセージ
                pushText = user_name + "さんがキャンセルしました";

                // メッセージ送信先配列の初期化
                let destination_list = ['ユーザID'];

                // メッセージ配列の初期化
                let message_list = [];
                message_list = [{type: 'text',text: pushText}];

                // 同じグループの人たちを取り出す処理

                // 宛先リストにユーザIDを追加

                console.log(destination_list);
                console.log(message_list);

                // 対象は同じグループの人たち
                client.multicast(destination_list,
                message_list
                )


            }catch(err){
                console.log(err.name +  ': ' + err.message);
                process.exit(-1);
            }
            // resolveを返す
            return Promise.resolve(null);

        // 連絡事項が来た時の処理 飲みに行く同じグループの人へ届ける
        }else if(check_contact(message_arr[0])){
            console.log("連絡事項あり！");
            try{
                       
                // すでに今日飲みに行きたい人に自分が入っているか確認。入ってなかったら登録されてませんと連絡して終了。
                            
                // 連絡事項の場合はそのままのメッセージを返す
                pushText = event.message.text;

                // メッセージ送信先配列の初期化
                let destination_list = ['ユーザID'];

                // メッセージ配列の初期化
                let message_list = [];
                message_list = [{type: 'text',text: pushText}];

                // 同じグループの人たちを取り出す処理

                // 宛先リストにユーザIDを追加

                console.log(destination_list);
                console.log(message_list);

                // 対象は同じグループの人たち
                client.multicast(destination_list,
                message_list
                )


            }catch(err){
                console.log(err.name +  ': ' + err.message);
                process.exit(-1);
            }
            // resolveを返す
            return Promise.resolve(null);
            



        }else{
            // 提供している機能以外（飲みに行きたい・キャンセルしたい・連絡）だった時
            return client.replyMessage(event.replyToken, {
                type: 'text',
                text: '「飲みに行きたい　名前」か「キャンセル　名前」か「連絡　内容を入れる」（全角スペースを真ん中に入れます。）と話しかけてね。'
            });
        }
        // 「プッシュ」で後からユーザーに通知します
        return client.pushMessage(event.source.userId, {
            type: 'text',
            text: pushText,
        });
    }

    
}

// 飲みに行きたいパターンかチェック
function check_go(event_text) {
    if(event_text === '飲みに行きたい'){
        return true;
    }else {
        return false;
    }
}

// キャンセルしたいパターンかチェック
function check_cancel(event_text) {
    if(event_text === 'キャンセル'){
        return true;
    }else {
        return false;
    }
}

// キャンセルしたいパターンかチェック
function check_contact(event_text) {
    if(event_text === '連絡'){
        return true;
    }else {
        return false;
    }
}


exports.handler = function linebot_message (req, res) {
  Promise
    .all(req.body.events.map(handleEvent))
    .then(result => res.status(200).send(`Success: ${result}`))
    .catch(err => res.status(400).send(err.toString()));
};

```



#今後の展開
　・飲み会の同グループの人たちを抽出する機能を作る。
　・データ登録機能からつくる
　・キャンセル（削除）を作る。
　・エラーが起きたときのユーザへのメッセージ
　・人数の枠を可変にするのは、後々検討