20210321のNode.jsに関する記事は8件です。

初めての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

目次

  1. LINE側の準備
  2. Node.js側の準備
  3. コードの作成
  4. 応答テスト
  5. 本番環境(heroku)にデプロイ
  6. 参考文献

LINE側の準備

この見出しでは、LINE側で行うことをまとめていきます。

LINE Developerアカウントの作成

まずはこちらのURLからLINE Developerのアカウントを作成します
普段使用されているLINEアカウントがあればすぐに作成できます
https://developers.line.biz/ja/

プロバイダーの作成

次にプロバイダーの作成を行います。トップページにある以下の作成ボタンを押します。
スクリーンショット 2021-03-19 17.28.36.png
ここでは新しく作るプロバイダーをtestとしておきます。
スクリーンショット 2021-03-19 17.29.43.png

チャネルの作成

新しくプロバイダを作成すると以下の画面に移行します。ここでは「Messaging API」を選択します。
スクリーンショット 2021-03-19 17.30.02.png
その後、チャネルの種類を「Messaging API」に指定し、プロバイダーを先ほど作成した「test」に指定します。その後
・チャネルアイコン ※一度変更すると、1日経過しなければ変更することができません
・チャネル名 ※一度変更すると、7日経過しなければ変更することができません
・チャネル説明
・大業種
・小業種
・メールアドレス
・プライバシーポリシーURL(任意)
・サービス利用規約URL(任意)
を入力し、利用規約にチェックを入れ、作成ボタンを押します
スクリーンショット 2021-03-19 17.32.20.png

チャネルシークレットとチャネルアクセストークンの取得

次に外部からLINE APIにアクセスするためのチャネルシークレットとチャネルアクセストークン(長期)を取得します。
こちらの情報は外部に漏れないように気を付けましょう。それぞれの場所は
・チャネルシークレット
 チャネル基本設定の下部にあります
・チャネルアクセストークン(長期)
 Messaging API設定の下部にあり、発行ボタンを押すと表示されます
上記二つが取得できたら、とりあえずはメモ帳等に記録しておきましょう。

その他設定

Messaging API設定タブの応答メッセージ、編集、にて応答設定の中の詳細設定の、応答メッセージを以下の画像のようにオフ、Webhookをオンにしましょう。あいさつメッセージはオフにしていますが、オンでも構いません。
※Webhook URLに関しては後ほど入力します
スクリーンショット 2021-03-19 17.59.27.png
こちらで一旦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側の準備で取得したチャネルシークレットとチャネルアクセストークンを用意し、以下のコードに貼り付けてください

.env
LINE_ACCESS_TOKEN='メモしたチャネルアクセストークン'
LINE_CHANNEL_SECRET='メモしたチャネルシークレット'

フォルダ構成は以下のようになります
スクリーンショット 2021-03-19 18.48.35.png

応答テスト

いよいよテストになります。

LINEbotの友達登録

LINE DevelopeのMessaging API設定のボット情報にある「ボットのベーシックID」をコピーして、自分のLINEの友達検索、にてIDで検索すると作成したbotが出てくるので、そちらを友達にします

スクリーンショット 2021-03-19 23.28.47.png

このボット情報の下にQRコードが表示されているので、そちらから友達になっても構いません

ngrokの起動

コンソールを二つ立ち上げ、片方では

コンソール
ngrok http 3000

とすると、以下のようになるので

スクリーンショット 2021-03-19 18.58.29.png

https://~~~~.ngrok.io の部分をコピーし

LINE DevelopeのMessaging API設定のWebhook設定、webhook URLに貼り付け、後ろに「/webhook」を記入します

スクリーンショット 2021-03-19 19.02.24.png

index.jsの起動

もう一方のコンソールにて、

コンソール
node index.js

としてサーバーを起動します

応答テスト

いよいよテストです。
botに対して「ありがとう」と入力しましょう

すると、「どういたしまして」と返ってきます

それ以外の言葉を入力すると、「こんにちは」と返ってくるはずです。
スクリーンショット 2021-03-19 23.35.54.png

本番環境(heroku)にデプロイ

git init

herokuにデプロイする際はgitを使用するので、まずgit initを行います

コンソール
git init

git ignore

その後、チャネルアクセストークンなどが外部に漏れてしまわないように.gitignoreファイルを作成し、
以下のように記述しておきましょう

.gitignore
npm-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内は以下のように記します

Procfile
web: node index.js

デプロイ

いよいよデプロイです、以下のようにgit addを行い、git commitを行って、herokuにプッシュしましょう

コンソール
git add -A
git commit -m "コミット名"
git push heroku master

デプロイ後、LINE Developersのwebhook URLを変更

コンソールからherokuにデプロイを行うと、以下のようなログが流れます
スクリーンショット 2021-03-20 0.13.40.png
https://~~~~~.herokuapp.com/ の部分をコピーして、webhook URLに張り付けます

スクリーンショット 2021-03-20 0.16.48.png

この後、再度LINEbotにメッセージを送ってみましょう、localでテストしたときと同じ返答が帰ってくれば成功です

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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"
        }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 -g

