2018/05/10

GoogleAppsScriptとSlackを連携して東京メトロの運行状況を通知できるようにしてみた

久しぶりのプログラミング回です.

Sponsored Link

使うもの

Google Apps Scriptって何?

Googleのサーバー上で動かせるスクリプトのこと.基本的にJavascriptで書ける.Google上で動くので,自分のサーバーを持たなくとも常時稼働するようにしたり,Googleドライブのファイルと連携させたりすることができる.非常に便利.

Slackって何?

使い始めたばかりなので全貌を未だに把握しきれていないのだが,ビジネス用のコミュニケーションツールというのが基本的な理解と思われる.

管理者がワークスペースを管理できるとか,ログを追えるとか特徴は色々あるが,大きな特徴の一つとして他のサービスとの連携が容易であることがあるらしい.

今回久しぶりにプログラミングやってみっか!と思い立ったのも,Slackでなんか色々できるらしいからやってみようか!というのが動機の一つ.

東京メトロのAPIって何?

これは文字通り.東京メトロの様々な情報を提供してくれるAPIで,東京メトロが公式に提供している.今回は各路線の運行状況を取得するためにAPIを利用する.

作ったもの

イメージ

プログラムを専門にしているわけではないのでてきとーな図でサーセンだが,全体像はだいたいこんな感じである.

なんでこれを作ろうと思ったの?

以前GoogleHomeに話しかけて東京メトロの運行状況を返すプログラムを書いたが,慣れないサーバーサイドに苦戦しよくわからないままHerokuを使った結果どうやってデプロイしたのかさえ思い出せなくなったので新しくわかりやすいものを作りたかった,というのが動機です.

こんなの作らなくてもYahoo乗換案内でいいよね?

はい.

コード

function getInformation() {
  //URL指定
  var url = '[東京メトロAPIのURL]';
  //JSONを取得
  var json = UrlFetchApp.fetch(url).getContentText();
  var jsonData = JSON.parse(json);
  return jsonData;  
}

function analyzeData(data){
  for (var i=0; i < data.length; i++){
    var linename = data[i]["odpt:railway"];
    var Information = data[i]["odpt:trainInformationText"];
    var TimeOfOrigin = data[i]["odpt:timeOfOrigin"]
    var current = getDB(linename);
    //運行情報に変更があればメッセ送信.
    if(Information!=current[0]){
      var payload = {
        'username': '東京メトロ運行状況(From Google Apps Script)',
        'text': '【'+ getRealLineName(linename) + '】' +Information      
      };
      var options = {
        'method': 'post',
        'contentType': 'application/json',
        'payload': JSON.stringify(payload),
      };      
      var webhook = '[Slackにメッセ投げる用のWebhookURL]';
      UrlFetchApp.fetch(webhook, options);          
    }
    //DB書き換え
    writeDB(linename, Information, TimeOfOrigin);
  } 
}

//現在格納されている情報の取得
function getDB(linename){
  //スプレッドシート取得
  var sp_url = '[前回データ保管用スプレッドシートのURL]';
  var sheet = SpreadsheetApp.openByUrl(sp_url);
  var sheets = sheet.getSheets();
  //'DB'シートを開く
  var linenumber = getLineNumber(linename);
  for(var i in sheets){
    if(sheets[i].getSheetName() == 'DB'){
      var CurrentInformation = sheets[i].getRange(linenumber, 2).getValue();
      var CurrentTimeOfOrigin = sheets[i].getRange(linenumber, 3).getValue();
    }
  }
  return [CurrentInformation, CurrentTimeOfOrigin]  
}

function writeDB(linename, Information, TimeOfOrigin){
  //スプレッドシート取得
  var sp_url = '[前回データ保管用スプレッドシートのURL]';
  var sheet = SpreadsheetApp.openByUrl(sp_url);
  var sheets = sheet.getSheets();
  //'DB'シートを開く
  var linenumber = getLineNumber(linename);
  for(var i in sheets){
    if(sheets[i].getSheetName() == 'DB'){
      sheets[i].getRange(linenumber, 2).setValue(Information);
      sheets[i].getRange(linenumber, 3).setValue(TimeOfOrigin);
    }
  }  
} 

function main() {
  //情報取得  
  var data = getInformation();
  analyzeData(data);
}

function getLineNumber(linename){
  var linenumber = 0;
  switch(linename){
    case 'odpt.Railway:TokyoMetro.Yurakucho':
      linenumber = 2;
      break;
    case 'odpt.Railway:TokyoMetro.Chiyoda':
      linenumber = 3;
      break;
    case 'odpt.Railway:TokyoMetro.Hibiya':
      linenumber = 4;
      break;
    case 'odpt.Railway:TokyoMetro.Hanzomon':
      linenumber = 5;
      break;
    case 'odpt.Railway:TokyoMetro.Namboku':
      linenumber = 6;
      break;
    case 'odpt.Railway:TokyoMetro.Marunouchi':
      linenumber = 7;
      break;
    case 'odpt.Railway:TokyoMetro.Ginza':
      linenumber = 8;
      break;
    case 'odpt.Railway:TokyoMetro.Fukutoshin':
      linenumber = 9;
      break;
    case 'odpt.Railway:TokyoMetro.Tozai':
      linenumber = 10;
      break;
  }
  return linenumber
}

function getRealLineName(linename){
  var reallinename = '';
  switch(linename){
    case 'odpt.Railway:TokyoMetro.Yurakucho':
      reallinename = '有楽町線';
      break;
    case 'odpt.Railway:TokyoMetro.Chiyoda':
      reallinename = '千代田線';
      break;
    case 'odpt.Railway:TokyoMetro.Hibiya':
      reallinename = '日比谷線';
      break;
    case 'odpt.Railway:TokyoMetro.Hanzomon':
      reallinename = '半蔵門線';
      break;
    case 'odpt.Railway:TokyoMetro.Namboku':
      reallinename = '南北線';
      break;
    case 'odpt.Railway:TokyoMetro.Marunouchi':
      reallinename = '丸ノ内線';
      break;
    case 'odpt.Railway:TokyoMetro.Ginza':
      reallinename = '銀座線';
      break;
    case 'odpt.Railway:TokyoMetro.Fukutoshin':
      reallinename = '副都心線';
      break;
    case 'odpt.Railway:TokyoMetro.Tozai':
      reallinename = '東西線';
      break;
  }
  return reallinename
} 

参考にしたのは以下のページ.

サンプル

こんな感じです.

雑感

まずGoogle Apps Scriptを使うのはメールbotを作った伝説の黒歴史以来だが,関数を決められた時間や間隔で自動実行できるのが良いし,Herokuにデプロイして~みたいな苦労がないのも良い.Pythonに慣れたからかjsはやや使いにくいなと思うこともあるが,このメリットがあるならjsで色々書くのも良いかなと思った.

Slackに関して言えば噂通り他のあれこれと連携が非常に容易だし,今回使っていない連携の方法も色々と用意されている印象.また,アプリやら何やらを作る時(前の艦これ遠征タイマーのときもそうだが)には通知周りの実装というのが意外と大変だったりするのだが,そこを丸投げできるというのもSlackのメリットなのかなと思う.次は何か実用性のあるものを作ってみたいと思う.

というか,メールbotプロジェクトの残骸として予定をメールで通知する機能が残ってるんだが,それSlackに移そうか.

やっぱオライリーいっとく?

0 件のコメント:

コメントを投稿