GASで電車が遅延・運休したらメールするスクリプトを書いてみた

## 背景

GASの勉強がてら何か作って見ようと思っていたら [電車が遅延・運休したらLINEに通知するスクリプトを書いてみた](https://qiita.com/S_eki/items/c93355a4e3ff93293e26)という記事が目に入ったので真似してみました。<br>※構成も真似してます。すいません。

ただ、おじさん未だにガラケーなのでLINEじゃなくてガラケーにメールに通知するだけですが。

## 事前に用意するもの

- Googleアカウント

## しくみ

基本的には元記事と同じ([鉄道運行情報](http://www.jikokuhyo.co.jp/)から情報取得)ですが、テキストで持ってた情報はスプレッドシートに記述することにしました。

というわけでGoogleスプレッドシートで新規作成しておきます。

A列には元記事の`SENKU_DB.txt`の内容を、B列には`URL_DB.txt`の内容をコピペします。

と思ったけど、メールを何通も送られると料金的に困るので

- スプレッドシートにチェックマークが付いているものだけ対象

ということにします。というわけでA列の左に1列挿入して`A1:A22`にチェックボックスを挿入しておきます。

![spreadsheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122792/07a1ab81-c673-58cc-8a73-da735a335270.png)

というわけで、A列: チェックボックス、B列: 線区名、C列: URL、となっています。

GASを使うので ツール - スクリプトエディタ からスクリプトエディタを開いて、適当な名前で保存しておきます。

## 実装したスクリプト

遅延のキーワードも真似してます。

実装で変えているのは、

- 午前二時から四時にはそもそも情報提供されていないので何もしない(GASの制限対策)
- キーワードの抽出は正規表現で手抜き
- D列に前回チェックした内容を記憶しておく
- 前回の内容とスクレイピングした内容が違っていればメール送信

といったところでしょうか。

```javascript
function range(begin, end) {
  var result = [];
  for (var i = begin; i <= end; ++i) {
    result.push(i);
  }
  return result;
}

function myFunction() {
  try {
    // 2：00～4：00は何もしない
    var hours = new Date().getHours();
    if (2 <= hours && hours < 4) return; 
    
    var sheet = SpreadsheetApp.getActiveSheet(),
        lastRow = sheet.getLastRow(),
        messages = range(1, lastRow)
    .map(function (row) {
      // チェックマークが付いているところだけ対象
      if (!sheet.getRange(row, 1).isChecked()) return '';
      // C列がURL
      var url = sheet.getRange(row, 3).getDisplayValue(),
          // URLにアクセスして取得した内容から必要な部分だけ抽出(正規表現で手抜き)
          message = (UrlFetchApp.fetch(url).getContentText().match(/<div\s+class="corner_block_row_detail_d".*?>\s*([\s\S]*?)\s*<\/div>/)||[])[1];
      // 何もないときは空文字列
      if (message === '現在、平常通り運転しています。' || message === '情報提供時間は4：00～翌2：00となっています。') message = '';
      // 前回のチェック内容と比較(前回の内容はD列に記録)
      var rng = sheet.getRange(row, 4),
      old = rng.getValue();
      if (old === message) return '';
      rng.setValue(message);
      // 何もないときは通知しない
      if (!message) return '';
      // B列は線区名
      var name = sheet.getRange(row, 2).getDisplayValue();
      return name + ': ' + message + '\n';
    }).join('');
    // すべての線区でなにもなければ通知しない
    if (!messages) return;
    console.log(messages);
    // 宛先はスクリプトのプロパティから取得
    var notifyTo = PropertiesService.getScriptProperties().getProperty('NOTIFY_TO');
    if (notifyTo) {
      GmailApp.createDraft(, '鉄道運行情報', messages).send();
    }
  } finally {
    console.log('end');
  }
}
```

メール通知はGmailを使って送ります。

メールの宛先は ファイル - プロジェクトのプロパティ から スクリプトのプロパティ を開いて NOTIFY_TO を追加して設定しておきます。

ここまで設定できたら一度実行しておきます。実行 - 関数を実行 - myFunction で実行すると初回は認証やら許可やらを求められますので適当に許可して下さい。

あとは 編集 - 現在のプロジェクトのトリガー からトリガーを追加して5分おきで実行されるようにしておきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122792/2b5c6af8-231d-09e4-ea2d-0f054c97e3b6.png" width="300">

GASから1日にWEBアクセスしたりメール送信できる回数は制限されているらしいんですが、5分おきなら $12 × (24 - 2) = 264$ でたかが知れてるかなーと。

## 実行結果

こんな感じのメールが来ます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122792/14d3f2c0-c1f5-dcc0-1e93-43062341eb44.jpeg" width="200">

## 使用上の注意点

一つのスクリプトだとたかがしれてますが、調子に乗ってこんなスクリプトをバカスカ作っているとGASの制限を超えてしまっていろいろと動かなくなるらしいです。

https://developers.google.com/apps-script/guides/services/quotas

を見ながら、制限を超えないように調整しましょう。

## まとめ

GASがあると自前のサーバーが無くてもこういうことできるんですね。