質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Google カレンダー

Google カレンダーは、Google社が提供する無料のスケジュール管理ツールです。パソコンやスマートフォン、タブレットなどからアクセスし、スケジュールの追加・変更が可能。Googleアカウントがあれば誰でも使用できます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Slack

Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

Q&A

解決済

1回答

362閲覧

Google App ScriptでGooleカレンダーのイベントで変更、追加、削除が行われたらSlackに通知

kks

総合スコア3

Google カレンダー

Google カレンダーは、Google社が提供する無料のスケジュール管理ツールです。パソコンやスマートフォン、タブレットなどからアクセスし、スケジュールの追加・変更が可能。Googleアカウントがあれば誰でも使用できます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Slack

Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

0グッド

2クリップ

投稿2024/04/05 01:08

編集2024/04/08 08:40

実現したいこと

表題の件ですが、Gooleカレンダーのイベントで変更、追加、削除が行われた場合、特定のアカウントSlackに通知するという仕組みです。

発生している問題・分からないこと

https://www.yukibnb.com/entry/slack_incoming_webhook_url

現在、上記のサイトを参考に「Incoming Webhook URL」を取得して特定のアカウントに紐づけて、
例えばSlackのPCやスマホアプリが入っていたら通知がくる仕組みのはずですが、
グーグルカレンダーで何か変更等があれば、通知できるのですが1点問題があります。

・1回の変更だけで2件通知が着てしまう

イメージ説明

通知はできていますが、挙動や表示のされ方がおかしいという事です。
こちらのご教示のほど宜しくお願い致します。

エラーメッセージ

error

1エラーメッセージはありません。

該当のソースコード

Google

