Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all 8882 articles
Browse latest View live

toio準備

$
0
0

1) Node.js
nodist 0.9.1 //nodist は Node.js のバージョンを管理するツール。
npm -v 6.9.0

2) nobleインストール
nobleはNode.jsでBluetooth LEを扱うためのモジュールです。toioはnobleを使います。

a) Windows10にnobleをインストールする https://qiita.com/s_nkg/items/3f27328e108d7fa8d076
b) [Windowsでnpm installしてnode-gypでつまずいた時対処方法] https://qiita.com/AkihiroTakamura/items/25ba516f8ec624e66ee7


次のエラーがでるので"npm install -g node-gyp"をしておく
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.Cpp.Platform.targets(57,5): error MSB8020: The build t ools for v141 (Platform Toolset = 'v141') cannot be found. To build using the v141 build tools, please install v141 bui ld tools. Alternatively, you may upgrade to the current Visual Studio tools by selecting the Project menu or right-cli ck the solution, and then selecting "Retarget solution".

☆ python27の場所も教え解く
npm config set python C:\Python27\python.exe

☆ npm install noble 再実行するとOK

注意点:
・VS2015はV140、VS2017=V141です。
・Powershellを開発者モードで開く
・python27を指定しているか(pathではなくnpmコマンドで指定する)

VCTargetsPath=C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140

3) bluetooth ドライバ更新
デスクトップだとBlueToohドングルをつける必要あるので、準備してください。
image.png


WSL+Ubuntuの初期設定(インストールからGit/Node.js設定まで)

$
0
0

やりたいこと

WSLでUbuntuを動かす。

最低限の環境を構築する。

初期設定時に毎回調べるのは面倒なので、手順をまとめてメモしておく。

到達目標

  • Ubuntuの初期設定ができている
    • CUI/GUI環境ができている
  • Gitの初期設定ができている
    • GitHubにssh接続できる
  • Python3が動かせる
  • Node.jsが動かせる

環境

  • Microsoft Windows 1909 (OS ビルド 18363.535)
  • Ubuntu 20.04 LTS

手順

1. WSLの有効か

  1. [Windows + i]で設定メニューを開く
  2. [アプリ] → [アプリと機能] → [プログラムと機能] → [Windows の機能の有効化または無効化] の順にクリック
  3. 機能の一覧から、[WSL(Windows Subsystem for Linux)]にチェックをいれ、[OK]ボタンをクリック
  4. Windowsを再起動する

2. Ubuntuの入手

Microsoft StoreのUbuntuのページから、Ubuntuをインストールする。

Ubuntuには、16,18,20とバージョンがいくつかあるが、最新版の20をインストールした。

コマンドプロンプトなどでubuntuと打つと起動できる。または、wslでも起動できる。

wsl -lでインストールされているディストリビューションの一覧を確認できる(この時点ではUbuntuのみ。
wsl -d <ディストリビューション名>でディストリビューションを指定して起動させることができる。

3. Ubuntuの初期設定

3.1 ユーザ名とパスワード

初回起動時、ユーザ名とパスワードを決定する。

パスワードは、[sudo]コマンドを使う時に聞かれるので覚えておく。

3.2 リポジトリ変更

日本語のリポジトリを見に行くように変更する。

$ cd /etc/apt
$ sudo sed -i.bak -e "s/http:¥/¥/archive¥.ubuntu¥.com/http:¥/¥/jp¥.archive¥.ubuntu¥.com/g"
$ diff sources.list.bak sources.list

3.3 更新

$ sudo apt update
$ sudo apt upgrade

3.4 日本語環境設定

$ sudo apt install language-pack-ja
$ sudo update-locale LANG=ja_JP.UTF-8

一度Ubuntuを再起動する。

echo $LANGと入力し、ja-JP.UTF-8という出力が返ってくるか確認。

タイムゾーンを設定する。

$ sudo dpkg-reconfigure tzdata

dateコマンドの出力結果がjstになっているか確認。

3.5 マニュアルの日本語化

$ sudo apt install manpages-ja manpages-ja-dev

man lsなどmanコマンドの出力が日本語になっているか確認。

3.6 VcXsrvのインストール

WSLでGUIを扱うために、まずWindowsにVcXsrvをインストールする。

 Xサーバは、Windows OSで言えば、GUIのウィンドウや部品などを描画、管理したり、キーボードやマウスなどのデバイスを管理したりする部分だけを独立させたようなものと考えればよいだろう。Xのサーバとクライアント間はXプロトコルで通信しており、同一システム上になくても動作するし、Xサーバを実現するソフトウェアも、機種やアーキテクチャなどは問わない。
 Windows 10で利用できるXサーバソフトウェアは幾つかある。
VcXsrv: フリーのXサーバ

【引用元】 Tech TIPS:WSL上にXサーバをインストールしてGUIを実現する(VcXsrv編)

  1. VcXsrvのサイトからインストーラーをダウンロード
  2. インストーラーを起動して、デフォルト設定のままインストール
  3. デスクトップに[XLaunch]というショートカットがあるのでそれを起動
  4. すべてデフォルトのまま[次へ]を押し、[完了]を押す
  5. ファイアウォールの警告画面がでたら、[キャンセル]を押す(外部との通信は不要なため)

3.7 GUIツールのインストール

GUIツールを導入。WSLを起動し、下記コマンドを実行。

$ sudo apt install x11-apps x11-utils x11-xserver-utils dbus-x11
$ echo 'export DISPLAY=localhost:0.0' >> ~/.bash_profile
$ source ~/.bash_profile

最後に、xeyesコマンドが動作するか確認。

3.8 デスクトップの導入

GUIよ用の日本語フォントをインストールする。

$ sudo apt install fonts-ipafont

デスクトップをインストール。これには時間がかかる。

$ sudo apt install xfce4-terminal
$ sudo apt install xfce4-session
$ sudo apt install xfce4
$ export DISPLAY=:0.0
$ export LIBGL_ALWAYS_INDIRECT=1

最後に、startxfce4でデスクトップが起動するか確認。

4. Gitの設定

4.1 初期設定

下記コマンドを実行。最も必要なのは上の2行で、ユーザ名とメールアドレスを設定する。これがGitのログに刻まれる。

あとの設定は任意。エイリアスはお好きなように。

$ git config --global user.name "blindsoup"
$ git config --global user.email "@"
$ git config --global core.editor vim
// ファイル名の大文字小文字を検出
$ git config --global core.ignorecase false
// git status時にファイル名日本語が文字化けしないようになる
$ git config --global core.quotepath false
// 以降エイリアス
$ git config --global alias.br branch
$ git config --global alias.cm commit
$ git config --global alias.co checkout
$ git config --global alias.last 'log -1 HEAD'
$ git config --global alias.mr merge
$ git config --global alias.st status
$ git config --global alias.unstage 'reset HEAD --'

4.2 GitHubにssh接続する

4.2.1 鍵の作成

まず鍵を作成する。公開鍵暗号方式で秘密鍵と公開鍵の二つを生成。

$ cd ~/.ssh
$ ssh-keygen -t rsa -b 4096 -C "<your email>"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/<username>/.ssh/id_rsa): #ファイル名入力、デフォルトは[id_rsa]
Enter passphrase (empty for no passphrase):
Enter same passphrase again: 

デフォルトでは、[id_rsa](秘密鍵)と、id_rsa.pubのファイルが作成される。鍵を作成するたび、デフォルトファイル名で上書きされて行ってしまうため、ファイル名は変更しておくと良い。

chmod 600 <秘密鍵のファイル名>で、ファイルアクセス権を変更しておく。

4.2.2 ~/.ssh/configの設定

ssh経由でリモートサーバに接続する際に参照される設定ファイル。ここにユーザ名はポート番号、鍵の場所などを記載しておくと、コマンドタイプ時にファイル内容を参照して保管してくれる。

Gitの場合は以下を記載。

$ vim ~/.ssh/config

Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/id_git_rsa # 秘密鍵のファイルへのパスを記入
  User git

これも、$ chmod 600 configで、ファイルアクセス権を変更しておく。

4.2.3 GitHub側の設定

まず、下記を実行してクリップボードに公開鍵をコピーする。

$ clip.exe < <公開鍵のファイルへのパス>

次に、GitHubにログインし、[Settings] → [SSH and GPG keys] → [New SSH key]の順にクリック。

[Title] に鍵の識別子(任意の名前)、[Key]にコピーした公開鍵をペーストし、[Add SSH key]ボタンを押下。

WSLターミナルで書きを実行し、接続できるかを確認。

$ ssh -T git@github.com
Hi <username>! You've successfully authenticated, but GitHub does not provide shell access.

5. Pythonの設定

Python3系はデフォルトでインストールされている。確認してみる。

$ sudo apt list python3
python3/focal,now 3.8.2-0ubuntu2 amd64 [インストール済み、自動]

後は、pipが使えるようにしておく。

$ sudo apt install python3-pip -y

6. Node.jsの設定

6.1 NVMのセットアップ

もしすでにNodejsがインストールされている場合は削除する。

$ sudo apt remove --purge node

NVMをインストールする。
公式GitHubを参照。

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
$ source ~/.bashrc

.bashrcに環境変数追記の記述があるので、.bash_profileで読み込むようにしておく。

$ echo source ~/.bashrc >> ~/.bash_profile

NVMをアップデートする場合は↓

$ cd ~/.nvm
$ git pull origin master

6.2 node, npmのインストール

Node.jsの最新版をインストール。

$ nvm install --lts
$ node -v
v12.16.3
$ npm -v
6.14.4
$ nvm use v12.16.3
Now using node v12.16.3 (npm v6.14.4)

参考

React メモ

$
0
0

React.js

Reactの導入とメモ

環境構築

まずはNode.jsのインストール
次にnpmのインストール(yarnを使いたければインストール)

npmの場合
//Reactのプロジェクト作成 
$ npx create-react-app 作成したいディレクトリ名
yarnの場合
//Reactインストール 
$ yarn global add create-react-app
//Reactのプロジェクト作成
$ create-react-app 作成したいディレクトリ名
//yarnで起動
$yarn start
//npmで起動
$npm start

