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

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

ただいまの
回答率

90.38%

  • Google Apps Script

    1404questions

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

  • Slack

    240questions

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

Slackで作ったオリジナルのスラッシュコマンドを入力するとエラーが返ってきてしまう

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 373

jimunomado

score 6

前提・実現したいこと

特定の電車の遅延情報を知らせるSlackBotを作っています。
オリジナルのスラッシュコマンド /traininfo_nowを作り、このスラッシュコマンドを入力した時に、電車の遅延情報を返すようにしたいと思っています。
以下のサイトを参考に作成しました。

SlackBotで電車の運行情報をスラッシュコマンドで通知してもらうhttps://qiita.com/yuina_i/items/617066e09426194bcd71

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

/trainindfo_nowを入力するとbotは遅延情報を返してくれますが、その直後にエラーを返します。
コマンドを入力すると10:32の遅延状況を返しますが、直後にエラーも返ってきます。中身をよく読むと末尾に

The Script completed but did not return anything

と書いてあります

スラッシュコマンド入力後に帰ってくるエラー

該当のソースコード

var slackAccessToken = PropertiesService.getScriptProperties().getProperty('slack APIで取得した Verification TOKEN');

function doPost(e) {
var slackApp = SlackApp.create(slackAccessToken);
// 対象チャンネル
var channelId = "#train_info";
var options = {
// 投稿するユーザーの名前
username: "train_info",
icon_emoji: ":train:",
}

  var currentDate = new Date();
  var weekday = currentDate.getDay();
  var date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分');

  if (weekday == 0 || weekday == 6) {
    return;
  }
  var calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
  if (calendar.getEventsForDay(currentDate, {max: 1}).length > 0) {
    return;
  }

  //soubu line info
  var yahoodata = UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/40/0/").getContentText();
  if(yahoodata.indexOf('現在、事故・遅延に関する情報はありません。') > -1){
    // match the word
    postMessage("\n" + "◆総武線は平常運転です。\n",'slack APIで取得した Webhook Address');
  }else{    
    //get error info
    var yahoodatastart = yahoodata.indexOf('og:description" content="');
    //4 japanese word only
    yahoodatastart += 25;
    var yahoodataend = yahoodata.indexOf('の情報です。');
    var yahoodataoutput = yahoodata.substring(yahoodatastart, yahoodataend);

    postMessage("\n" + "◆総武線 " + date + "\n" + yahoodataoutput + "\n",'slack APIで取得した Webhook Address');
  }


  //tokyometro tozai line info
  var yahoodata2 = UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/135/0/").getContentText();
  if(yahoodata2.indexOf('現在、事故・遅延に関する情報はありません。') > -1){
    // match the word
    postMessage("\n" + "◆東西線は平常運転です。\n",'slack APIで取得した Webhook Address');
  }else{    
    //get error info
    var yahoodatastart2 = yahoodata2.indexOf('og:description" content="');
    //4 japanese word only
    yahoodatastart2 += 25;
    var yahoodataend2 = yahoodata2.indexOf('の情報です。');
    var yahoodataoutput2 = yahoodata2.substring(yahoodatastart2, yahoodataend2);

    postMessage("\n" + "◆東京メトロ東西線 " + date + yahoodataoutput2 + "\n",'slack APIで取得した Webhook Address');

  }

  // JR Chuo line info
  var yahoodata2 = UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/38/0/").getContentText();
  if(yahoodata2.indexOf('現在、事故・遅延に関する情報はありません。') > -1){
    // match the word
    postMessage("\n" + "◆JR中央線(快速)は平常運転です。\n",'slack APIで取得した Webhook Address')
  }else{    
    //get error info
    var yahoodatastart2 = yahoodata2.indexOf('og:description" content="');
    //4 japanese word only
    yahoodatastart2 += 25;
    var yahoodataend2 = yahoodata2.indexOf('の情報です。');
    var yahoodataoutput2 = yahoodata2.substring(yahoodatastart2, yahoodataend2);

    postMessage("\n" + "◆JR中央線(快速) " + date + yahoodataoutput2 + "\n",'slack APIで取得した Webhook Address');

  }


}


function postMessage(message, hookpoint){
  var payload = {
    "text": message,
    "channelId": '#train_info',
    "userName": 'train_info',
    "icon_emoji": ':train:'
  }
  var options = {
    "method": "POST",
    "payload": JSON.stringify(payload),
    "headers": {
      "Content-type": "application/json",
    }
  }
    var response = UrlFetchApp.fetch('slack APIで取得した Webhook Address',options);

  if (response.getResponseCode() == 200) {
    return response;
  }
  return false;
}

事の発端と考えてみたこと

もともと定時に電車の遅延を知らせるbotを作っていました。
※参考: https://teratail.com/questions/174195#

この後ネットの海をさまよっていたところ、スラッシュコマンド入力でbotに電車遅延を知らせることができるようになると知りました。
個人的には定時&任意の時に知りたい→任意の時に知りたいならスラッシュコマンド便利じゃん!となり、実装を決意しました。
最初、もともと実装していたコードをそのまま動かそうとしたのですが「doPostがないよ!」とエラーを返されました。そのため元々のコードにdoPost Functionを足し、またメッセージを返すWebhook URLもslack API側のWebhook URLに直しました。(元のコードでは、Incoming Webhookから取得したURLを利用しています)
自分がいじったコードがまずそう、というのはなんとなくわかるのですが、何をどう処理したらよいのか(そもそもコードの問題でもなくて、slackでbot生成した際の不具合なのか?)わからずにいます。

