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

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

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

HubotはGitHub社が開発したチャットbotのフレームワークです。

JavaScript

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1274閲覧

slackAPIで取得したユーザーIDをslackに投稿すると不具合

tarou212

総合スコア7

Hubot

HubotはGitHub社が開発したチャットbotのフレームワークです。

JavaScript

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2018/03/01 05:47

編集2018/03/02 01:27

backlogの課題が追加&更新された時に、hubotを通じてslackのチャンネルに投稿できるようにしました。
個人通知出来るように、slackAPIのuser.list(https://api.slack.com/methods/users.list/test)を使用し、backlogから取得した通知相手の名前を元にユーザーIDをslackに投稿し個人通知出来るようにしたのですが、backlogを更新すると通知相手がずれて通知されてしまいます。


1回目
山田さんに対してbacklog更新→slackに通知されない
2回目
山田さんに対してbacklog更新→山田さんに対してslackに通知される
3回目
佐藤さんに対してbacklog更新→山田さんに対してslackに通知される
4回目
山田さんに対してbacklog更新→佐藤さんに対してslackに通知される
5回目
鈴木さんに対してbacklog更新→山田さんに対してslackに通知される

下記の部分を消すとズレが無くなるので、slackAPIの部分の記述が原因だと考えています。
1回目のslackに通知されない時に、エラーログを見ると「ReferenceError: memberid is not defined」と書かれていました。

message += "<@" + memberid + ">"; //ここを消すとズレが直る

backlogからユーザー名の取得とユーザー名を元にslackAPIからslackのユーザーIDを取得する箇所です。

if (body.notifications.length > 0) { ref1 = body.notifications; for (i = 0, len = ref1.length; i < len; i++) { a = ref1[i]; username = "" + a.user.name; message += "" + a.user.name; //名前表示 console.log(a.user.name); console.log(a.user.id); request.get({ url: "https://slack.com/api/users.list?token=" + process.env.HUBOT_SLACK_TOKEN }, function(err, response, body) { var member; var j, len1, ref2; ref2 = JSON.parse(body).members; for (j = 0, len1 = ref2.length; j < len1; j++) { member = ref2[j]; if (member.profile.display_name === username) { //slackの表示名とバックログの名前が一致した時に、slackID memberid = member.id;//slackID取得 } } }); message += "<@" + memberid + ">"; //ここを消すとズレが直る } }

全体のコード

var backlogUrl, request; backlogUrl = 'https://backlog.jp/'; request = require('request'); module.exports = (function(_this) { return function(robot) { return robot.router.post("/slackroom/:room", function(req, res) { var a, body, error, i, label, len, message, username, ref, ref1, ref2, room, url,memberid; room = req.params.room; body = req.body; console.log('body type = ' + body.type); console.log('room = ' + room); try { switch (body.type) { case 1: label = '課題の追加'; break; case 2: case 3: label = '課題の更新'; break; default: return; } url = backlogUrl + "view/" + body.project.projectKey + "-" + body.content.key_id; if (((ref = body.content.comment) !== null ? ref.id : void 0) !== null) { url += "#comment-" + body.content.comment.id; } message = "*Backlog " + label + "*\n"; if (body.notifications.length > 0) { ref1 = body.notifications; for (i = 0, len = ref1.length; i < len; i++) { a = ref1[i]; username = "" + a.user.name; message += "" + a.user.name; //名前表示 console.log(a.user.name); console.log(a.user.id); request.get({ url: "https://slack.com/api/users.list?token=" + process.env.HUBOT_SLACK_TOKEN }, function(err, response, body) { var member; var j, len1, ref2; ref2 = JSON.parse(body).members; for (j = 0, len1 = ref2.length; j < len1; j++) { member = ref2[j]; if (member.profile.display_name === username) { //slackの表示名とバックログの名前が一致した時に、slackID memberid = member.id;//slackID取得 } } }); message += "<@" + memberid + ">"; } } message += "\n[" + body.project.projectKey + "-" + body.content.key_id + "] - "; message += body.content.summary + " _by" + body.createdUser.name + "_\n>>> "; if (((ref2 = body.content.comment) !== null ? ref2.content : void 0) !== null) { message += body.content.comment.content + "\n"; } message += "" + url; console.log('message = ' + message); if (message !== null) { robot.messageRoom(room, message); return res.end("OK"); } else { robot.messageRoom(room, "Backlog integration error."); return res.end("Error"); } } catch (_error) { error = _error; console.log(error); return robot.send; } }); }; })(this);

コールバック関数を使用した記述

if (body.notifications.length > 0) { ref1 = body.notifications; for (i = 0, len = ref1.length; i < len; i++) { a = ref1[i]; username = "" + a.user.name; message += "" + a.user.name; //名前表示 console.log(a.user.name); console.log(a.user.id); } function execCallback (callback) { request.get({ url: "https://slack.com/api/users.list?token=" + process.env.HUBOT_SLACK_TOKEN }, function(err, response, body) { var member; var j, len1, ref2; ref2 = JSON.parse(body).members; for (j = 0, len1 = ref2.length; j < len1; j++) { member = ref2[j]; if (member.profile.display_name === username) { //slackの表示名とバックログの名前が一致した時に、slackID memberid = member.id;//slackID取得 } } }); callback(); } var myCallback = function () { message += "<@" + memberid + ">"; }; execCallback(myCallback); }

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

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

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

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

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

CHERRY

2018/03/01 06:25

コードは質問文の編集ページでコードを選択し、編集ページの上に並んでいるボタンの「<code>」ボタンを押すことで、コードブロックにしてください。
karamarimo

2018/03/01 07:34 編集

エラーの通りmemberidの宣言が見当たらないです。あと backlogやhubotは知らないのですが https://slack.com/api/users.list に複数回アクセスする必要があるのでしょうか?
tarou212

2018/03/01 08:05

おっしゃる通り、var memberidと宣言すると一回目のslack通知が出来るようになりました。その変わり通知相手がundefinedと出てしまいました。もしかしたらグローバル変数で処理を行っていたからかもしれないです。「https://slack.com/api/users.list」記述方法がわからずに、ループ内に書いてしまったのですが、複数回アクセスするようにしてしまったのですが1度のアクセスで大丈夫だと思います。
karamarimo

2018/03/01 08:25

「通知相手がundefined」とはコードでどこのことでしょうか?また、やりたいことは body.notifications の各ユーザーについて相当する slack id を取得して message に追加するということでしょうか?コードを見た限り request.get が同期処理であるかのように扱っているのが原因だと思います。
CHERRY

2018/03/01 08:40

slack api の呼び出しをを非同期で実行されていますが、「message += "<@" + memberid + ">";」の部分で、memberid に slack の id は、入っているのでしょうか?
tarou212

2018/03/01 08:41

message += "<@" + memberid + ">";で、通知相手(slackのID)をslackに投稿している部分で、こちらがslack上で「undefined」と表示されました。backlogのユーザー名(a.user.name)とslackの表示名(member.profile.display_name)が一致した人のみ、slackのID(member.id)を取得し、slackのIDをslackに投稿したいです。
tarou212

2018/03/01 08:45

message += "<@" + memberid + ">";で、backlogから1度目の更新&追加した時は、「ReferenceError: memberid is not defined」とエラーログが表示されて入っていないのですが、2回目以降は、slackIDは、入っています。途中で通知相手を変えると質問の例に書いてあるように、一人分ズレて相手に通知されます。
guest

回答1

0

ベストアンサー

原因はおそらく、memberidがグローバル変数になっていてrequest.getのコールバック内で非同期に値が変わるため、このような状況になっているのからではないかと思います。

  • memberid = undefined
  • 1回目 -> request -> memberid = undefined に通知
  • requestのresponseが返ってくる -> memberid = 1回目のslack id
  • 2回目 -> request -> memberid = 1回目のslack id に通知
  • ...

request.getは非同期なので完了を待って結果を得てから送信しなければいけません。つまりrequest.getの後に書いてある処理はすべてrequest.getのコールバックで実行する必要があります。

補足: 上の最後の文は、request.getforループ内で毎回実行するのではなく、最初に一回だけ行う、という前提での話でした。


細かい所は適当ですがこんな感じの構成にすればいいのではないでしょうか。

if (body.notifications.length > 0) { ref1 = body.notifications; request.get({ url: "https://slack.com/api/users.list?token=" + process.env.HUBOT_SLACK_TOKEN }, function(err, response, body) { var member; var j, len1, ref2; ref2 = JSON.parse(body).members; for (i = 0, len = ref1.length; i < len; i++) { a = ref1[i]; username = "" + a.user.name; message += "" + a.user.name; //名前表示 console.log(a.user.name); console.log(a.user.id); for (j = 0, len1 = ref2.length; j < len1; j++) { member = ref2[j]; if (member.profile.display_name === username) { //slackの表示名とバックログの名前が一致した時に、slackID var memberid = member.id; //slackID取得 message += "<@" + memberid + ">"; } } } appendFooterAndSend(); }); } else { appendFooterAndSend(); } function appendFooterAndSend() { message += "\n[" + body.project.projectKey + "-" + body.content.key_id + "] - "; message += body.content.summary + " _by" + body.createdUser.name + "_\n>>> "; if (((ref2 = body.content.comment) !== null ? ref2.content : void 0) !== null) { message += body.content.comment.content + "\n"; } message += "" + url; console.log('message = ' + message); if (message !== null) { robot.messageRoom(room, message); return res.end("OK"); } else { robot.messageRoom(room, "Backlog integration error."); return res.end("Error"); } }

投稿2018/03/01 09:06

編集2018/03/01 11:45
karamarimo

総合スコア2551

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

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

tarou212

2018/03/01 09:27 編集

ご回答ありがとうございます! まずは、request.getをループ外で実行してみます!
tarou212

2018/03/01 10:01

コールバック関数を使ってみたのですが、試してみた結果動作は、変わりませんでした。どこかおかしい点がありましたらご教授お願いします。コードは、質問のコールバック関数を使用した記述に記載してあります。 参考サイト:https://qiita.com/matsuby/items/3f635943f25e520b7c20
karamarimo

2018/03/01 11:10

それだと何も変わってないですね...。また、結局 memberid はどこで宣言されているのでしょうか?
karamarimo

2018/03/01 11:13

また、コールバックというのはrequest.getの第2引数のことを言ってました。
tarou212

2018/03/02 01:52

ありがとうございます!回答のコードで、backlogから課題の更新&追加をした時に、hubotを通してslackに通知したい相手のslackIDを投稿することが出来ました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問