ガチャつくブログ

IT系のお勉強のために、やってみたことをアウトプットしていきます。

Google Apps Script で遊ぶ - 防災情報をMicrosoft Teams/Slackに通知してみる -

f:id:tmt-tty:20190214223911p:plain

 はじめに

気象庁が発表する警報・注意報をTeamsやSlackに通知できないかなぁと言うのがきっかけで、色々調べながら何とか実装できたので、記事にします。

 

 必要なもの

  • 防災情報の取得
    気象庁XML形式で出しているものを利用。Atomフィードというらしい。
    PUSH型とPULL型があるが、PUSH型がややこしかったので、PULL型を使用した。

    xml.kishou.go.jp

  • Google Apps Script
    気象庁Atomフィールドから情報を取得⇛TeamsやSlackに投稿する処理をさせます。

    developers.google.com

  • Microsoft Teams or Slack
    Microsoftが提供しているチャットコミュニケーションツールです。
    Office365のライセンスがあれば使用可能です。

    products.office.com
    Slack社が提供しているチャットコミュニケーションツールです。
    下記から簡単に作れるので、作成方法は割愛します。

    slack.com

 

全体感は下記の様になります。

f:id:tmt-tty:20190214215848p:plain

 

 やり方

Microsoft Teams もしくは SlackでGoogle Apps Script からの投稿が受けられる様に、Incoming Webhooksの設定をします。設定方法はそれぞれ過去の記事を参照して頂ければと思います。

 

[Microsoft Teamsの場合]

www.gachatsuku.com

 

[Slackの場合]

www.gachatsuku.com

 

続いて、Google Apps Script の設定です。

Googleドライブを開き、新規 > その他 > Google Apps Script をクリックします。

f:id:tmt-tty:20181114150702j:plain

 

コードは、それぞれ下記の様になります。

コードについては、下記のブログを参考にさせて頂いております。

skysan87.hatenablog.com

 

処理としては、このコード実行時から10分以内の東京のデータを取得し、それぞれのチャットに投稿する処理となります。

 

[Microsoft Teamsの場合]

コード.gs

// 気象庁防災情報XMLフォーマット形式電文の公開(PULL型)の高頻度フィード(随時)を取得
// see: http://www.data.jma.go.jp/developer/xmlpull.html
function pullMeteoHeadline0() {
  var url = 'http://www.data.jma.go.jp/developer/xml/feed/extra.xml';
  var xml = UrlFetchApp.fetch(url).getContentText();
  var xmlDoc = XmlService.parse(xml);
  var rootDoc = xmlDoc.getRootElement();
  
  var nsDefault = XmlService.getNamespace("", 'http://www.w3.org/2005/Atom');
   
  var entries = rootDoc.getChildren("entry", nsDefault);
  
  var length = entries.length;
  
  var currentDate = new Date().getTime();
  
  var title, updated, date, author, content;
  var headlines = "";
  // 最長で10分後に更新される
  var past10Min = 10 * 60 * 1000;
  
  // 10分以内に更新された東京都の気象警報のみ取得
  for(var i=0; i < length; i++) {
    title = entries[i].getChildText("title", nsDefault);
    if(title != "気象特別警報・警報・注意報") continue;
    
    updated = entries[i].getChildText("updated", nsDefault);
    date = new Date(updated).getTime();
    if(currentDate - date > past10Min) continue;
    
    author = entries[i].getChild("author", nsDefault).getChildText("name", nsDefault);
    if(author != "気象庁予報部") continue;
    
    content = entries[i].getChildText("content", nsDefault);
    if(content.indexOf('東京都') === -1) continue;
    
    headlines += Utilities.formatString('[%s]<br>%s<br>%s<br>', title, toLocalDate(updated), content);
  }
  
  if(headlines !=="")
  {
    Logger.log(headlines);
  }
  {
  // WebhookのURL
  var url = 'Teams Webhook URL';
  // 投稿タイトル
  var title = 'タイトル部分です!!!';
    // 投稿メッセージ
  var text = headlines ;
  
  // 送信する
  var method = 'POST'; 
  var payload = {
    'title'    : title,
    'text'       : text,
  };
  var params = {
    'method' : method,
    'contentType': 'application/json',
    'payload' : JSON.stringify(payload)
  };
  var response = UrlFetchApp.fetch(url, params);
}
}

function toLocalDate(dateString)
{
  var date = new Date(dateString);
  var formattedDate = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy年M月d日 HH時');
  return formattedDate;
}

 

[Slackの場合]

コード.gs

// 気象庁防災情報XMLフォーマット形式電文の公開(PULL型)の高頻度フィード(随時)を取得
// see: http://www.data.jma.go.jp/developer/xmlpull.html
function pullMeteoHeadline00() {
  var url = 'http://www.data.jma.go.jp/developer/xml/feed/extra.xml';
  var xml = UrlFetchApp.fetch(url).getContentText();
  var xmlDoc = XmlService.parse(xml);
  var rootDoc = xmlDoc.getRootElement();
  
  var nsDefault = XmlService.getNamespace("", 'http://www.w3.org/2005/Atom');
   
  var entries = rootDoc.getChildren("entry", nsDefault);
  
  var length = entries.length;
  
  var currentDate = new Date().getTime();
  
  var title, updated, date, author, content;
  var headlines = "";
  // 最長で10分後に更新される
  var past10Min = 10 * 60 * 1000;
  
  // 10分以内に更新された東京都の気象警報のみ取得
  for(var i=0; i < length; i++) {
    title = entries[i].getChildText("title", nsDefault);
    if(title != "気象特別警報・警報・注意報") continue;
    
    updated = entries[i].getChildText("updated", nsDefault);
    date = new Date(updated).getTime();
    if(currentDate - date > past10Min) continue;
    
    author = entries[i].getChild("author", nsDefault).getChildText("name", nsDefault);
    if(author != "気象庁予報部") continue;
    
    content = entries[i].getChildText("content", nsDefault);
    if(content.indexOf('東京都') === -1) continue;
    
    headlines += Utilities.formatString('[%s]\n%s\n%s\n', title, toLocalDate(updated), content);
  }
  
  if(headlines !=="")
  {
    Logger.log(headlines);
  }

var postUrl = 'Slack Webhook URL';
var username = 'hoge_bot';  // 通知時に表示されるユーザー名
var icon = ':sunny:';  // 通知時に表示されるアイコン
var message = headlines;  // 投稿メッセージ

  var jsonData =
  {
     "username" : username,
     "icon_emoji": icon,
     "text" : message
  };
  var payload = JSON.stringify(jsonData);

  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };

  UrlFetchApp.fetch(postUrl, options);
}


function toLocalDate(dateString)
{
  var date = new Date(dateString);
  var formattedDate = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy年M月d日 HH時');
  return formattedDate;
}

 

東京以外のデータの取得については、気象庁XMLフォーマットを確認して、適宜変更してください。

 

最後にこのコードの実行間隔を10分にするトリガーをGoogle Apps Scriptに設定しておきます。

 

 確認

タイミングよく東京都の警報が無い可能性があるので、絞り込む行はコメントアウトするなどして、試してください。

 

[Teamsの場合]

f:id:tmt-tty:20190214222444p:plain

Microsoft Teamsの場合、改行コードが \n では効かなかったところで、若干ハマりました。

<br> を入れることで、解消しています。

 

[Slackの場合]

f:id:tmt-tty:20190214222622p:plain