1function monitorAllCalendars(e) { 2 console.log(e.triggerUid); 3 4 try { 5 var calendarIds = getAllCalendarIds(); 6 var lastUpdated = PropertiesService.getScriptProperties().getProperty('lastUpdated'); 7 var currentTime = new Date(); 8 var notifiedEvents = getNotifiedEvents() || []; 9 10 var today = new Date(); 11 today.setHours(0, 0, 0, 0); 12 13 var twoDateLater = new Date(today); 14 twoDateLater.setDate(today.getDate() + 7); // 1週間後の日付を取得 15 twoDateLater.setHours(0, 0, 0, 0); // 時刻をリセットして日付のみにする 16 17 for (var i = 0; i < calendarIds.length; i++) { 18 var calendarId = calendarIds[i]; 19 var startDateTime = today; 20 var endDateTime = twoDateLater; 21 22 var events = CalendarApp.getCalendarById(calendarId).getEvents(startDateTime, endDateTime); 23 24 if (events && events.length > 0) { 25 for (var j = 0; j < events.length; j++) { 26 var event = events[j]; 27 var eventId = event.getId(); 28 var lastUpdatedTime = event.getLastUpdated(); 29 30 // イベントのリンクを生成 31 var calendarLink = 'https://calendar.google.com/calendar/render?action=VIEW&eid=' + eventId; 32 33 // すでに通知されたイベントでないか、最後の通知時間以降のイベントかを確認 34 if (lastUpdatedTime > new Date(lastUpdated)) { 35 var title = event.getTitle(); 36 if (!title) { 37 title = 'タイトルが設定されていません'; 38 Logger.log('イベントのタイトルがありませんでした。'); 39 } 40 41 var startTime = event.getStartTime() ? formatDate(event.getStartTime()) : '開始日時が設定されていません'; 42 var endTime = event.getEndTime() ? formatDate(event.getEndTime()) : '終了日時が設定されていません'; 43 var description = event.getDescription() || '詳細が設定されていません'; 44 var location = event.getLocation() || '場所が設定されていません'; 45 46 // イベントのIDが通知済みリストに含まれているかを確認 47 //if (!notifiedEvents.includes(eventId)) { 48 // 通知されていない場合のみ通知を送信 49 var eventDetails = { 50 title: title, 51 startTime: startTime, 52 endTime: endTime, 53 description: description, 54 location: location, 55 url: calendarLink, 56 triggerUid: "your_trigger_uid_here", 57 authMode: "your_auth_mode_here", 58 calendarId: calendarId 59 }; 60 61 sendSlackNotification(eventDetails); 62 63 // 通知されたイベントを記録 64 notifiedEvents.push(eventId); 65 //} 66 } 67 } 68 } 69 } 70 71 // 通知されたイベントと最後の通知時間を保存 72 PropertiesService.getScriptProperties().setProperty('notifiedEvents', notifiedEvents.join(',')); 73 PropertiesService.getScriptProperties().setProperty('lastUpdated', currentTime.toISOString()); 74 } catch (error) { 75 Logger.log('エラーが発生しました: ' + error); 76 } 77} 78 79// 日付を指定された形式に整形する関数 80function formatDate(date) { 81 var year = date.getFullYear(); 82 var month = ('0' + (date.getMonth() + 1)).slice(-2); 83 var day = ('0' + date.getDate()).slice(-2); 84 var hours = ('0' + date.getHours()).slice(-2); 85 var minutes = ('0' + date.getMinutes()).slice(-2); 86 return year + '/' + month + '/' + day + ' ' + hours + ':' + minutes; 87} 88 89 90function getNotifiedEvents() { 91 var notifiedEvents = PropertiesService.getScriptProperties().getProperty('notifiedEvents'); 92 return notifiedEvents ? notifiedEvents.split(',') : []; 93} 94 95function getAllCalendarIds() { 96 var calendars = CalendarApp.getAllCalendars(); 97 var calendarIds = []; 98 for (var i = 0; i < calendars.length; i++) { 99 var calendar = calendars[i]; 100 calendarIds.push(calendar.getId()); 101 } 102 return calendarIds; 103} 104 105function sendSlackNotification(eventDetails) { 106var webhookUrl = 'SlackのIncoming WebhookのWebhook URLを入力'; 107 var message = { 108 text: 'Googleカレンダーのイベントが更新されました。\n' + 109 'タイトル: ' + eventDetails.title + '\n' + 110 '開始日時: ' + eventDetails.startTime + '\n' + 111 '終了日時: ' + eventDetails.endTime + '\n' + 112 '詳細: ' + eventDetails.description + '\n' + 113 '場所: ' + eventDetails.location + '\n' + 114 'URL: ' + eventDetails.url, 115 }; 116 117 var options = { 118 method: 'post', 119 contentType: 'application/json', 120 payload: JSON.stringify(message) 121 }; 122 123 UrlFetchApp.fetch(webhookUrl, options); 124} 125 126 127

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

コンソールデバックで調べても特にエラーなことはありませんでした。
またGoogle App Scriptを利用することでトリガーというものも設定しています。
そちらは今回3つの関数で制御していましたが、1つトリガーに登録しています。

イメージ説明

この状態でイベント更新があると複数の通知が着てしまいます。
この複数通知とは2通ずつ遅れながら3回ずつ送られます、その合計が6通の通知となります。
ゴールは1通だけでよいです。

補足

今回はAGSでコードを集約して書いています。
その中で以下の記述はWebhookのWebhook URLが入ります。
今回は伏せて置いています。

var webhookUrl = 'SlackのIncoming WebhookのWebhook URLを入力';

急ぎの案件ではありますので
どなたかご教示いただけたらと思います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YellowGreen

2024/04/05 20:42

なぜ設定されているのかわからないトリガーが2つあります。 getAllCalendarIds sendSlackNotification この2つの関数をトリガーに設定しているのは どのような理由によるものなのでしょうか。 試しに2つを削除してみるとどうなりますか?
kks

2024/04/08 00:52

YellowGreen様 ご質問ありがとうございます。 上記トリガーを外しますとカレンダーで変更があっても通知は着ませんでした。 「monitorAllCalendars」関数だけのトリガー登録では動きませんが、 「sendSlackNotification」もトリガー登録しないと通知が来ない状態です。 ちなみに「getAllCalendarIds」は削除しても問題内容でした。 その代わり、以下の記述で2回通知が呼ばれるのは変わりません。 ==== Googleカレンダーのイベントが更新されました。 undefined 開始日時: undefined 終了日時: undefined 詳細: undefined 場所: undefined URL: undefined ====
kks

2024/04/08 03:02

YellowGreen様 すみません、現在ソースコードを修正したものに差し替えました。 現状トリガーの登録は「monitorAllCalendars」だけとなります。 この状態でグーグルカレンダーでイベント変更すると5~6通来てしまいます。
guest

回答1

0

ベストアンサー

結論

通知の重複を防ぐための応急的な対応方法しか思い浮かびません。
トリガーを削除して再設定しても変わりませんでした。

時間の経過で改善するかどうかも不明ですが、
過去にもトリガーによる重複起動があったようですから、
もしかするといつか改善するかもしれません。

応急的な対応

このスクリプトが実行中であることを
プロパティーサービスに保存したisExecutingの値で確認できれば、
後発のスクリプトは中断するように修正してみました。

ただし、カレンダーの予定が実際に同時期に複数更新された時に1つしか通知されなくなる可能性があります。

JavaScript

1 try { 2 const lock = LockService.getScriptLock(); // ←以下13行目まで追加 3 lock.tryLock(200); 4 const properties = PropertiesService.getScriptProperties(); 5 const isExecuting = properties.getProperty('isExecuting'); 6 if (isExecuting === 'Yes') { 7 lock.releaseLock(); 8 console.log('実行中のスクリプトが重複しているので処理を中断しました。'); 9 return; 10 } else { 11 properties.setProperty('isExecuting', 'Yes'); 12 } 13 lock.releaseLock(); // ←この行まで追加 14 const lastUpdated = properties.getProperty('lastUpdated'); // ←ここに移動して修正 15 const calendarIds = getAllCalendarIds(); // ←ここに移動 16 const currentTime = new Date(); // 以下同じ 17 const notifiedEvents = getNotifiedEvents() || []; 18 19 // --- 中略 --- 20 21 // 通知されたイベントを記録 22 notifiedEvents.push(eventId); 23 } 24 } 25 } 26 } 27 28 // 通知されたイベントと最後の通知時間を保存 29 properties.setProperty('notifiedEvents', notifiedEvents.join(',')); // ←修正 30 properties.setProperty('lastUpdated', currentTime.toISOString()); // ←修正 31 properties.setProperty('isExecuting', 'No'); // ←追加 32 } catch (error) { 33 Logger.log('エラーが発生しました: ' + error); 34 } 35}

追試してみました。

monitorAllCalendarsの最後の方(62行目)で、
sendSlackNotification(eventDetails);
を呼び出しているので、カレンダー更新時のトリガーをmonitorAllCalendarsに設定して
カレンダーにテスト用の予定を登録してみました。

結果

私のところでは、
予定のタイトル、開始時刻、終了時刻、場所、詳細が正常に記載された通知が
slackに届きました。(ただし時刻の表記は書式設定されていません)

通知の内容は正常でしたが、質問者様と同じように2通の通知が届きました。
エディタの実行数からログを確認したところトリガーによる起動のログが2回分ありました。
カレンダーを更新した際のトリガーが重複してスクリプトを起動していることになりますので、
Googleサイドの不具合と受け止めるしかないのかもしれません。
ユーザー側で対応するには二つの処理の中で、どちらかが二回目の起動だと判定する方法は現時点では思い浮かびません。

コードを修正して e.triggerUid を取得して確認しましたが、全て同じIDになるので区別できません。

slack通知
イメージ説明

実行数ログ
イメージ説明

投稿2024/04/08 03:23

編集2024/04/08 06:01
YellowGreen

総合スコア731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kks

2024/04/08 03:39

こちらご確認とご回答いただきましてありがとうございます。 またソースコードも最新に反映しました。 上記「console.log(e.triggerUid);」で確認したところログは確認できました。 >カレンダーを更新した際のトリガーが重複してスクリプトを起動していることになりますので、 >Googleサイドの不具合と受け止めるしかないのかもしれません。 なるほど、こればかりは仕方がなさそうですね。。 ちなみに私のほうでは3回ずつの合計で6つの通知が着てしまいます。 こちらはグーグルカレンダー側の何かしらの具合なのでしょうか?
YellowGreen

2024/04/08 03:49

console.log(e.triggerUid)でイベント(予定更新)ごとのIDを取得できると勘違いしておりましたが、 設定したトリガーのIDでした。 なので、何度やっても同じIDになりますので重複チェックには使えませんでした。
kks

2024/04/08 04:11

ありがとうございます。 1回の更新でいくつか重複して通知されてしまう回避方法は難しいという事ですかね。。
YellowGreen

2024/04/08 05:57 編集

とりあえず思いついた重複の回避方法を追記しました。 当方では、トリガーでスクリプトは重複して起動していますが、 片方は、実行を中断するので通知は1通になっています。
kks

2024/04/08 08:01 編集

ソースコードの参考ありがとうございます。 上記のコードですと2通はどうしても通知になりますが、PCは問題ないのですが 別問題でスマホアプリ(iOS)のSlackに通知のアラートが1通も来なくなりました。 どちらかといいますと、スマホアプリのSlackに通知(1回編集で1回通知)がくるのが最大のゴールであります。
YellowGreen

2024/04/08 08:01

PCに通知が来て、iOSのアプリに通知が来ないというのは、それぞれのアカウントが違うのですか? また、これまでいろいろお試しになった中で、削除漏れのスクリプトやトリガーが残っていたりはしませんか?
kks

2024/04/08 08:08

現状確認をしましたが、 PCとiOSのアカウントは一緒です。 またスクリプトは上記を参考に、トリガーは「monitorAllCalendars」一つのみとしています。
kks

2024/04/08 08:12

挙動のパターンがわかりました。 PCは必ずアラートが来ますが、 iOSアプリの場合、アラートがある時とない時があります。 ないと思ったら時間差でアラートがあります。
YellowGreen

2024/04/08 21:41 編集

> iOSアプリの場合、アラートがある時とない時があります。 ないと思ったら時間差でアラートがあります。 ↓ teratailの範疇ではありませんが、 iOSアプリを一度削除して、もう一度インストールしてみてはどうですか。 LINEなどの通知が来なくなった時の対応方法です。 > 上記のコードですと2通はどうしても通知になります ↓ カレンダーの予定を更新して、通知が2通届いた後**しばらくしてから**、 スクリプトエディタの画面左側の実行数を開いて、 予定を更新したのと同じ時刻(1〜2秒程度違い)のトリガーによるログがいくつあるのか、 また、それぞれのログの内容には何が表示されているのかをご確認ください。 **通知後すぐに開くと、作成が間に合わずログに内容が表示されないことが多いですので、 ログの内容が表示されていないときは、ブラウザをリロードしてみてください。
kks

2024/04/09 01:40

>teratailの範疇ではありませんが、 >iOSアプリを一度削除して、もう一度インストールしてみてはどうですか。 >LINEなどの通知が来なくなった時の対応方法です。 →ありがとうございます、一度再インストールして問題はなさそうです、ありがとうございます。 >**通知後すぐに開くと、作成が間に合わずログに内容が表示されないことが多いですので、 >ログの内容が表示されていないときは、ブラウザをリロードしてみてください。 →このあたりはランダムで解決しなさそうですが、ひとまず承知しました。 また別件ですが、先ほどグーグルカレンダー内のイベント変更をしたらそのイベント以外の通知まで来てしまい、トータルで9つの通知(変更したイベントも含む)となります。 ただその後は2通知になりました、とても不思議です。
kks

2024/04/10 07:27 編集

ご回答ありがとうございました、こちらで様子をみていきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問