Botを使った出欠確認機能の実装 - 自作サービスづくり7
今回の記事もWeb開発に関する記事です。
前回はslack上のbotから前々回実装した出欠更新APIを叩きました。
developer-bpeldi2oerkd8.hatenablog.com
このままでは、現在の出欠情報を確認する際にその都度出欠を更新する必要があります。
このため、出欠情報の確認のみをする機能も必要だと考えました。
そこで、今回は出欠確認APIを実装し、botからこのAPIを叩いてみたいと思います。
出欠確認APIの実装
出欠更新APIと同じように実装していきます。
基本的には同じで、変更部分はAvailabilityの更新部分をfindOneに変えるだけです。
getData() .then(([schedule, user, date]) => { Availability.findOne({ where: { scheduleId: schedule.scheduleId, userId: user.userId, dateId: date.dateId } }) .then((a) => { if(a) { res.json({ status: 'OK', data: { slackId: user.slackId, date: date.date, availability: a.availability } }); } //出欠登録情報がない場合は欠席 else { res.json({ status: 'OK', data: { slackId: user.slackId, date: date.date, availability: 0 } }); } }); }) .catch(([scheduleMessage, userMessage, dateMessage]) => { res.json({ status: 'NG', error: { messages: [scheduleMessage, userMessage, dateMessage] } }); });
データベースに出欠情報が登録されていない場合は欠席として扱っているため、その処理が入っています。
そのほかのコードについてはこちらです。
github.com
エラーメッセージが正しく出力されるように修正
テストコードを書き、正常時は登録が可能になったことが確認できたのですが、予定に存在しない日付を入れるとエラーメッセージが正常に返ってこない問題がありました。
私はエラーが出た場合Promiseのrejectでエラーメッセージを返していたのですが、Javascriptでは複数のPromiseを非同期処理する場合、1つrejectでエラーを返されると、そこでcatch内の処理に入ってしまうそうです。
今回はエラーが発生した場合、そのすべてのエラーメッセージを出力したかったため、エラーが起きた場合でもresolveでエラー状態であることを返し、その後エラーメッセージを配列にしてJSONで返す情報に入れました。
具体的には、以下のようにエラーの場合'error'という文字列を返し、
if(d) { resolve(d); } else { resolve('error'); }
エラーの場合は、そのエラーメッセージをmessagesという配列に入れるようにしました。
schedule = schedule === 'error' ? 'このルームIDはシステムに登録されていません' : ''; user = user === 'error' ? 'このSlackIDはシステムに登録されていません' : ''; date = date === 'error' ? '入力した日付はこの予定に存在しません' : ''; const messages = []; if(schedule) { messages.push(schedule); } if(user) { messages.push(user); } if(date) { messages.push(date); }
もう少しきれいに書けるような気もしますが、ひとまずこちらで行きます。
コードの詳細については以下のようになっています。
github.com
Jestでテストコードを書き、問題がないか確認しました。
結果がこちらです。
問題なくテストが通っています。
BotからAPIを叩く
APIが完成したので、今度はbotのほうを実装していきます。
出欠更新APIの時と同じように実装します。
違いは、今回はPOSTではなく、GETを用いる点です。
function confirmAvailability(msg, roomId, slackId, dateString){ const confirm_url = api_url + '/' + roomId + '/users/' + slackId + '/dates/' + dateString; msg.http(confirm_url) .get() ((err, res, body) => { if(err) { msg.send(err); return; } const data = JSON.parse(body); const availabilityStatus = ['欠席', '不明', '出席']; if(data.status === 'OK'){ msg.send('出欠確認成功:' + '<@' + data.data.slackId + '> さんの' + data.data.date + 'の予定は ' + availabilityStatus[data.data.availability] + ' です'); } else { msg.send('出欠確認失敗:' + '\n' + data.error.messages.join('\n')); } }); }
そのほかのコードについてはこちらです。
github.com