20191008のNode.jsに関する記事は12件です。

twitモジュール使ってキーワード指定したつぶやきをリアルタイムで抽出する

はじめに

twitモジュールが便利すぎたので記念に投稿。

参考書籍

JS+Node.jsによるWebクローラー/ネットエージェント開発テクニック

実行環境

・Windows10
・VirtualBox
・Vagrant 2.2.5
・Node.js v6.17.1
・Twitter Developers 登録済み

モジュールのインストール

ソースコード置き場に移動して以下のコマンド実行。
成功すると、同ディレクトリ上にnode_modulesディレクトリができあがる

[vagrant@localhost 02-twitter]$ npm install twit --no-bin-links
/vagrant_data/src/ch06/02-twitter
mqw twit@2.2.11
  mqw request@2.88.0
    mqw http-signature@1.2.0
      mqw sshpk@1.16.1
        tqq asn1@0.2.4
        tqq bcrypt-pbkdf@1.0.2
        tqq dashdash@1.14.1
        tqq ecc-jsbn@0.1.2
        tqq getpass@0.1.7
        tqq jsbn@0.1.1
        tqq safer-buffer@2.1.2
        mqq tweetnacl@0.14.5

npm WARN enoent ENOENT: no such file or directory, open '/vagrant_data/src/ch06/02-twitter/package.json'
npm WARN 02-twitter No description
npm WARN 02-twitter No repository field.
npm WARN 02-twitter No README data
npm WARN 02-twitter No license field.
[vagrant@localhost 02-twitter]$ ls
node_modules  twi-app-test.js

Twitter APIキーを確認する

  1. Twitter Developersにログインする
  2. 画面右上あたりにある[Get Started]クリック
  3. 画面真ん中あたり[Create An App]クリック
  4. 画面の指示に従ってアプリ登録に必要な事項を記入&登録
  5. 登録されたら4種のキーが発行されるのでメモとる ↓↓みたいなやつがもらえる
キーは使われると困るので伏字(***)にしてます
Consumer API keys
******************* (API key)
@@@@@@@@@@@@@@@@@@@ (API secret key)

Regenerate
Access token & access token secret
???????????????????? (Access token)
!!!!!!!!!!!!!!!!!!!! (Access token secret)

プログラムの作成

ごく短いプログラムを作る↓↓

// Twitterを使ったテスト
var Twit = require('twit');

// 以下正しいキーを設定
var T = Twit({
    consumer_key:'*******************',
    consumer_secret:'@@@@@@@@@@@@@@@@@@@',
    access_token:'????????????????????',
    access_token_secret:'!!!!!!!!!!!!!!!!!!!!'
});

// Javascriptに関するつぶやきを表示する
var stream = T.stream('statuses/filter', {track: 'Kaggle'} );
// つぶやきがあったときに呼ばれるイベントを設定
stream.on('tweet', function (tw) {
    var text = tw.text;
    var user_name = tw.user.name;
    console.log(user_name + "> " + text);
});

うごかしてみる

実行結果は↓↓。 ※試しの雰囲気を見てほしいだけなので名前とかは伏字にしときます
起動してぼんやり眺めるだけでもなんとなく楽しいかもしれない。

[vagrant@localhost 02-twitter]$ node twi-app-test.js
????> RT @MLBear2: 幸いにも上位に入れたので初めてSolutionを投稿しました。特殊なコンペ(?)だったので他コンペにそのまま流用で きるノウハウは多くないかもですが、adversarial validationをあえて完全無視したとか、他のsolutionが書いてないよ…
????> @radekosmulski @jeremyphoward @kaggle @RSNA @threader_app
????> Curiosamente, las mayores dificultades que encuentro son la manipulacion de datos previa entrada a la red, y que el… https://t.co/jHmvM68xdu
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

npmでのモジュールのインストールしたときに失敗した時の対処法

はじめに

Windows上でVirtualboxを使って開発環境を作ったとき
共有フォルダ設定を使ったパス上でnpm install...してるとエラーがでた。
これの対処法をメモ

参考

https://qiita.com/sansaisoba/items/0fd5c77c9fbbfe61a629

によると、
 Windows環境(と、Windowsホストの共有フォルダにVagrantなどからnpmを実行した場合)では、
 npm installで以下のエラーが発生することがある。
…だそうです。

自分の環境は、Windows+Virtualbox+Vagrantなのでまんま同じシチュエーションだった。。。

やること

npm install [モジュール名] --no-bin-links
という感じで末尾にオプションを作る

実際は↓↓な感じ。twitモジュールをインストールするときはこうする。

$ npm install twit --no-bin-links
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node.jsをインストールしてurl指定のファイルをダウンロードする

前提条件

 CentOS6.5
 node.js v0.12.4 ← これをインストールする

手順

  1. node.jsのインストール
  2. sudoコマンド実行時のパスを普段のユーザのパスと同等にしてやる
  3. プログラム作成
  4. 実行

1.node.jsのインストール

CentOSにsshログインして以下のコマンド実行。
実は一度インストールした後にコマンドの再確認的な意味合いでやったので
already installedとか出てるけど、そこは気にしないことにする

[vagrant@localhost ~]$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.3/install.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7149  100  7149    0     0  10538      0 --:--:-- --:--:-- --:--:-- 25084
=> Downloading nvm from git to '/home/vagrant/.nvm'
=> fatal: destination path '/home/vagrant/.nvm' already exists and is not an empty directory.
[vagrant@localhost ~]$ nvm install v0.12.4
v0.12.4 is already installed.
Now using node v0.12.4 (npm v2.10.1)
[vagrant@localhost ~]$ nvm alias default v0.12.4
default -> v0.12.4
[vagrant@localhost ~]$ node -v
v0.12.4
[vagrant@localhost ~]$

2. sudoコマンド実行時のパスを普段のユーザのパスと同等にしてやる

