- 投稿日:2021-03-21T22:30:30+09:00
初めてのLINEbot作成【Node.js + heroku】
はじめに
Qiita初投稿になります
Node.jsによるLINEbot製作を行ってみたく、自学のために行った流れをまとめていきます
Node.js、npmのインストール、Herokuのアカウント登録などは省きます
成果物としては、「ありがとう」と送信すると、「どういたしまして」、それ以外は「こんにちは」と返ってくるLINEbotを制作します動作環境
・MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)
・mac OS Catalina バージョン 10.15.7
・node v15.3.0
・npm 7.0.14
・git 2.23.0目次
LINE側の準備
この見出しでは、LINE側で行うことをまとめていきます。
LINE Developerアカウントの作成
まずはこちらのURLからLINE Developerのアカウントを作成します
普段使用されているLINEアカウントがあればすぐに作成できます
https://developers.line.biz/ja/プロバイダーの作成
次にプロバイダーの作成を行います。トップページにある以下の作成ボタンを押します。
ここでは新しく作るプロバイダーをtestとしておきます。
チャネルの作成
新しくプロバイダを作成すると以下の画面に移行します。ここでは「Messaging API」を選択します。
その後、チャネルの種類を「Messaging API」に指定し、プロバイダーを先ほど作成した「test」に指定します。その後
・チャネルアイコン ※一度変更すると、1日経過しなければ変更することができません
・チャネル名 ※一度変更すると、7日経過しなければ変更することができません
・チャネル説明
・大業種
・小業種
・メールアドレス
・プライバシーポリシーURL(任意)
・サービス利用規約URL(任意)
を入力し、利用規約にチェックを入れ、作成ボタンを押します
チャネルシークレットとチャネルアクセストークンの取得
次に外部からLINE APIにアクセスするためのチャネルシークレットとチャネルアクセストークン(長期)を取得します。
こちらの情報は外部に漏れないように気を付けましょう。それぞれの場所は
・チャネルシークレット
チャネル基本設定の下部にあります
・チャネルアクセストークン(長期)
Messaging API設定の下部にあり、発行ボタンを押すと表示されます
上記二つが取得できたら、とりあえずはメモ帳等に記録しておきましょう。その他設定
Messaging API設定タブの応答メッセージ、編集、にて応答設定の中の詳細設定の、応答メッセージを以下の画像のようにオフ、Webhookをオンにしましょう。あいさつメッセージはオフにしていますが、オンでも構いません。
※Webhook URLに関しては後ほど入力します
こちらで一旦LINE側の準備は終わりになります。Node.js側の準備
npm init
任意のフォルダ(ここではlinebot_test)を作成し、そのフォルダ内で、npmのイニシャライズを実行します
コンソールmkdir linebot_test cd linebot_test npm init
npm init実行後、いろいろ聞かれますが、全て空のままEnterで構いません
モジュールのインストール
LINEbotを動かすために必要なnpmモジュールをそれぞれインストールします
コンソールnpm install express @line/bot-sdk dotenv --save
ローカルでテストするためのトンネリングツールをインストール
ngrokというトンネリングツールを使用することで、簡単にテストが行えます。
コンソールnpm install -g ngrok
Node側の準備はこのぐらいです、次からコードを書いていきます。
コードの作成
先ほど作成したフォルダ内で以下を実行し、index.jsを作成します
コンソールtouch index.js
その後、以下のコードをコピペします
index.js// モジュールのインポート const server = require('express')(); const line = require('@line/bot-sdk'); // Messaging APIのSDKをインポート require('dotenv').config(); // ----------------------------------------------------------------------------- // パラメータ設定 const lineConfig = { channelAccessToken: process.env.LINE_ACCESS_TOKEN, // 環境変数からアクセストークンをセットしています channelSecret: process.env.LINE_CHANNEL_SECRET, // 環境変数からChannel Secretをセットしています }; // ----------------------------------------------------------------------------- // Webサーバー設定 server.listen(process.env.PORT || 3000); // ----------------------------------------------------------------------------- // ルーター設定 const bot = new line.Client(lineConfig); // APIコールのためのクライアントインスタンスを作成 server.post('/webhook', line.middleware(lineConfig), async (req, res) => { res.sendStatus(200); // 先行してLINE側にステータスコード200でレスポンスする。 const [lineEvent] = req.body.events; // events配列から配列の0番目の要素だけを変数に代入 const inputMessage = lineEvent.message.text; //入力された文字を代入 if (!lineEvent) { return; } if (lineEvent.type !== 'message' || lineEvent.message.type !== 'text') { return; } if (inputMessage === 'ありがとう') { //「ありがとう」と入力された場合 bot.replyMessage(lineEvent.replyToken, { type: 'text', text: 'どういたしまして', }); } else { //それ以外の文字が入力された場合 bot.replyMessage(lineEvent.replyToken, { type: 'text', text: 'こんにちは', }); } });そして環境変数のため、.envファイルを作成します。
コンソールtouch .env
.envファイル内は、LINE側の準備で取得したチャネルシークレットとチャネルアクセストークンを用意し、以下のコードに貼り付けてください
.envLINE_ACCESS_TOKEN='メモしたチャネルアクセストークン' LINE_CHANNEL_SECRET='メモしたチャネルシークレット'
応答テスト
いよいよテストになります。
LINEbotの友達登録
LINE DevelopeのMessaging API設定のボット情報にある「ボットのベーシックID」をコピーして、自分のLINEの友達検索、にてIDで検索すると作成したbotが出てくるので、そちらを友達にします
このボット情報の下にQRコードが表示されているので、そちらから友達になっても構いません
ngrokの起動
コンソールを二つ立ち上げ、片方では
コンソールngrok http 3000
とすると、以下のようになるので
https://~~~~.ngrok.io の部分をコピーし
LINE DevelopeのMessaging API設定のWebhook設定、webhook URLに貼り付け、後ろに「/webhook」を記入します
index.jsの起動
もう一方のコンソールにて、
コンソールnode index.js
としてサーバーを起動します
応答テスト
いよいよテストです。
botに対して「ありがとう」と入力しましょうすると、「どういたしまして」と返ってきます
それ以外の言葉を入力すると、「こんにちは」と返ってくるはずです。
本番環境(heroku)にデプロイ
git init
herokuにデプロイする際はgitを使用するので、まずgit initを行います
コンソールgit init
git ignore
その後、チャネルアクセストークンなどが外部に漏れてしまわないように.gitignoreファイルを作成し、
以下のように記述しておきましょう.gitignorenpm-debug.log node_modules .env
こうしておくことで、pushしても.envファイルが外部に漏れることはなくなります
また、node_modules npm-debug.logに関してもプッシュする必要がないのでignoreしておきましょうheroku create
その後、herokuにログインし、heroku createを実施して新たにサーバーを作成しましょう
その後、herokuに環境変数を読ませるため、heroku config:setにて環境変数を定義しましょうコンソールheroku login heroku create heroku config:set LINE_ACCESS_TOKEN='メモしたチャネルアクセストークン' heroku config:set LINE_CHANNEL_SECRET='メモしたチャネルシークレット'
Procfileの作成
次に、herokuがまず何を実行すればいいかを記したファイル「Procfile」を作成します
コンソールtouch Procfile
Procfile内は以下のように記します
Procfileweb: node index.js
デプロイ
いよいよデプロイです、以下のようにgit addを行い、git commitを行って、herokuにプッシュしましょう
コンソールgit add -A git commit -m "コミット名" git push heroku master
デプロイ後、LINE Developersのwebhook URLを変更
コンソールからherokuにデプロイを行うと、以下のようなログが流れます
https://~~~~~.herokuapp.com/ の部分をコピーして、webhook URLに張り付けますこの後、再度LINEbotにメッセージを送ってみましょう、localでテストしたときと同じ返答が帰ってくれば成功です
参考文献
- 投稿日:2021-03-21T22:28:42+09:00
AWS for JavaScript で S3 の getObject で NoSuchKey を期待してたのに AccessDenied が返ってくる
問題
以下のようなコードコードを実行し
let prev = null; try { prev = await S3.getObject({ Bucket: 'my-bucket-hogehoge', Key: 'path/to/object', }).promise(); } catch(e) { // オブジェクトが存在しない場合(NoSuchKey)は無視,それ以外は throw し直す if (e.code !== 'NoSuchKey') { throw e; } }存在しないオブジェクトへのアクセスは
NoSuchKey
が返ってくるものと期待していて、s3rver を利用したローカル環境での動作確認はそれで問題なかった。しかし、デプロイして実際にどうさせると AccessDenied が返ってくる。
原因
なんで?
と1時間くらい悩んだが SDK のドキュメントに書いてあったhttps://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property
Permissions
You need the s3:GetObject permission for this operation. For more information, see Specifying Permissions in a Policy. If the object you request does not exist, the error Amazon S3 returns depends on whether you also have the s3:ListBucket permission.
- If you have the s3:ListBucket permission on the bucket, Amazon S3 will return an HTTP status code 404 ("no such key") error.
- If you don’t have the s3:ListBucket permission, Amazon S3 will return an HTTP status code 403 ("access denied") error.
s3:ListBucket
Action が許可されていないとaccess denied
を返すと対応
以下のようにポリシードキュメントで権限を付与したら解決。
Resource の指定方法がs3:getObject
と異なるので注意。(一部抜粋) { "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::my-bucket-hogehoge/*", "Effect": "Allow" }, { "Action": [ "s3:ListBucket" ], "Resource": "arn:aws:s3:::my-bucket-hogehoge", "Effect": "Allow" }
- 投稿日:2021-03-21T21:40:34+09:00
node.jsで仮チャットサイトを作ってみる
初めに
TwitterのようなSNS系のサイトを作ってみたいと思っていたものの、まずは最初には何をすればいいのかと考えれば、何から手を付ければいいのかさっぱりわからなかったため、とりあえず仮でNode.jsのSocket.ioモジュールを利用して、チャットサイトを作ってみようと思います。
環境
・さくらVPSのCentOS7
・Node.js v15.11.0
・npm 7.6.2
・Mongodb 4.4.4因みにですがさくらVPSの初期設定やnginxの設定までは載せません。そりゃそうですね。駅地図に火星の場所なんて書かないし。
プログラミングの前に
実際に作って見る前に必要な機能を考えてみましょう。
YouTubeやニコニコのコメントのことを参考にしてみれば、コメントをサーバー側に保存して後で見る人のために再生する機能が必要となります。また、ライブなどのリアルタイムであれば、即座に見ている全員にブロードキャストされているようです。
まとめると
・コメントのブロードキャスト
・コメントの保存機能
・コメントの再生機能
これらを作っていこうと思います。モジュールのインストール
npm install socket.io npm install mongodb npm install express-generator -gexpress-generator
コマンドラインで
express -eと入力すればウェブサイトを作る前の雛形を作成することができます。お気に入りなので、とりあえずこれを元に作っていきます。
雛形に必要なモジュールは一緒にインストールされてるわけではないので、別途インストールを実行します。npm install公開は作成されたbinディレクトリのwwwファイルからすることができます。
node bin/wwwとしてChromeなどでアクセスしてみれば、デフォルトのHTMLが表示されます。
socket.io
bin/wwwファイルの中をいじっていきます。
node.js/** * Create HTTP server. */ var server = http.createServer(app); ↓すぐ下に追加 var io = require("socket.io")(server);別に必ずではないですが、今回はこの場所においておきましょう。
node.jsserver.listen(port); server.on('error', onError); server.on('listening', onListening); ↓すぐ下に追加 io.on('connection',function(socket){ socket.on('chat',function(data){ io.emit('chat',{message:data}); }); });サーバー側の設定はこれだけにしましょう。
次はviews/index.ejsのファイルをいじっていきます。<!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script> $(function(){ var socket = io.connect('http://133.167.44.189:80'); //var socket = io.connect(); $('#submit').click(function(){ var message = $('#message'); if(message[0]){ socket.emit("chat",{message:message.val()}) message.val(""); } }) socket.on("chat",function(data){appendMsg(data.message)}); function appendMsg(text){ console.log(text); $("#chatLogs").append("<li>"+text+"</li>"); } }) </script> </head> <body> <input id="message" type="text" /> <input id="submit" type="submit" value="send" /> <ul id="chatLogs"></ul> </body> </html>機能美もデザイン性も考えずにとりあえずこうしましょう。
socket.emit(~)はデータをサーバー側に送信するためのもので、socket.onは逆にデータをサーバー側から受け取るためのものです。
さて、ここまでで一度動作の確認と行きましょう。node bin/wwwとexpress-generatorで作成したファイルをカレントディレクトリにして入力すれば、サーバーは起動します。IPアドレスなりドメインなりにchromeなどからアクセスすると
シンプルオブベストな画面が表示されます。複数のタブでこのサイトを開いて、枠に文字列を打ち込んでsendのボタンを押せば、全部のタブにおいて共有されているのがわかります。リアルタイム性のあるブロードキャスト機能はこれで完成です。次は保存ですね。mongodb
このままbin/wwwのファイルの中に直接mongodbについての情報を書き込んでもいいんですが、しかし如何せん長くなってしまうので別のファイルにわけて書こうと思います。
というわけでアクセスから何から何まで書こうと思ったのですが、それはそれで如何せん長くなってしまうのでチートシートをご用意しました!まぁそれでは不親切すぎるので全コピーできるファイルもおいて置きましょう。
node.js//./database/mongo_connect.js const MongoClient = require('mongodb').MongoClient function open(){ let url = 'mongodb://ユーザー名:パスワード@localhost:27017'; const connectOptions = { useNewUrlParser: true, useUnifiedTopology: true, } return new Promise((resolve,reject)=>{ MongoClient.connect(url,connectOptions,(err,db)=>{ if(err) reject(err); else resolve(db); }); }); } function close(db){ if(db)db.close(); } let db = { open:open, close:close } module.exports=db;node.js//./database/insertOne.js const zenodb = require('./mongo_connect.js'); function insertOne(object,col){ let database = null; zenodb.open() .then((db)=>{ database = db; const dbName = db.db("自分のデータベース名を入力してね!"); return dbName.collection(col); }) .then((collection)=>{ return collection.insertOne(object); }) .catch((err)=>{ console.error(err) }) .finally(()=>{ zenodb.close(database); }) } module.exports=insertOne;node.js//./database/methods.js const insertOne = require("./insertOne.js"); let methods = { insertOne:insertOne, } module.exports=methods;こんな感じです。databaseディレクトリを作成して以上3つのファイルを作成しました。
編集する必要があるのは、最も最初にあるlet urlのユーザー名とパスワード、自分のデータベース名を入力してね!と書いてある場所ですね。
これらのファイルを使っていきます。
bin/wwwのファイルを編集します。$vim bin/wwwnode.jsserver.listen(port); server.on('error', onError); server.on('listening', onListening); ↓すぐ下に追加 var methods = require("../database/methods.js");requireをとりあえず追加しまして、先程作ったsocket.ioの中身も変えます。
node.jsio.on('connection',function(socket){ socket.on('chat',function(data){ methods.insertOne(data,"comments"); io.emit('chat',data); }); });dataの構造はこれまで通りにしていれば、{message:"何かしらのコメント"}になっているはずなのでokです。これで保存機能は完成ですね。これも先程と同じように試してみてください。
次は再生機能です。再生機能のためにfindでデータを探すメソッドを作る必要があります。
node.js// ./database/findLimit.js const zenodb = require('./mongo_connect.js'); function findLimit(col,limit){ let database = null; return zenodb.open() .then((db)=>{ database = db; const dbName = db.db("自分のデータベース名を入力してね!"); return dbName.collection(col); }) .then((collection)=>{ return collection.find(); }) .then((results)=>{ return results.limit(limit).toArray(); }) .catch((err)=>{ console.error(err) }) .finally(()=>{ zenodb.close(database); }) } module.exports=findLimit;集合部分であるmethodsも編集します。
node.js// ./database/methods.js const insertOne = require("./insertOne.js"); const findLimit = require("./findLimit.js"); let methods = { insertOne:insertOne, findLimit,findLimit, } module.exports=methods;取得してきたコメントをhttpでクライアント側に反映させる必要があります。なので次に編集するのはroutes/index.jsです。
node.jsvar express = require('express'); var router = express.Router(); var methods = require('../database/methods'); /* GET home page. */ router.get('/', function(req, res, next) { methods.findLimit("comments",20) .then((results)=>{ res.render('index',{title:'Express',datas:results}); }); }); module.exports = router;以上のように書き換えます。
resultsのデータ構造は[{id:,message:},{id:,message}]という風になっており、コメントを表示するというのはmessageだけが取得できればいいのですが、そのデータ処理は次の場所でします。ejsを使用するので、views/index.ejsを編集します。
上の方で一度作っていたHTMLのbodyを少し改変しただけです。<body> <input id="message" type="text" /> <input id="submit" type="submit" value="send" /> <ul id="chatLogs"> <% for(data of datas){ %> <li><%=data.message %></li> <% } %> </ul> </body>以上の通りです。
これらすべてを作成し終えたところで$node bin/wwwと実行してみてアクセスしてみます。
適当にコメントをうってsendボタンを押してみて。
reloadをしてみれば。
見事に保存されているのがわかります!今後
ここまで作ることができれば、あとはいろいろと要素を詰め込んで、デザインを変えていけばTwitterのようなSNSwebアプリケーションだってすぐです!夢が広がりますね。今後はSNSもうすこし機能を強化してみて、SNSとして特色をつけようとしたところだけ記事にしてみようと思います。
大事な部分だけを記事にしようと思います。今回の記事は少し長くしすぎた感がありますからね。(それに丁寧さがなかったから)
以上です。お疲れ様でした。
- 投稿日:2021-03-21T20:28:08+09:00
LIFFとStripe CheckoutでLINE上で使える決済画面を作るよ
LINE上でLINE Pay以外の方法で決済をしたいというクライアント様のご要望があり、LIFFとStripeを絡めたサンプルを作ってみました。この組み合わせはあまり記事が無かったので記録として残しておきます。
今回は、Stripeの決済にLINEのユーザーIDをメタデータとして乗せてみます。
StripeのGithubにあがっていたサンプルをLIFF向けに少し修正しました。出来上がったもの
デモサイト
テスト用のカード4242-4242-4242-4242を使って決済の流れをご確認頂けます。カード有効期限とCVC、所有者名、メールアドレスは適当でokです。Herokuの無料プランなので遅いです。LINEが立ち上がります
開発環境
Node.js v11.13.0
LINE側の設定
まずはLINE Developers からチャンネルを作成します。LINEログインのチャンネルにLIFFアプリを登録していきます。
認証するときに必要ですので、Scopeのopenidにチェックを入れることをお忘れなく。
エンドポイントURLはひとまず適当で大丈夫です(後から直せます)
チャネルIDとLIFF IDを控えておいてください。
LIFF IDはLIFFアプリ作成後に付与されます。Stripe側の設定
次にStripeのダッシュボードから定期支払いの商品を作成します。
詳細欄の商品ID(prod_XXXXXX)と料金欄の価格ID(price_XXXXXXXX)、ホーム画面で確認できる公開可能キー(pk_XXXXXXX)とシークレットキー(sk_XXXXXXX)を控えておいてください。サーバーの設置
コードはGitHubのリポジトリを公開してますので、そちらを落としてみてください。
↓まずはプロジェクトの依存パッケージをダウンロードします
npm install↓プロジェクト内のファイルを2か所、先ほど控えたご自身のIDに書き換えて頂く必要があります。
.env
# Stripe keys STRIPE_PUBLISHABLE_KEY=(Stripeの公開可能キー) STRIPE_SECRET_KEY=(Stirpeのシークレットキー) # Required to run webhook # See README on how to use the Stripe CLI to setup # STRIPE_WEBHOOK_SECRET=whsec_1234 # Checkout options DONATION_PRODUCT_ID=(作成した定期支払い商品のID) SUBSCRIPTION_PRICE_ID=(価格ID) # ex.https://amabot-payment.herokuapp.com DOMAIN=(デプロイ先のドメイン) # Environment variables STATIC_DIR=client # LINE CHANNEL_ID=(LINE Developersで設定したチャネルID)client/liff.js (1行目)
const liffId = (作成したLIFFアプリのLIFF ID)LINEのユーザー情報の取り扱いに注意!!
クライアント側で取得したユーザー情報をサーバーに送ることは公式で禁止されています。
今回はクライアント側でIDトークンを発行して、サーバーサイドでトークンの検証を行いユーザー情報を取得するようにしました。
https://developers.line.biz/ja/docs/liff/using-user-profile/
https://developers.line.biz/ja/reference/line-login/#verify-id-token最後にLINE DevelopersのLIFFアプリ詳細からエンドポイントURLをご自身のものに書き換えます。
ここが厄介なのですが、LIFFアプリのエンドポイントURLはhttpsでないと登録できないのでご注意ください。ローカルでデバックする際はngrok経由で動きを確認する方が多いようですね。
私はそのままherokuにデプロイしてしまいました。なお、.envファイルのDOMAINの値もこちらと合わせてください。
決済してみる
↓サーバーを起動します。
node server.jsLIFFアプリのURLを開くと決済画面が立ち上がるかと思います。
決済してからStripeのダッシュボードを確認してみると、、
処理が成功しています。メタデータのユーザーIDも登録されてました!参考にしたサイト
あまり情報がなかったので公式ドキュメント中心です
https://developers.line.biz/ja/reference/line-login/
https://developers.line.biz/ja/docs/liff/using-user-profile/
https://stripe.com/docs/api/checkout/sessions/create
https://support.stripe.com/questions/using-metadata-with-checkout-sessions宣伝
自作機能を公開してます。良かったら使ってみてください
- 投稿日:2021-03-21T18:36:23+09:00
Windowsユーザー必見!scoopを使ってコマンドからGit、Node、npm、PHPをダウンロードしてHomebrewを実現しよう!!
皆さんこんにちは!
今日はWinodwsでコマンドから色々ものをダウンロードして見ようかなと思います。
良く解説動画を見ると、Macで説明されている方が多くその度に
Homebrew
と言う言葉を耳にします。残念ながらWindowsではこのHomebrewと言うものは存在しません(多分)。
ですが、Homebrewと同じような機能をもつものがWindowsにも搭載されています!
その名はscoop!!
これを使えば、コマンドからNodeやらGitやらをインストールすることができます。
他にもscoopを使えばバージョンの指定を行うことも可能なので、わざわざサイトからダウンロードするなんて作業にはもうさよならです。
scoopをインストールするには
PowerShell
での作業が必須となりますのでご注意を。それでは早速scoopを使って色々やってみましょう!
scoopのインストール
もう一度言います。
PowerShellで行ってくださいね。
Set-ExecutionPolicy RemoteSigned -scope CurrentUser // 実行ポリシーの変更について聞かれるので「Y」を選択 iex (new-object net.webclient).downloadstring('https://get.scoop.sh')scoop bucket add extras scoop bucket add versionsこの2つは良く使うのでインストールしてください。
Gitの導入
scoop install gitこれでGitをインストールすることができました!
git --versionバージョンが返ってくればOK!
環境変数のPATHも自動で通してくれるのでめちゃ便利!
ついでに
openssh
も取得scoop install opensshNodeのインストール
お次はNodeをインストールし見ましょう!
scoop install nodejsバージョン指定
バージョン指定したい場合は以下のように実行
scoop install nodejs8ただし、
scoop bucket add versions
を行っていない場合は出来ないので注意。node -v npm -vバージョンが返ってくればOK!
PHPの導入
ここからはおまけみたいな感じです。
scoop install php-nts php-nts-xdebug vcredist2017 composerこれでPHPとComposerを使える環境が整いました。
php -v composer -vバージョンが返ってくればOK!
'****.dll' ** is not compatible with this PHP build linked with ** in Unknown on line 0このようなエラーが出る方は、下記の記事が参考になります。
・「MSVCR140.dll/VCRUNTIME140.dllがないため、プログラムが開始できません」と表示された場合
コマンドで操作を行うってやっぱり夢ありますよね。
これでバージョン管理も楽になるので、是非活用してください!
以上、「Windowsユーザー必見!Homebrewみたいにscoopを使ってコマンドからGit、Node、npm、PHPをダウンロードしてみよう!!」でした!
Thank you for reading
- 投稿日:2021-03-21T17:03:49+09:00
Node.jsのMongodbをPromiseで行ったチートシート(?)
初めに
Node.jsでMongodbを操作したいという際にもうちょっと簡単で楽にならないかなと考えて作ったのが今回のプログラムです。楽is神。
前提
・Node.jsのインストールを済ませていること
・Mongodbのインストールを済ませていること
・npmのインストールを済ませていること
・mongodbのNode.jsのAPIをインストールしていること環境
・さくらVPSのCentos7
・node.js v15.11.0
・npm 7.6.2
・mongodb v4.4.4Mongodb
わかりやすいようにMongodbを操作する用のディレクトリをとりあえず作っておきましょう。
$mkdir database $cd database接続部分
まずはMongodbとの接続についてのファイルを作成します。
$vim mongo_connect.jsnode.js//mongo_connect.js const MongoClient = require('mongodb').MongoClient function open(){ let url = 'mongodb://ユーザー名:パスワード@localhost:27017'; const connectOptions = { useNewUrlParser: true, useUnifiedTopology: true, } return new Promise((resolve,reject)=>{ MongoClient.connect(url,connectOptions,(err,db)=>{ if(err) reject(err); else resolve(db); }); }); } function close(db){ if(db)db.close(); } let db = { open:open, close:close } module.exports=db;urlについてですがユーザーを作成していた場合は以上のとおりになります。ユーザー名とパスワードを設定したとおりに入れてくださいね。
認証を設定したいという方はこちらの記事の最後の方に書いてあるので、是非参考にしてくださいな。
またMongodbをwebサイトのデータベースとしてでもなんでも、本格的に運用したいという方は27017からポートの変更をしておいたほうがいいです。今回はテストも兼ねていたのでデフォルトのポートのままです。クエリ部分
Mongodbにおいてもクエリと呼んでいいのかどうかはわかりませんがとにかくクエリです。
$vim insertOne.jsnode.js//insertOne.js const zenodb = require('./mongo_connect.js'); function insertOne(object,col){ let database = null; zenodb.open() .then((db)=>{ database = db; const dbName = db.db("自分の使うデータベース名を入力してね!"); return dbName.collection(col); }) .then((collection)=>{ return collection.insertOne(object); }) .catch((err)=>{ console.error(err) }) .finally(()=>{ zenodb.close(database); }) } module.exports=insertOne;insertOne({データ名,データ},コレクション名)とすることで実行できるメソッドを用意しました。requireしている接続ファイルがzenodbですが、参考にさせていただいたQ&Aの回答者の人がそう書いていたのでそう書かせてもらいました。意味は・・・調べてみたんですがよくわからなかったっす。
念の為、参考にさせていただいたQ&Aのサイトを載せておきます。https://stackoverflow.com/questions/37911838/how-to-use-mongodb-with-promises-in-node-js
集合部分
今回はinsertOneだけでしたが、他にも作れば当然便利になるでしょう。しかしそうしたらrequireするのがめんどくせぇ!とかなりそうなので、集合部分を予め作っておきましょう。
$vim methods.jsnode.jsconst insertOne = require("./insertOne.js"); let methods = { insertOne:insertOne, } module.exports=methods;let methodsの場所にクエリをたくさん追加できるようになれば便利ですね。
最後に一応今回作ったプログラムを試しておきましょう。
使用するのは先程作ったmethodsファイル。node.jsconst insertOne = require("./insertOne.js"); let methods = { insertOne:insertOne, } methods.insertOne({name:"tekitou"},"users"); module.exports=methods;node methods.jsこれでmongodbシェルにログインしてみて、対象のデータベースのコレクションの中にデータが入っていればOKです。
以上!
なにか質問があれば書いてください!わからないかもしれませんけどねw
- 投稿日:2021-03-21T16:39:45+09:00
Node.jsでgRPCを動かそう - xhack勉強会
※こちらの記事は3/21に開催するxhack勉強会「Node.jsでgRPCを動かそう」の資料となります
本日のお品書き
- 始めに
- 自己紹介
- 想定参加者について
- 今日のゴール
- Node.jsでgRPCを動かそう
- gRPCって何?
- ハンズオン
- 質疑応答
- 最後に
始めに
ぜひ#xhack勉強会 で感想をツイートしてください!
また、可能な方はカメラオンにして欲しいです!顔が見えない中ひとりで話すのは寂しい、、自己紹介
とむといいます。
新卒未経験からエンジニアになってまもなく2年。
今年の2月に転職をし、大阪から東京に引っ越してきました。
転職前はJavaを使って主にサーバ側の開発をしていましたが、現在はスマホアプリ開発をメインに行っている株式会社マンハッタンコードで働いています。
Twitterはこちらをクリック←ぜひフォローしてください!以前からX-HACKさんの勉強会にはものすごくお世話になっていたのですが、今回初めて勉強会を主催させていただきます。
お手柔らかにお願いします、、想定参加者
- gRPCって聞いてピンと来ない人
- JavaScriptが読める人
- サーバ、クライアント、API、HTTPといった用語をある程度理解している人
- Macを持っている人
- ターミナルで基本的なコマンドが扱える人(npm・nodeコマンドがインストールされている人)
今日のゴール
- gRPCをふわっと理解する
- 公式チュートリアルを参考に実際に動かしてみる
注意:今回の勉強会では書き方の細かいルールなどは説明しません!
Node.jsでgRPCを動かそう
gRPCって何?
- Googleが公開したRPCフレームワークの一つ
そもそもRPCって???
RPCはRemote Procedure Callの略。
たけがみまさきさん著のスターティングgRPCではRemote Procedure Callを訳すと遠隔手続き呼び出しという意味になります。すなわち、あるサービスからべつのサービスのアプリケーションの処理(サブルーチン/クラス/関数など)を呼び出す技術ということです。
と説明されています。
遠くにある関数とかを呼び出せちゃう便利なやつがRPCで、gRPCはその中の1つということをふんわりと頭に入れておいてもらえたらOKです!gRPCのここがすごい
- HTTP/2によって高速な通信ができる
- ProtocolBuffers
ここからは実際に手を動かしていきましょう!
ハンズオン
基本的な流れはこちら。
1. 必要なツールやライブラリをインストールする
2. Protocol Buffersを使って定義ファイルを書く
3. (定義ファイルをコンパイルしてコードを生成する)
4. 定義に沿ってサーバとクライアントを実装する公式チュートリアルを参考に、よりシンプルなものを作ってみましょう
作るもの
指定した人に挨拶をするアプリみたいなやつ
- クライアント側:誰に挨拶するかを決める
- サーバ側:挨拶するフレーズを生成
1. 必要なツールやライブラリをインストールする
npm init npm install grpc @grpc/proto-loader or npm install @grpc/grpc-js @grpc/proto-loadergrpcパッケージじゃなく下のgrpc-jsの方がいいかも?
参考2. Protocol Buffersを使って定義ファイルを書く
helloworld.proto// Protocol Buffersのバージョンを指定 syntax = "proto3"; // パッケージを指定 package helloworld; // サービスを定義 service Greeter { // 引数の型:HelloRequestメッセージ // 戻り値の型:HelloReplyメッセージ rpc SayHello (HelloRequest) returns (HelloReply) {} } // メッセージの型を定義 message HelloRequest { // 各フィールドに識別子としてタグを付ける // 値をフィールドに代入しているわけではないことに注意 string name = 1; } message HelloReply { string message = 1; }3. (定義ファイルをコンパイルしてコードを生成する)
node.jsはコンパイルをせず2.で作成した定義ファイルを読み込めばヨシ!!
4. 定義に沿ってサーバとクライアントを実装する
サーバ側
クライアントからアクセスがあったら挨拶文を生成する(sayHelloする)サーバを動かしたい
server.jsconst protoLoader = require('@grpc/proto-loader'); // インストールしたパッケージに合わせる // const grpc = require('grpc'); const grpc = require('@grpc/grpc-js'); const PROTO_PATH = __dirname + '/helloworld.proto' // 定義ファイル(.protoファイル)の読み込み const packageDefinition = protoLoader.loadSync( PROTO_PATH, {keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; /** * sayHelloメソッド */ function sayHello(call, callback) { callback(null, {message: 'Hello ' + call.request.name}); } /** * mainメソッド */ function main() { // サーバのインスタンスを生成 const server = new grpc.Server(); // サーバがGreeterサービスのリクエストを受け取るようにする server.addService(hello_proto.Greeter.service, {sayHello: sayHello}); // クライアントのリクエストをリッスンする(外部からのアクセスに備えて待機する)ためのアドレスとポートを指定 server.bindAsync('127.0.0.1:50051', grpc.ServerCredentials.createInsecure(), () => { // サーバを起動する server.start(); }); } main();サーバを起動!
node server.jsクライアント側
クライアントがやりたいのは
- 誰に挨拶をするか決める
- サーバ側(Remote)のsayHello(Procedure)を呼び出し(Call)
client.jsconst PROTO_PATH = __dirname + '/helloworld.proto'; // インストールしたパッケージに合わせる // const grpc = require('grpc'); const grpc = require('@grpc/grpc-js'); // 定義ファイル(.protoファイル)の読み込み const protoLoader = require('@grpc/proto-loader'); const packageDefinition = protoLoader.loadSync( PROTO_PATH, {keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; /** * mainメソッド */ function main() { // サーバのアドレスとポートを指定してGreeterサービスのスタブコンストラクタを呼び出す const client = new hello_proto.Greeter('127.0.0.1:50051', grpc.credentials.createInsecure()); // スタブでsayHelloメソッドの呼び出し // リクエスト(HelloRequestメッセージ型のオブジェクト)とコールバック関数をサーバ側に渡す client.sayHello({name: 'World'}, function(err, response) { console.log('Greeting:', response.message); }); } main();クライアントを起動!
node server.js
Greeting:Hello World
と出力されれば成功です!!お疲れ様でした!!
最後に
初めての勉強会開催だったので皆さんの感想が気になります!!
#xhack勉強会 でツイートしてくれたら嬉しいです!
近日開催されるxhack勉強会
- 「デジタル・マーケティングの定石を学ぶ」著:垣内勇威 読書会 vol.2
- 【アフィリエイトについて語ろう】検索エンジンを再発明する Meet Up vol.01
- みんなでUIを改善してみるUIデザイン勉強会
株式会社マンハッタンコード
現在私が所属している株式会社マンハッタンコードでは、スマホアプリ開発を主軸にさまざまな挑戦をしています。
毎週土曜日にはイベントを開催しているので、気軽に遊びに来てください!
最後に、今回の勉強会を開く後押しをしてくださり、当日も参加してサポートしてくださったX-HACKの松田さん、とよももさん、そして日曜の夜にわざわざ時間を作って参加してくださった皆さん、ありがとうございました!
参考
- 投稿日:2021-03-21T16:39:45+09:00
Node.jsでgRPCを動かそう
※こちらの記事は3/21に開催するxhack勉強会「Node.jsでgRPCを動かそう」の資料となります
本日のお品書き
- 始めに
- 自己紹介
- 想定参加者について
- 今日のゴール
- Node.jsでgRPCを動かそう
- gRPCって何?
- ハンズオン
- 質疑応答
- 最後に
始めに
ぜひ#xhack勉強会 で感想をツイートしてください!
また、可能な方はカメラオンにして欲しいです!顔が見えない中ひとりで話すのは寂しい、、自己紹介
とむといいます。
新卒未経験からエンジニアになってまもなく2年。
今年の2月に転職をし、大阪から東京に引っ越してきました。
転職前はJavaを使って主にサーバ側の開発をしていましたが、現在はスマホアプリ開発をメインに行っている株式会社マンハッタンコードで働いています。
Twitterはこちらをクリック←ぜひフォローしてください!以前からX-HACKさんの勉強会にはものすごくお世話になっていたのですが、今回初めて勉強会を主催させていただきます。
お手柔らかにお願いします、、想定参加者
- gRPCって聞いてピンと来ない人
- JavaScriptが読める人
- サーバ、クライアント、API、HTTPといった用語をある程度理解している人
- Macを持っている人
- ターミナルで基本的なコマンドが扱える人(npm・nodeコマンドがインストールされている人)
今日のゴール
- gRPCをふわっと理解する
- 公式チュートリアルを参考に実際に動かしてみる
注意:今回の勉強会では書き方の細かいルールなどは説明しません!
Node.jsでgRPCを動かそう
gRPCって何?
- Googleが公開したRPCフレームワークの一つ
そもそもRPCって???
RPCはRemote Procedure Callの略。
たけがみまさきさん著のスターティングgRPCではRemote Procedure Callを訳すと遠隔手続き呼び出しという意味になります。すなわち、あるサービスからべつのサービスのアプリケーションの処理(サブルーチン/クラス/関数など)を呼び出す技術ということです。
と説明されています。
遠くにある関数とかを呼び出せちゃう便利なやつがRPCで、gRPCはその中の1つということをふんわりと頭に入れておいてもらえたらOKです!gRPCのここがすごい
- HTTP/2によって高速な通信ができる
- ProtocolBuffers
ここからは実際に手を動かしていきましょう!
ハンズオン
基本的な流れはこちら。
1. 必要なツールやライブラリをインストールする
2. Protocol Buffersを使って定義ファイルを書く
3. (定義ファイルをコンパイルしてコードを生成する)
4. 定義に沿ってサーバとクライアントを実装する公式チュートリアルを参考に、よりシンプルなものを作ってみましょう
作るもの
指定した人に挨拶をするアプリみたいなやつ
- クライアント側:誰に挨拶するかを決める
- サーバ側:挨拶するフレーズを生成
1. 必要なツールやライブラリをインストールする
npm init npm install grpc @grpc/proto-loader or npm install @grpc/grpc-js @grpc/proto-loadergrpcパッケージじゃなく下のgrpc-jsの方がいいかも?
参考2. Protocol Buffersを使って定義ファイルを書く
helloworld.proto// Protocol Buffersのバージョンを指定 syntax = "proto3"; // パッケージを指定 package helloworld; // サービスを定義 service Greeter { // 引数の型:HelloRequestメッセージ // 戻り値の型:HelloReplyメッセージ rpc SayHello (HelloRequest) returns (HelloReply) {} } // メッセージの型を定義 message HelloRequest { // 各フィールドに識別子としてタグを付ける // 値をフィールドに代入しているわけではないことに注意 string name = 1; } message HelloReply { string message = 1; }3. (定義ファイルをコンパイルしてコードを生成する)
node.jsはコンパイルをせず2.で作成した定義ファイルを読み込めばヨシ!!
4. 定義に沿ってサーバとクライアントを実装する
サーバ側
クライアントからアクセスがあったら挨拶文を生成する(sayHelloする)サーバを動かしたい
server.jsconst protoLoader = require('@grpc/proto-loader'); // インストールしたパッケージに合わせる // const grpc = require('grpc'); const grpc = require('@grpc/grpc-js'); const PROTO_PATH = __dirname + '/helloworld.proto' // 定義ファイル(.protoファイル)の読み込み const packageDefinition = protoLoader.loadSync( PROTO_PATH, {keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; /** * sayHelloメソッド */ function sayHello(call, callback) { callback(null, {message: 'Hello ' + call.request.name}); } /** * mainメソッド */ function main() { // サーバのインスタンスを生成 const server = new grpc.Server(); // サーバがGreeterサービスのリクエストを受け取るようにする server.addService(hello_proto.Greeter.service, {sayHello: sayHello}); // クライアントのリクエストをリッスンする(外部からのアクセスに備えて待機する)ためのアドレスとポートを指定 server.bindAsync('127.0.0.1:50051', grpc.ServerCredentials.createInsecure(), () => { // サーバを起動する server.start(); }); } main();サーバを起動!
node server.jsクライアント側
クライアントがやりたいのは
- 誰に挨拶をするか決める
- サーバ側(Remote)のsayHello(Procedure)を呼び出し(Call)
client.jsconst PROTO_PATH = __dirname + '/helloworld.proto'; // インストールしたパッケージに合わせる // const grpc = require('grpc'); const grpc = require('@grpc/grpc-js'); // 定義ファイル(.protoファイル)の読み込み const protoLoader = require('@grpc/proto-loader'); const packageDefinition = protoLoader.loadSync( PROTO_PATH, {keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; /** * mainメソッド */ function main() { // サーバのアドレスとポートを指定してGreeterサービスのスタブコンストラクタを呼び出す const client = new hello_proto.Greeter('127.0.0.1:50051', grpc.credentials.createInsecure()); // スタブでsayHelloメソッドの呼び出し // リクエスト(HelloRequestメッセージ型のオブジェクト)とコールバック関数をサーバ側に渡す client.sayHello({name: 'World'}, function(err, response) { console.log('Greeting:', response.message); }); } main();クライアントを起動!
node server.js
Greeting:Hello World
と出力されれば成功です!!お疲れ様でした!!
最後に
初めての勉強会開催だったので皆さんの感想が気になります!!
#xhack勉強会 でツイートしてくれたら嬉しいです!
近日開催されるxhack勉強会
- 「デジタル・マーケティングの定石を学ぶ」著:垣内勇威 読書会 vol.2
- 【アフィリエイトについて語ろう】検索エンジンを再発明する Meet Up vol.01
- みんなでUIを改善してみるUIデザイン勉強会
株式会社マンハッタンコード
現在私が所属している株式会社マンハッタンコードでは、スマホアプリ開発を主軸にさまざまな挑戦をしています。
毎週土曜日にはイベントを開催しているので、気軽に遊びに来てください!
最後に、今回の勉強会を開く後押しをしてくださり、当日も参加してサポートしてくださったX-HACKの松田さん、とよももさん、そして日曜の夜にわざわざ時間を作って参加してくださった皆さん、ありがとうございました!
参考