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

Pocket