ご教示願えますと幸いです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

doPost関数が何も返していないので何か返すようにすればエラーは解消されると思います。
例えば空文字を返すとか
return ContentService.createTextOutput("");

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/21 14:33

    こちらで一応解決しました!
    記事と同様の実装については今晩からでもさっそく実行してみます。

    キャンセル

  • 2019/02/21 14:44

    土日祝日にスラッシュコマンド打ったら同じエラー再現すると思う

    キャンセル

  • 2019/02/21 14:51

    土日祝除く設定にしているのは把握しております。ひとまずスラッシュコマンドを試してみたかったというような感じですので、細かい設定ほかについては改めて実装しなおします。

    キャンセル

+1

postSlackを実行するのではなく、参考リンクのようにjsonにしてreturnしましょう

方針としては、メッセージ取得部分を切り離して、トリガーでコールされたときと、doPost(slack command)でコールされたときで、それぞれのハンドラが何をするか制御したほうがいいですね。

ただこうしたとき、時刻トリガで動作したときに、遅延がなくてもメッセージが送られてしまいますね
それがいやだとなると、ちょっと面倒(既存コードのコピペですまないので、自分で考えてほしいです)

const slackAccessToken = PropertiesService.getScriptProperties().getProperty('slack APIで取得した Verification TOKEN');

function triggerDriver() {
  const slackApp = SlackApp.create(slackAccessToken);
  // 対象チャンネル
  const channelId = "#train_info";
  const options = {
    // 投稿するユーザーの名前
    username: "train_info",
    icon_emoji: ":train:",
  }

  const currentDate = new Date();
  const weekday = currentDate.getDay();
  const date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分');

  if (weekday === 0 || weekday === 6) {
    return;
  }
  const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
  if (calendar.getEventsForDay(currentDate, {max: 1}).length > 0) {
    return;
  }
  const infos = getMessages();
  postMessage(infos, 'slack APIで取得した Webhook Address');
}
function doPost(e) {
    const infos = getMessages();
    const res = {"text": infos};
    return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON);
}
function getMessages() {
  //soubu line info
  const soubuLine = clipInfo("総武線", UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/40/0/").getContentText());

  //tokyometro tozai line info
  const tozaiLine = clipInfo("東西線", UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/135/0").getContentText());

  // JR Chuo line info
  const chuoLine = clipInfo("R中央線(快速)", UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/38/0").getContentText());
  return soubuLine + "\n" + tozaiLine + "\n" + chuoLine + "\n";
}

function clipInfo(line, content) {
  if(content.indexOf('現在、事故・遅延に関する情報はありません。') > -1){
    return "◆" + "は平常運転です";
  }
  const currentDate = new Date();
  const date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分');
  const yahoodatastart = content.indexOf('og:description" content="') + 25;
  const yahoodataend = content.indexOf('の情報です。');
  const yahoodataoutput = content.substring(yahoodatastart, yahoodataend);

  return "◆" + line + date + "\n" + yahoodataoutput ;
}
function postMessage(message, hookpoint){
  var payload = {
    "text": message,
    "channelId": '#train_info',
    "userName": 'train_info',
    "icon_emoji": ':train:'
  }
  var options = {
    "method": "POST",
    "payload": JSON.stringify(payload),
    "headers": {
      "Content-type": "application/json",
    }
  }
    var response = UrlFetchApp.fetch('slack APIで取得した Webhook Address',options);

  if (response.getResponseCode() == 200) {
    return response;
  }
  return false;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/21 14:36

    こちらは先般作ったのとは別のGASファイルを作りました。ので時刻トリガーとは連動しておりません。
    プログラミングど初心者ですが、いただいた情報をもとに何とか頑張って作ってみようと思います。いつもありがとうございます。

    キャンセル

  • 2019/02/21 14:42

    連動する必要は全くありませんし、連動しているのではなく、機能ごとに関数切り出しをすべきだという提案です。
    別のGASを作ればいいというのは発想としてあまり良いものではないです。それは同じ実装をコピーしたということですよね?バージョン管理しているのですか?引越し・転職で路線がかわったときに2つ直すのですか?

    私は「基本的に動けばいい」の方針ですが、ベストの回答はエラーを握り潰しているだけです。
    APIに則ったコーディングをすべきです。

    キャンセル

  • 2019/02/21 14:57

    お恥ずかしながらプログラミングど初心者(普段はVBAをちょろっと触る人間で、元はBASICを少し習っていた程度です)で、JavaScriptなんて触ったことがなかったのです。
    今回別のGASを作ったというのが発想としてよろしくないというのは理解しております。
    しかし私の足りない頭ではこうするよりほかなかった、というのが正直なところです。
    貴重なご意見、本当にありがとうございます。おっしゃることごもっともですので、今後の糧にしてまいりたいと思います。

    キャンセル

  • 2019/02/21 15:49

    何か変な誤解が生じていたら嫌なので一応僕の回答について説明します。(特に誤解がなければ無視してください)
    僕はエラー文を検索して、なぜエラーが発生したのか?どうすればエラーがなくなるかを調べただけです。この質問の背景、コード、元ネタの記事等はよく読んでいないです。
    また僕が回答に記載し始めた時は回答が0でした。papinianusさんの回答を読んでいない状態で自分の回答を送信しました。もしpapinianusさんの回答を読んでいたら自分の回答を送信しようとは思わなかったです。

    キャンセル

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

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Google Apps Script

    1404questions

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

  • Slack

    240questions

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