nvmを利用してNode.jsをインストールした場合、sudoコマンドを利用した時に
npmやnodeコマンドが利用できないためvisudoを使って利用できるようにする

$sudo visudo

テキストファイルの編集画面に切り替わるので以下のように編集する

Defaults env_reset
↓↓
Defaults !env_reset

# Defaults env_keep += "HOME"
↓↓
Defaults env_keep += "HOME"

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
↓↓
# Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

3. プログラム作成

以下のプログラムを作成する。ミニサイズなので全文おいとく。
拡張子は"js"

/home/vagrant/src/ch02/01-download/download-node.js
// urlにあるファイルを savepath にダウンロードする

// ダウンロード元URLの指定
var url = "http://kujirahand.com"

//保存先のパスを指定
var savepath = "test.html"

// 利用モジュールの取り込み
var http = require('http'); // HTTPのモジュール
var fs = require('fs');     // ファイル関連モジュール

// 出力先を指定
var outfile = fs.createWriteStream(savepath);

// 非同期でURLからファイルをダウンロード
http.get(url, function(res) {
    res.pipe(outfile);
    res.on('end', function (){
        outfile.close();
        console.log("ok");
    });
});

4.実行する

jsのファイルのある場所まで移動してnodeコマンド実行。
プログラムのつくりの問題だけど"ok"の出力があれば無事成功。

[vagrant@localhost 01-download]$ pwd
/home/vagrant/src/ch02/01-download
[vagrant@localhost 01-download]$ node download-node.js
ok

結果確認

同フォルダにtest.htmlができているので内容チェックして確認

[vagrant@localhost 01-download]$ ls
download-node.js  test.html
[vagrant@localhost 01-download]$ cat test.html
<html><body><a href="https://kujirahand.com/wiki/index.php">kujirahand.com</a><br></body></html>[vagrant@localhost 01-download]$

おわりに

インストールしてしまえば結構さらっと終わった
javascriptでこんなに作りこんだことないから
ちょっと慌てるけど徐々に慣れていけばいいかなと。

~おしまい~

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

SendGrid,Heroku,Gmailを使って無料で特定のメールだけをSlackチャンネルに転送する

はじめに

今までZappierとgmailを使って特定のメールをSlackチャンネルに転送をしていました。
Zappierは設定がとっても楽チンで非常に良かったんですが、
無料プランだと1月当たり100通しか転送できず別の方法を考えることにしました。

Slackも無料プランのためEmailアドオンが使うことができず、
それでも無料でチャンネルにメール転送したいと思い実際にやってみました。
(個人アカウントへの転送はSlackが無料プランでもメールアドレス発行出来るので出来ます)

本記事での目標

Gmailで件名に【TEST】が入っているメールを受け取ったら、
Slackのテストチャンネルに、送信元、件名、本文が自動で投稿されるようにする。

目次

今回使用するもの、サービス

  • SendGrid(Parse Webhook) : メール受け取り、Herokuに用意したAPIにPOSTする
  • Heroku(Node, Express) : 受け取ったメールをパース、整形し、Slackのincomig-webhookにPOSTする
  • freenom : 無料ドメイン取得、Parse Webhookを利用するため必要
  • gmail : メールをフィルタリングし、Slackに送りたいメールだけ転送する
  • Slack : Incoming Webhookでメール内容受け取り、任意チャンネルに投稿する

概要図

summary.png

手順

※各サービスのアカウント作成とfreenomでのドメイン取得方法に関しては割愛します。

※今回用に事前にfreenomで以下ドメインを取得しました。
2019-10-06_21h45_14.png

SendGrid : Domain Authentication設定

SendGridでメールを受け取るためのドメインの設定をします。

SendGrid管理画面からSender Authenticationをクリック
2019-10-06_21h41_18.png

Authentication Your Domainをクリック
2019-10-06_21h41_55.png

Nextをクリック
2019-10-06_21h44_09.png

Domain You Send Fromに取得したドメインを入力しNextをクリック
2019-10-06_21h45_36.png

ここまで来たら以下画像のように3件のCNAMEレコードが表示されるのでfreenomで追加します。
2019-10-06_21h46_12.png

CNAMEレコード追加
2019-10-08_16h34_56.png

SendGridでVerifyをクリックし3件全てVerifiedになったらOKです。
※注意※ドメイン取得から使用できるようになるまで最大3日程度かかる場合があります。
2019-10-08_16h40_36.png

Slack : Incoming Webhookの設定

チャンネルにIncoming Webhookアプリを追加、Webhook URLを取得します。

2019-10-08_16h45_53.png

2019-10-08_16h46_22.png

2019-10-08_16h46_49.png

2019-10-08_16h47_19.png

Webhook URLをゲット☆
2019-10-08_16h48_21.png

プログラム作成

※nodeは10.13.0を使用しています。

適当なディレクトリを作成し、必要モジュールをインストール

  • express : Webアプリケーションフレームワーク
  • multer : メールがmultipart/form-data形式で飛んでくるため使用
  • axios : Incoming WebhookへPOSTするため使用
  • html-to-text : HTML形式メール対応のため使用
$ mkdir test
$ cd test
$ npm -y init
$ npm i --save express multer axios html-to-text
$ touch index.js

プログラム本体:index.js

index.js
const multer = require("multer");
const axios = require("axios");
const htmlToText = require("html-to-text");
const app = require("express")();

app.set("port", process.env.PORT || 3000);

const webhookUrl =
  "https://hooks.slack.com/services/*********/*********/**********************"; // 各自webhookUrlを設定ください

app.post("/", multer().any(), (req, res) => {
  (async () => {
    try {
      await axios.post(webhookUrl, {
        text: `
From : ${req.body.from}
Subject : ${req.body.subject}
Body :
${req.body.text || htmlToText.fromString(req.body.html)}
`
      });
      res.status(200).send({ success: true });
    } catch (e) {
      console.error(e);
      res.status(500).send({
        success: false,
        error: e
      });
    }
  })();
});

