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

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

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

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

Q&A

解決済

1回答

588閲覧

node.jsの出力について

Okkawa

総合スコア6

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

0グッド

0クリップ

投稿2020/01/21 03:19

前提・実現したいこと

Line Massaging APIとfirebaseを連携させ、お天気の情報のweb API(livedoor お天気サービス)から読み取りそれをユーザのメッセージに対して送信する。

該当のソースコード

Java

1async function handleEvent(event) { 2 if (event.type !== 'message' || event.message.type !== 'text') { 3 return Promise.resolve(null); 4 } 5 usersRef.set(event.message.text); 6 7 var x = event.message.text; 8 var obj = { type: 'text', text: x + 'が実行されました' }; 9 10 //LINEに対応するコマンドはここへ追加 11 switch (x) { 12 13 case 'おはよう': //お天気情報取得 14 const RSS = "http://weather.livedoor.com/forecast/rss/area/130010.xml"; // RSSのURLを指定 --- (*1) 15 const cli = require('cheerio-httpcli'); // cheerio-httpcli モジュールを取り込む 16 // ダウンロードして解析 17 cli.fetch(RSS, {}, (err, $, res) => { 18 // エラーがあればメッセージを表示 19 if (err) { console.log("失敗", err); return; } 20 // ダウンロードしたデータから必要な部分を取り出す --- (*2) 21 $("item > title").each((index, elem) => { 22 var e = $(elem); 23 console.log(e.text()); // テキスト部分を表示 24 obj = { 25 type: 'text', 26 text: "おはようございます。今週の天気です" > +e.text 27 }; 28 }); 29 }); 30 31 break; 32 33 case 'lon': 34 obj; 35 break; 36 37 case 'loff': 38 obj;  39 break; 40 41 //例外処理 42 default: 43 obj = { type: 'text', text: '不可能です。今後に期待して!!' }; 44 break; 45 } 46 //返信機能 47 return client.replyMessage(event.replyToken, obj); 48} 49exports.app = functions.https.onRequest(app);

試したこと

objにお天気サービスから読み取った情報(e.text)を代入し、出力しようとしたのすがうまくいきません。
firebaseのログには、読み取ったお天気情報が表示されているので、読み取り自体に問題はないはずです。

補足情報(FW/ツールのバージョンなど)

現在、プログラミング初心者の学生でして、ふとfirebase、LINE、Raspberry Piを用いてスマートホーム を作ろうと
思い立ち、学習しています。ご不明な点ございましたら、すぐに対応させていただきますので、何卒よろしくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

コードが古いので軽く整形

js

1// requireはファイルの先頭で行う 2const httpcli = require('cheerio-httpcli'); // cheerio-httpcli モジュールを取り込む 3 4// 普通の関数宣言は巻き上げがあるので、こちらの方が推奨 5const handleEvent = async event => { 6 // ガード節は1行でOK 7 if (event.type !== 'message' || event.message.type !== 'text') return; 8 usersRef.set(event.message.text); 9 10 // objってなんやねん、おもちゃ箱に「箱」ってラベル貼って管理するの? 11 // resultもあまり気の利いた名前じゃないけどまだマシかな 12 let result = null; 13 14 const command = event.message.text; 15 switch (command) { 16 case 'おはよう': //お天気情報取得 17 try { 18 const url = "http://weather.livedoor.com/forecast/rss/area/130010.xml"; 19 // await構文使わないとasync関数の意味がないからね! 20 const res = await httpcli.fetch(url, {}); 21 const $ = res.$; 22 $("item > title").each((index, elem) => { 23 var e = $(elem); 24 console.log(e.text()); // テキスト部分を表示 25 result = { 26 type: 'text', 27 text: "おはようございます。今週の天気です" > + e.text 28 }; 29 }); 30 } catch (err) { 31 console.error("失敗", err); 32 return; 33 } 34 break; 35 default: 36 result = { 37 type: 'text', 38 text: `${command}は不可能です。今後に期待して!!` 39 }; 40 } 41 42 // resultに何か代入されたら発火の方が良さそう 43 if (result) return client.replyMessage(event.replyToken, result); 44} 45 46exports.app = functions.https.onRequest(app);

こんな感じだね。
問題は大きく分けて2つ

text: "おはようございます。今週の天気です" > + e.text

e.text()という風に実行してないから値がとれないんじゃない?
これ自体はよくあるうっかりミスだね、次!

$("item > title").each((index, elem) => {

この.eachの意味を理解して使ってる?
eachというのは日本語訳すると各、それぞれ、おのおのといった単語になるんだ
今回だとitem要素の子であるtitle要素を探して、
それぞれ全てを関数にぶちこんで実行という使い方になる。

それ自体はまぁ良いんだよ。
問題はこの後。

js

1result = { 2 type: 'text', 3 text: "おはようございます。今週の天気です" > + e.text() 4};

それぞれのタイトルがresult変数へ代入しちゃってるよね。
そうなると上書き上書きで後勝ちになっちゃうんだよ。
つまり最後の1件の情報しか取得できない。

もしこれが1個だけならこのコードでも動作はするだろうけど、
後から見たエンジニアがかなり困るから、1個想定の場合、eachは絶対に削っておくべきだね。

もし複数タイトルに対応させたいのであれば、
外でresultへ入れる用の変数を作って文字列を足し込む等して対処する必要があるね。

js

1// eachを使う場合 2let titles = []; 3const $ = res.$; 4$("item > title").each((index, elem) => { 5 titles.push("おはようございます。今週の天気です > " + $(elem).text()); 6}); 7result = { 8 type: "text", 9 text: titles.join(',') 10} 11 12// 配列にするならmapを使った方がスマートだね 13const $ = res.$; 14const titles = $("item > title").map((_, elem) => 15 "おはようございます。今週の天気です > " + $(elem).text() 16).get(); 17result = { 18 type: "text", 19 text: titles.join(',') 20}

投稿2020/01/21 04:02

編集2020/01/21 05:58
miyabi-sun

総合スコア21158

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

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

Okkawa

2020/01/21 05:09

丁寧なご回答ありがとうございます。とても勉強になります。 miyabi様から教えていただいたコードを参考に書き直してみたのですが、 「ReferenceError: $ is not defined」が出てしまいます。 ---java script res.$("item > title") --- に問題があるようです。 原因を調べたのですが、改善することが出来ません。 何かわかりますでしょうか。よろしければお願い致します。
miyabi-sun

2020/01/21 06:00

うっかりしてた!ごめんね!! https://www.npmjs.com/package/cheerio-httpcli これのPromise版にresponse.$があって 結果を自動的に$で包んでくれているからこれ利用すれば$不要じゃんって思ってたけど 2箇所以上で使ってるから宣言した方が綺麗になると思い返したから回答を修正したよ!
Okkawa

2020/01/21 06:40

ご返答ありがとうございます! 出来ました!!これを元にもっと勉強に精進したいと思います!ありがとうございます。 またの機会ありましたらよろしくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問