第○週に対応したゴミの日SlackリマインダーをGASで使ってみた

# できたもの
Slackで、第○週に応じてゴミの日をリマインダーすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/e2fc7d34-e5fb-63d1-15ea-184eca0386a0.png)

# はじめに
１ヶ月前に、誤って割ってしまったガラスのボウルの破片を未だに捨てられていません。
私の済んでいる地域は、金属・陶器・ガラスごみは第１、第３木曜日に出すことになっているのですが、いつも忘れます。

そこで、次の日が何ゴミを出す日か教えてくれるリマインダーをSlackで設定しようと思いました。
しかし、Slackのリマインダーだと、2023年7月現在で、第○週に対応していません。
無理やりやろうとすると、「今日が第１、３週なら金属・陶器・ガラスごみです。」みたいなメッセージを毎週投稿することになり、ややかっこ悪いです。
また、先駆者たちはGoogle Calendarと連携していますが、それで作成すると、カレンダーがゴミの日だらけになってしまうので、避けたいです。

そこで、GAS（Google Apps Script)のみを使用して、作成してみました。

# つくりかた

## 仕組み
* GASでSlackのチャンネルに投稿する関数を作ります。
    * 明日が、第○週の何曜日か判定します。
    * 明日がゴミ出しの日であれば、出すゴミをチャンネルに投稿します。
        * 何もなければ無視します。
    * ゴミ出し表に対応するものは、コードに直書きしました。
* GASのトリガーを使用して、毎日上記の関数を実行します。
    


## 事前準備
今回はSlackのボットを利用して、チャンネルにメッセージ投稿しました。
以下の記事などを参考に、ボットの作成とtokenを取得しておいてください。
[【SlackAPI】GASでpostMessageを叩いて、Slackにメッセージを投稿する方法まとめ](https://tanuhack.com/gas-slackapi-postmessage/)
tokenとメッセージ投稿するチャンネルのIDを控えておいてください。

## GASのスクリプト
以下のスクリプトを作成しました。
```javascript
//ゴミ出し表のDictionary
//燃えるゴミ：毎週水,土曜日
//金属・陶器・ガラスゴミ：第１、第３木曜日
//資源ゴミ：	毎週月曜日
//地域に応じて変更してください。
const garbageSchedules = [
  {
    type: "燃えるごみ",
    day: ["水","土"], 
    weekNumber: [1,2,3,4,5,6]//毎週
  },
  {
    type: "金属・陶器・ガラスごみ",
    day: ["火"], 
    weekNumber: [1,3]
  },
  {
    type: "資源ごみ",
    day: ["月"], 
    weekNumber: [1,2,3,4,5,6]//毎週
  }
]

//Slackにメッセージを投稿
function postMessage(text) {
  const url = "https://slack.com/api/chat.postMessage"
  try{
    const payload = {
      // GASのPropertyから情報を取得
      token: PropertiesService.getScriptProperties().getProperty('slack_token'),
      channel: PropertiesService.getScriptProperties().getProperty('slack_channel_id'),
      text: text,
    }
    const params = {
      method: "post",
      payload: payload,
    }
    UrlFetchApp.fetch(url, params)
  } catch (e){
    Logger.log(e)
  }
}

//指定した日が第○週の第○曜日か算出
function getWeekdayOfMonth(date) {
  const firstDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1)
  const dayOfWeekOfFirstDay = firstDayOfMonth.getDay()
  const dayOfMonth = date.getDate()
  const weekNumber = Math.ceil((dayOfMonth + dayOfWeekOfFirstDay) / 7)
  const weekdays = ["日", "月", "火", "水", "木", "金", "土"]
  const weekday = weekdays[date.getDay()]
  return {
    weekNumber: weekNumber,
    day: weekday,
  }
}

//ゴミ出し表から何のゴミの日か算出する。なければ空テキストを返す
function garbageScheduleType(result) {
  for (const garbageSchedule of garbageSchedules) {
    if (garbageSchedule.day.includes(result.day) && garbageSchedule.weekNumber.includes(result.weekNumber)){
      return garbageSchedule.type
    }
  }
  return ""
}

//時間トリガーで実行する関数
function trigger(){
  const tomorrow = new Date()
  tomorrow.setDate(tomorrow.getDate() + 1)
  const result = getWeekdayOfMonth(tomorrow)
  const type = garbageScheduleType(result)
  if (type){
    //必要に応じてメンションをつけるなり、投稿内容を変えてください。
    const text = `明日は${type}です。`
    postMessage(text)
  }
}

```
"slack_token"及び、"slack_channel_id"は、事前準備で取得したものを、スクリプトプロパティに設定してください。


## トリガー設定

前日の夜頃に通知して欲しいので、午後７時〜８時に設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/f0ce8706-aeec-f15f-2f74-78e5f8a1b751.png)

# 結果
（再掲）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/e2fc7d34-e5fb-63d1-15ea-184eca0386a0.png)


# おわりに
GASを使用して、Slackで第○週に対応したリマインダーを作成することができました。
今回はSlackのボットを利用しましたが、スクリプトを使い回せば、他のツールでも、通知することができます。

# スペシャルサンクス
大変お世話になりました。
- [【SlackAPI】GASでpostMessageを叩いて、Slackにメッセージを投稿する方法まとめ](https://tanuhack.com/gas-slackapi-postmessage/)