app.listen(app.get("port"), () => {
  console.log(`Express server listening on port ${app.get("port")}`);
});

Herokuデプロイ

※Heroku CLIをインストールしておいてください(https://devcenter.heroku.com/articles/heroku-cli)

Heroku上で空のアプリを用意しておいてください。
今回はアプリ名takahirosato-test-appで作成しました。

login

$ heroku login

さっき作ったtestディレクトリ下で以下実行

$ git init
$ heroku git:remote -a takahirosato-test-app

node_modulesをignore

$ echo "/node_modules/" > .gitignore

Procfile作成

$ echo "web: node index.js" > Procfile

commit & push

$ git add .
$ git commit -am "make it better"
$ git push heroku master

エラーがでなければオッケイ☆

SendGrid : Inbound Parse設定

SendGrid管理画面からInbound Parseをクリック

2019-10-08_17h41_38.png

Add Host & URLをクリック
2019-10-08_17h44_16.png

こんな感じで設定
2019-10-08_17h45_56.png

ここまでで、とりあえずem8892.takahirosato.tkに送られるメールは全てSlackのテストチャンネルに転送されるようになりました。

↓こんな感じで届きます。
2019-10-08_17h51_13.png

Gmail : フィルタリング & 転送

Gmailで受け取ったメールから特定のメールだけを転送するよう設定します。

Gmailの設定からメール転送とPOP/IMAPをクリック

2019-10-08_17h57_57.png

転送先アドレスを追加をクリックしアドレス入力
※@の前は何でも良いです
2019-10-08_17h55_44.png

続行
2019-10-08_17h54_53.png

確認コードがSlackに届きます

2019-10-08_18h01_17.png

確認コードを入力して転送先アドレス設定完了

2019-10-08_18h02_53.png

新規フィルタ作成
検索フォームの▼をクリック
2019-10-08_18h07_21.png

含むに【TEST】を入力しフィルタを作成をクリック
2019-10-08_18h07_47.png

次のアドレスに転送するにチェックを入れ、先程登録したアドレスを設定しフィルタを作成をクリック
2019-10-08_18h08_16.png

ここまでで、このGmailアカウントに送られたメールの内、件名に【TEST】が含まれるものだけがSlackのテストチャンネルに送られるようになりました。

めでたい

終わりに

実際に職場のメールとSlackで2ヶ月ほど使用しましたが、Herokuの1月当たりの無料使用可能時間(550時間)の内、数十時間程度しか使用してなかったので、Zappierと比べてかなり余裕ありそうです。
また、今回はSlackへの転送でしたが、SendGridとHerokuの組み合わせはかなり色々できそうだなと思いました。
添付ファイルも受け取れるので、添付Excelの中身を見てSlackに報告なんてこともやってます。
GASにAPI作ってスプレッドシートに書き込むみたいなのも楽しそう。

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

【Node.js】指定したディレクトリ以下のファイル群をコピーする

指定したディレクトリ以下のファイルをコピーする

指定したでディレクトリ配下のファイルをコピーし、
コピー先にファイルがない場合にのみコピーを行う処理を行うモジュールが
必要であったため自作したものを備忘録としてあげておきます。

また、取得する関数の紹介ばかりで、
同期処理など含めておらず実用的でない記事が多かったため、
この記事を書きました。

記事を読むために

  • node npm の環境構築が可能
  • ES6 が理解できる
  • async await (同期処理/非同期処理)を理解できる

コード

まずfsモジュールのreaddirSync()を用いて該当ディレクトリ配下にある、
ディレクトリ、またはファイル名を取得する処理を書いていきます。
readdir():非同期処理
readdirSync(): 同期処理
これらを用いることで引数に渡したディレクトリ配下の
ディレクトリ名やファイル名を取得することができます。

関数の処理が非同期であると戻り値が担保されないため、
async awaitとthen()を利用します。

import fs from 'fs'

const getFileNameList = async (originFilePath) => {
  // fileListがreturnされるまで待機
  return await fs.readdirSync(originFilePath, (err, fileList) => {
     if (err) throw err
     return fileList
  })
}

次にfsモジュールのcopyFileSync()を利用し、
取得したファイル群を指定したディレクトリ配下にコピーしていきます。

import fs from 'fs'
import path from 'path'

const copyFilesToDir = (originDir, copyDir) => {
  getFileNameList(path.resolve(originDir) + '/')
  .then(list => { // 処理完了後に処理を実行し戻り値を担保
    const fileNameList = list.slice()
    fileNameList.forEach((fileName) => {
      try {
        // fs.constants.COPYFILE_EXCLをオプションに設定
        // コピー先に同名ファイルが存在した場合に例外を出す
        // 指定しない場合は上書き
        fs.copyFileSync(
          path.resolve(copyDir + fileName), 
          path.resolve(originDir + fileName), 
          fs.constants.COPYFILE_EXCL
        )
        console.log('copied:' + path.resolve(originDir + fileName))
      } catch(err) {
        // ファイルがすでに存在する場合 EEXIST
        // ディレクトリが存在しない場合 ENOENT
        console.log(err)
      }
    })
  })
}

汎用的にしたつもりですので、
カスタムなどして利用してみてもいいかもしれません。

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

YarnやNPMでscriptsを実行する際に、コマンド名がわからずにpackage.jsonを確認する人へ

package.jsonに定義しているstartやtestは覚えていますが、自分で新たに定義したscriptsの名称はしばらく実行していないと忘れてしまいます。

yarn run or npm runと実行するだけでscriptsの一覧が見れます。
yarnに至っては実行後にコマンドの入力を求めてくれます。

# yarnで実行した場合
$ yarn run 
   - build
      react-scripts-ts build
   - eject
      react-scripts-ts eject
   - start
      react-scripts-ts start
question Which command would you like to run?:

yarn runyarn run xxxとして使うコマンドとして覚えていると、気づかない機能でした :sweat:

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

Node.jsのコンソールから入力サンプル

はじめに

Node.jsにおいてコンソール(ターミナル)から値を入力するサンプルを掲載します。
例題として、基礎代謝量の計算例を示します。
1日の必要なカロリーを計算して、ダイエットにお役立てください。

前提

  • OS : Windows7以上
  • PoweShellのターミナルで実行
  • VSCodeでコード編集
  • node.js環境構築済み

基礎代謝量とは

生命を維持するために必要なエネルギー量を基礎代謝量(BMR)といいます。
ハリス・ベネディクト方程式(改良版)を使って基礎代謝量を計算します。
男性: 13.397×体重kg+4.799×身長cm−5.677×年齢+88.362
女性: 9.247×体重kg+3.098×身長cm−4.33×年齢+447.593

bmr.js

/**
 * 基礎代謝量(BMR)計算
 * @param {int} sex           - 性別 男=0 女=1
 * @param {float} weight      - 体重
 * @param {float} hight       - 身長 
 * @param {int} age           - 年齢
 */
const bmr = (sex,weight,hight,age) => {
    if (sex == 0 ) {
        var kcal = 13.397 * weight + 4.799 * hight - 5.677 * age + 88.362;
    } else {
        var kcal = 9.247 * weight + 3.098 * hight - 4.33 * age + 447.593;
    }
    return kcal;
}

/**
 * コンソール出力メッセージ
 * @param {int} index         - メッセージインデックス
 */
const outmsg = (index) => {
    var msg = '';
    switch (index) {
        case 0:
            msg = "性別"
            break;
        case 1:
            msg = "体重 Kg"
            break;
        case 2:
            msg = "身長 cm"
            break;
        case 3:
            msg = "年齢"
            break;
        default:
            msg = "???"
            break;
    }
    return msg;
}

var count = 0;             // メッセージカウンター
var msg = '';              // メッセージ
var buf = [];              // 一時バッファ 

var standard_input = process.stdin;

standard_input.setEncoding('utf-8');

console.log("性別 男性:0 女性:1");

standard_input.on('data', function (data) {
    var msg = outmsg(count);
    console.log(msg + " = "+ data);
    buf.push(data);
    count++;
    if (count == 4 ) {
        console.log("基礎代謝量 Kcal = " + bmr(buf[0],buf[1],buf[2],buf[3]));
        process.exit();
    }
    var msg = outmsg(count);
    console.log(msg);
});

説明

  • 関数 bmr 性別,体重,身長,年齢を引数として、基礎代謝量を返却します。
  • 関数 outmsg インデックスを引数として、対応するメッセージを返却します。
  • 標準入力はprocess.stdinでハンドルします。ハンドルはstamdard_inputで定義。
  • 標準入力のonイベントで入力をトラップします。
  • onイベントで入力した結果のdataをカウント順にバッファリングします。
  • カウンタが4になったら、bmr関数へバッファリングした値を引数として呼びだします。
  • bmr関数の返却値、つまり基礎代謝量を出力します。

実行方法

node bmr.js

実行結果

性別 男性:0 女性:1
0
性別 = 0

体重 Kg
69
体重 Kg = 69

身長 cm
168
身長 cm = 168

年齢
36
年齢 = 36

基礎代謝量 Kcal = 1614.615

まとめ

htmlの画面を作るまでもない、単純入力をコンソールから入力する場合、
process.stdinはonイベントでprocess.exitするまでコンソールからの入力を取得できます。
このやりかたをマスターすれば、色々応用できます。
ネットで検索すると、コンソール入力の色々な方法を見いだせます。
今回のやり方も参考にしてください。

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

WEBフロントエンドはじめにシンプルに覚える事 (NodeJS)

関連技術とポイント

とりあえずGitHub

なんでもOSSな時代、gitで人のソースをとにかく読んで書き方を参考にするべし。

シンプルどころで言えば、こちらを参考としてみるのも有りかもしれないUnderscore日本語リファレンス

データを扱う参考になるし、いたってシンプルな書き方をしている。

フレームワーク

なくても動かせるようだが、基本使うもの

- Express

シンプルなよく使われるフレームワーク

他にも有名どころとして、「Meteor」や「Sails」などが挙げられる。

基本や関連(フロントサイド多め)

非同期処理

ちょっと理解が難しいですが、ある関数が返す結果が欲しいんだけど、書き方によっては結果が返ってくるのを待たずに次の処理に移る状態。

多分DB連携とか、データをどこかから取得してくる時にぶつかる壁だろう。asyncとかpromiseとかコールバックとかネストとか書き方がそれぞれあるけど、最初は読みやすいコードや、似ているコードのやつとかを書いてみると、理解を深めて行けると思う。

※ 書き方が多いだけで正直そんなに難しい話しじゃない

JSフレームワーク

JQuery,React,Angular,Vue等々あるが、

JQueryと後の3つはかなりの別物である。 基本的にJQueryは簡単に慣れると思うし使いやすいと感じる。 後の3つは概念を理解するのが少し大変であるが、使用できた場合の恩恵が強いと思う。(高速,再利用,コーディング量)
vueなら比較的簡単に覚えられる気がするので、入り口に向いているかもしれない。

コーディング

JSの事

まずECMAScript2015のこと。 ES5とES6について理解が必要。
簡単に言えば古いブラウザとかは新しい書き方すると動かないよって話し。※念の為頭の片隅にでも、できたらbabelとトランスパイルとかも、、

基本的にはES6で書いていればいいと思う。

○ざっと簡単な所

- 変数宣言: letvarconst

- アロー関数: => 関数定義をシンプルに

- テンプレート文字列? バッククォート ※これ便利

const URL = 'https://hogehoge'
const HOGA_URL = `${URL}/hogahoga/`

コーディングのこと

書くことが慣れてきたら、eslintで書き方を統一させてみる。

デザイン

cssフレームワークを導入することにより、ある程度のデザインをおまかせしよう。

BootstrapやSemanticUIなど有名どころでアイコンやボタンなどは簡単にそれらしく出来る。

パッケージマネージャ(yarn・npm)

パッケージマネージャーは、npmだけでは無い。(だよね)

yarnの方が早いよって事だけ知っていれば大丈夫。

ビルドやwebpack babelのこと

古いブラウザで使ってもらうためトランスパイルや、早く表示するために圧縮したりをbabelやwebpack使ってやるよって話し。※なんとなく単語だけ知っていればいいかなって感じです

CDN(コンテンツ・デリバリ・ネットワーク)

ソースとか画像とかを、見てる人の近くのCDNサーバから取ってこよって技術。

JQueryとかBootstrapとかこんな感じにHTMLに記述すれば、読み込めるよって事。

※ちなみにCDN市場最大の会社は アカマイ(akamai)

 <!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Bootstrapの基本テンプレート</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <h1>Bootstrapの基本テンプレート</h1>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
    </body>
</html>

サーバーレス(クラウド)

もはやNodeJS関係ないが、マイクロサービスやRestAPIの事は抑えておく必要がある。

簡単な説明だと、フロントに静的webサイト等を設け、バックエンドにサーバーレス構成を挟むような形を取る。そうする事でセキュリティ・コスト・運用を最適化する事が出来るようだ。
- 静的webサイトホスティング・・・AWS/S3, gitHub, Firebase

- サーバーレス・・・AWS/lambda, IBM/Functions

※このサーバーレスにNode,jsがよく使われたりする。

テスト

jestやmochaを使ってテストをしよう。

どうやらjestがいいらしい。。

基本や便利npmモジュール

  • request

    どこかのRestAPI叩きたい時に使う

  • async

    非同期処理をシンプル化

  • moment

    時間や日付系

  • body-parser

    リクエストのbodyをパースする(POSTでJSONとかを送りたい場合に使った気がする)

  • Underscore

    関数や配列、オブジェクトを扱う際に発生する処理をシンプル化

  • dotenv

    環境変数 .envとか

  • helmet

    アプリケーション保護

  • passport

    認証ライブラリ

  • forever

    デーモン化

  • fs

    ファイル読み込みとか出力とか

  • データベース接続系

    mysql,mongodb...etc

ツール

  • VSコード(Visual Studio Code )

    協力コードエディタ、Gitやdockerなど連携が容易でかなり軽い。 最強だと思っている。

  • GitLab
    無料だし。 静的Webサイトをホスト出来る。

さいごに

覚える事が多い世界だが、複雑で面白いと思う。

クラウドが出てきて、確実に昔の世代より簡単にモノが作れるようになっていると思う。

そんな時代に何か新しいサービスを発信したいですね。

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

シンプルNodeJS理解 実践

はじめに

備忘録および、これからNodeJS等を体系的にシンプルに理解したい方向けに簡単に書いてみようと思う。

NodeJSとは

サーバーで動くJavaScript環境のこと。

言語がフロントエンド・バックエンド同じような書き方で作成することができ、学習コストが低い。

特徴 メリット

  • スクリプト言語であること(インタプリタ型)・・・コンパイルがいらない=機械語に変換する必要がないので簡単(めんどくさくない)
  • 軽量かんたん・・・軽量で簡単に使えます。。
  • リアルタイム処理に向いている(ゲームとかチャットボットとか向いてるって)

npmとNode起動の所

パッケージ管理npmについて

ここから簡単にNodeの使用について説明していこうと思う。

初めての人はインストールして、実践しながら見てもらえればと思う。 ※推奨版を推奨
NodeJSインストール

node -v ・・・バージョン確認

npmとは

まずNodeをインストールをするとnpmも一緒にインストールされている事がわかる。

npm -v ・・・確認

これは先人たちの技術の結晶であるパッケージ、npmはそのマネージャーであり、コマンド一発でその恩恵を受けることができる。

  • 簡単にnpmでできること
パッケージインストール
テスト実行
アプリ起動
バージョン管理

Nodeではpackage.jsonファイルで内容を管理されている。

理解するために以下を実施
1: 準備

// 必要なモジュールをインストール(gオプションはグローバル(PC)つけないとローカル(ディレクトリ)へって意味)
npm install -g express
npm install -g express-generator

2: 空フォルダでプロジェクト作成

express sampleapp

sampleappのフォルダが作成され、実行に必要なファイルが作られている。

.
├── app.js //実行ファイル
├── bin
│   └── www
├── package.json //※※※これ※※※
├── public //フロントサイド側 JS等
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes //サーバーサイド側 NodeJS
│   ├── index.js
│   └── users.js
└── views //サーバーサイド側HTMLみたいな
    ├── error.jade
    ├── index.jade
    └── layout.jade

package.jsonの中身を簡単にご説明

scriptsに書かれている事がnpmで実行できること、ここではnpm startコマンドで実行される内容が書いてある。

scriptsにはtestとかlintとかビルド系とかを書いたり、環境変数をつけたり等、色々実行コマンドを書くことが出来る。

dependenciesではモジュールの名前を書く

何のパッケージなのかは省略。基本パッケージ名 npm のように調べればすぐ見つかる。

横の数字はパッケージのバージョン。

※たまにバージョンで起動出来ないこととかある(Nodeのバージョンとか、一緒に開発しててとか)

package.json
{
  "name": "sampleapp",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "jade": "~1.11.0",
    "morgan": "~1.9.0"
  }
}

