LINEBotに興味を持ったこの頃。何か面白いものが作れないかと悩んでいました。
そこでLINEBotの定番(?)のクイズアプリを作ってみることにしました。
下準備(LINE)
まずはLINE Messaging APIのページにログインします。
プロバイダーを作成してください。Botの作成者のようなものです。
Messaging APIを選択してください
流れにそってチャネルを作っていき、Messaging API設定のタブへ行き、
応答メッセージの設定を無効化してください
以上でLINE側の設定はほぼ終わりです。
下準備(GAS)
Google Spreadsheetにアクセスし、新しいスプレッドシートを作成してください。
シートに
のように好きな問題を設定してください。
コードの設定
設定したら、拡張機能→App Scriptを開きます。
以下のコードをコード.gsコピペしてください。
// LINE developersのメッセージ送受信設定に記載のアクセストークン
const ACCESS_TOKEN = アクセストークン';
// スプレッドシートのID
const SPREADSHEET_ID = 'シートID';
// スプレッドシートのシート名
const SHEET_NAME = 'シート名';
// スプレッドシートから問題と正解を取得する関数
function getQuestionsAndAnswers() {
// スプレッドシートを開く
const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
// シートを取得する
const sheet = spreadsheet.getSheetByName(SHEET_NAME);
// データの範囲を取得する
const range = sheet.getDataRange();
// データを二次元配列として取得する
const values = range.getValues();
// ヘッダー行を除く
values.shift();
// 問題と正解のオブジェクトの配列に変換する
const questionsAndAnswers = values.map(row => {
return {
question: row[0],
choices: row.slice(1, 5),
answer: row[5]
};
});
// 結果を返す
return questionsAndAnswers;
}
// LINEからWebhookで受信したデータを処理する関数
function doPost(e) {
// Webhookで受信した応答用Token
const replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
// ユーザーID
const userId = JSON.parse(e.postData.contents).events[0].source.userId;
// ユーザーのメッセージを取得
const userMessage = JSON.parse(e.postData.contents).events[0].message.text;
// クイズの状態を管理するオブジェクト(プロパティストアに保存)
const quizState = PropertiesService.getScriptProperties();
// クイズが開始されているかどうか判定する
if (quizState.getProperty(userId)) {
// クイズが開始されている場合
// 現在の問題番号とスコアを取得する
const currentQuestionIndex = Number(quizState.getProperty(userId + '_currentQuestionIndex'));
const score = Number(quizState.getProperty(userId + '_score'));
// 問題と正解のデータを取得する
const questionsAndAnswers = getQuestionsAndAnswers();
// 現在の問題と正解を取得する
const currentQuestion = questionsAndAnswers[currentQuestionIndex];
const currentAnswer = currentQuestion.answer;
// ユーザーが「終了」と言ったらクイズを終了する(追加した部分)
if (userMessage === '終了') {
// 終了メッセージを送信する
replyLine(replyToken, `クイズを終了します。😊\nあなたの正解数は${score}問でした!🎉`);
// クイズの状態をリセットする
quizState.deleteProperty(userId);
quizState.deleteProperty(userId + '_currentQuestionIndex');
quizState.deleteProperty(userId + '_score');
return; // 関数を終了する
}
// ユーザーの回答が正解かどうか判定する
if (userMessage === currentAnswer) {
// 正解の場合
// スコアを加算する
const newScore = score + 1;
quizState.setProperty(userId + '_score', newScore);
// 正解メッセージを送信する
replyLine(replyToken, '正解です!👏');
// 次の問題があるかどうか判定する
if (currentQuestionIndex < questionsAndAnswers.length - 1) {
// 次の問題がある場合
// 問題番号を更新する
const nextQuestionIndex = currentQuestionIndex + 1;
quizState.setProperty(userId + '_currentQuestionIndex', nextQuestionIndex);
// 次の問題を送信する
sendQuestion(userId, questionsAndAnswers[nextQuestionIndex]);
} else {
// 次の問題がない場合
// クイズ終了メッセージを送信する(修正した部分)
replyLine(replyToken, `すべての問題に回答しました!😊\nあなたの正解数は${newScore}問です!🎉`);
// クイズの状態をリセットする
quizState.deleteProperty(userId);
quizState.deleteProperty(userId + '_currentQuestionIndex');
quizState.deleteProperty(userId + '_score');
}
} else {
// 不正解の場合
// 不正解メッセージを送信する
replyLine(replyToken, `残念、不正解です...😢\n正解は${currentAnswer}でした。`);
// 次の問題があるかどうか判定する
if (currentQuestionIndex < questionsAndAnswers.length - 1) {
// 次の問題がある場合
// 問題番号を更新する
const nextQuestionIndex = currentQuestionIndex + 1;
quizState.setProperty(userId + '_currentQuestionIndex', nextQuestionIndex);
// 次の問題を送信する
sendQuestion(userId, questionsAndAnswers[nextQuestionIndex]);
} else {
// 次の問題がない場合
// クイズ終了メッセージを送信する(修正した部分)
replyLine(replyToken, `すべての問題に回答しました!😊\nあなたの正解数は${score}問です!🎉`);
// クイズの状態をリセットする
quizState.deleteProperty(userId);
quizState.deleteProperty(userId + '_currentQuestionIndex');
quizState.deleteProperty(userId + '_score');
}
}
} else {
// クイズが開始されていない場合
// ユーザーが「クイズ」と言ったらクイズを開始する
if (userMessage === 'クイズ') {
// 問題と正解のデータを取得する
const questionsAndAnswers = getQuestionsAndAnswers();
// 最初の問題を取得する
const firstQuestion = questionsAndAnswers[0];
// クイズ開始メッセージを送信する
replyLine(replyToken, '英単語の四択クイズを始めます!👍\n「終了」と言ったらクイズを終了します。');
// 最初の問題を送信する
sendQuestion(userId, firstQuestion);
// クイズの状態を設定する
quizState.setProperty(userId, true); // クイズ中であることを示すフラグ
quizState.setProperty(userId + '_currentQuestionIndex', 0); // 現在の問題番号(0から始まる)
quizState.setProperty(userId + '_score', 0); // 現在のスコア
} else if (userMessage === '終了') {
// 終了メッセージを送信する
replyLine(replyToken, 'クイズはまだ始まっていません。😅');
} else {
// それ以外のメッセージの場合
// ヘルプメッセージを送信する
replyLine(replyToken, '「クイズ」と言って英単語の四択クイズを始めてください。😊');
}
}
}
// 問題を送信する関数
function sendQuestion(userId, question) {
// ボタンテンプレートのオブジェクトを作成する
const buttonTemplate = {
type: 'template',
altText: question.question,
template: {
type: 'buttons',
text: question.question,
actions: question.choices.map(choice => {
return {
type: 'message',
label: choice,
text: choice
};
})
}
};
// メッセージオブジェクトを作成する
const message = {
type: 'text',
text: '次の問題です!👇'
};
// メッセージとボタンテンプレートを配列に入れる
const messages = [message, buttonTemplate];
// LINEにメッセージを送信する
pushLine(userId, messages);
}
// LINEにメッセージを送信する関数(応答用Tokenを使う)
function replyLine(replyToken, message) {
// メッセージオブジェクトを作成する
const messageObject = {
type: 'text',
text: message
};
// リクエストURL
const url = 'https://api.line.me/v2/bot/message/reply';
// リクエストヘッダー
const headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + ACCESS_TOKEN
};
// リクエストボディ
const body = {
replyToken: replyToken,
messages: [messageObject]
};
// リクエストオプション
const options = {
method: 'post',
headers: headers,
payload: JSON.stringify(body)
};
// リクエストを送信する
UrlFetchApp.fetch(url, options);
}
// LINEにメッセージを送信する関数(ユーザーIDを使う)
function pushLine(userId, messages) {
// リクエストURL
const url = 'https://api.line.me/v2/bot/message/push';
// リクエストヘッダー
const headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + ACCESS_TOKEN
};
// リクエストボディ
const body = {
to: userId,
messages: messages
};
// リクエストオプション
const options = {
method: 'post',
headers: headers,
payload: JSON.stringify(body)
};
// リクエストを送信する
UrlFetchApp.fetch(url, options);
}
Apps Scriptの画面でコードの一部を編集します。
LINE Messaging APIのページに戻り、アクセストークンを取得します。Messaging APIタブの最下部にあるチャネルアクセストークンの欄から、
const ACCESS_TOKEN = アクセストークン'; のアクセストークンの部分に
発行したアクセストークンを貼り付けます。
const SPREADSHEET_ID = 'シートID';のシートIDは
https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXXXXXX/edit#gid=0
のXの部分にあたります。
const SHEET_NAME = 'シート名';は
任意の名前を設定してください。
また、左上のタブのファイル→共有→ウェブに公開の設定を忘れずに行ってください。
デプロイ
右上のデプロイボタンから、デプロイを行います。
新しいデプロイ→種類の選択⚙→ウェブアプリ
アクセスできるユーザーを全員にします。次にアクセスを承認します。
Advancedを押し、Go to ファイル名をクリック。許可をします。
デプロイが完了するとURLが生成されます。コピーして、LINE Messaging APIの
編集→URLを貼り付け→更新→検証を行います。
そしてWebhookの利用を許可します。以上で設定は終了です。
完成
これで完成です。実際にQRコードをスキャンして友達追加してみてください。ユーザーが「クイズ」といったらクイズを開始し、「終了」といったら成績発表が行われます。よいクイズライフをおくってください。