ゴミ出し日の前日にLINEで通知してくれるアプリを作る
なぜ作るのか
1ヶ月半前でしょうか、新しく引っ越したマンションのゴミの分別が厳しい。
覚えるのもめんどくさいし、怒られるのも嫌なので、前日に通知してくれるやつ作ってしまおう。
というのがきっかけ。
事前準備
LINE Developers (Messaging API)
LINE DevelopersでLINEアカウントでログインします。
[新規プロバイダー作成] - [新規チャネル作成] - [MessagingAPI]順で進み、
アプリの情報を書いていきましょう。
メッセージ送受信設定
のところにあるアクセストークン
と、
その他
にあるYour user ID
をメモしておきましょう。
Amazon Web Service (AWS Lambda, Amazon CloudWatch)
これで事前準備は完了です。
ローカルでの環境
Lambdaのコンソールで作成しても良いのですが、便宜上ローカルで開発を行います。
npm
npm i @line/bot-sdk moment-timezone
ゴミ出し日ロジックの実装
まず、曜日を扱うので、moment-timezone
を使ってロジックを実装しました。
const moment = require('moment-timezone');
moment.tz('Asia/Tokyo').locale('ja');
const Monday = 1;
const Tuesday = 2;
const Wednesday = 3;
const Thursday = 4;
const Friday = 5;
const Saturday = 6;
const Sunday = 7;
// 今日
function getMoment(date = new Date()) {
return moment(date)
.tz('Asia/Tokyo')
.locale('ja');
}
// 何番目の週か
function getWeekOfMonth(date) {
return Math.ceil(date.date() / 7);
}
module.exports = {
Monday: Monday,
Tuesday: Tuesday,
Wednesday: Wednesday,
Thursday: Thursday,
Friday: Friday,
Saturday: Saturday,
Sunday: Sunday,
getMoment: getMoment,
getWeekOfMonth: getWeekOfMonth,
};
私の住んでるところのゴミ出し日の情報を書いていきます。
可燃ゴミは
水・土、不燃ゴミ
は2週・4週目の火曜日、資源ゴミ
は月曜日だったので、
以下のように書きました。
const {
getMoment,
getWeekOfMonth,
Monday,
Tuesday,
Wednesday,
Saturday,
} = require('./utils/date');
const info = {
burnable: {
message: '明日は燃やすゴミの日です',
days: [Wednesday, Saturday],
weeks: [],
},
unburnable: {
message: '明日は燃やさないゴミの日です',
days: [Tuesday],
weeks: [2, 4],
},
recyclable: {
message: '明日は資源ゴミの日です',
days: [Monday],
weeks: [],
},
};
...
そして、今日がゴミ出しの日かどうかを判断する関数を書けばOKです。
...
// 曜日が合ってるか
const isDateDay = (date, days = []) => {
return days.includes(date.day());
};
// 週が合ってるか
const isWeekDay = (date, weeks = []) => {
const weekOfMonth = getWeekOfMonth(date);
return weeks.length > 0 ? weeks.includes(weekOfMonth) : true;
};
// ゴミ出しの日か
const isTrashDay = (date, obj) => {
return isDateDay(date, obj.days) && isWeekDay(date, obj.weeks);
};
// ゴミ出しの日だったら、メッセージを返す
const getMessage = date => {
let message = undefined;
Object.keys(info).forEach(key => {
const obj = info[key];
if (isTrashDay(date, obj)) message = obj.message;
});
return message;
};
...
LINE Messaging APIの実装
@line/bot-sdk
からline
をインポート、
一番最初にメモしておいたアクセストークン
を使います。
ですが、そのまま書くのではなく、Lambdaでもenv
設定ができるので、
process.env.ACCESS_TOKEN
を渡しましょう。
const line = require('@line/bot-sdk');
...
const client = new line.Client({
channelAccessToken: process.env.ACCESS_TOKEN
});
最後にメイン処理のhandler
を実装します。
requestが来たら、Lambdaがhandler
が実行されます。
もし、ゴミ出し日でなかったらメッセージは送られないように作っていきます。
exports.handler = async event => {
//明日がゴミ出し日かどうか
const tomorrow = getMoment().add(1, 'days');
const message = getMessage(tomorrow);
if (message) {
const postMessage = {
type:'text',
text: message,
}
try {
await client.pushMessage(process.env.USER_ID, postMessage);
} catch (error) {
console.log(error)
}
return {
statusCode: 200,
body: JSON.stringify(postMessage)
};
}
return {
statusCode: 200
}
};
client.pushMessage
メソッドにUSER_ID
と、postMessage
を渡してあげることで完成です。
Lambdaの設定
今までローカルで作業してたフォルダーを圧縮し、.zip
ファイルにします。
書いたコードをアップロードできます。
そして、環境変数にACCESS_TOKEN
とUSER_ID
を設定しましょう。
CloudWatchで毎晩10時にeventを実行する
トリガーを追加
でCloudWatch Events
を選び、
新しいルール
を追加します。
私はスケジュール式でcron式
を書きました。(時間はUTCで、日本の時間と違うので注意)
cron(0 13 * * ? *)
夜10:00に通知を送ってくれるようになりました。
最後に
いや、分別めんどくさいわ!