こんがりぃ

都内在住フリーランスのエンジニア。主にRuby on Rails。Twitter(@Kongari_Bug)で格ゲー。

Googleマイマップの更新情報をSlackに通知する

やりたいこと

Googleマイマップにラーメン屋の感想を入力し、Slackに内容を通知して共有したい

調べた限り、マイマップには更新を検知するためのwebhook設定などはない。
今回はGoogle Apps Script, Fusion Tablesを利用して実現する。
※Fusion Tablesは2019年12月でサービス終了のアナウンスが流れているため注意してください

f:id:KongariBug:20181215041931p:plain

各種利用するサービスについて

マイマップ

マイマップ – 概要 – Google マップ

自分専用のGoogle Mapを作り、メモとかピンができる

https://i.gyazo.com/c68be0a1c5033d08c08c51427be08558.png

Fusion Tables

About Fusion Tables - Fusion Tables Help

スプレッドシートRDBMSのようにSQLで編集することができる。

実装

既存マイマップをFusion Tablesに落とし込む

マイマップはkmlというxml形式でエクスポートすることができる。

f:id:KongariBug:20181215042807p:plain

ダウンロードしたkmlファイルを開いてURLをたどっていくと以下のような形式のkmlがダウンロードできるリンクにたどり着く

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <name>hogehogeマップ</name>
    <description>hogehoge</description>

上記kmlをダウンロードし、新規作成したFusion Tablesにインポートする

f:id:KongariBug:20181215043309p:plain

正しくインポートされたら name , description カラムが追加される

f:id:KongariBug:20181215044107p:plain

Google Apps Scriptでkmlを監視する

以下に全文ソース記載。やっていることは

  1. 現在のFusion Tablesのデータを取得
  2. 現在のkmlのデータを取得
  3. kmlからpinデータのみを抽出
  4. Fusion Tablesのデータと比較
  5. Fusion Tablesにないものは新規レビューとしてFusion Tablesに追加、Slackに通知
function myFunction() {
  // table id を入力
  var tableId = '*****************************************';
  var selectSql = 'SELECT name, description FROM ' + tableId;
  var res = FusionTables.Query.sql(selectSql);
  
  // fusion tableのデータをハッシュに
  var fusionTable = {};
  
  for(var i = 0; i < res.rows.length; i++) {
    var name = res.rows[i][0];
    var description = res.rows[i][1];
    fusionTable[name] = fusionTable[name] || [];
    fusionTable[name].push(description);
  }
  
  // kml urlを入力
  var kmlUrl = 'https://www.google.com/maps/d/kml?forcekml=1&mid=******************************';
  var kmlResponse = UrlFetchApp.fetch(kmlUrl);
  var xml = XmlService.parse(kmlResponse.getContentText());
  
  // ハードコーディングしているが取得したほうが安全
  var namespace = XmlService.getNamespace('http://www.opengis.net/kml/2.2')
  
  // kmlのFolder Elementの中にデータあり
  var folders = xml.getRootElement().getChildren()[0].getChildren('Folder', namespace);
  
  for(var i = 0; i < folders.length; i++) {
    var folder = folders[i];

    // name, descriptionのみを取り出す
    var placemarks = folder.getChildren("Placemark", namespace);
    for(var j = 0; j < placemarks.length; j++) {
      var nameElement = placemarks[j].getChild("name", namespace);
      var descriptionElement = placemarks[j].getChild("description", namespace);
      var name = '';
      var description = '';
      
      if(nameElement) name = nameElement.getValue().trim();
      if(descriptionElement) description = descriptionElement.getValue().trim();
      
      // 現在のFusion Tablesとの比較
      if(!fusionTable[name] || fusionTable[name].indexOf(description) == -1) {
        Logger.log(name + ": false");
        Logger.log("name")
        Logger.log(name);
        Logger.log("description");
        Logger.log(description);
        Logger.log("fusionTable");
        Logger.log(fusionTable[name]);
        var insertSql = 'INSERT INTO ' + tableId + '(name, description) VALUES (\'' + name + '\', \'' + description + '\');';
        FusionTables.Query.sql(insertSql);
        sendSlackMessage(name, description);
      }
    }
  }
}

function sendSlackMessage(name, description) {
  // Slack incoming webhook URLを入力
  var slackWebhook = 'https://hooks.slack.com/services/****************************;
  var options = {
    "method": "post",
    "contentType": "application/json",
    "payload": JSON.stringify({ "text": "*" + name + "*\n" + description })
  };
  UrlFetchApp.fetch(slackWebhook, options);
}

定期的に実行する

GASを定期実行するトリガーを設定する

f:id:KongariBug:20181215044913p:plain

Done

参考URL

Fusion Tables×Google Apps Script(Webアプリケーション作成編1) - Qiita