- 投稿日:2020-01-20T23:45:14+09:00
Node.js(Express) + Multer + S3で画像をフォームからアップロードする
目的
フォームから画像やファイルをクラウド上(今回はS3)にアップロードするため
背景
最近Nodeを触っていて、ググっても色々情報はあるものの、フォームからS3に上げるどうこうっていうのはまとまってなかったので。
前提条件
・AWS
・S3
・環境変数、aws-sdk, multer, multer-s3をインストールしておくこと
上記のセットアップが終わっていること。コード
node.jsvar express = require('express'); var router = express.Router(); var path = require('path'); var AWS = require('aws-sdk'); var multer = require('multer'); var multerS3 = require('multer-s3'); const s3 = new AWS.S3({ accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_S3_SECRET_KEY, Bucket: '自分のバケット' }); const profileImgUpload = multer({ storage: multerS3({ s3: s3, bucket: '自分のバケット', metadata: function (req, file, cb) { cb(null, {fieldName: file.fieldname}); }, key: function (req, file, cb) { cb(null, Date.now() + file.originalname); } }), limits: { fileSize: 2000000 }, // In bytes: 2000000 bytes = 2 MB fileFilter: function (req, file, cb) { checkFileType(file, cb); } }).single('フォーム上のnameのパラメータ'); function checkFileType (file, cb) { // Allowed ext const filetypes = /jpeg|jpg|png|gif/; // Check ext const extname = filetypes.test(path.extname(file.originalname).toLowerCase()); // Check mime const mimetype = filetypes.test(file.mimetype); if (mimetype && extname) { return cb(null, true); } else { cb('Error: Images Only!'); } } router.get('/', function (req, res, next) { var data = { title: '画像アップロード', }; res.render('index', data); }); router.post('/profile-img-upload', (req, res, next) => { profileImgUpload(req, res, (error) => { if (error) { console.log('errors', error); res.json({ error: error }); } else { // If File not found if (req.file === undefined) { console.log('Error: No File Selected!'); res.json('Error: No File Selected'); } else { // If Success const imageName = req.file.key; const imageLocation = req.file.location; // Save the file name into database into profile model res.json({ image: imageName, location: imageLocation }); } } }); });index.pugform(action='/profile-img-upload', enctype='multipart/form-data', method='post') h3 プロフィールイメージ input(type='file', name='profileImage') input(type='submit', value='登録')感想
バババッと適当に書いてしまったので、もし質問等あれば、コメントください!
何を思ったのか急に投稿してみようって思ったので、初投稿です。
大した記事でないけれど、次回以降は丁寧に書いて、価値のある記事を書きます
- 投稿日:2020-01-20T20:23:11+09:00
obnizのBLEでペリフェラルに接続する
BLEデバイスを見つけるだけでなく接続するというのをやってみます。
接続することで実際にデータを送ったり、データを受け取ることができるようになります。見つけてから接続
接続するためにはまず、見つけなければなりません。
そして見つけたperipheralに対してconnect()を呼ぶことで接続できます。接続とスキャンの同時実行はできないため、自動でスキャンは停止されます。
ただ、接続してしまったあとの両立はできますので再度スキャンの実行ができます。それでは、同じくアプリで作ったBlankというBLEデバイスに対して接続してみます。
var obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localName: "Blank" }; var peripheral = await obniz.ble.scan.startOneWait(target); if(peripheral) { console.log("found"); await peripheral.connectWait(); console.log("connected"); obniz.ble.scan.start(); } }callbackではこのように記載できます。
var obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localName: "Blank" }; obniz.ble.scan.start(target); obniz.ble.scan.onfind = function(peripheral){ console.log("found"); obniz.ble.scan.end(); peripheral.onconnect = function(){ console.log("connected"); } peripheral.ondisconnect = function(){ console.log("closed"); } peripheral.connect(); }; obniz.ble.scan.onfinish = function(peripheral){ console.log("scan timeout!") }; }接続できたでしょうか。
うまく行けばこのようなログが出ると思います。接続するためにはscanを終了してから接続する必要があります。
awaitな書き方
スキャンと同じく、ペリフェラルとの接続も
await
を利用して書くことができます。var obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localName: "Blank" }; var peripheral = await obniz.ble.scan.startOneWait(target); if(peripheral) { console.log("found"); var connected = await peripheral.connectWait(); if(connected){ console.log("connected"); }else{ console.log("failed"); } } }エラーハンドリング
今は接続しているだけですが、通信を始めるとエラーが起こることがあります。
途中で相手がいなくなったとか、できないことを要求したとか。ペリフェラルとのあいだで起きたエラーはこのように検出できます。
var obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localName: "Blank" }; obniz.ble.scan.start(target); obniz.ble.scan.onfind = function(peripheral){ console.log("found"); obniz.ble.scan.end(); peripheral.onerror = function(err){ console.log("error : " + err.message); } peripheral.onconnect = function(){ console.log("connected"); } peripheral.ondisconnect = function(){ console.log("closed"); } peripheral.connect(); }; obniz.ble.scan.onfinish = function(peripheral){ console.log("scan timeout!") }; }エラーには何に対してやった何のエラーなのかが入っています。
詳しくはBLE Central Docをご覧ください。切断
接続できたペリフェラルと切断するには
peripheral.disconnectWait();を利用します。
繋がったらすぐに切るというプログラムにする場合はこのようになります。var obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localName: "Blank" }; obniz.ble.scan.start(target); obniz.ble.scan.onfind = function(peripheral){ console.log("found"); obniz.ble.scan.end(); peripheral.onconnect = async function(){ console.log("connected"); peripheral.disconnect(); } peripheral.ondisconnect = function(){ console.log("closed"); } peripheral.connect(); }; obniz.ble.scan.onfinish = function(peripheral){ console.log("scan timeout!") }; }これを実行するとこのようになります。
または、同期的な切断は以下のようなやり方です。
var obniz = new Obniz("OBNIZ_ID_HERE"); obniz.onconnect = async function () { await obniz.ble.initWait(); var target = { localName: "Blank" }; var peripheral = await obniz.ble.scan.startOneWait(target); if(peripheral) { console.log("found"); await peripheral.connectWait(); console.log("connected"); await peripheral.disconnectWait(); console.log("disconnected"); } }
- 投稿日:2020-01-20T19:35:38+09:00
gulpへの理解を深め、環境構築をしてみよう!
はじめに
フロントエンドエンジニアとして働き始めたばかりの新米エンジニアです。
今回はフロントエンドに必須のタスクランナーであるgulpについてです。
自分自身、gulpをきちんと理解して使用しておらず、勉強しても時間が経過すると忘れると思ったので、今回はメモとして残す意味で、あとは誰かの役に立てば良いな思いながら書いて行こうと思います。
初心者の方、他のタスクランナーからgulpに移行しようと思っている方にも分かりやすく、gulpについて&環境構築&実践の説明をしていきます。
主な内容
- gulpとは
- gulpで出来る事
- 導入までの簡単な流れ
- Node.jsとは
- package.jsonとは
- npmとは
- 実際に環境構築してみよう
- 1 . Node.jpのインストール
- 2 . package.jsonファイルの作成
- 3 . gulpをインストール
- 4 . gulpfile.jsを作成
- 準備:package.jsonの編集の仕方
- 実践:gulpを動かそう!
- さいごに
以上の流れで今回は進めていきたいと思います。
フォルダ構成
今回はデスクトップにいファイルを作成しました。
gulp-test ├ htdocs/ │ └ index.html │ └ css/ │ └ style.css └ src/ └ scss/ └ style.cssgulpとは
- フロントエンド開発用のタスクランナーです。(ビルドシステムヘルパーと呼ばれる事もある)
- タスクランナーとは、処理(タスク)を自動化で行ってくれるツールです。 gulpにはパッケージが沢山あり、プロジェクトに合わせて実行したい処理を組み合わせる事で、様々なタスクを実行できます。
つまり、普通だったら手間がかかるめんどくさい作業を、自動的に実行してくれるのがgulpと言う事です。
使用したい機能(パッケージ)を選択して導入するだけで、自分でカスタマイズした好きな機能で実装することができるのです。しかも案件ごとに。
なんて素敵なツールなのでしょう。
<参考サイト>
gulpの公式サイト:https://gulpjs.com/
リポジトリ:https://github.com/gulpjs/gulp※開発の現場では、今回ご紹介する
gulp
とGrunt
がよく使用されます。
→gulpとGruntの違いについて詳しく知りたい方は「絶対つまずかないGulp入門」こちらの記事が分かりやすかったのでご参考までに。gulpで出来る事
では、それほどめんどくさい作業をgulpが行ってくれるのか。
よく使用されるパッケージの例を挙げてみたいと思います。SassやLESSなどのコンパイル
SassやLESSなどのCSSプリプロセッサ(CSSメタ言語)を自動的にCSSにコンパイルしてくれます。
※コンパイル:ソースコード(プログラミング言語)を、オブジェクトコード(コンピュータが実行可能な形式)に変換する作業
※エディタの拡張機能で、コンパイルを自動的に行ってくれる物もあります。ベンダープレフィックスの自動付与
IE対策などで使用する、CSSの
ベンダープレフィックス
(-webkit-や-ms-がついたcssコード)を自動的に吐き出してくれます。<参考記事>
ベンダープレフィックスとは画像の圧縮
ウェブサイトを表示するロード時間を減らす方法として、画像の圧縮があります。
サイトからの離脱率を減らし、ユーザーに気持ちよくサイトをみてもらう為にも、画像の圧縮は必須です。
手作業でtinypngやtinyjpg、jpegminiでも圧縮する事もできますが、gulpはその作業を自動的に行ってくれます。CSSやJavaScriptなどのミニファイ
JavaScriptやCSSなどのコードの中の不要な改行、インデントなどを削除し、動作はそのままで圧縮・軽量化してくれます。
これもロード時間を減らす方法として大事な作業です。
※ミニファイ:圧縮,軽量化ブラウザーシンク
HTML/CSS/JSを保存するたびに、ブラウザをリロードしてくれます。
他にも多くのパッケージがgulpには存在しているので、お好みでカスタマイズして使用できます。
gulpのパッケージが書いてある一覧ページがありましたので、ご参考にどうぞ。
gulp-パッケージ一覧 : https://qiita.com/oreo3@github/items/0f037e7409be02336cb9導入までの簡単な流れ
gulpを導入するまでの流れ、説明を大雑把にしていきます。
1 . Node.jsのインストール
2 . package.jsonファイルを作成
3 . gulpをインストールNode.js とは
JavaScriptは本来クライアントサイドで動く言語であり、HTMLで書かれたページに動きをつけたりする。
→Node.jsはサーバサイドで動くJavaScriptである。package.jsonとは
npmではpackege.jsonというファイルで依存関係のあるパッケージを一括インストールできたり、タスクも管理できる。
必要な設定事項を記述することで、簡単にプロジェクトの管理や環境構築を行うことができるのだ。npmとは
正式名称は"Node Package Managernpm"と言い、Node.jsのパッケージを管理することができる。
Node.jsをインストールすることで自動的にインストールされます。環境構築してみよう
次は、実際にコマンドを打ってgulpを使用してみましょう。
1. Node.jsをインストール
こちらのリンクからNode.jsをダウンロードします。
↓
Node.jsの公式サイト
https://nodejs.org/ja/Windowsの方はこちらからです
↓
Node.jsダウンロードページ
https://nodejs.org/ja/download/ちなみに、ダウンロードの際は推奨版を入れる事をオススメします!!!
(最新版だとパッケージで対応してない場合がある)ダウンロードが終わったら、保存されたファイルを解凍して開いてくださいね。
インストールが完了したらターミナルを起動し、以下のコマンドを実行します。
node -v ・・・Node.jsのバージョンの確認 ↓ v12.13.1自身がダウンロードしたバージョンが表示されたら完了です。
*余談
ちなみにですが、ターミナルの使用方法は複数あり、
- 「ターミナル」Macに入ってるアプリケーション
- 「iTerm2」
- エディタ(VScode,Atom,Sublimeなど)
から使用することが多いです。
(私はエディタ:VScodeからがほとんど)詳細はこちらをご参考にしてください◎
VSCodeでターミナルを起動するショートカット:https://utano.jp/entry/2018/01/visual-studio-code-terminal-window/
Macターミナルは何ができる?初心者向けの使い方と困った時のQ&A:https://www.sejuku.net/blog/42022.package.jsonファイルを作成
パッケージをインストールするにあたり、まずはプロジェクトディレクトリ配下にpackage.jsonファイルを準備します。
この記事の冒頭に表記したフォルダ構成のところを参考にしてくださいね。
cd
コマンド(=移動する)でプロジェクトのディレクトリの場所まで移動します(パスは適宜変更して下さい)。cd \Users\{ユーザ名}\Desktop\gulp-test今回はデスクトップにgulpを導入したいファイル(gulptest)を作成したので、上記のようなパスになりました。
次です。
node.jsをインストールをするとnpmコマンドが使えるようになっています。
package.jsonファイルを作成するために、このコマンドを入力してください。npm init -yこの表示が出てきたら成功です。
package.json{ "name": "gulp-test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
-y
をつけたことで、設定がデフォルトになりました。もし、npmをインストール済みであれば、アップデートします。
npm update -g npm(npmのアップデートはnpm自体で実行)
もし、permissionがなんとか〜〜〜ってエラーが出たら、頭にsudo
をつけて実行してみてください!sudo npm update -g npm
sudo
コマンドは、スーパーユーザー:root(や他のユーザ)の権限でコマンドを実行するときに使用します。わざわざユーザーを切り替えずに、他のユーザーの権限で操作が可能なので、非常に便利で、必殺技みたいな感じです。(乱用禁止)
npmのバージョンも確認してみましょう。
npm -v ・・・npmのバージョンの確認 ↓ 6.13.63. gulpをインストール
やっと、gulpを導入するところまで来ました。
gulpのダウンロード
npm install -D gulp ・・・ローカルインストール npm install -g gulp ・・・グローバルインストール両方のコマンドを打って導入します。
ローカルインストールはそのプロジェクトのフォルダ内でのみ利用でき、グローバルインストールはそのマシン上のどこからでも利用できるようになるります。
デフォルトはローカルインストールされるようになっており、グローバルインストールしたい場合は-g
オプションを付けて実行します。<参考記事>
gulpのアプローチ "なぜグローバルとローカルにインストールが必要なのか"
node_mosules
というファイルが作成されていたら成功です!!!先程まではpackage.jsonファイルしかありませんでしたが、
gulを導入したことで、ファイルが3つに増えているかと思います。package.json
node_modules
package-lock.jsonまた、package.jsonに記載されてる内容を確認すると
devDependeces
という項目が追加されてるかと思います。jackage.json{ "name": "gulp-test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "gulp": "^4.0.2" } }下二行ですね。ちゃんと、インストールしたgulpのバージョンも記載してあります。
"gulp": "^4.0.2"
ここまで来たらあと少しです!
4.gulpfile.jsを作成
gulpを使用する準備ができたので、
具体的に実行するタスク内容を設定するgulpfile.js
を他のファイルと同じディレクトリに作ります。touch gulpfile.js中身は空ですが
gulpfile.js
が作成されたかと思います。
touch
はgulpに関係はなく、ターミナルのコマンドでファイルを新規作成するものです。この時点でディレクトリ内に存在してるファイルは
node_modules
package-lock.json
package.json
gulpfile.jsの4つです。
フォルダの中身を確認してみましょう。
gulp-test ├ htdocs... ├ src... ├ node_modules ├ package-lock.json ├ package.json └ gulpfile.jsdesktop配下のgulp-testというファイルの中に、4つのファイルが追加されてるのがわかります。
最後にgulpのバージョンを確認してみましょう。
gulp -v ・・・gulpのバージョンの確認 ↓ CLI version: 2.2.0 Local version: 4.0.2もし、Localのバージョンが下記のように
Unknown
になっていたらCLI version: 2.2.0 Local version: Unknown以下のコマンドを入力すれば大丈夫です◎
sudo npm install --save-dev gulpgulpfile.js内に
以下のコードを入力することで、gulpが使用できるようになります。gulpfile.jsvar gulp = require("gulp");これで、gulpを使用する一通りの作業はできたと思います。
お疲れ様でした!!!
準備:gulpfile.jsの編集の仕方
コマンドラインで必要なパッケージをインストール
以下のコマンドを使用する事で、パッケージをインストールできます。
npm install --save-dev {パッケージ名}また、コマンドは以下のように省略することも可能です。
//"install" → "i" //"--save-dev" → "-D" npm i -D gulp {パッケージ名}gulpfile.jsでタスクを作成
package.jsに記入するタスクの書き方の例です。
gulpfile.js//使うパッケージの宣言 var {変数} = require('{パッケージ名}'); //個々のタスク gulp.task('{タスク名}', function(){ //実行される処理 }); //watchタスク… タスク名は任意。「gulp.watch()」でファイルの状態を監視・タスク実行 gulp.task('watch', function(){ gulp.watch('{監視したいファイルのパス}', [{実行するタスク名}]); }); //defaultタスク… 「npx gulp」コマンドで実行するタスクを設定 gulp.task('default', ['{タスク名}', 'watch']);地味に大事な余談
パッケージをダウンロードする時のコマンド
npm i -D gulp {パッケージ名}
の-D
を実行することで、package.json
のdevDependencies
インストールしたパッケージ名とバージョンが記録されます。
-D
つけない場合はdependencies
に記録されます。
devDependencies
は主に開発用。(gulpやsassなど)
dependencies
は表側。(jqueryやslickなど)実践:gulpを動かそう!
では、実際にgulpを動かしてみましょう!
私がいつも使用するのはこれらのパッケージです。
- SASSのコンパイル
- ベンダープレフィックスを自動的に付与
- エラーが原因でタスクが強制停止するのを防止
この3つを行うために必要な
gulpfile.js
を書きたいと思います。まずは、ターミナルに以下のコマンドを実行して、パッケージをインストールします。
※省略した形で書きます。npm i -D gulp npm i -D gulp-sass npm i -D gulp-postcss npm i -D gulp-autoprefixer npm i -D gulp-sass-glob npm i -D gulp-csscomb全部打つのは面倒なので、もっと省略した形があります。
以下のようにパッケージごとに半角で区切って一行にまとめて書くことで、一括インストールすることも可能です。//npm i -D {パッケージ} {パッケージ} {パッケージ} //例 ) npm i -D gulp gulp-sass gulp-postcss gulp-autoprefixer gulp-sass-glob gulp-csscomb実行します。
次に、gulpfile.jsにはタスクの内容を記述します。
gulpfile.jsvar gulp = require('gulp'); //gulpを使用する宣言 var sass = require('gulp-sass'); //SASSの使用 var postcss = require('gulp-postcss'); var csscomb = require('gulp-csscomb'); //cssを綺麗に並び替える var sassGlob = require('gulp-sass-glob'); // Sassの@importにおけるglobを有効にする gulp.task('sass', function(){ return gulp.src('src/**/*.scss') .pipe(sassGlob()) .pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError)) .pipe(postcss([ require('autoprefixer')({grid:true}), ])) .pipe(gulp.dest('htdocs/css/')) .pipe(csscomb()); }); gulp.task('w', function(){ gulp.watch('src/**/*.scss', gulp.series('sass')); });確認:gulpが実行されているか見てみよう!
それでは現在のディレクトリの確認です。
構造はこのようになっているかと思います。gulp-test ├ htdocs/ │ └ index.html │ └ css/ │ └ style.css └ src/ │ └ scss/ │ └ style.css ├ node_modules ├ gulpfile.js ├ package.json └ package-lock.jsonそれでは、実際にsassがコンパイルされるか、確認してみたいと思います。
src/scss/style.css
に以下のコードを記入しましょう。style.scss.box { display: flex; align-items: center; justify-content: center; color: plum; } .button { transition: 0.3s; background-color: grey; color: #000; &:hover { transition: 0.3s; background-color: #fff; } }そして、実行するために、このコマンドを入力します。
gulp wすると、
htdocs/css/style.css
には見事コンパイルされ、ベンダープレフィックスが付与されたコードになってるかと思います。style.css.box { display: -webkit-box; display: flex; -webkit-box-align: center; align-items: center; -webkit-box-pack: center; justify-content: center; color: plum; } .button { -webkit-transition: 0.3s; transition: 0.3s; background-color: grey; color: #000; } .button:hover { -webkit-transition: 0.3s; transition: 0.3s; background-color: white; }
command + s
で保存する必要もなく、
stylle.scssの内容を変更するだけで自動的にコンパイルされるのもわかるかと思います。自動的に更新されるのはとても便利ですね。
自分の好きなプラグインを見つけて、オリジナルのgulpを作ってみましょう!
お疲れ様でした!!!
おまけ
今までの流れが、初めてgulpを使用する人に向けた内容です。
一度gulpの環境構築をしたら、
2回目以降は初回と少し違った流れになります。主に違うのは
①Node.jsをインストールしなくて良い
②nodeとnpmとgulpのバージョンを確認して、必要があればアップデートする
くらいです。npmのアップデートの時に、npm audit fixというエラーが出る時があるので、
私が以前書いた記事を先に軽く読んで、参考にしていただけると幸いです。<参考サイト>
昔gulpを使用していたサ大体ここら辺のコマンドを実行したら動きます◎
npm init -y npm install -D gulp gulp -v npm install -D gulp gulp-sassご参考までに。
さいごに
gulpの使い方は、なんとなくご理解いただけたでしょうか?
最初は私も訳がわからなかったのですが、最近は使っていくうちに理解できるようになってきました。フロントエンドは毎年新しい技術が出てくるため追いつくのが大変ですが、がんばっていきましょう><!!!
実践できるか何度も確認して記事にしていますが、間違いや不備等見つけた方がいらっしゃいましたら
ご連絡いただけると幸いです。参考サイト一覧
https://www.go-next.co.jp/blog/web/soft_tool/13407/#Gulp
https://parashuto.com/rriver/tools/updating-node-js-and-npm
https://ics.media/entry/3290/
- 投稿日:2020-01-20T13:52:07+09:00
Microsoft Bot Framework SDK for JavaScript で特定のメッセージに特定の返答を返せるように実装してみる
はじめに~目的
この記事ではMicrosoft Bot Frameworkをベースにボットの挙動を編集してみました。
Microsoftの公式チュートリアルでは質問に対しておうむ返しするものと、Q&Aのチュートリアルがあります。
ただ、Q&A対応ボットのチュートリアルはいろいろ複雑で、どの部分がどのように動いているかがパッとわかりにくかったので、そもそもどの部分がBotの制御にどうかかわっているのか実際に動かして確認してみました。目標
公式チュートリアル「Bot Framework SDK for JavaScript を使用したボットの作成」で作ったボットに「こんにちは」というメッセージが来た時だけ、「Hi」と返し、それ以外はEchoするように書き換えてみます。
前提条件
Windows10のローカル環境で実行します。
また、下記チュートリアルが完了している想定になります。
Bot Framework SDK for JavaScript を使用したボットの作成このチュートリアルを実施すると、入力したものにそのままオウム返しするボットができます。
参考にしたもの
主にMicrosoft Bot Frameworkのリファレンスを参考にしています。
実行環境はBot Framework Emulatorで実行します。また、@Shota_Fukudaさんの下記記事を参考にさせていただきました。
Bot Frameworkと雑談対話APIを使用したチャットBotMicrosoft Bot Frameworkの構造
前提条件にあるようなチュートリアルを実施していると、bot.tsが生成されますが、下記のようなEchobotクラスの制御があります。このEchoBotクラスがボット挙動の制御をしている部分になっています。
ここをいじることで返答をさせることができます。node.jsexport class EchoBot extends ActivityHandler { constructor() { super(); // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types. this.onMessage(async (context, next) => { const replyText = `Echo!!: ${ context.activity.text }`; await context.sendActivity(MessageFactory.text(replyText, replyText)); // By calling next() you ensure that the next BotHandler is run. await next(); }); this.onMembersAdded(async (context, next) => { const membersAdded = context.activity.membersAdded; const welcomeText = 'Hello and welcome!'; for (const member of membersAdded) { if (member.id !== context.activity.recipient.id) { await context.sendActivity(MessageFactory.text(welcomeText, welcomeText)); } } // By calling next() you ensure that the next BotHandler is run. await next(); }); } }Microsoft Bot Frameworkが実行できる挙動(ActivityHandlerで定義されているハンドラ)に関しては、ボットのしくみ:ボットの構造の周辺に載っていますので、参考にしてみてください。
実際に構成してみる
「こんにちは」というメッセージが来た時だけ、「Hi」と返し、それ以外はEchoするように書き換えてみます。
メッセージに対して実行を書けるので、onMessageハンドラ内に編集します。
変更前this.onMessage(async (context, next) => { const replyText = `Echo!!: ${ context.activity.text }`; await context.sendActivity(MessageFactory.text(replyText, replyText)); // By calling next() you ensure that the next BotHandler is run. await next(); });変更後this.onMessage(async (context, next) => { let replyText: string = ''; if (context.activity.text != null && context.activity.text === 'こんにちは') { replyText = `HI!`; } else { replyText = `Echo!!: ${ context.activity.text }`; } await context.sendActivity(MessageFactory.text(replyText, replyText)); // By calling next() you ensure that the next BotHandler is run. await next(); });ローカルでの反映
一旦動いているものを切って、下記のようにcmd上で再起動します。
npm startローカルで利用する分にはこれだけで書き換えたコードが機能します。すごい。
動作結果
ちゃんと「こんにちは」に対して「Hi!」と返してくれました。
参考資料
- 投稿日:2020-01-20T13:22:09+09:00
nodeのバージョンが古く、npmがアップデートできない(バージョン管理:nodebrewとanyenv)
はじめに
概要
Webサイト作るお仕事をしている方向けの内容です。
- gulpを使用してフロントエンドの環境構築
- バージョン管理はnodebrewとanyenv
- 既にgulpを使用している
(nodebrewとanyenvに関しては後々記事を書いていこうと思います。)
出来事
gulpを使用したかったので、他の記事にもあるように
① Node.js
② npm
③ gulpの順番で確認しました。
今回は私が普段からgulpを使用しているので、ダウンロードではなくバージョンを確認してgulpを導入する。という方向から進めました。
(もしバージョンが古ければ適宜アップデートする必要がある)nodeバージョン確認
まず、ターミナルから、Node.jsのバージョンを確認します。
node.jsnode -v結果
node.jsv9.2.0nodeのバージョンが、9.2.0であることがわかりました。
(当時の最新バージョンは13.6.0、推奨バージョンは12.14.1なので若干古いことが分かります。)npmのバージョンの確認
npm -v結果
EROOR: npm is known not to run on Node.js v9.2.0 Node.js is 9 is supported but the specific version you're running has a bug known to break npm.Please update to at least 9.0.0 to use this version of npm.You can find the latest release of Node.js at https://node.js.org/はい、エラーが出ました。
エラー内容
なんとなくの翻訳
→npmはNode.jsの9.2.0で実行されない
→Node.jsは9がサポートされているが、実行している特定のバージョンにはnpmを壊すバグがあるよ(?)
→最低9.0.0のバージョンにアップデートしてください先程調べたように、現在のnodeのバージョンは9.2.0
けど、このエラーは最低9.0.0のバージョンにアップデートして欲しいらしい。謎。試した事
色々コマンドを試しました。
(例)
nodebrew ls-remote ・・・nodebrewで使用可能なnodeのバージョンの確認 nodebrew install-binary {バージョン} ・・・nodebrewを使用してnodeのアップデート sudo npm install -g npm ・・・npmのアップデート他にも沢山。
どれもダメでした。そして最終的に行き着いた、解決できそうな方法が2つ。
選択肢
- 選択肢 1
- このまましつこくトライする(nodeのアップデートを続けてみる)
- 選択肢 2
- 一度nodeを消して、再ダウンロード
↓
選んだのは、選択肢 1 の、しつこくトライ。
理由
node.jsのバージョン管理をnodebrewとanyenvで行なっており、まだ詳しく理解していないので、更なるエラーが出るのが怖かったから。
解決した方法
nodenv install -l ・・・インストール可能なバージョンのリストを確認結果
12.8.1 12.9.0 12.9.1 12.10.0 12.11.0 12.11.1 12.12.0 12.13.0 12.13.1 13.0.0 13.0.1 13.1.0 13.2.0 chakracore-dev chakracore-nightly chakracore-8.1.2 chakracore-8.1.4 chakracore-8.2.1 chakracore-8.3.0 ・・・・・・たくさん出てきます。
自分が今欲しいと思っているバージョンをインストールしよう。
nodenv install {バージョン}↓ 私は当時の推奨版をインストールしました。
nodenv install 12.13.0過去に複数のバージョンをインストールしてきていると思うので、
以下のコマンドでインストール済みのバージョンを確認してみます。nodenv whencee npm結果
8.10.0 9.2.0 10.9.0 12.13.1コンピュータのデフォルトのバージョンを指定します。
指定できるのはインストールしたバージョンなので、nodenv global 12.13.1再度、nodeのバージョンを確認してみました。
node -v v12.13.1nodeのアップデートが終わったところで、npmのエラーがどうなったのか確認しました。
なんと消えていました。nodeとnpmのアップデートが無事終わったと言う事で一件落着。
さいごに
"自分のPCの開発環境を知ってるのは自分だけだからね"
と、エンジニア歴十数年のベテランインフラエンジニアの友人に言われた事を思い出しました。
ひとつひとつの原理原則を、きちんと理解して進めないといけないなぁと思うばかり。参考サイト
・MacにNode.jsをインストール(anyenv + nodenv編)
https://qiita.com/kyosuke5_20/items/eece817eb283fc9d214f
- 投稿日:2020-01-20T12:01:27+09:00
Auth0で簡単にユーザー認証を実装(花粉カレンダー作成②)
概要
耳鼻咽喉科の開業医をしています。
花粉症の患者さんに使ってもらえるような花粉飛散情報が分かるカレンダーアプリを作りたいと思っています。
前回カレンダーを表示して予定を入れるところまで挑戦してみました。
Vue.js×FullCallendarでカレンダー作成(花粉カレンダー作成①)今回はユーザー個別のカレンダーを表示するために、ユーザー認証機能の実装に挑戦しました。
完成動画
作成
こちらの記事を参考にさせていただきました。ありがとうございました。
Auth0 + GitHub Pagesでミニマムなログインサンプルを作る
ファイル一つコピペで試すAuth0+Vue.jsのログインサンプル1. Auth0のアカウント作成・サインイン
こちらから行ってください。
Auth0ホームページ2.アプリケーションの作成
[Applications]>[Settings]のタブに移動し、
Allowed Callback URLs、Allowed Logout URLsを以下に設定します。
http://localhost:8080/#/calendar
Allowed Web Origins、Allowed Origins (CORS)を以下に設定します。
http://localhost:8080
DomainとClient IDは後で使うのでひかえておきます。3.ユーザー認証の実装
以前作成したCalendar.vueに書き込んでいきます。
Vue.js×FullCallendarでWEBカレンダー作成(花粉カレンダー作成①)templateタグの中に以下を追加していきます。
<button id="btn-login" v-on:click="auth0login()">Log in</button> <button id="btn-logout" v-on:click="auth0logout()">Log out</button> <div v-if="login" id="gated-content"> <p> You're seeing this content because you're currently </p> <label> User profile Image: <img :src="userData.picture" id="ipt-user-profile-image" width="200px"> <br /> </label> <label> User profile: <pre id="ipt-user-profile">{{userData}}</pre> </label> <label> Access token: <pre id="ipt-access-token">{{userData.token}}</pre> </label> </div>ログイン後にカレンダーが表示されるようにします。
<div v-if="login"> <FullCalendar default-view="dayGridMonth" :locale="locale" :header="calendarHeader" :weekends="calendarWeekends" :plugins="calendarPlugins" :events="calendarEvents" @dateClick="handleDateClick" /> </div>scriptタグの内に以下を書き込んでいきます。
import createAuth0Client from '@auth0/auth0-spa-js';data(){ }の中に以下を追記します。
data() { return { auth0:{}, APP_PATH:'/#/calendar', userData:{}, login:false, } }methods: { }の中に以下を追記します。
async updateUI(){ const isAuthenticated = await this.auth0.isAuthenticated(); if (isAuthenticated) { this.login = true; //ログイン後の情報が表示 this.userData = await this.auth0.getUser(); this.userData.token = await this.auth0.getTokenSilently(); } }, async auth0login(){ await this.auth0.loginWithRedirect({ redirect_uri: window.location.origin + this.APP_PATH }); }, auth0logout(){ this.auth0.logout({ returnTo: window.location.origin + this.APP_PATH }); },最後にこちらを追記して完了です。
async created() { this.auth0 = await createAuth0Client({ domain: 'domain名を記載', client_id: 'client_idを記載', // redirect_uri: '<MY_CALLBACK_URL>' }); this.updateUI(); const isAuthenticated = await this.auth0.isAuthenticated(); if (isAuthenticated) { return; } const query = window.location.search; if (query.includes("code=") && query.includes("state=")) { // Process the login state await this.auth0.handleRedirectCallback(); this.updateUI(); // Use replaceState to redirect the user away and remove the querystring parameters window.history.replaceState({}, document.title, this.APP_PATH); } }Auth0でユーザー認証を入れたいところをONにします。
考察
最初は参考記事のコピペで出来るかな?と軽く考えていました。しかし、vue.jsを全く勉強していなかったのですこし時間がかかってしまいました。追記する場所が分かればこれだけで面倒なユーザー認証が実装できるので便利ですね。
- 投稿日:2020-01-20T07:43:19+09:00
Vue.js×FullCallendarでWEBカレンダー作成
はじめに
耳鼻咽喉科の開業医をしています。
花粉症の患者さんに使ってもらえるような花粉飛散情報が分かるカレンダーアプリを作りたいと思っています。
調べてみるとFullCallendarというオープンソースのJavaScriptライブラリがあり、カレンダーのUIと機能を簡単に実装できるようです。
今回カレンダーを表示して予定を入れるところまで挑戦してみました。完成図
作成
こちらの記事を参考にさせていただきました。ありがとうございます。
【忘却のJavaScript #3】Vue.jsでカレンダーを表示してみる1.vueプロジェクトの作成
コマンドプロンプトから以下のコマンドを実行し、雛形プロジェクトを作成します。
> vue create sample-app質問に答えていきます。今回は以下のように設定しました。
Please pick a preset: ⇒ "Manually select features"
Check the features needed for your project:
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
( ) CSS Pre-processors
(*) Linter / Formatter
(*) Unit Testing
(*) E2E Testing
(*) CSS Pre-processors
User history mode for router? ⇒ "n"
Pick a liner / formatter config: ⇒ "ESLint + Prettier"
Pick additional lint features: ⇒ "Lint on save"
Pick a unit testing solution: ⇒ "Jest"
Pick a E2E testing solution: ⇒ "Cypress (Chrome only)"
Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? ⇒ "In package.json"
Save this as a preset for future projects? ⇒ "y"
Save preset as: ⇒ "sample-app"
Pick the package manager to use when installing dependencies: ⇒ "Use Yarn"プロジェクトをVSCodeから開いて確認してみると以下の画像のようにプロジェクトのディレクトリ階層が構築されていることを確認できます。
以下のコマンドを実行して起動を行います。
> yarn servehttp://localhost:8080/
にアクセスし、「Welcome to Your Vue.js App」のページが表示されれば成功です。2.FullCalendarのインストール
以下のコマンドを実行し、ライブラリをインストールします。
> npm install --save @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid3.Calendar.vueの作成
src\components配下にCalendar.vueを作成しました。
<style lang='scss'> @import '~@fullcalendar/core/main.css'; @import '~@fullcalendar/daygrid/main.css'; </style> <template> <FullCalendar defaultView="dayGridMonth" :plugins="calendarPlugins" /> </template> <script> import FullCalendar from '@fullcalendar/vue' import dayGridPlugin from '@fullcalendar/daygrid' export default { components: { FullCalendar // make the <FullCalendar> tag available }, data() { return { calendarPlugins: [ dayGridPlugin ] } } }; </script>4.src\index.jsにCalendar.vueへのリクエストパスを記述
import Vue from "vue"; import VueRouter from "vue-router"; import Home from "../views/Home.vue"; Vue.use(VueRouter); const routes = [ { path: "/", name: "home", component: Home }, { path: "/about", name: "about", // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ "../views/About.vue") }, ///////ここに追記/////// { path: "/calendar", name: "calendar", component: () =>import("../components/Calendar.vue") } ///////ここに追記/////// ]; const router = new VueRouter({ routes }); export default router;5.App.vueの表示画面の変更
Calender.vueへのリンクを作成します。<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/calendar">Calendar</router-link> </div> <router-view /> </div> </template>6.カレンダーの表示
以下のコマンドを実行します。> yarn servehttp://localhost:8080/
にアクセスします。
Calendarへのリンクが表示されていればOKです。
Calendarに移動するとカレンダーが表示されています。
7.カレンダーに予定を入れられるようにする
こちらの記事を参考にさせていただきました。ありがとうございました。
高機能でかつ軽快に動作するカレンダーFullCalendarをNuxt.jsで使うCalendar.vueを以下のように変更しました。
<style lang="scss"> @import "~@fullcalendar/core/main.css"; @import "~@fullcalendar/daygrid/main.css"; </style> <template> <FullCalendar default-view="dayGridMonth" :locale="locale" :header="calendarHeader" :weekends="calendarWeekends" :plugins="calendarPlugins" :events="calendarEvents" @dateClick="handleDateClick" /> </template> <script> import FullCalendar from "@fullcalendar/vue"; import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin from "@fullcalendar/interaction"; import jaLocale from "@fullcalendar/core/locales/ja"; // 日本語化用 export default { components: { FullCalendar // make the <FullCalendar> tag available }, data() { return { locale: jaLocale, // 日本語化 // カレンダーヘッダーのデザイン calendarHeader: { left: "prev,next today", center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek" }, calendarWeekends: true, // 土日を表示するか // カレンダーで使用するプラグイン calendarPlugins: [dayGridPlugin, timeGridPlugin, interactionPlugin], // カレンダーに表示するスケジュール一覧 calendarEvents: [ { title: "報告会", start: "2020-03-10T10:00:00", end: "2020-03-10T12:30:00" }, { title: "ミーティング", start: "2020-03-12T10:30:00", end: "2020-03-12T12:30:00" }, { title: "打ち合わせ", start: "2020-03-18T13:30:00", end: "2020-03-18T14:30:00" } ] }; }, methods: { handleDateClick(arg) { if (confirm("新しいスケジュールを" + arg.dateStr + "に追加しますか ?")) { this.calendarEvents.push({ // add new event data title: "新規スケジュール", start: arg.date, allDay: arg.allDay }); } } </script>予定を表示することができました。
考察
FullCallendarを利用してカレンダーを表示することができました。このデザインを自分で最初からやっていたらとても大変ですね。
今度はユーザー認証機能を実装したいと思っています。
- 投稿日:2020-01-20T07:43:19+09:00
Vue.js×FullCallendarでWEBカレンダー作成(花粉カレンダー作成①)
はじめに
耳鼻咽喉科の開業医をしています。
花粉症の患者さんに使ってもらえるような花粉飛散情報が分かるカレンダーアプリを作りたいと思っています。
調べてみるとFullCallendarというオープンソースのJavaScriptライブラリがあり、カレンダーのUIと機能を簡単に実装できるようです。
今回カレンダーを表示して予定を入れるところまで挑戦してみました。完成図
作成
こちらの記事を参考にさせていただきました。ありがとうございます。
【忘却のJavaScript #3】Vue.jsでカレンダーを表示してみる1.vueプロジェクトの作成
コマンドプロンプトから以下のコマンドを実行し、雛形プロジェクトを作成します。
> vue create sample-app質問に答えていきます。今回は以下のように設定しました。
Please pick a preset: ⇒ "Manually select features"
Check the features needed for your project:
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
( ) CSS Pre-processors
(*) Linter / Formatter
(*) Unit Testing
(*) E2E Testing
(*) CSS Pre-processors
User history mode for router? ⇒ "n"
Pick a liner / formatter config: ⇒ "ESLint + Prettier"
Pick additional lint features: ⇒ "Lint on save"
Pick a unit testing solution: ⇒ "Jest"
Pick a E2E testing solution: ⇒ "Cypress (Chrome only)"
Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? ⇒ "In package.json"
Save this as a preset for future projects? ⇒ "y"
Save preset as: ⇒ "sample-app"
Pick the package manager to use when installing dependencies: ⇒ "Use Yarn"プロジェクトをVSCodeから開いて確認してみると以下の画像のようにプロジェクトのディレクトリ階層が構築されていることを確認できます。
以下のコマンドを実行して起動を行います。
> yarn servehttp://localhost:8080/
にアクセスし、「Welcome to Your Vue.js App」のページが表示されれば成功です。2.FullCalendarのインストール
以下のコマンドを実行し、ライブラリをインストールします。
> npm install --save @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid3.Calendar.vueの作成
src\components配下にCalendar.vueを作成しました。
<style lang='scss'> @import '~@fullcalendar/core/main.css'; @import '~@fullcalendar/daygrid/main.css'; </style> <template> <FullCalendar defaultView="dayGridMonth" :plugins="calendarPlugins" /> </template> <script> import FullCalendar from '@fullcalendar/vue' import dayGridPlugin from '@fullcalendar/daygrid' export default { components: { FullCalendar // make the <FullCalendar> tag available }, data() { return { calendarPlugins: [ dayGridPlugin ] } } }; </script>4.src\index.jsにCalendar.vueへのリクエストパスを記述
import Vue from "vue"; import VueRouter from "vue-router"; import Home from "../views/Home.vue"; Vue.use(VueRouter); const routes = [ { path: "/", name: "home", component: Home }, { path: "/about", name: "about", // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ "../views/About.vue") }, ///////ここに追記/////// { path: "/calendar", name: "calendar", component: () =>import("../components/Calendar.vue") } ///////ここに追記/////// ]; const router = new VueRouter({ routes }); export default router;5.App.vueの表示画面の変更
Calender.vueへのリンクを作成します。<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/calendar">Calendar</router-link> </div> <router-view /> </div> </template>6.カレンダーの表示
以下のコマンドを実行します。> yarn servehttp://localhost:8080/
にアクセスします。
Calendarへのリンクが表示されていればOKです。
Calendarに移動するとカレンダーが表示されています。
7.カレンダーに予定を入れられるようにする
こちらの記事を参考にさせていただきました。ありがとうございました。
高機能でかつ軽快に動作するカレンダーFullCalendarをNuxt.jsで使うCalendar.vueを以下のように変更しました。
<style lang="scss"> @import "~@fullcalendar/core/main.css"; @import "~@fullcalendar/daygrid/main.css"; </style> <template> <FullCalendar default-view="dayGridMonth" :locale="locale" :header="calendarHeader" :weekends="calendarWeekends" :plugins="calendarPlugins" :events="calendarEvents" @dateClick="handleDateClick" /> </template> <script> import FullCalendar from "@fullcalendar/vue"; import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin from "@fullcalendar/interaction"; import jaLocale from "@fullcalendar/core/locales/ja"; // 日本語化用 export default { components: { FullCalendar // make the <FullCalendar> tag available }, data() { return { locale: jaLocale, // 日本語化 // カレンダーヘッダーのデザイン calendarHeader: { left: "prev,next today", center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek" }, calendarWeekends: true, // 土日を表示するか // カレンダーで使用するプラグイン calendarPlugins: [dayGridPlugin, timeGridPlugin, interactionPlugin], // カレンダーに表示するスケジュール一覧 calendarEvents: [ { title: "報告会", start: "2020-03-10T10:00:00", end: "2020-03-10T12:30:00" }, { title: "ミーティング", start: "2020-03-12T10:30:00", end: "2020-03-12T12:30:00" }, { title: "打ち合わせ", start: "2020-03-18T13:30:00", end: "2020-03-18T14:30:00" } ] }; }, methods: { handleDateClick(arg) { if (confirm("新しいスケジュールを" + arg.dateStr + "に追加しますか ?")) { this.calendarEvents.push({ // add new event data title: "新規スケジュール", start: arg.date, allDay: arg.allDay }); } } </script>予定を表示することができました。
考察
FullCallendarを利用してカレンダーを表示することができました。このデザインを自分で最初からやっていたらとても大変ですね。
今度はユーザー認証機能を実装したいと思っています。