express-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.js
server.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などからアクセスすると
line_20210319_003701.png
シンプルオブベストな画面が表示されます。複数のタブでこのサイトを開いて、枠に文字列を打ち込んでsendのボタンを押せば、全部のタブにおいて共有されているのがわかります。リアルタイム性のあるブロードキャスト機能はこれで完成です。次は保存ですね。

mongodb

このままbin/wwwのファイルの中に直接mongodbについての情報を書き込んでもいいんですが、しかし如何せん長くなってしまうので別のファイルにわけて書こうと思います。
というわけでアクセスから何から何まで書こうと思ったのですが、それはそれで如何せん長くなってしまうのでチートシートをご用意しました!

https://qiita.com/SUNAsan/items/45cf7d8a2da0dabcce1b

まぁそれでは不親切すぎるので全コピーできるファイルもおいて置きましょう。

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/www
node.js
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

すぐ下に追加

var methods = require("../database/methods.js");

requireをとりあえず追加しまして、先程作ったsocket.ioの中身も変えます。

node.js
io.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.js
var 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として特色をつけようとしたところだけ記事にしてみようと思います。
大事な部分だけを記事にしようと思います。今回の記事は少し長くしすぎた感がありますからね。(それに丁寧さがなかったから)
以上です。お疲れ様でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LIFFとStripe CheckoutでLINE上で使える決済画面を作るよ

https___qiita-image-store.s3.amazonaws.com_0_71113_9a76fa60-ccff-afc6-b374-1a7a444c4a8b.png

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はひとまず適当で大丈夫です(後から直せます)
image.png

チャネルIDLIFF IDを控えておいてください。
LIFF IDはLIFFアプリ作成後に付与されます。

Stripe側の設定

次にStripeのダッシュボードから定期支払いの商品を作成します。
image.png
詳細欄の商品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.js

LIFFアプリのURLを開くと決済画面が立ち上がるかと思います。
決済してからStripeのダッシュボードを確認してみると、、

20200728093917.jpg
処理が成功しています。メタデータのユーザー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

宣伝

自作機能を公開してます。良かったら使ってみてください

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 openssh

Nodeのインストール

お次は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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.4

Mongodb

わかりやすいようにMongodbを操作する用のディレクトリをとりあえず作っておきましょう。

$mkdir database
$cd database

接続部分

まずはMongodbとの接続についてのファイルを作成します。

$vim mongo_connect.js
node.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.js
node.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.js
node.js
const insertOne = require("./insertOne.js");

let methods = {
  insertOne:insertOne,
}

module.exports=methods;

let methodsの場所にクエリをたくさん追加できるようになれば便利ですね。
最後に一応今回作ったプログラムを試しておきましょう。
使用するのは先程作ったmethodsファイル。

node.js
const insertOne = require("./insertOne.js");

let methods = {
  insertOne:insertOne,
}

methods.insertOne({name:"tekitou"},"users");

module.exports=methods;
node methods.js

これでmongodbシェルにログインしてみて、対象のデータベースのコレクションの中にデータが入っていればOKです。
以上!
なにか質問があれば書いてください!わからないかもしれませんけどねw

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsでgRPCを動かそう - xhack勉強会

※こちらの記事は3/21に開催するxhack勉強会「Node.jsでgRPCを動かそう」の資料となります

本日のお品書き

始めに

ぜひ#xhack勉強会 で感想をツイートしてください!
また、可能な方はカメラオンにして欲しいです!顔が見えない中ひとりで話すのは寂しい、、

自己紹介

とむといいます。
新卒未経験からエンジニアになってまもなく2年。
今年の2月に転職をし、大阪から東京に引っ越してきました。
転職前はJavaを使って主にサーバ側の開発をしていましたが、現在はスマホアプリ開発をメインに行っている株式会社マンハッタンコードで働いています。
Twitterはこちらをクリック←ぜひフォローしてください!

以前からX-HACKさんの勉強会にはものすごくお世話になっていたのですが、今回初めて勉強会を主催させていただきます。
お手柔らかにお願いします、、

想定参加者

  • gRPCって聞いてピンと来ない人
  • JavaScriptが読める人
  • サーバ、クライアント、API、HTTPといった用語をある程度理解している人
  • Macを持っている人
  • ターミナルで基本的なコマンドが扱える人(npm・nodeコマンドがインストールされている人)

今日のゴール

注意:今回の勉強会では書き方の細かいルールなどは説明しません!

Node.jsでgRPCを動かそう

gRPCって何?

  • Googleが公開したRPCフレームワークの一つ

そもそもRPCって???

RPCはRemote Procedure Callの略。
たけがみまさきさん著のスターティングgRPCでは

Remote Procedure Callを訳すと遠隔手続き呼び出しという意味になります。すなわち、あるサービスからべつのサービスのアプリケーションの処理(サブルーチン/クラス/関数など)を呼び出す技術ということです。

と説明されています。
遠くにある関数とかを呼び出せちゃう便利なやつがRPCで、gRPCはその中の1つということをふんわりと頭に入れておいてもらえたらOKです!