Node起動

sampleapp起動

モジュールをインストールする。
ディレクトリにある、package.jsonを見て必要なモジュールをnode_modulesフォルダを作成して入れてくれる。

npm install

完了したらアプリ起動してみよう

npm start
//またはstartに記載されていた
node ./bin/www

起動した状態で以下のURLにアクセスする。

http://localhost:3000/

ここまでのステップで難しく思えた人はいないだろう。

ここから、応用に移っていきたいと思う。

Node起動をもう少しシンプルに掘り下げる

単体起動とnpm起動

hello.js
function Hello(hi) {
  console.log(hi)
}

function main(){
  Hello('Hello, World')
}

main()

上で作成したsampleappのフォルダで問題ないので、このhello.jsを作って単体で実行する。

※かなり適当なシンプルさだが、こちらで理解していただけると嬉しい。

実行

node hello.js

実行するとコンソールにHello, Worldが表示されただろうか。
このように単体でも簡単に起動やテスト等の確認をすることが出来る。 たまに簡単なツールを作りたい場合はこのように切り離して使用するような事もする。

次はこのHello, Worldを表示するだけのやつをnpmで実行したいと思う。
statの部分を以下に変更してnpm startで実行する。

package.json
{
  "name": "sampleapp",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node hello"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "jade": "~1.11.0",
    "morgan": "~1.9.0"
  }
}