1. React.jsとは

Facebook社が公開したUI構築のためのjsライブラリ
全てのReactコンポーネントは、自己のprops に対して純関数のように振る舞わねばならない

2.JSXとは

React.createElement関数
javaScriptの機能を全て備えた構文の拡張の為テンプレート言語とは異なる
ReactDOMはHTMLの属性ではなくキャメルケース (camelCase) のプロパティ命名規則を使用
※class→className

classAppextendsReact.Component{render(){//jsを書ける範囲return(<div>{'中括弧内ならjsを書ける'}</div>
);}}

利点
インジェクション攻撃を防ぐ
jQueryと比べてDOMの管理が楽になる

3.props

properties(プロパティ)の略称
財産、性質と言う意味を持つ

読み取り専用で外部から注入される変数の事

4.stat 

状態と言う意味を持つ

props に似ているが、コンポーネントによって完全に管理されるプライベートなもの
そのコンポーネントが内部的に持っている状態のことで外部から注入できない

//こんにちは と表示されるコードclassAppextendsReact.Component{constructor(props){super(props);this.state={name:‘こんにちは’};}render(){return(<div><h1>{this.state.name}</h1>
</div>
);}}

5.Redux

ReactJSが扱うUIのstate(状態)を管理をするためのフレームワーク
ReduxはFluxの概念を拡張してより扱いやすく設計されもの

Reduxの基本設計3つの原則

  • Single source of truth アプリケーション内でStoreは1つのみとし、Stateは単独のオブジェクトとしてStoreに保持される
  • State is read-only Stateを直接変更することはできず、actionをStoreへdispatchすることでしかStateは変更できない。
  • Mutations are written as pure functions Stateを変更する関数(Reducer)はpureな関数にする

6. hooks

コンポーネントの中で呼び出されるHooksは
いつなんどきでも必ず同じ順番で同じ回数呼び出されること

@babel/plugin-transform-runtime を理解する(Babel 7)

$
0
0

概要

Babelの主要プラグインの一つである、@babel/plugin-transform-runtimeに関して、雰囲気で使わずに理解を深めるためにまとめた内容です。

概ね上記公式ドキュメントに書いてある内容を要約しただけになります。(2020/05/01 閲覧)

バージョン情報

以下で動作確認済み

  • Node v12.16.3
  • @babel/core v7.4.5
  • @babel/plugin-transform-runtime v7.4.5
  • @babel/runtime@ v7.9.2
  • core-js v3.x

@babel/plugin-transform-runtime is 何

本来はBabelによって注入されるヘルパーコードを、再利用可能なヘルパーをインポートする形に変換するプラグインです。これによってグローバル汚染を避けながら、成果物のコードサイズを小さくすることができます。

ES6+のインスタンスメソッドの使用にはcore-js@3が別途必要です。@babel/preset-envuseBuiltInsを設定するのが手っ取り早いですがここでは割愛します

インストール

@babel/plugin-transform-runtimeはコードビルド時に必要なプラグインになるので、devDependencyで充分です。

$ yarn add -D @babel/plugin-transform-runtime

ビルド後のコードから参照されるヘルパー本体が別途必要になります。こちらは実行用なのでproductionDependencyになります。

$ yarn add @babel/runtime

設定

.babelrcなどの設定ファイル内に使用するプラグインを追加するだけ。オプションも豊富ですが、基本的にはデフォルトで問題無さそう。

{"plugins":["@babel/plugin-transform-runtime"]}

なぜ必要なのか

Babelは通常、一般的によく使われる関数(Class生成など)に対して、都度ヘルパー関数を生成しますが、アプリケーションのファイルが分散している場合、ヘルパーを必要とするそれぞれに対して同様のコードを複製してしまいます。

そうすると複製したコードが溜まっていき、全体のファイルサイズが大きくなってしまい、アプリケーションの初期読み込み時間が長くなる問題に繋がってしまいます。

そこで @babel/plugin-transform-runtimeを用いると、ヘルパーを必要とするそれぞれのファイルがヘルパー関数を定義するのでなく、@babel/runtimeを参照するように変更されます。必要な関数は全て @babel/runtimeに配置してあるので、コードがどれだけ分散していても全体のファイルサイズに影響を与えません。

また、@babel/plugin-transform-runtimeを使わずに、babel/polyfillなどを直接インポートして変換すると、グローバル汚染が発生し、そのコードを外部ライブラリとした他のコードに影響を与える可能性があります。 (逆に言えばアプリケーションやコマンドラインツールであれば大した問題にはならない)

CLIで挙動を見る

実際の挙動をCLIで確認するとイメージが湧くので、まずbabel-cliと、preset-envcore-jsも用意しておきます。

$ yarn add -D @babel/cli @babel/preset-env core-js@3

babelの設定は必要最低限に

babelrc.json
{"presets":[["@babel/preset-env",{"modules":false,"targets":{"browsers":"> 1%",},"corejs":{"version":3,"proposals":false},"useBuiltIns":"usage"}]],"plugins":[]}

検証対象のスクリプトは以下のような、クラスを通じて文字列を出力する程度のものになります。

script.js
classHuman{constructor(name){this.name=name}sayHello(){return`Hello, ${this.name}`}}consthuman=newHuman('sasaki')console.log(human.sayHello())

babel-cliを実行すると、es5に変換されます。

