GoogleSiteの変更通知をSlackで受け取る
はじめに
ある日、Googleサイトの通知をSlackで受け取りたいという話がありました。
しかし、DriveやCalendarの通知を受け取ることはできるSlackくんですが、なんとSiteの通知は受け取れないのです。
調べたところ先人の方たちは自力で実装していた。
今回は先人に習って自力での実装をしてみた。
Googleサイトの変更通知をSlackに流すまで
上記の通り、SlackとGoogleサイトを紐付けるAPPはなかった。
仕方ないから自力で実装する。
流れは下記の通り。
- サイトの変更通知をメールで受け取る
- GASでGmail見て変更通知から必要な情報を抜き取る
- SlackAPI使って抜き取った情報を適当なチャンネルに流す
サイトの変更通知を受け取る
サイトでShift + f
で通知を受け取れるようになる。
もしくは、サイト右上の歯車から「サイトの操作→サイトの変更通知を受け取る」でもOK。
GASからGmailの情報を抜きとる
サイトの通知メールはnoreply@google.com
というアドレスで来るので、
このアドレスから送られてきた未読メールを対象に情報を取得する。
未読を取得するには下記ようにするだけでOK。
function getUnreadNotificationMail() { const unReadThreads = GmailApp.search("from:noreply@google.com is:unread"); }
メールはHTML形式 & テンプレフォーマットで届くので、
必要な情報をごちゃごちゃして抜き出す。
抜き出すのは下記のように。
function getUnreadNotificationMail() { const unReadThreads = GmailApp.search("from:noreply@google.com is:unread"); unReadThreads.forEach(function(unReadThread, index, array) { const mails = unReadThread.getMessages(); mails.forEach(function(mail, index, array){ if (mail.isUnread()){ const items = createItems(mail); if (items != null) { // ここにSlackへの通知処理を記載する } } }); }); } function extractBody(body) { if (body.indexOf("しました") == -1) { // テンプレフォーマット以外は無視 return null; } //本文から必要な範囲を取り出す return body.substring(0,body.indexOf("しました") + "しました".length); } function createItems(mail) { const message = extractBody(mail.getBody()); if (message == null) { return null; } //通知に必要な情報をオブジェクトにまとめる const items = {}; // タイトルから変更ページ名を取得する。 // タイトルの頭にはサイト名が着いているのでそこは削除 items.text = mail.getSubject().substring("[サイト名称]".length) + "\r" + mail.getDate().toLocaleString(); // 更新者取得 items.author_name = message.substring(message.indexOf(">") + 1, message.indexOf("さん") + "さん".length); // 更新ページ名取得 items.title = message.substring(message.indexOf(">", 80) + 1, message.indexOf("<", 80)) + message.substring(message.lastIndexOf("を")); // 更新ページURL取得 items.title_link = message.substring(message.indexOf("http://sites.google.com/site/"), message.indexOf("\"", message.indexOf("http://sites.google.com/site/"))); return items; }
Slackに変更内容を通知する
toke取得
SlackAPIを使うのにtokenが必要となる。
ここからtoken取得しておく。
Slackに通知を飛ばす
Slackへの通知はAPIを使う。
プレーンテキストで送ることもできるが、見やすいようにちょっと見た目を変えて上げる。
function postNotice(items) { const token = "先程取得したトークン"; const channel = "チャンネル名"; const username = "通知するBOT名"; const attachments = JSON.stringify([ { color: "#89CEEB", //インデント線の色 author_name: items.author_name, //インデント内に表示される著者名 title: items.title ,//インデント内に表示されるタイトル title_link: items.title_link,//そのリンク text: "上記リンクをクリックすると対象のページやファイルを表示します。" //インデント内に表示されるテキスト } ]); const payload = { "channel" : channel, //通知先チャンネル名 "text" : items.text, //送信テキスト "username": username, //BOTの名前 "attachments": attachments //リッチなメッセージを送る用データ }; const option = { "method" : "POST", "payload" : payload }; return UrlFetchApp.fetch("https://slack.com/api/chat.postMessage?token=" + token, option); }
この関数をgetUnreadNotificationMail()
のコメント部で呼び出してあげれば完成。
まとめ
コードの最終形は下記の通り。
function getUnreadNotificationMail() { const unReadThreads = GmailApp.search("from:noreply@google.com is:unread"); unReadThreads.forEach(function(unReadThread, index, array) { const mails = unReadThread.getMessages(); mails.forEach(function(mail, index, array){ if (mail.isUnread()){ const items = createItems(mail); if (items != null) { // ここにSlackへの通知処理を記載する const result = JSON.parse(postNotice(items)); if (result.ok) { mail.markRead(); } } } }); }); } function extractBody(body) { if (body.indexOf("しました") == -1) { return null; } //本文から必要な範囲を取り出す return body.substring(0,body.indexOf("しました") + "しました".length); } function createItems(mail) { const message = extractBody(mail.getBody()); if (message == null) { return null; } //通知に必要な情報をオブジェクトにまとめる const items = {}; items.text = mail.getSubject().substring("[UbiquitousHome]".length) + "\r" + mail.getDate().toLocaleString(); //年/月/日 時:分:秒 JST形式になる items.author_name = message.substring(message.indexOf(">") + 1, message.indexOf("さん") + "さん".length); items.title = message.substring(message.indexOf(">", 80) + 1, message.indexOf("<", 80)) + message.substring(message.lastIndexOf("を")); items.title_link = message.substring(message.indexOf("http://sites.google.com/site/"), message.indexOf("\"", message.indexOf("http://sites.google.com/site/"))); return items; } function postNotice(items) { const token = "先程取得したトークン"; const channel = "チャンネル名"; const username = "通知するBOT名"; const attachments = JSON.stringify([ { color: "#89CEEB", //インデント線の色 author_name: items.author_name, //インデント内に表示される著者名 title: items.title ,//インデント内に表示されるタイトル title_link: items.title_link,//そのリンク text: "上記リンクをクリックすると対象のページやファイルを表示します。" //インデント内に表示されるテキスト } ]); const payload = { "channel" : channel, //通知先チャンネル名 "text" : items.text, //送信テキスト "username": username, //BOTの名前 "attachments": attachments //リッチなメッセージを送る用データ }; const option = { "method" : "POST", "payload" : payload }; return UrlFetchApp.fetch("https://slack.com/api/chat.postMessage?token=" + token, option); }