ここまでで、起動部分のNodeとnpmの関連性が把握出来てくれれば嬉しい。

npmモジュールを追加とhtml+Node

  1. indexファイル作成
  • sampleappのフォルダに下の超シンプルindex.jsを作成する。
    ※基本app.jsかindex.jsかserver.jsがメインのファイルだと思って貰えればよいです。
index.js
// 使うモジュールの宣言
var express = require('express');
var app = express();
var cfenv = require('cfenv');

// 静的なフォルダの場所を宣言
app.use(express.static(__dirname + '/public'));

// このアプリの情報をget
var appEnv = cfenv.getAppEnv();

// URL(get)の処理、この場合上で宣言したフォルダのindex.htmlをレンダリングしている
app.get('/', function(req, res, next) {
  // res.send('ページが表示されました!'); こんな送り方もある。
  res.render('index', {});
});

// ポートとか勝手に選んで開始してくれる
// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
  // print a message when the server starts listening
  console.log("server starting on " + appEnv.url);
});
  • public直下に単純なHTMLのindex.htmlを作成
index.html
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/css/index.css">
</head>

<body>
    <h1>hello world</h1>
</body>

</html>
  1. 足りないモジュールを追加
    新しく使うcfenvを追加する
npm install cfenv

package.jsonにcfenvが追加されただろうか。 されていない場合は-sオプションをつけて追加しよう。