$ yarn babel script.js
import"core-js/modules/es.function.name";function_classCallCheck(instance,Constructor){if(!(instanceinstanceofConstructor)){thrownewTypeError("Cannot call a class as a function");}}function_defineProperties(target,props){for(vari=0;i<props.length;i++){vardescriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"indescriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function_createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);returnConstructor;}varHuman=/*#__PURE__*/function(){functionHuman(name){_classCallCheck(this,Human);this.name=name;}_createClass(Human,[{key:"sayHello",value:functionsayHello(){return"Hello, ".concat(this.name);}}]);returnHuman;}();varhuman=newHuman('sasaki');console.log(human.sayHello());

特筆すべきは、 _classCallCheck_defineProperties_createClassと言った、ES5でES6+相当と同等の仕組みを提供するためにbabel(正確にはbabelプラグイン)が生成したヘルパー関数です。

では次に、 @babel/plugin-transform-runtimeを有効にしてみます。

$ yarn babel --plugins @babel/plugin-transform-runtime script.js
import"core-js/modules/es.function.name";import_classCallCheckfrom"@babel/runtime/helpers/classCallCheck";import_createClassfrom"@babel/runtime/helpers/createClass";varHuman=/*#__PURE__*/function(){functionHuman(name){_classCallCheck(this,Human);this.name=name;}_createClass(Human,[{key:"sayHello",value:functionsayHello(){return"Hello, ".concat(this.name);}}]);returnHuman;}();varhuman=newHuman('sasaki');console.log(human.sayHello());

おや? 先程まで直接生成されていたヘルパーコードが、

import_classCallCheckfrom"@babel/runtime/helpers/classCallCheck";`

のように、他のモジュールを参照するように振る舞いが変わっていますね。

ではこの @babel/runtime/helpers/classCallCheckを見てみましょう。

classCallCheck.js
function_classCallCheck(instance,Constructor){if(!(instanceinstanceofConstructor)){thrownewTypeError("Cannot call a class as a function");}}module.exports=_classCallCheck;

本来は動的に生成されていたコードがこちらに配置されてることが確認できました。

これが @babel/plugin-transform-runtimeのほかに @babel/runtimeを、それもProductionに入れる必要があるのはこういうワケでした。

Gulp3 => Gulp4 移行 エラー【 primordials is not defined 】

$
0
0

Gulp3からGulp4へ:airplane:

今回Gulp3からGulp4へ(何回書くねん:imp:)移行したのですがその際に出たエラーについて共有
アップデートはnpm-check-updatesというツールを使いnpmライブラリを総括アップデートを行いました。

エラー内容:see_no_evil:

アップデート後gulpコマンドが叩けるかを確認するために

index.js
importgulpfrom'gulp'import{compileStylus}from'./tasks/stylus'exports.default=gulp.series(compileStylus)//↑gulpと叩くとcompileStylusというタスクを実行するよ〜という処理
./tasks/stylus.js
importgulpfrom'gulp'importplumberfrom'gulp-plumber'importrunSequencefrom'run-sequence'importdelfrom'del'importheaderfrom'gulp-header'importstylusfrom'gulp-stylus'importpleeeasefrom'gulp-pleeease'importcsscombfrom'gulp-csscomb'importsourcemapsfrom'gulp-sourcemaps'importjeetfrom'jeet'importaxisfrom'axis'importpathsfrom'../paths'importrupturefrom'rupture'exportconstcompileStylus=()=>{returngulp.src([paths.stylusPath+'/*.styl','!'+paths.stylusPath+'/_*/*.styl']).pipe(plumber()).pipe(sourcemaps.init()).pipe(stylus({use:[axis(),jeet(),rupture()]})).pipe(pleeease({minifier:false,autoprefixer:{"browsers":["last 4 versions"]}})).pipe(csscomb()).on('error',console.error.bind(console)).pipe(header('@charset "utf-8";\n')).pipe(gulp.dest(paths.distCss))}

と二つのファイルを用意し

terminal
hogehoge $gulp 
//index.jsの中身を実行する。

と叩くと

terminal
[17:48:43] Requiring external module @babel/register
fs.js:35
} = primordials;    ^

ReferenceError: primordials is not defined
    at fs.js:35:5
    at req_ ~~~~~

とよくわからないエラーが出てきました。:poop:

原因:thinking:

こちらの原因としては
https://hepokon365.hatenablog.com/entry/2019/10/31/022524
こちらの記事に同じようにエラーが起きていまして
どうやら古いgraceful-fsが使われているnpmパッケージがある可能性があったため

ターミナルにてgranceful-fsをnpm lsコマンドで確認

terminal
hoge$npm ls graceful-fs
setting2@1.0.0 ~~~~
├─┬ browser-sync@2.26.7
│ ├─┬ chokidar@2.1.8
│ │ └─┬ readdirp@2.2.1
│ │   └── graceful-fs@4.2.3 
│ ├─┬ fs-extra@3.0.1
│ │ ├── graceful-fs@4.2.3 
│ │ └─┬ jsonfile@3.0.1
│ │   └── graceful-fs@4.2.3 
│ └─┬ yargs@6.4.0
│   └─┬ read-pkg-up@1.0.1
│     └─┬ read-pkg@1.1.0
│       ├─┬ load-json-file@1.1.0
│       │ └── graceful-fs@4.2.3 
│       └─┬ path-type@1.1.0
│         └── graceful-fs@4.2.3 
├─┬ del@5.1.0
│ └── graceful-fs@4.2.3 
├─┬ gulp@3.9.1 invalid
│ └─┬ vinyl-fs@0.3.14
│   ├─┬ glob-watcher@0.0.6
│   │ └─┬ gaze@0.5.2
│   │   └─┬ globule@0.1.0
│   │     └─┬ glob@3.1.21
│   │       └── graceful-fs@1.2.3 
│   └── graceful-fs@3.0.12 
├─┬ gulp-cssmin@0.2.0
│ ├── graceful-fs@4.1.15 
│ └─┬ temp-write@0.1.1
│   └── graceful-fs@2.0.3 
├─┬ gulp-imagemin@7.1.0
│ ├─┬ imagemin@7.0.1
│ │ └── graceful-fs@4.2.3 
│ └─┬ imagemin-gifsicle@7.0.0
│   └─┬ gifsicle@5.0.0
│     └─┬ bin-build@3.0.0
│       └─┬ decompress@4.2.1
│         └── graceful-fs@4.2.3 
├─┬ gulp-pleeease@2.0.2
│ └─┬ pleeease@4.3.0
│   ├─┬ css-mqpacker@4.0.1
│   │ └─┬ fs-extra@0.26.7
│   │   ├── graceful-fs@4.2.3 
│   │   ├─┬ jsonfile@2.4.0
│   │   │ └── graceful-fs@4.2.3  deduped
│   │   └─┬ klaw@1.3.1
│   │     └── graceful-fs@4.2.3 
│   ├─┬ csswring@4.2.3
│   │ └─┬ fs-extra@0.30.0
│   │   ├── graceful-fs@4.2.3 
│   │   └─┬ jsonfile@2.4.0
│   │     └── graceful-fs@4.2.3  deduped
│   ├─┬ less@2.7.3
│   │ └── graceful-fs@4.2.3 
│   └─┬ node-sass@4.14.0
│     └─┬ node-gyp@3.8.0
│       ├─┬ fstream@1.0.12
│       │ └── graceful-fs@4.2.3 
│       └── graceful-fs@4.2.3 
├─┬ gulp-rev@9.0.0
│ └─┬ vinyl-file@3.0.0
│   └── graceful-fs@4.2.3 
├─┬ gulp-sourcemaps@2.6.5
│ └── graceful-fs@4.2.3 
├─┬ gulp-uncss@1.0.6
│ └─┬ uncss@0.14.1
│   └─┬ phridge@2.0.0
│     └─┬ phantomjs-prebuilt@2.1.16
│       └─┬ fs-extra@1.0.0
│         ├── graceful-fs@4.2.3 
│         └─┬ jsonfile@2.4.0
│           └── graceful-fs@4.2.3  deduped
├─┬ gulp-useref@4.0.1
│ └─┬ vinyl-fs@3.0.3
│   ├─┬ fs-mkdirp-stream@1.0.0
│   │ └── graceful-fs@4.2.3 
│   ├── graceful-fs@4.2.3 
│   └─┬ vinyl-sourcemap@1.1.0
│     └── graceful-fs@4.2.3 
├─┬ gulp-watch@5.0.1
│ └─┬ vinyl-file@2.0.0
│   └── graceful-fs@4.2.3 
├─┬ npm-check-updates@4.1.2
│ ├─┬ pacote@11.1.4
│ │ ├─┬ @npmcli/installed-package-contents@1.0.5
│ │ │ └─┬ readdir-scoped-modules@1.1.0
│ │ │   └── graceful-fs@4.2.3 
│ │ └─┬ cacache@15.0.0
│ │   └─┬ move-concurrently@1.0.1
│ │     └─┬ fs-write-stream-atomic@1.0.10
│ │       └── graceful-fs@4.2.3 
│ └─┬ update-notifier@4.1.0
│   └─┬ configstore@5.0.1
│     └── graceful-fs@4.2.3 
└─┬ spritesmith@3.4.0
  └─┬ pixelsmith@2.4.1
    └─┬ vinyl-file@1.3.0
      └── graceful-fs@4.2.3 

npm ERR! invalid: gulp@3.9.1

とでてきた
よくみるとgraceful-fs@1.2.3とバチクソ古いのも見つかったが
gulp@3.9.1となぜか3も残っていた

解決法:bulb:

原因までわかればあとは簡単です
いらないものを消すだけです。

package.json
"dependencies":{"gulp":"^3.9.1"}

僕の場合はなぜか開発環境でしか使わないgulpがdependenciesにはいっていたため
こちらを削除
それ以外の方はgraceful-fs@~ を削除するとうまくいくと思います。
参考記事にも載っていますのでそちらを参考にしてみてください

terminal
hoge $gulp
[18:02:21] Requiring external module @babel/register
[18:02:23] Using gulpfile ~/hoge/hoge~~~/gulpfile.babel.js
[18:02:23] Starting 'default'...
[18:02:23] Starting 'compileStylus'...
[18:02:24] Finished 'compileStylus' after 1.46 s
[18:02:24] Finished 'default' after 1.47 s
hoge $

修正後gulpコマンドが綺麗に通ります

おわりに

記事を探すとあまり見つからなかったのですが検索力が悪いせいか
まあQiitaで探す方多いと思うのでこちらで参考になればいいかなと
ここおかしくない?ってやつあればコメントください:rice:

参考記事

npm-check-updatesについて

Node.js v12にアップデートするとgulp v4でもfs.jsで「ReferenceError: primordials is not defined」エラーが発生

Cognito+API Gateway+Lambdaでユーザ作成APIを作りたいんだー!

$
0
0

AWSの認定は保有していますが
実践できていない主なサービスがサーバレスまわり…

ということで勉強を兼ねて、簡単なAPIを作成してみます。

やりたいこと

APIでユーザ作成
- username と passwordをリクエストボディに指定しAPIをコールするだけでユーザ作成する。
- メールアドレス/電話番号の認証は不要。

参考

LambdaでCognito認証(ユーザー作成)

やってみよう!

ユーザプールの作成

こんな私でもCognitoでユーザ管理をするにはユーザプールを作成しなければならないことは知っている。

属性は必要最低限を指定
image.png

image.png

image.png

image.png

認証フローはよくわからないため全てチェック。※今後勉強します
ALLOW_USER_PASSWORD_AUTH が絶対必要
「クライアントシークレットを作成」にはチェックを入れないこと。
image.png

Lambda用IAMロール

Lambdaの基本的なポリシーに加えて、「AmazonCognitoPowerUser」をアタッチする。
image.png

ユーザ作成用のLambdaを作成

今回、ソースコード内のアプリクライアントIDはLambdaの環境変数にセット
バリデーションやエラー処理は適当なので、適宜変更をお願いします

index.js
'use strict';constAWS=require('aws-sdk');constcognito=newAWS.CognitoIdentityServiceProvider();/**
 * SignUp
 * @param {string} loginName
 * @param {string} password
 * @returns {Promise<Object>} statusCode,headers,body
 */exports.handler=async(event,context)=>{constresponse={};letloginName;letpassword;console.log(event);// Validationif(!(event.body)||!('loginName'inJSON.parse(event.body))||!('password'inJSON.parse(event.body))){response["statusCode"]=400;returnresponse;}else{letreqestBody=JSON.parse(event.body);loginName=reqestBody["loginName"];password=reqestBody["password"];}// SignUp parametersconstparams={ClientId:process.env['APP_CLIENT_ID'],Username:loginName,Password:password};response["headers"]={"Access-Control-Allow-Origin":"*","Content-Type":"application/json"};// SignUptry{constuser=awaitcognito.signUp(params).promise();console.log('User sign up success!!!',JSON.stringify(user,null,4));response["statusCode"]=201;response["body"]=JSON.stringify({"loginName":loginName});returnresponse;}catch(err){console.log('User sign up failed...'+err);if(err.code=='UsernameExistsException'){response["statusCode"]=409;}elseif(err.code=='InvalidPasswordException'){response["statusCode"]=400;}else{response["statusCode"]=500;}returnresponse;}};

Lambdaのテスト

image.png

テストを実行
image.png

ユーザプールにユーザが作成された。めでたい!
image.png

API Gatewayの作成

image.png

「Lambdaプロキシの統合」にチェックを入れ、作成したLambda関数を選択する。
image.png

API Gatewayからのテスト実行
image.png

こちらもユーザが作成された。めでたい!!!
image.png

今後の宿題

  • 作成したユーザのステータスがUNCONFIRMEDなので,CONFIRMに変更するプログラムを追加する
  • APIでユーザ認証をし、アクセストークンを取得する
  • APIでユーザ情報を取得する

Let's Encryptを使用しているウェブページをブロックするプロキシサーバー

$
0
0

Let's Encryptはドメイン認証証明書を無料で発行してくれるたいへん素晴らしいサービスです。ウェブサイトをHTTPSで提供するためには証明書が必要ですが、Let's Encryptの登場以前は認証局から有料で証明書を発行してもらうのが主流でした。それを無料で発行してもらえるのは大変ありがたいことです。また、発行プロセスは自動化されておりとても簡単です。筆者も個人のウェブサイトは全てLet's Encryptで証明書を取得しています。

ところが、Let's Encryptが発行する無料の証明書なんて信頼できないという教義を信奉するタイプの人々も存在するようです。筆者は最近Twitterで見かけました。ということで、そのような思想を持つ方も安心してインターネットを利用できるように、Let's Encryptによって発行された証明書を使用しているウェブサイトのみブロックするプロキシサーバーを作りました。

完成品はこちらです。→ https://github.com/uhyo/proxy-for-mammonists

ソースコードをクローンし、npm installで依存関係をダウンロード後にnpm startでプロキシサーバーを起動し、お使いのブラウザで127.0.0.1:8111をプロキシサーバーに指定しましょう。

動作の様子

今回はFirefoxにこのプロキシサーバーを設定して試してみました。

まず、Let's Encryptを使用していないqiita.comにアクセスしてみると、ちゃんと表示されます。

スクリーンショット 2020-05-02 1.21.44.png

プロキシサーバーのログを見ると、どのサーバー名へのレスポンスをプロキシしたのかがログに残されています。

スクリーンショット 2020-05-02 1.22.51.png

次に、筆者のウェブサイト uhy.ooo にアクセスしてみます。このサイトは証明書としてLet's Encryptが発行したものを使用しています。

すると、プロキシサーバーが接続を拒否した旨のメッセージが出ます。

スクリーンショット 2020-05-02 1.24.15.png

プロキシサーバーのログにはuhy.oooへの接続をブロックした旨のログが残されています。

スクリーンショット 2020-05-02 1.25.23.png

これで、Let's Encryptを利用する危険なウェブサイトにアクセスしてしまうのを事前に防ぐことができました。とても安全で嬉しいですね。

実装解説

こういう記事はちゃんと実装を解説しないと叩かれるので、ここからはこのプロキシサーバーを解説します。今回はnode.jsを用いて、サードパーティのライブラリは用いずに実装しました。

全体のコードを一瞥したい方は前述のGitHubをご参照ください。ここでは順を追って解説します。

まずHTTPサーバーを建てる

プロキシサーバーは、基本的にはHTTPサーバーです。よって、まずnode.js標準のhttpモジュールを使用してHTTPサーバーを立てます。

importhttpfrom"http";importnetfrom"net";importtlsfrom"tls";constserver=http.createServer((req,res)=>{// HTTP リクエストをプロキシする処理constu=newURL(req.url,`http://${req.headers.host}`);console.log(`proxying HTTP request to ${req.headers.host}`);constproxyReq=http.request(u,{method:req.method,},(proxyRes)=>{res.writeHead(proxyRes.statusCode,proxyRes.headers);proxyRes.pipe(res);});req.pipe(proxyReq);});

このように、http.createServerを用いてHTTPサーバーを作成します。コールバックの(req, res)=> { ... }という関数はrequestイベントのハンドラとして登録される関数で、すなわちHTTPリクエストが来るたびに呼び出される関数です。

この中身は、HTTPリクエストをプロキシする処理となっています(本命のHTTPSはまた別です)。これはプロキシサーバーなので、クライアントからの全てのサイトへのHTTPリクエストがこのサーバーへのHTTPリクエストとなります。よって、プロキシサーバーがすべきことは、指定されたサイトへのHTTPリクエストを作成してもらったデータをそのままクライアントに渡すことです。

そのために、http.requestによりプロキシサーバーから実際のウェブサイトへのHTTPリクエストを作成します。HTTPサーバーを建てておりプロキシから実際のサーバーへの接続もHTTPなので、ヘッダと本文は別々に処理する必要があります。http.requestのコールバックはサーバーからヘッダが返ってきた(ステータスコードとヘッダ一覧が確定した)段階で呼び出されますので、ここでステータスコードとヘッダをそのままプロキシサーバーからクライアントに送ります。レスポンスの本文も全て仲介するべきですが、それはリクエストやレスポンスがそれぞれReadableストリーム・Writableストリームであることを利用してpipeメソッドにより行なっています。

ここでは特にLet's Encryptをブロックする処理は入っていません。HTTPは暗号化されていない接続なのでそもそも証明書は登場せず、Let's Encryptが出る幕がないからです。今回作成したプロキシでは、HTTP接続はLet's Encryptを使っていないので安全とみなしてアクセスを許します。

HTTPSリクエストをプロキシする

以上でHTTPリクエストはプロキシできましたが、本命はHTTPSの方です。クライアントがプロキシサーバーを介してHTTPSリクエストを行いたい場合はHTTPとは方式が異なります。HTTPの場合は平文なのでプロキシサーバーがHTTPを喋りましたが、暗号化された接続の場合は中間者であるプロキシサーバーが通信の中身に介入することができません。そのため、プロキシサーバーはHTTPではなくTCPのレベルのトンネルとなり接続を仲介します。

この場合、クライアントはプロキシサーバーに対してCONNECTメソッドのリクエストを行います。CONNECTメソッドの説明はMDNにも書いてありますね。

このリクエストには、クライアントがどのホスト名に接続したいかという情報が含まれています。プロキシサーバーが了承した場合、以後その接続はトンネルとして機能することになります。

今回のプロキシサーバーは接続先のサーバーがLet's Encryptの証明書を使用しているかどうかチェックしなければなりません。今回は、実際にプロキシサーバーからTLS接続を貼ってみて証明書情報を取得するという方法を採っています。当該部分のソースコードはこの通りです。

functioncheckCertificateIsNotLetsEncrypt(host,port){returnnewPromise((resolve,reject)=>{constcheckConn=tls.connect({host,port,servername:host,},()=>{constcert=checkConn.getPeerCertificate();constissuer=cert&&cert.issuer;if(issuer){if(issuer.O==="Let's Encrypt"){// this should be blockedresolve(false);}else{// OKresolve(true);}}else{// no issuer?reject(newError("Could not get certificate issuer"));}});checkConn.on("error",reject);});}

tls.connectで接続先サーバーとのTLSコネクションを張り、成功したらcheckConn.getPeerCertificate()で証明書情報を得ています。今回はissuerのOフィールドがLet's EncryptだったらLet's Encryptが発行した証明書と判断するという実装です。

この方法は簡単ですが、実際のリクエストとは別にもう一つコネクションが貼られるという問題があります。プロキシされたTLS接続のデータを盗み見たら証明書の情報が得られるかもしれませんが、大変そうなので今回それはやりませんでした。

さて、実際のHTTPSプロキシ処理は以下のようになっています。node.jsのHTTPサーバーでは、クライアントがCONNECTメソッドの要求を送ってきたら専用のconnectイベントが発火するようになっていますから、これをハンドルすることでCONNECTメソッドに応答できます。

server.on("connect",(req,socket,head)=>{console.log(`proxying HTTPS request to ${req.headers.host}`);constu=newURL(`https://${req.headers.host}`);constcertificateCheckP=checkCertificateIsNotLetsEncrypt(u.hostname,u.port||443);constconn=net.createConnection({host:u.hostname,port:u.port||443,},()=>{certificateCheckP.then((ok)=>{if(ok){socket.write("HTTP/1.1 200 OK\n\n");conn.pipe(socket);}else{console.log(`Request to ${u.hostname} is blocked`);socket.end("HTTP/1.1 403 Forbidden\n\n");}}).catch((err)=>{// ?socket.end("HTTP/1.1 500 Internal Server Error\n\n"+err.toString());});// pipeTLSResponse(socket, checkConn);});if(head){conn.write(head);}socket.pipe(conn);conn.on("error",(err)=>{console.error(err);socket.end();});});

今回、CONNECTメソッドを受けたプロキシサーバーは実際の接続先に対してnet.createConnectionで接続します。これはTCPのソケットです。今回TLSやHTTPではなくTCPのソケットなのは、TLSハンドシェイクがクライアントと接続先サーバーの間で直接行われるからです。それを仲介する役目を持つプロキシサーバーはその下のレベルであるTCPで両者をトンネルしなければいけません。

CONNECTメソッドを受けたプロキシサーバーは、接続先がLet's Encryptを使用しているかどうかチェックするcertificateCheckPの結果を持って、使用していない(接続を許可する)のであればクライアントにHTTP/1.1 200 OK\n\nを返します。この直後からクライアントに対しては接続先からのデータが直接渡されることになります(このことはRFC 7231に明記されているのでそれに従いました。ステータスコード200台を返せば何でもいいようです)。接続を許可しない場合は403を返しています。

成功した場合、200をクライアントに送った直後から接続先サーバーのデータをクライアントへパイプします。また、クライアントからのデータは最初から接続先サーバーにパイプされています。これによりトンネルが完成し、HTTPS通信を仲介できました。

まとめ

これでLet's Encryptを信頼しない教義の方も安心ですね。

webpack超超入門(備忘)

$
0
0

webpackとは

webpackはフロントエンド開発用のモジュールバンドラー、簡潔にはモジュールをまとめてくれるツール

用語

  • モジュール
    javascriptやcssなどのファイル。

  • バンドル/バンドルファイル
    モジュールが一つにまとめられたファイル。

  • ビルド
    バンドルを出力するまでの一連の処理

利点

  • 機能ごとにファイルを分割(モジュール化することができる。)
  • 可読性の向上
  • 開発作業の分担やテストがし易くなる
  • モジュールの再利用性を向上できる。
  • 転送効率を向上させることができる。
  • 最適化されたファイルを出力できる。

install

何はともあれやってみないといまいちよくわからないので、早速nodeからwebpackをインストール。

  • 適当なディレクトリを切って、package.jsonを初期化
yarn init -y
  • webpackとwebpack-cliをインストール(webpack4からcliが別モジュールとして管理されるようになったため、別途インストールが必要らしい。)
yarn add webpack webpack-cli -D

package.jsonはこんな感じになり、インストールされたことを確認できる。

package.json
{"name":"webpack-tmp","version":"1.0.0","main":"index.js","license":"MIT","devDependencies":{"webpack":"^4.43.0","webpack-cli":"^3.3.11"}}

バンドル確認

この段階でwebpackを実行して、モジュールをバンドルすることができるので、動作確認としてcliからバンドル。適当にjsを作成。

root/
 ├ node_modules/
 ├ src/     #作業ディレクトリ
 │ └ index.js
 └ package.json
index.js
console.log('bundle test');

webpackを実行。(modeオプションで開発用(development)かプロダクション用を選択できる。

yarn webpack --mode development

実行が完了すると、新たにdistフォルダが作られ、バンドルされたmain.jsが格納されていることを確認できる。

root/
 ├ dist
 │ └ main.js ←new! 
 ├ node_modules/
 ├ src/     #作業ディレクトリ
 │ └ index.js
 └ package.json

webpack.config.js(webpackの設定ファイル)

cliでバンドルする際には、--modeや色んなオプションをコマンドで付与することでwebpackの挙動を制御をしますが、毎回それを打つのは面倒なので、設定ファイルを読み込ますことで様々な挙動をコントロールできます。

オブジェクトリテラル(名前と値のペア)で記述するだけなので、nodeがサポートしているcommonJSの記法(module.exports = ...)でも構わないのですが、個人的にes6で書きたいので、babelを使ってconfigをes6→es5にトランスパイルします。
具体的にはbabel/registerでconfigファイルを読み込む前にes6をトランスパイルさせます。

install

yarn add @babel/core @babel/register @babel/preset-env -D

babelを使ってトランスパイルするので.babelrcをプロジェクト直下に配置します。(.babelrcはes6をトランスパイルできればいいので、適当)

{"presets":["@babel/preset-env"]}

これでes6で書けるようになったので、中身を書いていきます。
babelでconfigファイルをトランスパイルする際は、webpack.config.babel.jsとしないと認識しないので注意(トランスパイルとか面倒なことしないよ、という場合はwebpack.config.jsで問題ないです。)

webpack.config.babel.js
importpathfrom'path';exportdefault{mode:'development',entry:'./src/index.js',output:{path:path.resolve(__dirname,'public'),filename:'bundle.js'}}

もうただバンドルするだけだぜ、な設定ですが、超超入門なので問題ないでしょう。
先ほどcliからwebpackコマンドでバンドルした際には--modeなどを設定しましたが、configファイル内に
オプションを記載してます。
見ればなんとなくわかるような気がしますが、それぞれの項目のざっとした意味を↓に。
詳細は公式なりを参照してください。

  • mode: 'development' 'production' 'none'を指定する。productionを指定すると難読化や最小化を行ってくれる。(必須設定項目)
  • entry: 'エントリーポイントとなるjsファイル
  • output: バンドルした結果をどのディレクトリに、どのファイル名で出力するかの設定。

これでconfigファイルを使って、バンドルする準備ができたのでバンドルしてみます。
先ほどはオプション指定しましたが、configファイルを自動で読んでくれるので、今回は指定しないで大丈夫です。

yarn webpack

結果

コマンドが成功すると、以下のようなディレクトリになっているはずです。

root/
 ├ dist
 │ └ main.js 
 ├ public  ←new!
 │ └ bundle.js  ←new! 
 ├ node_modules/
 ├ src/     #作業ディレクトリ
 │ └ index.js
 └ package.json

webpack.babel.jsに書いた設定でバンドルできました!
javascriptだけ単純にバンドルする場合は以上のような感じになります。
webpackでは他にもloaderという機能を使ってjavascript以外(画像とかcss)をバンドルすることも可能です。

まとめ

おおざっぱに理解していたwebpackの知識を一旦整理してみたけど、loaderとかpluginの話に到達しないで力尽きた。。。
webpackをまとめようとすると、babelやらscssやらの話が付き纏うのでいまいちうまくまとめられない。
そのうちloaderやらについても書いてみたい。


Node.jsのバージョンアップ for Mac

$
0
0

Macで動いているNode開発環境を最新状態にするための方法です。
(いつも忘れちゃうので、書き留めておこうと思います。)

手順は以下のとおりです。
 1. 各種ツールの最新バージョンを確認する。
 2. 各種ツールを最新にする。

各種ツール最新(安定)バージョンを確認する。

私の環境は、Homebrewで作ったので、以下のものを確認します。
(2020/5/1時点の情報です。)

  • Homebrew
  • Nodebrew
  • Node.js

Homebrew:

Homebrewのバーション情報は、こちらから確認できます。
Bildschirmfoto_2020-05-01_um_18_38_50.png

私の環境は、ちょっと古いですね。

Homebrew
>brew-vHomebrew2.0.0Homebrew/homebrew-core(gitrevision0b1c;lastcommit2019-02-04)Homebrew/homebrew-cask(gitrevision1e6e6;lastcommit2019-02-05)

Nodebrew:

Nodebrewのバージョン情報は、こちらから確認できます。
Bildschirmfoto_2020-05-01_um_19_15_35.png

私の環境は、これも古い、、、(そりゃそうか。)

nodebrew
>nodebrew-vnodebrew0.9.7

Node.js:

Node.jsのバージョン情報は、こちらから確認できます。
Bildschirmfoto_2020-05-01_um_18_14_45.png

これも、古いですね。

node.js
>node-vv10.16.0

各種ツールを最新にする。

先ほどのステップで確認した各種ツールを最新にします。

Homebrew:

brew updateコマンドでアップデートします。

Homebrew
>brewupdate// しばらく時間かかっても、気長に待つ、、、、>brew-vHomebrew2.2.14Homebrew/homebrew-core(gitrevisionb303d;lastcommit2020-05-01)Homebrew/homebrew-cask(gitrevision90c68;lastcommit2020-05-01)

Nodebrew:

brew upgrade nodebrewコマンドでアップデートします。

nodebrew
>brewupgradenodebrew>nodebrew-vnodebrew1.0.1

Node.js:

Node.jsは、nodebrewを使って、アップデートします。
まずは、インストールできるバージョンの確認です。

>nodebrewls-remote// バージョンがずらりと並びます。v12.0.0v12.1.0v12.2.0v12.3.0v12.3.1v12.4.0v12.5.0v12.6.0v12.7.0v12.8.0v12.8.1v12.9.0v12.9.1v12.10.0v12.11.0v12.11.1v12.12.0v12.13.0v12.13.1v12.14.0v12.14.1v12.15.0v12.16.0v12.16.1v12.16.2v12.16.3v13.0.0v13.0.1v13.1.0v13.2.0v13.3.0v13.4.0v13.5.0v13.6.0v13.7.0v13.8.0v13.9.0v13.10.0v13.10.1v13.11.0v13.12.0v13.13.0v13.14.0

先ほど調べた、安定版:v12.16.3でアップデートします。

>nodebrewinstall-binaryv12.16.3//インストールが始まります。Fetching:https://nodejs.org/dist/v12.16.3/node-v12.16.3-darwin-x64.tar.gz########################################################################100,0%// しばらく待つと、完了します。Installedsuccessfully

利用可能なバージョンをリスト表示し、使用するバージョンを指定します。

>nodebrewlistv10.16.0v12.16.3>nodebrewusev12.16.3usev12.16.3

最後にバージョンを確認します。

>nodebrewlsv12.16.3current:v12.16.3

ついでに、nodeのバージョンも確認しておきましょう。

>node-vv12.16.3

以上で、最新バージョンに更新されました。

ちなみに、nodebrewでインストールしたモジュールは、以下のディレクトリにインストールされています。

/Users/[ユーザー名]/.nodebrew

このディレクトリにある currentというシンボリックリンクで、今使っているバージョンを判別しています。

current -> /Users/[ユーザー名]/.nodebrew/node/v12.16.3

よくあるエラー対処法

その1: node -vでエラーが発生する。

node -vコマンドを実行した時、下記のようなエラーが発生する場合があります。
.bash_profileの設定が正しくできていないことが原因です。

>node-v-bash:node:commandnotfound

その時の対処法を以下に記載します。

1. .bash_profileにPATHを設定します。

vi~/.bash_profile//以下の行を記述するexportPATH=$HOME/.nodebrew/current/bin:$PATH

2. .bash_profileを有効化します。

source~/.bash_profile


その2: node -vで表示されるバージョンが異なる。

node -vコマンドを実行した時、nodebrew useで指定したものと異なるバージョンが表示されることがあります。

>node-vv10.16.0

nodebrewのインストールの仕様が変わった、過去に別の方法で、Node.jsをインストールしたなど、いくつか原因は考えられます。

そんな時は、まずnodebrewでインストールされたnodeモジュールを探します。
mdfindコマンドを使うと便利です。

>mdfindv12.16.3-name/usr/local/var/nodebrew/src/v12.16.3/usr/local/var/nodebrew/src/v12.16.3/node-v12.16.3-darwin-x64.tar.gz/usr/local/var/nodebrew/node/v12.16.3

usr/local/var/nodebrew/node/v12.16.3にインストールされていることがわかります。

このディレクトリのnodeを利用するためには、モジュールがインストールされたPATHに、currentのシンボリックリンクを作成します。

cd/Users/[ユーザー名]/.nodebrewln-scurrent/usr/local/var/nodebrew/node/v12.16.3

これで、useで指定したバージョンが使えるようになります。

>node-vv12.16.3

Macの Node.js環境をバージョンアップする方法の説明は、以上で終わりです。




LINEBotをみんなで作ろう〜おうむ返しbotを作ろう編〜【GWアドベントカレンダー3日目】

$
0
0

この記事は下記の #GWアドベントカレンダーの 2日目の記事になります。

楽しそうなのでやってみる ( @inoue2002) | GWアドベントカレンダー

はじめに

こちらの内容は超初心者向けです。
公式ドキュメントを読める方はこちらをお読みいただく方が正確です。

昨日の記事をご覧になってない方はぜひ。
こちらの記事はGWアドベントカレンダーを通してLINEBotをサーバレスで作れるようになろう!ということを目標に書いている記事です。

LINEBotはどんなもんか大体知ってるけど、作り方はわからんという方に読んでいただきたいです。

それではおうむ返しbotを作って行きましょう!
注)途中にモザイク処理をしていない環境変数が出てきていますが、更新しておりますのでご安心ください。

アカウントの作成

LINEDevelopersのサイトに行き、ログインします。
流れとしては、
ログイン→プロバイダーを作成→新規チャネルを作成→Messaging APIのチャンル作成する→Botの設定と進みます。

右上のログインをクリック

スクリーンショット 2020-05-02 10.08.31.png

ログインを初めてすると以下のような画面が出るので名前とメールアドレスを記入します

スクリーンショット 2020-05-02 10.09.54.png

次にプロバイダーを作成します

スクリーンショット 2020-05-02 10.10.31.png

プロバイダー名はBotの名前ではないのでざっくりとした名前をつけます。

スクリーンショット 2020-05-02 10.11.19.png

チャネル設定の画面が現れるのでMessagingAPIをクリック

スクリーンショット 2020-05-02 10.11.35.png

Botの詳細を設定するフォームが現れるので以下四角いところを記入します。

・チャネル名→Botの名前
・適宜選ぶ
・適宜選ぶ
・メールアドレス記入
・同意に2箇所チェック
スクリーンショットBot設定画面.png

アクセスキー二種類を取得します

1つ目、チャネルシークレットをメモします。
ボット作成後画面、1.png
2つ目、アクセストークンをメモします。(最初は表示されていないので発行ボタンを押します)
スクリーンショット 2020-05-02 10.17.33.png

これで、Botとの連携に必要なキーを取得する事ができました。次からコードを書いていきましょう。

コードを書く

分かりやすいようにデスクトップにディレクトリを作成していきましょう。
ターミナルを開き、以下のコマンドを順番に実行します

cd deskTop
mkdir test-linebot
cd test-linebot
npm init -y 
npm i @line/bot-sdk express
touch index.js

そして test-linebot のディレクトリをプログラムがかけるエディタで開きます(VSCode等)
そして、index.jsを開き、以下のコードを全コピーして貼り付けます。のびすけさんの記事を参考にしてます

index.js
"use strict";constexpress=require("express");constline=require("@line/bot-sdk");constPORT=process.env.PORT||5000;constconfig={channelSecret:"先ほどLINEBotのアクセストークンを入れる",channelAccessToken:"先ほど発行したBOTのチャンネルアクセストークンを入れる"};constapp=express();app.post("/webhook",line.middleware(config),(req,res)=>{console.log(req.body.events);Promise.all(req.body.events.map(handleEvent)).then((result)=>res.json(result));});constclient=newline.Client(config);asyncfunctionhandleEvent(event){if(event.type!=="message"||event.message.type!=="text"){returnPromise.resolve(null);};letmes={type:"text",text:event.message.text};returnclient.replyMessage(event.replyToken,mes);}app.listen(PORT);console.log(`Server running at ${PORT}`);

環境変数を記入する

index.js内の"チャネルシークレットを入れる"、"アクセストークンを入れる"と書かれているところに先ほどメモしておいたキーを入力してください。記入例は
channelSecret: "先ほどLINEBotのアクセストークンを入れる",
channelAccessToken: "先ほど発行したBOTのチャンネルアクセストークンを入れる"

channelSecret: "5b7f3b9f97e37ccde..b448bd1b99c3",
channelAccessToken: "+hp3cv+Nyr38VKVOg89.../1O/w1cDnyilFU="

コードを実際に動かしてみる

ディレクトリを作る時に開いていたターミナルを開いてください。

もし閉じてしまった人は、サイドターミナルを開き、以下のコマンドを入力してください。

cd deskTop/test-linebot

そして、以下のコマンドを入力し、コードを実行します。
node index.js
以下のように表示されると成功です。
Server running at 5000

外部にポートを公開する

ここからngrokを使って、外部からアクセスできるようにしていきます。
先ほどまで使っていたポートとは別で新しいターミナルを開いてください
以下の写真のようにシェル>新規ウィンドウをクリックすると新しいターミナルが表示されます。
スクリーンショット 2020-05-02 10.48.42.png
新しいターミナルが表示されると、以下のコマンドを入力し、enterを押します、
ngrok http 5000
すると、黒い画面が出てくると思います。エラーが出る場合はngrokのインストールに失敗している可能性があります。
以下の写真のような黒い画面が出た人は一番↓のURL、https:/350f70.....ioをコピーします。
スクリーンショット 2020-05-02 10.51.16.png

WebhookURLを設定する

先ほどngrokを起動して表示されたURLをLINEBotのコンソールに入力します。
先ほど、アクセストークンをメモした画面に移動し、WebhookURLという記入欄に ngrokでコピーしたURL+/webhook を入力します。
記入例は以下の写真です。
スクリーンショット 2020-05-02 10.57.29.png
入力できたら、更新ボタンを押し、下に現れるWebhookの利用というスイッチをオンにします。
スクリーンショット 2020-05-02 11.01.01.png

応答設定をする

WebhookURLを記入できたら、その下にある応答設定を変更していきます。
以下の写真のような場所を見つけたら、あいさつメッセージと書かれた欄の右端にある編集をクリックします。
スクリーンショット 2020-05-02 11.02.44.png
編集をクリックすると以下のような画面が出てきます。
スクリーンショット 2020-05-02 11.05.02.png
上の写真と同じようにクリックしてください。ここでWebhookがオフになっている場合が時々あります。その場合はその下のMessagingAPIの設定をクリックし、webhookURLを再度入力し、保存を押します。
スクリーンショット 2020-05-02 11.07.22.png

ここまで完成するとあとは動くか確認するだけ!

Botと友達になる

開発途中に見たであろうQRコードをスマホで読み込み、友達登録を行ってください。
スクリーンショット 2020-05-02 11.09.42.png
そして、そのアカウントにメッセージを送ります。
以下に結果、その下に対処法書きます。

おうむ返ししない人の対処法

アクセスキーが間違っていないかもう一度確認してください。
コードを改変した時は、コードを起動した方のターミナルで controlキー + Cを押し、一度コードを停止させ、もう一度node index.jsで起動する必要がありますのでお忘れなく。
それでも動かない場合は、コードを停止,ngrokも停止(ngrokのターミナルでcontrolキー+C)→コードを起動→ngrokを起動→URLをWebhookに設定の順番でもう一度トライしてみてください。

おわりに

初めて僕もBotが動いた時は感動しました。半年前、LINEBotが動く事を「命が吹き込まれた」って表現してよろこんでいたぐらいです。その感動を少しでも多くの皆さんにも体験してもらいたい。その一心で初心者ながらもこのような記事を書いています。
トライあるのみです。色々弄っているといつか動くはずです。頑張ってください。
もしどうしても動かなかったらTwitterやqiitaにコメントいただけるとお答えできる範囲で相談に乗らせていただきます。ではまた明日

07.Heroku Demo作成(Node JS)

$
0
0

0.準備条件

  1. Salesforce 組織
  2. Heroku
    • Web Application
    • Heroku Connect (取引先のMapping設定)
    • Heroku Postgres

1.Node.js 実装 Resource 構成

  • routes
    • account.js
  • views
    • account.ejs
    • accountList.ejs
  • app.js
  • package.json
  • Procfile

image.png

2.account.js

varexpress=require('express');varrouter=express.Router();const{Pool}=require('pg');constpool=newPool({connectionString:process.env.DATABASE_URL,ssl:true});router.get('/',(req,res,next)=>{// 登録したら一覧に戻るres.redirect('/account/list');});router.get('/new',(req,res,next)=>{res.render('account');});router.post('/save',async(req,res,next)=>{// 登録内容をフォームから引っこ抜くconstname=req.body.name;constphone=req.body.phone;constfax=req.body.fax;constaccountUUID=req.body.accountUUID;// 取引先を新規登録するconstclient=awaitpool.connect();constinsertData={text:'insert into salesforce.account (name, phone, fax, accountuuid__c) values ($1, $2, $3, $4)',values:[name,phone,fax,accountUUID],}constresult=awaitclient.query(insertData);client.release();// 登録したら一覧に戻るres.redirect('/account/list');});router.get('/list',async(req,res,next)=>{constclient=awaitpool.connect();constresult=awaitclient.query('select * from salesforce.account order by id DESC');constresults={'results':(result)?result.rows:null};client.release();res.render('accountList',results);});module.exports=router;

3.account.ejs

<!DOCTYPE html><html><head><title>登録</title></head><body><h1>新規取引先</h1><formaction="/account/save"method="POST"><table><tr><th>取引先名</th><td><textareaname="name"></textarea></td></tr><tr><th>電話</th><td><textareaname="phone"></textarea></td></tr><tr><th>Fax</th><td><textareaname="fax"></textarea></td></tr><tr><th>取引先UUID</th><td><textareaname="accountUUID"></textarea></td></tr><tr><th></th><td><buttontype="submit">保存</button></td></tr></table></form></body></html>

4.accountList.ejs

<!DOCTYPE html><html><!-- Bootstrap CSS --><linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"crossorigin="anonymous"><head><title>取引先一覧</title></head><body><divclass="container"><divclass="row"><divclass="col"><h1>取引先情報</h1></div></br><divclass="col-md-12"><ahref="/account/new">新規追加</a><br></div><br><tableclass="table table-bordered"><theadclass="thead-dark"><tr><thscope="col">No</th><thscope="col">取引先名</th><thscope="col">電話</th><thscope="col">Fax</th><thscope="col">取引先UUID</th></tr></thead><tbody><%for(vari=0;i<results.length;i++){%><tr><td><%=results[i].id%></td><td><%=results[i].name%></td><td><%=results[i].phone%></td><td><%=results[i].fax%></td><td><%=results[i].accountuuid__c%></td></tr><%}%></tbody></table></div></div><script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.bundle.min.js"integrity="sha384-zDnhMsjVZfS3hiP7oCBRmfjkQC4fzxVxFhBx8Hkz2aZX8gEvA/jsP3eXRCvzTofP"crossorigin="anonymous"></script></body></html>

5.app.js

varexpress=require('express');varbodyParser=require('body-parser');// express の実態 Application を生成varapp=express();app.set('port',process.env.PORT||3000);// urlencodedとjsonは別々に初期化するapp.use(bodyParser.urlencoded({extended:true}));app.use(bodyParser.json());// テンプレートエンジンを EJS に設定app.set('views','./views');app.set('view engine','ejs');// 静的ファイルは無条件に公開app.use('/public',express.static('public'));// ルーティング設定app.use('/',require('./routes/account.js'));app.use('/account',require('./routes/account.js'));// アプリケーション開始ログapp.listen(app.get('port'),function(){console.log('Express server listening on port '+app.get('port'));});

6.package.json

{"name":"a03","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\"&& exit 1"},"author":"","license":"ISC","dependencies":{"body-parser":"^1.19.0","dotenv":"^8.2.0","ejs":"^3.1.2","express":"^4.17.1","pg":"^7.18.2"},"engines":{"node":"12.1.0","npm":"6.12.1"}}

7.Procfile

web: node app.js

8.画面イメージ

取引先情報一覧画面
image.png

取引先情報新規登録画面
image.png

Cognito+API Gateway+LambdaでログインAPIを作りたいんだー!

$
0
0

前回の続きで、Cognitoを使ったユーザ認証を行う。

やりたいこと

APIでログイン
- ログイン名 と パスワードをリクエストボディに指定しAPIをコールしアクセストークンを取得する

参考

LambdaでCognito認証(ユーザー認証)

やってみよう

Lambda用IAMロール

前回同様に、Lambdaの基本的なポリシーに加えて、「AmazonCognitoPowerUser」をアタッチする。

ログイン用のLambda関数を作成

前回と異なっていた点ですが、引数に渡すUSERNAME・PASSWORDは大文字で記載しないとエラーになりました。

index.js
'use strict';constAWS=require('aws-sdk');constcognito=newAWS.CognitoIdentityServiceProvider();/**
 * SignIn
 */exports.handler=async(event,context)=>{constresponse={};letloginName;letpassword;console.log(event);// Validationif(!(event.body)||!('loginName'inJSON.parse(event.body))||!('password'inJSON.parse(event.body))){response["statusCode"]=400;returnresponse;}else{letreqestBody=JSON.parse(event.body);loginName=reqestBody["loginName"];password=reqestBody["password"];}// SignIn parametersconstparams={AuthFlow:'USER_PASSWORD_AUTH',ClientId:process.env['APP_CLIENT_ID'],AuthParameters:{USERNAME:loginName,PASSWORD:password}};response["headers"]={"Access-Control-Allow-Origin":"*","Content-Type":"application/json"};// SignIntry{constresult=awaitcognito.initiateAuth(params).promise();console.log('User sign in success!!!',JSON.stringify(result,null,4));response["statusCode"]=200;response["body"]=JSON.stringify(result['AuthenticationResult']);returnresponse;}catch(err){console.log('User sign in failed...'+err);if((err.code=='NotAuthorizedException')||(err.code=='UserNotConfirmedException')){response["statusCode"]=400;}else{response["statusCode"]=500;}returnresponse;}};

API Gateway リソース・メソッドの追加

前回同様、「Lambdaプロキシの統合」にチェックを入れ、作成したLambda関数を選択する。

API Gatewayからのテスト実行
image.png

無事にアクセストークンが取得できたので、目的達成!!!

感想

レスポンスの有効期限(expired)が3600なのでん?と思ったら、アクセストークン・IDトークンの有効期限は1時間固定のよう。
変更できないのか?? 調べておきます。
アプリクライアントの設定で指定したトークンの有効期限はリフレッシュトークンの有効期限のことである。

今後の宿題

  • ユーザ情報を取得する

新版・中華製スマートプラグを node で制御する

$
0
0

中華製スマートプラグを node で制御するの記事はそれなりに閲覧があってありがたい限りなのですが、2020年5月に元の Github を見たところ、このセットアップ方法が deprecated になっていました。

そこで、2020年5月時点最新のセットアップ方法を改めて書いておきます。
元のセットアップガイドは GitHubにあります

スマートプラグを API で叩きたい

Amazonで スマートプラグを見つけたので購入してみました。

公式の言うところによると、こいつは Google Home / Alexa / IFTTT との連携が
可能とのこと(IFTTTのみ動作確認しました)。おうちハックがはかどりそうです。

セットアップ後、スマートフォンアプリからはほとんどラグなく操作できるのに、
IFTTT 経由だと最大 10秒近く遅延することがあったので、API で直接叩けたらいいのにな……

と思っていたのですが、ちょいと面倒だったので記事にしておきます。

Tuya IoT の設定

https://iot.tuya.comにアクセスして、アカウントを作ります。

プロジェクトの作成

ログインしたら、ページ最上部にある "Cloud Development" を選択。

image.png

[Create] ボタンを押します。

image.png

ここで適当なプロジェクト名と説明を入力します。industry は何でもいいっぽいですが、Smart homeにしました。

image.png

[create] を押すとプロジェクトが作成されます。この Access ID と Access Secret をメモっておきましょう。

アプリの作成

次に、ページ最上部の App Service を選択。左のメニューから App SDK を選ぶと、次の画面になります。

image.png

Obtain SDK ボタンを押して、Wi-Fi device solution を選択。

image.png

Next を押すとアプリの詳細を入力するように言われますが、今回はアプリを作るわけではないので適当でOKです。
アプリ名には短い名前を、次の iOS / Android Bundle name は逆ドメイン形式でアプリパッケージ名を入力します。実在しないものでも大丈夫のようです。

終わったらアプリの詳細が表示されます。

image.png

Channel ID を控えておきましょう。
node の開発では、iOS Bundle ID と Android Package Name は必要ありません。

プロジェクトにアプリをひもづけ

Cloud Development ページに戻り、最初に作ったプロジェクトを選択します。
左メニューから Linked Device を選び、タブを Linked devices added ... に切り替えます。

image.png

Add Apps ボタンを押して、先程作ったアプリを追加します。

image.png

これでクラウド側の設定は完了しました。

デバイスを追加

すでにデバイスを Tuya Smart アプリ1に追加している場合は削除します。
node から制御するように設定すると、Tuya Smart アプリからコントロールはできません(たぶん)。

あとからアプリに追加しなおしてきちんと動くかどうかは、検証していないのでわかりません。
試してみた方は編集リクエストをいただけると嬉しいです。

さて、デバイスの接続には以下の要件があります。

  • 2.4GHz 帯の WiFi があること
  • 操作している PC が、接続したい WiFi につながっていること
  • そのネットワークでクライアント間通信ができること
  • 操作している PC に他のネットワークインタフェースがないこと
    • 複数のインタフェースがあると、優先順位によってはパケットがうまく飛びません。

ちなみに、接続作業とその後の開発は別の PC を使っても問題ありません。
ということで、接続作業だけは誰でも持ってる Raspberry Pi Zero W でやるのが安定します。

普段使いのPCで接続作業をされる場合は、WiFi 以外の登録されているインタフェースを全部無効にしておきましょう。

CLI のインストール

npm i -g @tuyapi/cli

Raspberry Pi で実行したら、権限がないと言われました。
推奨ではないですが、接続作業が終わったらすぐアンインストールするつもりで、安直に sudo をつけて実行しました。

API との接続

まず、本体を電源に接続し、ボタンを長押ししてペアリングモードにします。ペアリングモードには2種類ありますが、LEDが早く点滅するほうにしてください。

ペアリングモードにしたら、以下のコマンドを実行します。

tuya-cli link--api-key"Access ID"--api-secret"Access Secret"--schema"Channel ID"--ssid"ネットワークのSSID"--password"ネットワークのパスワード"--region us

これで、うまくいくとデバイスIDとローカルキーが表示されるはずです。
あとは、この情報を使って制御することになります。

API を叩く

ID と key が取得できたら、あとは簡単です。
codetheweb/tuyapiをダウンロードしてきて、readme にある通り書けば動きます。

$ npm i -S codetheweb/tuyapi
readmeより転載
constTuyAPI=require('tuyapi');constdevice=newTuyAPI({id:'xxxxxxxxxxxxxxxxxxxx',key:'xxxxxxxxxxxxxxxx'});letstateHasChanged=false;// Find device on networkdevice.find().then(()=>{// Connect to devicedevice.connect();});// Add event listenersdevice.on('connected',()=>{console.log('Connected to device!');});device.on('disconnected',()=>{console.log('Disconnected from device.');});device.on('error',error=>{console.log('Error!',error);});device.on('data',data=>{console.log('Data from device:',data);console.log(`Boolean status of default property: ${data.dps['1']}.`);// Set default property to oppositeif(!stateHasChanged){device.set({set:!(data.dps['1'])});// Otherwise we'll be stuck in an endless// loop of toggling the state.stateHasChanged=true;}});// Disconnect after 10 secondssetTimeout(()=>{device.disconnect();},10000);

ちなみに、on('data')で取得できる dataはこんな感じなのですが、

data
{devId:'42122031cc50e3c3',dps:{'1':false,'9':0,'18':0,'19':0,'20':1074,'21':1,'22':1428,'23':14342,'24':18691,'25':965}}

dps[1]がスイッチの状態 (false = オフ / true = オン) であること以外、
まったくわかりません。おそらく電波強度とかだと思うのですが。

どなたかドキュメントを見つけたら編集リクエストをいただけると助かります。

19/7/25 追記:node-red-contrib-tuyapi-cloudにそれっぽい内容が。


  1. 複数の別名アプリが OEM で出ています。Smart Life 等があります。操作方法は変わりません。 

Node.jsでport 3000のプロセスを探してkillするDOS バッチファイル(Windows10)

$
0
0

環境: Windows10 (7でもokと思われ)
Node.jsの開発などで時折localhost:3000とタイプすると

error
Port 3000 is already in use

と出て進まないとき、手動でプロセス番号を探してkillするのが手間なので、DOSバッチファイルにしました。

processkill.bat
FOR /F "delims=" %%i in ('netstat -aon ^| findstr 0.0:3000') do set NODEPORT=%%i
echo off
@REM 出力の最後がPORTを表しているので、末尾まで読んでいる
for %%a in (%NODEPORT%) do (
set TEMPB=%%a
)
echo %TEMPB%
taskkill /pid %TEMPB% /F

実行法はコマンドプロンプトから

cmd
>processkill.bat

だけです。

元は
netstat -aon ^| findstr 0.0:3000
で出てきたプロセス番号を読んで
taskkill /pid <プロセス番号>
とするコマンドで、このプロセス番号が一意に決まっていないので、ちょっと面倒でした。

以上です。

【NodeJS】メール送信

$
0
0

NodeJSがインストールされていることを確認。

node -v
v12.16.2

nodemailerモジュールをダウンロード

npm install nodemailer

※バージョンを指定する場合

npm install nodemailer@6.4.6

ダウンロード済みのモジュールを確認

npm list --depth=0
`-- nodemailer@6.4.6

メール送信スクリプトを作成

mail.js
"use strict";constnodemailer=require("nodemailer");asyncfunctionmain(){// create reusable transporter object using the default SMTP transportlettransporter=nodemailer.createTransport({host:"example.com",port:587,secure:false,auth:{user:"example.com",// usernamepass:"XXXXXXXX"// password},tls:{// do not fail on invalid certsrejectUnauthorized:false}});// send mail with defined transport objectletinfo=awaittransporter.sendMail({from:'"テスト送信者" <sender@example.com>',// sender addressto:"receiver@example.com",// list of receiverssubject:"テストタイトル",// Subject linetext:"テスト本文",// plain text body});console.log("Message sent: %s",info.messageId);}main().catch(console.error);

実行

node mail

SIerフロントエンド・ディベロッパーのWindows10セットアップ

$
0
0

はじめに

SIer所属のエンタープライズ系フロントエンド・ディベロッパーがWindows10端末を1からセットアップすることにしたため、SIer仕様の端末を作るために最低限必要なものをメモしておきました。

ブラウザー

一通り入れましょう

便利ツール

ソースコード管理

Java開発

Node.js開発

Node.jsは公式インストーラーで入れると、Nodeのバージョン変更が大変なのでnvm経由でインストールをします。

nvm on
nvm install 12.13.1 (お好きなバージョンで)
nvm use 12.13.1

案件に応じて用意するミドルウェア

package.jsonのpeerDependenciesMetaってなんだ?

$
0
0

TL;TD

  • package.jsonに記述するフィールドで、peerDependenciesで定義したバージョンを満たしてなくても警告を出さなくするためのオプションを設定することができる (2020/05/03時点)
  • パッケージを公開する人以外はあんまり気にしなくても大丈夫そう

そもそもpeerDependenciesとは

peerDependenciesは、あるモジュールXに対するインタフェースを持っており、モジュールXから参照されることを想定するが、モジュールXのどこまでにバージョン互換性を持っているかを表記したものです。

例えば eslint-plugin-vueは、 eslintでVueファイルを扱うためのプラグインですが、どのバージョンの eslintに対して互換性のあるプラグインなのかがpeerDependenciesに記述されています。

package.json
"peerDependencies":{"eslint":"^5.0.0 || ^6.0.0"}

(引用)

上記の例だと、eslint-plugin-vueは、eslintの5系と6系に対応しているということになります。

その互換性をあえて無視して、eslintは4系を、eslint-plugin-vueは最新版を指定してインストールしてみます。すると以下のような、互換性がない旨の警告が出ます。

$ yarn add eslint@4.0.0 eslint-plugin-vue
warning " > eslint-plugin-vue@6.2.2" has incorrect peer dependency "eslint@^5.0.0 || ^6.0.0".

peerDependenciesMetaとは

peerDependenciesMetaは、 peerDependenciesの設定に関して、追加情報を定義するためのフィールドで、現在(2020/05/03)は、 optional属性のみ定義可能なようです。

optional属性はpeerDependenciesの互換性を無視しても良いかをBooleanで設定します。

例えば、もしeslint-plugin-vuepackage.jsonに、以下のようにpeerDependenciesMetaが設定されていると、前項の警告は出なくなります。(※ただし使用するパッケージマネージャによる)

package.json
"peerDependenciesMeta":{"eslint":{"optional":true}}

参考

node.jsでLINE Notifyを使ってみた

$
0
0

概要

webサービスやバッチ処理を作っていると、何かアクションがあった事をすぐに気づきたいと思うことがあるかと思います。
この通知がよく使うアプリに送られて来たら気づきやすいですよね!?

よく使うアプリは人それぞれかと思いますが、LINEは多くの人が利用しているかと思います。
そして、LINEでは個人で簡単に通知を投げられる機能 LINE Notifyを提供しています。

ここでは、LINE Notifyのパーソナルアクセストークンでの通知をnode.jsを用いて行うまでの軌跡をまとめています。

ざっと全体の流れ

手順はざっと以下な感じ。

  1. LINE) パーソナルアクセストークンを取得
  2. 開発) アクセストークンを使ってrequestを投げる
  3. LINE) 通知が届いた事を確認

とても簡単!

手順

1. パーソナルアクセストークンを取得

LINEアカウントを持っていれば簡単に作れます。

1-1. LINE Notifyページへ遷移

以下URLよりLINE Notifyのページへ遷移しましょう。
https://notify-bot.line.me/ja/

1-2. LINE ログイン

LINEにログインします。
メアドやパスワード登録がされている必要があります。
また、LINEアプリでPCでのログインを許可していないと弾かれるので、事前に外しておきましょう。

1-3. マイページに遷移

右上のアカウントメニューよりマイページに遷移。

1-4. アクセストークンの発行

マイページにある「アクセストークンの発行(開発者向け)」より、「トークンを発行」をクリックし、
トークン名や通知したい先を選択して発行!

1-5. アクセストークンをメモ

発行するとアクセストークンが表示されます。
このトークンは再発行されないので、確実にメモリましょう。
また、このトークンが流出すると、第三者が投稿し放題なので取り扱い要注意。


LINE_Notify.png

ここまででLINE Notifyの準備は完了です!

2. アクセストークンを使ってrequestを投げる

取得したTokenを利用して通知してみます。
ざっくり言うと、POSTでトークンをheaderに添えてメッセージ投げれば投げれます。簡単!

詳しいリクエスト方法は公式ドキュメントをみていただけたらと思います。
LINE Notify API Document
("通知系"項目が本記事で利用しているパーソナルアクセストークンでの通知です)

node.jsだとこんな感じで投げられるかと思います。
(requestモジュールがinstallされている前提)

app.js
constrequest=require('request');constmessage=`これは
テスト
ですよ`;sendRequest(message);/**
 * LINE Notifyへ送信依頼
 * @param {Object} message - 送信メッセージ
 */functionsendRequest(message){constoptions={uri:'https://notify-api.line.me/api/notify',headers:{// TOKENを誤ってgitに上げてしまわないように、環境変数から取得するようにした'Authorization':`Bearer ${process.env.LINE_TOKEN}`},form:{message}};request.post(options,(error,response,body)=>{if(error){console.error(error);return;}console.log(body);});}

実行

$ LINE_TOKEN=<取得したTOKEN> node app.js
{"status":200,"message":"ok"}

LINEの通知先にLINE Notifyさんが通知してきたら成功です。
(どのTOKENから通知されたかは、メッセージの先頭にテキストでTOKEN名が書かれています)

終わりに

利用準備も簡単で、実装もシンプルなのですぐに通知を実装したい時とか便利なのではないでしょうか?
ただし、1時間に叩けるAPIの上限はトークンごとに1000回までらしいのでご注意ください。
(1000回/時 LINE API叩く仕様見直したほうが良さそうですががが)

CloudFunctionsで文字列をハッシュ化したいならcrypto

$
0
0

複雑な家庭の事情でどうしてもfirebase上のアプリで任意の値をMD5にしなければならなかったのでメモ。

nuxt上でなんか処理しようかとおもったがいいライブラリがなく、CloudFunctionsならNode.jsなのでcryptoモジュールが使えることに気づいた。

/functions/index.js
constcrypto=require('crypto');consthash_ni_shitai_value="ハッシュ化したい値";consthash_ni_natta_value=crypto.createHash('md5').update(hash_ni_shitai_value).digest('hex');returnhash_ni_natta_value;

phpのmd5($str)ほど短くはないけどこれが最短なのでは。

Radiko再生アプリ

$
0
0

1 モチベーション

作業中にBGMが聞きたい時、RadikoのWebサイトからラジオ日経第2の音楽チャンネルを垂れ流しにしております。Radikoの場合、過去1週間分の番組であれば好きな時間にアクセスしてラジオ番組を楽しむことができます。ただ残念ながらRadikoのWebページはこれでもかというくらいユーザビリティーが悪く、Webページ自体も重く応答性も悪いと感じています。例えば今週火曜日19:00のラジオ日経第2の番組を聞きたい場合、再生までたどり着くのに1~2分程度かかってしまいます。
そこで、ボタン1つで、聞きたい番組にアクセスできるようにしてユーザービリティーを改善したいと思いました。

65.JPG

2 作成したアプリ

ラジオ日経第2(21:15~、21:30~の番組はラジオ日経第2)の聞きたい時間帯をセレクトボタンで選択し、クリックするのみでWebページに自動でアクセスし、音楽をストリーミングします。このアプリを作ってからは、わずか3クリックでラジオ日経第2の聞きたい番組のストリーミングができるようになり、ユーザービリティーが大きく向上しました。

66.gif

3 どうやって実現したか

ハードウエアはラズベリーパイ4800円のUSBスピーカーを組み合わせて作りました。

66.JPG

ソフトウエアは、フロントエンドはVue.js, バックエンドはpythonで実現しています。pythonのWebスクレイピングライブラリseleniumを使いRadikoのWebページから指定した番組データにアクセスし、番組音声を再生しています。また、環境を別のハードウエアに移動することも考え、仮想化アプリDockerの上で、フロントエンドを作成しております。

67.JPG

4 ソースコード

4-1 Vue-CLIのインストール

環境構築には、Vue-CLIのインストールが必要です。Vue-CLIのインストールはこちらに記載しています。

Vue-CLIのインストールが完了すると、ディレクトリ(下記図で説明すると第2階層と第3階層)が構成されているので、「Radiko.vue」「index.js」「radiko.py」「radikoend.py」「radikoendforce.py」を下記図記載のとおり所定のディレクトリに配置してください。

70.JPG

4-2 コードファイルの配置

こちらに必要ファイルをアップロードしました。
Radikoi.vueは、Vue-CLIの /scr/componentsに配置してください。
index.jsは、node.jsが動作する任意の場所にインストールしてください。

Viewing all 8882 articles
Browse latest View live