gRPCのここがすごい

  • HTTP/2によって高速な通信ができる
  • ProtocolBuffers
    • データをシリアライズ化する仕組み
    • 独自の書き方(IDL=インターフェース定義言語)で呼び出しの定義ができる!!→異なる言語を使っているサービスの処理も呼び出せる!!! image.png

ここからは実際に手を動かしていきましょう!

ハンズオン

基本的な流れはこちら。
1. 必要なツールやライブラリをインストールする
2. Protocol Buffersを使って定義ファイルを書く
3. (定義ファイルをコンパイルしてコードを生成する)
4. 定義に沿ってサーバとクライアントを実装する

公式チュートリアルを参考に、よりシンプルなものを作ってみましょう

作るもの
指定した人に挨拶をするアプリみたいなやつ

  • クライアント側:誰に挨拶するかを決める
  • サーバ側:挨拶するフレーズを生成

1. 必要なツールやライブラリをインストールする

npm init

npm install grpc @grpc/proto-loader
or
npm install @grpc/grpc-js @grpc/proto-loader

grpcパッケージじゃなく下の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.js
const 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.js
const 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勉強会

株式会社マンハッタンコード

現在私が所属している株式会社マンハッタンコードでは、スマホアプリ開発を主軸にさまざまな挑戦をしています。
毎週土曜日にはイベントを開催しているので、気軽に遊びに来てください!


最後に、今回の勉強会を開く後押しをしてくださり、当日も参加してサポートしてくださったX-HACKの松田さんとよももさん、そして日曜の夜にわざわざ時間を作って参加してくださった皆さん、ありがとうございました!

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsでgRPCを動かそう

※こちらの記事は3/21に開催するxhack勉強会「Node.jsでgRPCを動かそう」の資料となります

本日のお品書き

始めに

ぜひ#xhack勉強会 で感想をツイートしてください!
また、可能な方はカメラオンにして欲しいです!顔が見えない中ひとりで話すのは寂しい、、

自己紹介

とむといいます。
新卒未経験からエンジニアになってまもなく2年。
今年の2月に転職をし、大阪から東京に引っ越してきました。
転職前はJavaを使って主にサーバ側の開発をしていましたが、現在はスマホアプリ開発をメインに行っている株式会社マンハッタンコードで働いています。
Twitterはこちらをクリック←ぜひフォローしてください!

以前からX-HACKさんの勉強会にはものすごくお世話になっていたのですが、今回初めて勉強会を主催させていただきます。
お手柔らかにお願いします、、

想定参加者

  • gRPCって聞いてピンと来ない人
  • JavaScriptが読める人
  • サーバ、クライアント、API、HTTPといった用語をある程度理解している人
  • Macを持っている人
  • ターミナルで基本的なコマンドが扱える人(npm・nodeコマンドがインストールされている人)

今日のゴール

注意:今回の勉強会では書き方の細かいルールなどは説明しません!

Node.jsでgRPCを動かそう

gRPCって何?

  • Googleが公開したRPCフレームワークの一つ

そもそもRPCって???

RPCはRemote Procedure Callの略。
たけがみまさきさん著のスターティングgRPCでは

Remote Procedure Callを訳すと遠隔手続き呼び出しという意味になります。すなわち、あるサービスからべつのサービスのアプリケーションの処理(サブルーチン/クラス/関数など)を呼び出す技術ということです。

と説明されています。
遠くにある関数とかを呼び出せちゃう便利なやつがRPCで、gRPCはその中の1つということをふんわりと頭に入れておいてもらえたらOKです!

gRPCのここがすごい

  • HTTP/2によって高速な通信ができる
  • ProtocolBuffers
    • データをシリアライズ化する仕組み
    • 独自の書き方(IDL=インターフェース定義言語)で呼び出しの定義ができる!!→異なる言語を使っているサービスの処理も呼び出せる!!! image.png

ここからは実際に手を動かしていきましょう!

ハンズオン

基本的な流れはこちら。
1. 必要なツールやライブラリをインストールする
2. Protocol Buffersを使って定義ファイルを書く
3. (定義ファイルをコンパイルしてコードを生成する)
4. 定義に沿ってサーバとクライアントを実装する

公式チュートリアルを参考に、よりシンプルなものを作ってみましょう

作るもの
指定した人に挨拶をするアプリみたいなやつ

  • クライアント側:誰に挨拶するかを決める
  • サーバ側:挨拶するフレーズを生成

1. 必要なツールやライブラリをインストールする

npm init

npm install grpc @grpc/proto-loader
or
npm install @grpc/grpc-js @grpc/proto-loader

grpcパッケージじゃなく下の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.js
const 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.js
const 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勉強会

株式会社マンハッタンコード

現在私が所属している株式会社マンハッタンコードでは、スマホアプリ開発を主軸にさまざまな挑戦をしています。
毎週土曜日にはイベントを開催しているので、気軽に遊びに来てください!


最後に、今回の勉強会を開く後押しをしてくださり、当日も参加してサポートしてくださったX-HACKの松田さんとよももさん、そして日曜の夜にわざわざ時間を作って参加してくださった皆さん、ありがとうございました!

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む