※ なかったら起動の時に怒られて分かるので問題はあまり無いかもしれないが、

node indexかpackage.jsonのstart値を変更してnpm start

今度はコンソールにURLが表示されると思うのでserver starting on http://localhost:****、そのURLへ接続してhello world画面の確認。

まとめ

難しい話を無しにすると、ここまで出来れば後はカスタマイズしていくだけとなる。

フロント HTML+Javascript+CSS

バック  Node.js(get,post等のリクエストを)

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

AmazonAPIGatewayのLambdaAuthorizer(Node.js)でJWTを検証する(LambdaをServerlessFrameworkでデプロイする)

はじめに

AWSでAPIを構築する際、必ずといっていいほど登場するのがAmazonAPIGatewayですよね。
APIGatewayの認証ってどうされてますか?

  • 別に必要ないからしてない
  • APIKeyを使っている
  • CognitoをAuthorizerにしてトークンの検証をする
  • LambdaAuthorizerでトークンの検証をする

など色々なパターンがあると思います。今回は最後に書いた「LambdaAuthorizerでトークンの検証をする」について説明して、その構成をServerlessFrameworkでデプロイするところまでを書いていきます。

登場人物

JSON Web Token (JWT)

JSONをベースとしたトークン。
「ヘッダー / ペイロード / 署名」といった3つのセクションから構成されていて、署名はヘッダーとペイロードのハッシュされた組み合わせです。
hogehoge.foofoofoo.barbarbarbar のような文字列です。

ServerlessFramework

Serverlessなアーキテクチャを構築するためのフレームワーク。AWSだけじゃなくAzureやGCPなど他のクラウドサービスでも利用することができる。
詳しくは 公式ページ で確認してみてください。

構成

image.png

Lambda Authorizer

JWTの検証をLambda内で行っていきます。
今回はNode.js(TypeScript)での例を書いています。

authorizer.ts
import { Handler, Context, Callback, CustomAuthorizerEvent } from "aws-lambda"
import * as jsonwebtoken from "jsonwebtoken"
import jwkToPem from "jwk-to-pem"
import jwk from "./jwk"
const pem = jwkToPem(jwk as any)

export const handler: Handler = async (
  event: CustomAuthorizerEvent,
  _context: Context,
  callback: Callback
): Promise<any> => {
  console.log(JSON.stringify(event))

  jsonwebtoken.verify(
    event.authorizationToken,
    pem,
    {
      algorithms: ["RS256"]
    },
    (err: jsonwebtoken.VerifyErrors, decodedToken: object | string) => {
      if (err) {
        callback(null, {
          principalId: 1,
          policyDocument: {
            Version: "2012-10-17",
            Statement: [
              {
                Action: "execute-api:Invoke",
                Effect: "Deny",
                Resource: event.methodArn
              }
            ]
          },
          context: {
            messagge: "Custom Error Message"
          }
        })
      } else {
        console.log(decodedToken)
        callback(null, {
          principalId: 1,
          policyDocument: {
            Version: "2012-10-17",
            Statement: [
              {
                Action: "execute-api:Invoke",
                Effect: "Allow",
                Resource: event.methodArn
              }
            ]
          },
          context: {
            messagge: "Custom Allow Message"
          }
        })
      }
    }
  )
}

解説

JWT検証で使うモジュールをインストール

$ yarn add jsonwebtoken jwk-to-pem
$ yarn add -D @types/jsonwebtoken @types/jwk-to-pem

jsonwebtoken がJWTトークンの検証をするライブラリです。
jwt-to-pem はJWTトークンを検証するための JSON Web Key (JWK) をpem形式に変換するライブラリです。

JWT検証

jsonwebtokenverify というメソッドを使って検証をします。

