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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

3回答

1647閲覧

Hangout Chatに自動でメッセージを送るbotを作る。

ouoyoueee

総合スコア43

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/04/26 11:09

編集2020/04/26 14:09

前提・実現したいこと

カレンダーに登録した予定の時刻の3分前にHangout Chatに自動で通知を送るbotを作る。

発生している問題・エラーメッセージ

中学生です。
今学校が休校中でオンライン授業をしています。ただ、時間割がいつもと違うため、不便に感じています。そこで、Google calendarにあらかじめ予定を登録しておくと、予定した時間の3分前にHangout Chatにて自動で通知を送るbotを作ろうとしています。いかにソースコードを添付しましたが、このコードではエラーメッセージが出ないのにもかかわらず、メッセージが送られませんでした。僕はプログラミングを始めて1か月もたっていないので、どうしていいのかわからず立ち往生しています。どなたか改善策を教えていただけませんか?
ただ、Google calendar ID と、webhookUrlは入力してある状態でした。

Java

1ソースコード 2function getEvents(){ 3 var kaichiCal =CalendarApp.getCalendarById(''); //取得するGoogleカレンダーのIDを指定する。 4 5 // 取得したWebhookのURLを記載する。Chatで確認できるはずなので、それを入力します。 6 if(!kaichiCal) { 7 Logger.log("Unable to access calendar with id=" + kaichiCal); 8 return; 9 } 10 var events = kaichiCal.getEventsForDay(new Date()); // カレンダーから予定を取得する 11 var hello = 'こんにちは。\n 直近の予定をお知らせします。\n ------------------------------- '; 12 13 14 // 各予定1つ1つに実行する処理 15 for(var i=0; i < events.length; i++){ 16 17 18 19 20 // 予定の件名、開始時間を取得 21 startTime = events[i].getStartTime(); 22 eventName = events[i].getTitle(); 23 24 //予定の開始時間から3分引いた時刻を取得 25 var threeMinutesBefore = (startTime.getTime() - 3*60*1000); 26 27 //現在時刻を取得 28 var now = new Date(); 29 now = now.getTime(); 30 if (threeMinutesBefore < now && now < startTime){ 31 32 // 時間をJSTに変換 (GASの標準はUTC) 33 var startTimeJST = Utilities.formatDate(startTime, "JST", "HH:mm") 34   //送信用のメッセ―ジ 35 var message = hello + startTimeJST + " " + eventName + " "; 36 //chatに送る 37 postchat(message); 38} 39} 40} 41 42 // chatに投稿する 43 44 function postchat(message,webhookUrl){ 45 var webhookUrl = '';//webhookUrlを入力 46 var botMessage = { 'text' : message} 47 var options = { 48 'method': 'POST', 49 'headers' : { 50 'Content-Type': 'application/json; charset=UTF-8' 51 }, 52 'payload':JSON.stringify(botMessage) 53 }; 54 var result = UrlFetchApp.fetch( webhookUrl, 55 {payload: JSON.stringify(options), 56 muteHttpExceptions:true, 57 }); 58 Logger.log(result); 59} 60 61 62 63 64 65

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

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

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

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

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

guest

回答3

0

まず賛辞を。こんな改善をやろう!と思い立てるなんて、めちゃめちゃ偉いです!
更に、teratailという質問サイトを見つけてこれる検索能力も素晴らしいです。
これからも、色々調べて、どんどん知識を吸収していってください。

さて、問題点についてですが、2つの改善点があるようです。

まず、1つ目です。
for文の書き方が間違っているようです。

// 各予定1つ1つに実行する処理 for(var i=1; i < events.length; i++){

eventsの要素は、0番から始まっています。

一番最初の要素の、要素番号は0番 二番目の要素の、要素番号は1番 三番目の要素の、要素番号は2番

提示して頂いたソースコードのような書き方をすると、二番目の要素からしか検索を行ってくれません。
またその日の予定が1つしかないときには、for文に入らずに処理が終わってしまいます

なので、次のようにして0番から調べ始めると良いです。

// 各予定1つ1つに実行する処理 for(var i=0; i < events.length; i++){

次に、2つ目です。
postchatの引数が足りていないようです。

//chatに送る postchat(message);

postchat関数は、引数が2つ必要なので、次のように記載する必要がありそうです。

//chatに送る postchat(message, webhookUrl);

関数に引数を1つだけ渡した場合、
webhookUrlはundefined(未定義)になるので、エラーが起きます。
従ってエラーが起きていないという事は、
現時点では1つ目の部分でつまづいているものと思われます。

以下に全文を乗せます。

JavaScript

1ソースコード 2function getEvents(){ 3 var kaichiCal =CalendarApp.getCalendarById(''); //取得するGoogleカレンダーのIDを指定する。 4 var webhookUrl = ''; 5 // 取得したWebhookのURLを記載する。Chatで確認できるはずなので、それを入力します。 6 if(!kaichiCal) { 7 Logger.log("Unable to access calendar with id=" + kaichiCal); 8 return; 9 } 10 var events = kaichiCal.getEventsForDay(new Date()); // カレンダーから予定を取得する 11 var hello = 'こんにちは。\n 直近の予定をお知らせします。\n ------------------------------- '; 12 13 14 // 各予定1つ1つに実行する処理 15 for(var i=0; i < events.length; i++){ // <--- 1つ目の改善. 16 // 予定の件名、開始時間を取得 17 var startTime = events[i].getStartTime(); 18 var eventName = events[i].getTitle(); 19 20 //予定の開始時間から3分引いた時刻を取得 21 var threeMinutesBefore = (startTime.getTime() - 3*60*1000); 22 23 //現在時刻を取得 24 var now = new Date(); 25 26 if (threeMinutesBefore < now && now < startTime){ 27 28 // 時間をJSTに変換 (GASの標準はUTC) 29 var startTimeJST = Utilities.formatDate(startTime, "JST", "HH:mm") 30 //送信用のメッセ―ジ 31 var message = hello + startTimeJST + " " + eventName + " "; 32 //chatに送る 33 postchat(message, webhookUrl); // <--- 2つ目の改善. 34 } 35 } 36} 37 38// chatに投稿する 39function postchat(message,webhookUrl){ 40 var botMessage = { 'text' : message} 41 var options = { 42 'method': 'POST', 43 'headers' : { 44 'Content-Type': 'application/json; charset=UTF-8' 45 }, 46 'payload':JSON.stringify(botMessage) 47 }; 48 var result = UrlFetchApp.fetch(webhookUrl, options); 49 Logger.log(result); 50}

上手くいかなかったり、疑問点があるようでしたら、教えてください。

また、今後の勉強のために使えるキーワードとして次のものが有ります。
興味があったら、調べてみてください。

  1. 「Google App Script ブレークポイント デバッグ実行」

  今実行しているプログラムの変数の中身を調べることが出来ます。

  1. 「インデント」

  if文やfor文やfunctionを囲むカッコ{} (波括弧、中括弧とも言います。)
の中は、インデントを付けて字下げを行ってください。
どこまでがカッコの中なのか分かりやすくするためです。

投稿2020/04/26 13:11

hara64

総合スコア18

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

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

ouoyoueee

2020/04/26 14:04

ご返信ありがとうございます! for文とpostchatの関数を変えて、両方とも実行してもエラーが出てこなくなりました。 それから、function postchatの最後のUrlFetchApp.fetchの部分も、エラー400がでたので、muteHttpExceptions:true,を付け足しました。元の質問のソースコードも更新します。 しかし、https://script.google.com/homeこのサイトで調べてみると、自分の関数がまだ一度も実行された形跡がありません...どこが悪いのでしょうか。それとも、一日の上限回数に達してしまったのでしょうか…
hara64

2020/04/26 15:19 編集

エラー400ということで、一歩前進ですね! エラー400 について、軽くでも調べてみてください。 あなたのアプリケーションから、サーバーにアクセスするときに、 アクセスしちゃだめだよ、と言われている状態ですので、 エラーを無視しても動きません。 muteHttpExceptions:true は、付けないでください。 エラーが起きて、何が何やら分からないとき、問題を分解していくと良いです。 postchatをするときにうまく動いていないようですから これで動かしてみてください。 これで動かして、Hangout Chat にて test という文字列を受け取れたら良いわけですね。 function getEvents(){ var webhookUrl = ''; // 取得したWebhookのURLを記載する。Chatで確認できるはずなので、それを入力します。 postchat("test",webhookUrl); } まず最初に確認する点は、webhookUrlの文字を打ち間違えてないかという点です。 これが一番ありがちですので、確認をお願いします。 次に確認する点は、リクエスト送信先のアクセス許可という点です。 通知を送りたいHangout Chatというのは、学校の皆さんが使用されているのでしょうか。 もしくは、あなた個人で使用しているのでしょうか? 使用されているHangout Chatが、外部からの接続を許可していなければ、この手のスクリプトは動きません。 怪しいリクエストだ!ということで通信を弾いてしまうんですね。 一度、先生もしくは管理者の方にお願いをして、こういったものを動かしてみたい、と相談をしてみてください。
guest

0

(普段私はコードそのものを書く回答をしていますが、今回はそういう回答を求めてないと思っています。もしただただ答えが欲しいのであれば質問にその旨追記してください)

どうしていいのかわからず立ち往生しています。どなたか改善策を教えていただけませんか?

こういうとき、”デバッグ”をします。

Google Apps Script にはデバッガが付属しています。通常▼を反時計周りに 90 度回転させた関数の実行ボタンで実行しているか、トリガーで実行していると想定しますが、そうではなく、クモっぽいアイコンで実行します。その際に、あらかじめ行番号の左あたりをクリックすると赤い●をつけておくことができ、そのつけた行で実行を停止し、変数の状態を確認することができます。
また、そこから1行ずつすすめて、変数がどう変わっていくかを追いかけることができます。
このようにして、どこでどのようなエラーが起きているか突き止めることができます。

もう1点。 muteHTTPexception を付けたのはエラーメッセージを表示するには、というメッセージに従ったからだと思います。であれば、ログをみましょう。ご自身で Logger.log もしておられるので、それもログでみましょう。
メニューの”表示”を開いたときの、うえから3つを全て確認してください。
デバッガがないときは、このようにログをだしてデバッグをすることが有効な場合があります。また、質問の際にも、ログに何と出ているかを記載するのは有効な回答を得る助けになります。
特に外部システムからのメッセージが詳細に判明すれば検索するキーワードとして有用です。

投稿2020/04/26 16:25

papinianus

総合スコア12705

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

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

0

時間を比較するなら nownow.getTime()にする必要があるのではないでしょうか。

JavaScript

1var threeMinutesBefore = startTime.getTime() - 3 * 60 * 1000; 2//現在時刻を取得 3var now = new Date(); 4if (threeMinutesBefore < now && now < startTime) { 5}

投稿2020/04/26 12:52

draq

総合スコア2573

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問