jsonwebtoken.verify(
  event.authorizationToken, //  requestHeader内のToken
  pem, // JWKから生成したpem
  { algorithms: ["RS256"] },
  (err: jsonwebtoken.VerifyErrors, decodedToken: object | string) =>  {}
)

( Cognitoを使っている場合のJWK取得 )

Cognitoが発行したJWTの検証に使うJWKは https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json から取得する事ができます。
そのJSONを何かしらの方法でimportしてください。今回の例はTSファイルにしてimportしています。
また上記のURLからJWKを取得すると2つKeyが入っていますが、最初の一つを利用すればいいです。

jwk.ts
export default {
  alg: "RS256",
  e: "XXXX",
  kid: "xxxxxxxxxxxxxx",
  kty: "RSA",
  n: "xxxxxxxxxxxxxx",
  use: "sig"
}

検証後の処理

CallbackでAPIGatewayにレスポンスを返して行きます。
Statement内のEffectが AllowDeny かでその後の処理を判断させます。

// 成功時
callback(null, {
  principalId: 1,
  policyDocument: {
    Version: "2012-10-17",
    Statement: [
      {
        Action: "execute-api:Invoke",
        Effect: "Allow",
        Resource: event.methodArn
      }
    ]
  },
  context: {
    messagge: "Custom Allow Message"
  }
})

// 失敗時
callback(null, {
  principalId: 1,
  policyDocument: {
    Version: "2012-10-17",
    Statement: [
      {
        Action: "execute-api:Invoke",
        Effect: "Deny",
        Resource: event.methodArn
      }
    ]
  },
  context: {
    messagge: "Custom Error Message"
  }
})

ServerlessFrameworkでデプロイする

プロジェクト作成

LambdaのソースコードをTypeScriptで書いているので、TypeScript用のテンプレートを使ってプロジェクトを作成します。

$ npx -p serverless sls create -t aws-nodejs-typescript -p example-serverless-ts

serverless.yml

AuthorizerをつけたいAPIGatewayをイベントとするfunctionの中に authorizer を追加していきます。

  • name はAuthorizerとなるLambdaです。同じyml内で定義している場合はこの name で参照することができます。外部でデプロイされているLambdaをAuthorizerにしたい場合は、 arn に対してそのLambdaのARNを指定します。
  • identitySource はTokenをどこを参照すれば習得できるのかという設定です。この場合はリクエストヘッダー内の Authorization を参照するようになっています。
  • type はAuthorizerとなるLambdaのeventに渡される値の設定です。単純にTokenを取得したいだけなら token がおすすめです。リクエストの内容をすべて取得したい場合は request を指定します。
authorizer:
  name: authorizer
  identitySource: method.request.header.Authorization
  type: token

全体としてはこんな感じになります。

serverless.yml
service:
  name: lambdda-node-ts

plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs10.x
  region: ap-northeast-1

functions:
  authorizer:
    handler: authorizer.handler
  index:
    handler: index.handler
    events:
      - http:
          method: get
          path: hello
          cors: true
          authorizer:
            name: authorizer
            identitySource: method.request.header.Authorization
            type: token

あとは sls deploy でデプロイすれば作業は完了です。

さいごに

今回はLambdaAuthorizerを紹介しました。
トークンの検証にLamdbaを使うことで、トークンの検証以外にもAPIに対するリクエストのログを取ることができたり、怪しいリクエストが来た場合にメール送信などカスタマイズすることができます。
Lambdaを挟むことでかなりできることの幅が広がります!
ではまた!!

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

Nodeでスプシデータをcsv→jsonに変換して、条件に合う要素をリスト化する

スプシの大規模データを整理するときに楽になったので備忘録として残します。

この記事で扱うデータはフィクションです。実在の人物や団体などとは関係ありません。

※この記事のダミーデータはこちらからお借りしています。
テストデータ・ジェネレータ

スクリーンショット 2019-10-08 12.12.57.png
この記事の目標 : 住所が大阪の人をリストアップしてテキストデータに書き出す!

使用環境

OS: macOS
Node: v12.2.0
npm: 6.9.0

パッケージのインストール

Nodeとnpmの環境設定は省略しています。
まずはターミナルから適当なプロジェクトフォルダに必要なパッケージをインストールします。

$npm init -y
$npm i -D fs csvtojson js-beautify

csvtojsonがコンバータ

csv -> json の変換

スプシからcsvをダウンロード
スクリーンショット 2019-10-08 11.59.56.png

変換スクリプトを書く

csvjson_converter.js
let fs   = require('fs');
let csv  = require('csvtojson');
let beautify = require('js-beautify').js;

let csvFile = './checksheet.csv';


csv().fromFile(csvFile).then((jsonData)=>{
  fs.writeFile('checksheet.json', beautify(JSON.stringify(jsonData),{}), function(err) {
    if (err) console.log('error', err);
  });
});

スプシからダウンロードした[checksheet.csv]を[checksheet.json]に変換して
beautifyでインデントを追加して書き出す命令を記述。

$ node csvjson_converter.js

ターミナルからスクリプトを実行
スクリーンショット 2019-10-08 12.26.18.png
こんな感じのjsonが書き出されました。

必要な要素をリスト化してテキストデータに保存する。

条件を絞って、[.txt]データに書き出します。

checkitem.js
let fs   = require('fs');

// check item
let json = JSON.parse(fs.readFileSync("checksheet.json"));
let targetItem = [];
json.forEach(function(value,index){
  if(value.住所.match(/大阪/)){
    // console.log(value.url);
    targetItem.push(value.名前+" : "+value.住所+"\n");
  }
});

fs.writeFile('大阪の人.txt',targetItem,function(err){
  let texts = fs.readFileSync('大阪の人.txt','utf-8');
  console.log(texts);
  fs.writeFile('大阪の人.txt',texts.replace(/\,/g,""),function(err){});
});

先ほど書き出した[checksheet.json]を読み込んで、[住所]の項目が[大阪]を含む値を判定。
条件に当てはまったデータを[大阪の人.txt]に書き出し。

$ node checkitem.js

ターミナルからスクリプトを実行

正しく出て来た。

スクリーンショット 2019-10-08 12.36.47.png

この記事で扱うデータはフィクションです。実在の人物や団体などとは関係ありませ

条件式の使い方次第で色々絞り込めます。
↓生年月日から20代を絞り込みの場合

checkitem.js
//if(value.住所.match(/大阪/)){
if(1998 >= value.生年月日.slice(0,4) && 1989 <= value.生年月日.slice(0,4)){

おわりに

スプシのフィルタ機能でカバーできない様な、痒いところに手が届いた気がしました。
スプシ1行目に空のデータがあると、自動で "field番号":[{値},{..}]が当て込まれるので注意です。

うまく書き換えて、ejsを使ったHTML書き出しにも使えそうです。

出典

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

Node-redでスマートハウス-Gravioで戸締り確認[3/3]

はじめに

夏になって、窓を開ける機会も多くなってきました。ただ、家を出るときに戸締りを確認するのは面倒ですよね。
また、出かけてから「あれ?窓ちゃんと閉めたか記憶がない!?」ってことありませんか?
今回は、家の窓がちゃんと閉まっているかをお知らせしてくれる玄関ランプを制作してみたいと思います。

やりたいこと

最終的にやりたいのは、窓に取り付けた窓センサーの情報をDBに格納しておき、玄関に人が来た時にLEDライトを赤or青に光らせるというものです。

 1.窓センサーで窓の鍵の開閉情報を取得
 2.開閉情報をmongoDBに格納
 3.人感センサーで玄関に人が来たことを検知
 4.LEDライトを赤or青に光らせて戸締り状況をお知らせ
図1.png

実現に向けた連載

やりたいことを実現するために、以下のように少しずつに記事を書いていきます。
 1回目:窓センサーの設定
 2回目:人感センサーの設定
 3回目:LEDライトの設定 ←この記事

3回目:LEDライトの設定

第3回目では、LEDライトを設定し、全ての窓が閉まっていたら「青色」、どこかの窓が開いていたら「赤色」にLEDライトが光るように設定します。また、ライトが点きっぱなしだと困るので、1分で消灯するようにします。

1.スマートリモコンの設定

今回使用するLEDライトは、IFTTTからの制御ができるものなのですが、IFTTT連携の不具合があるようで、現在は使えません。そこで今回は、すでに家に設置済みのsRemo-Rを使用してLEDライトを制御します。sRemo-Rの設定は以下の通りですが、詳細は割愛します。

 1.LEDライト付属のリモコンから赤外線信号をsRemo-Rに学習させる
  -点灯ボタン(No.61に割り当て)
  -消灯ボタン(No.62に割り当て)
  -赤色ボタン(No.63に割り当て)
  -青色ボタン(No.64に割り当て)
 2.sRemo-Rのマクロ機能で以下を設定
  -点灯→赤色に変更(No.71に割り当て)
  -点灯→青色に変更(No.72に割り当て)

2.sRemo-R APIアクセストークンの取得

sRemo-RはWeb APIに対応していて、WebAPIを叩くことでリモコン操作が可能です。node-redから操作するためにAPIアクセストークンを取得します。ここも詳細は割愛します。

 1.sRemo-Rのユーザサイトにログイン
 2.API用アクセストークン管理のメニューを選択
 3.APIサーバ名とAPIアクセストークンを取得

3.Node-redの設定

ここからはNode-redを使って、sRemo-RのWebAPIを叩く設定を行っていきます。

①Switchノードの設定
前回設定した「編集」ノードの右側に、Switchノードを追加し、以下のように設定します。
図1.png

②execノードの設定1
次に、execノードを追加し、ライトを青色に点灯するように設定します。この部分が今回のキーポイントです。

・uapi1.sremo.netの部分:上で取得したAPIサーバ名
・AAAAAAAAAAAの部分:sRemo識別子(どのsRemo-Rから送信するか)
・0-71の部分:「0-」は固定でその後に、上で設定したリモコン番号。今回は「71」。
・Bearer XXXXXXXXの部分:「Bearer 」は固定で、その後に上で取得したAPIアクセストークン

コマンド
curl https://uapi1.sremo.net/user_api/AAAAAAAAAAA/send_sig?sig=0-71 -H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

図2.png

③Switchノードの設定2
同様に、execノードをもう一つ追加し、ライトを「赤色」に点灯するように設定します。今回は「72」を設定します。

コマンド
curl https://uapi1.sremo.net/user_api/AAAAAAAAAAA/send_sig?sig=0-72 -H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

④execノードの設定
次に、Delayノードを追加し、待ち時間を1分に設定します。

⑤execノードの設定3
execノードをもう一つ追加し、ライトを「消灯」するように設定します。今回は「62」を設定します。

コマンド
curl https://uapi1.sremo.net/user_api/AAAAAAAAAAA/send_sig?sig=0-62 -H "Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

⑥ノードの接続
追加したノードを以下のように接続し、LEDライトを赤or青に点灯させ、1分待った後に消灯するように設定します。
図3.png

⑦Deploy
右上の「Deploy」ボタンを押し、設定したフローをデブロイしましょう。

⑧テスト
これで設定は完了です。人感センサーの前に立つと、窓の状態に合わせてLEDライトが青色もしくは赤色に点灯しましたか?

おわりに

今回は玄関に設置するLEDライトの設定を行い、sRemo-rを用いてLEDライトを青色もしくは赤色に点灯することをやってみました。本来は、IFTTT連携でスマートにやりたかったので、IFTTT連携の不具合が解消されたら、記事も更新したいと思います。

連載記事
 1回目:窓センサーの設定
 2回目:人感センサーの設定
 3回目:LEDライトの設定 ←この記事

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