20200117のNode.jsに関する記事は10件です。

JSON Serverでオブジェクト以外を返す方法

JSON Serverで文字列を返す方法

公式のGetting startedをもとに、
/profileにリクエストが来た場合、nameの値を文字列として返却する方法を紹介する。
文字列として返したい箇所には、"type": "string"を記載している。

db.json
{
    "posts": [
      { "id": 1, "title": "json-server", "author": "typicode" }
    ],
    "comments": [
      { "id": 1, "body": "some comment", "postId": 1 }
    ],
    "profile": { "type": "string", "name": "typicode" }
  }

以下のように、JSON Serverをモジュールとして使用することで、上記内容を返却する前に後処理を行えるようにする。

server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

// Middleware(前処理)
server.use(middlewares)
server.use((req, res, next) => {
    // 受け取ったリクエストに前処理を行う場合はここに書く
    // POSTをGETに変換する例
    if (req.method === 'POST') {
        req.method = 'GET'
    }
    // リクエストURLを書き換える例
    req.url = req.url.replace(/\./g, "")
    console.log(req.url)
    next()
})

// ルーティングを使用する場合はここに書く
server.use(jsonServer.rewriter({
    "/api/*": "/$1",
    "/posts\\?id=:id": "/posts/:id",
}))
server.use(router)

// 後処理
router.render = function (req, res) {
    // レスポンスに後処理を行う場合はここに書く
    // db.jsonの返却値に"type":"string"がある場合、nameの値を文字列として返却する例
    if (res.locals.data.type && res.locals.data.type === 'string') {
        res.send(res.locals.data.name)
    } else { // それ以外はdb.jsonに記載したとおり返却する
        res.send(res.locals.data)
    }
}

// モックサーバ起動
server.listen(3000, () => {
    console.log('JSON Server is running')
})

あとは、nodeコマンドで実行する

$ node server.js

参考

https://github.com/typicode/json-server/issues/410

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

VS CodeでDocker開発コンテナを便利に使おう

はじめに

  • ローカル環境で開発し、Linux環境にデプロイしてテストするのが面倒
  • Dockerを使っていい感じに開発環境を作りたい
  • しかし色々設定や構築が面倒

そんな方のためにDockerコンテナを用いた開発環境をVS Codeから便利に構築、運用できる拡張機能「Remote-Containers」の使い方のご紹介です。

この拡張機能の素晴らしさ

VS Codeの拡張機能「Remote-Containers」はコンテナ内でVS Codeを立ち上げ、ホストマシンのVS Codeと通信させることであたかもローカル環境で開発しているような操作感でコンテナ内開発が行えるというものです。

詳しい構成は公式ドキュメントに図があります。


(https://code.visualstudio.com/assets/docs/remote/containers/)

また、複数の開発環境をVS Code上から管理して、ワンクリックでコンテナを立ち上げることが可能です。


(https://code.visualstudio.com/assets/docs/remote/containers/)

そのために開発を始める際にコンテナをコマンドから立ち上げ、シェルをアタッチしてコンテナ内に入るなどの作業が必要なくなります。

ローカル環境でVS Codeを開いて開発を始めるのとほぼ同じ感覚でコンテナ内での開発が始められるのです。

システム要件は以下になります。

  • Windows: Docker Desktop 2.0+ on Windows 10 Pro/Enterprise. (Docker Toolbox is not supported.)
  • macOS: Docker Desktop 2.0+.
  • Linux: Docker CE/EE 18.06+ and Docker Compose 1.21+. (The Ubuntu snap package is not supported.)

環境構築のための環境構築

Docker

まずDockerをインストールしますが、ここは省略します。

筆者はWindows環境にDocker Desktopをインストールしましたが、想像を絶する艱難辛苦を味わいました。

VS Code 拡張機能

VS Code上でctrl + shift + Xで拡張機能メニューを開き、「Remote-Containers」を検索してインストールします。

Microsoft公式なので安心(?)です。

Remote-Containers / Remote-SSH / Remote-WSLをひとつにしたRemote Developmentという拡張機能もあるのでそちらでも大丈夫です。

git

GithubのMicrosoft公式リポジトリに設定ファイルのサンプルがあるので、それをcloneしてくるとスムーズです。

なのでgitをインストールしましょう(手順省略)。

サンプルのリポジトリは以下です。

vscode-remote-try-python

今回はPythonを使いますが、node.jsやjava、goなどもあります。

必要なのは.devcontainerディレクトリ配下のDockerfileとdevcontainer.jsonなので、そこだけ持ってきても構いません。

Remote-Containersの機能で「Try a Sample」というのがあり、cloneしなくてもこれらのリポジトリを使って試すことができますが突然docker imageのビルドが始まるのでやや面喰います。

開発環境構築

プロジェクト構成

例えばPythonのアプリケーションの開発環境を作るとします。

ディレクトリ構成を以下のようにしてVS Codeからprojectディレクトリを開きます。

project/
    └ .devcontainer/
        ├ Dockerfile
        └ devcontainer.json
    └ .git/
    └ package/
        ├ __init__.py
        ├ __main__.py
        └  module.py
    ├ requirements.txt
    └ .gitignore

f1メニューまたは左下に現れる緑色のアイコンをクリックして「Remote-Containers: Open Folder in Container...」を選択します。


(https://code.visualstudio.com/assets/docs/remote/containers/)

するとVS Codeが.devcontainer配下のDockerfileとdevcontainer.jsonを読み込み、その設定に従ってDockerコンテナを立ち上げてくれるという寸法です。

それでは、Dockerfileとdevcontainer.jsonの中身を見て具体的に何が起こっているのかを理解しましょう。

Dockerfile

ここは普通のDockerfileで、特別なことはありませんがユーザー権限回りの設定をいい感じにやってくれています。

#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------

FROM python:3

Docker imageをビルドするための元となるイメージを指定する項目です。

pythonのバージョンを詳しく指定したい場合はここをpython:3.7などにします。

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

RUN apt-get update \
    && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \

    && apt-get -y install git iproute2 procps lsb-release \

    ~~~

    && groupadd --gid $USER_GID $USERNAME \
    && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \

    && apt-get install -y sudo \
    && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
    && chmod 0440 /etc/sudoers.d/$USERNAME \

ここでapt-getの設定とユーザーの権限回りを設定しています。

要はsudoできる権限を持ったvscodeというユーザーでコンテナを扱えるようにしているようです。

devcontainer.json

こちらがこの拡張機能のミソです。

    "name": "Python 3",
    "context": "..",
    "dockerFile": "Dockerfile",

    "settings": { 
        "terminal.integrated.shell.linux": "/bin/bash",
        "python.pythonPath": "/usr/local/bin/python",
        "python.linting.enabled": true,
        "python.linting.pylintEnabled": true,
        "python.linting.pylintPath": "/usr/local/bin/pylint"
    },

    "appPort": [ 9000 ],

    "postCreateCommand": "sudo pip install -r requirements.txt",

    "remoteUser": "vscode",

    "extensions": [
        "ms-python.python"
    ]
}

ここにjson形式で書かれている項目がRemote-Containers拡張機能の設定となります。

  • name
    • Dev Containerの表示名を指定できます(Dockerコンテナ名とは別物です)。
  • context
    • プロジェクトのルートを指定します。
    • この場合devcontainer.jsonがいる.devcontainerディレクトリの一つ上なので".."が指定されています。
  • settings
    • コンテナ側のVS Codeにおける各種設定を行う項目です。シェルやPythonのパスなど。
  • appPort
    • ホストマシンからアクセスできるコンテナのポート番号を指定します。
    • docker runするときの-pオプションで9000:9000と指定するのと同じです。
    • つまりホストマシンのブラウザでlocalhost:9000を叩くとコンテナのlocalhost:9000につながります。
  • postCreateCommand
    • イメージをビルドした後にコンテナ内で実行されるコマンドを書くことができます。
    • この場合はプロジェクトのルートにあるrequirements.txtに書かれたパッケージがインストールされます。
  • extensions
    • コンテナ側のVS Codeにインストールされる拡張機能を指定できます。

公式ドキュメントによると、その他にも色々設定できる項目があります。

デフォルトではプロジェクトのルートディレクトリがコンテナの/workspaceにバインドされますが、

{   
    "workspaceFolder": "/home/vscode",
    "workspaceMount": "type=bind,source=${localWorkspaceFolder},target=/home/vscode/project"
}

のようにすれば、/home/vscodeにバインドされてVS Codeで開くデフォルトのディレクトリもそこになります。

{   
    "containerEnv": {
        "WORKSPACE": "/home/vscode"
    }
}

containerEnv項目を指定すると、コンテナ内で使える環境変数を設定できます。

{   
    "runArgs": [
        "--name=project_dev_container"
    ]
}

runArgsの項目で、コンテナ立ち上げ時のオプションを直接指定することもできます。

実際にはVS Codeがこのdevcontainer.jsonを読み込んで各種オプションをつけてdocker runしてコンテナを立ち上げています。

その際にrunArgsの項目で指定した文字列のリストがスペース区切りで追加されるわけです。

さらに詳しくはこちら : Developing inside a Container - devcontainer.json reference

その他個別設定

git

コンテナにバインドするプロジェクトディレクトリに.git/が入っていると、そのままコンテナ内のVS Codeのバージョン管理機能が使えます。

VS Codeのバージョン管理機能は大変便利で、git addやgit commit、git pushなどがGUIで行えます。

しかしながらコンテナ内でモートリポジトリと通信しようとすると、毎回Githubの認証が必要になってしまいます。

ですがそこは我らがVS Code、gitの認証情報をホストマシンと共有できる機能が付いています。

Developing inside a Container - Sharing Git credentials with your container

まずホストマシンとでGithubのユーザー名やメールアドレスを.gitconfigファイルに保存しておきます。

$ git config --global user.name "Your Name"
$ git config --global user.email "your.email@address"

ユーザールートにある.gitconfigにこれらの設定が書き込まれていますが、これをVS Codeが自動でコンテナにコピーしてくれるようです。

次にパスワードなどの認証情報ですが、二通り設定方法があります。

https通信を使ってidとパスワードで認証している場合、gitのcredential helperにパスワードを保存しておけばその設定がコンテナと同期されます。

Caching your GitHub password in Git

$ git config --global credential.helper wincred

sshでの認証では、ホストマシンでSSH agentにGithub用の公開鍵を登録しておくとその設定が同期されるようです。

PowerShellで

ssh-add $HOME/.ssh/github_rsa

とするとSSH agentに鍵が登録されます。

しかしながらSSH agentが起動していない場合が多く、そのときは管理者権限でPowerShellに入って

Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
Get-Service ssh-agent

するか、GUIでサービス > OpenSSH Authentication Agentのプロパティから設定できます。

詳しくはWindows 10のssh-agentをコマンド プロンプト、WSL、Git Bashで使ってみた#ssh-agent-の有効化など。

AWS Access Key

コンテナ内からAWS S3と通信しようとすると、アクセスキーの問題が発生します。

ホストマシンのユーザールートにある.awsディレクトリ内にアクセスキーの情報があり、それをコンテナ内でも読み込みたいものです。

しかしながらgitの場合とは異なりそこは自動的に読み込んではくれないようです。

それゆえに一度コンテナの外からdocker cpを使ってコンテナにコピーしてくる必要があります。

docker cp $HOME/.aws {コンテナ名}:home/vscode

ここで、Remote-Containersで立ち上げるコンテナに名前がついてると便利です。

先ほどのdevcontainer.jsonのrunArgsの項目で、

{   
    "runArgs": [
        "--name=project_dev_container"
    ]
}

のようにしてコンテナ名をつけるようにすると良いでしょう。

素晴らしい航海

実際に使ってみると、普通にVS Codeで開発するのとほぼ同じ感覚で開発コンテナを扱うことができます。

また、Pythonで開発する際には仮想環境を用意するのが普通ですがコンテナ内で環境を構築することでその必要がなくなります。

なぜなら、各プロジェクトごとに違うコンテナを使っているのでパッケージをグローバルにインストールしても環境を汚染しないからです。

そして、Pythonのバージョンごとにイメージが用意されているので本番環境に合わせてそれを指定することもできます。

(この辺りはRemote-Containersというよりdockerを使うことのメリットですが)

こうした開発環境をワンクリックで開いたり、切り替えたりできるわけです。

また、この拡張機能はポートのバインドも自動で行ってくれるため、フロントエンド開発でのローカルサーバーもストレスなく使うことができます。

ただし、例えばnode.jsなどは3000番ポート指定でローカルサーバーが立ち上がるのでそのポートをローカルマシンに公開しなければなりません。

その場合はdevcontainer.jsonで

{   
    "appPort": [ 3000 ]
}

のように設定しておきましょう。

参考

公式ドキュメント、長い

この記事を見てRemote-Containersを使い始めました。感謝!

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

JSON.Stringifyで循環オブジェクト参照構造体が処理できないのをcycle.jsで処理した

概要

https://qiita.com/saitoeku3/items/9e9a608e53029d541a8f
と同じエラーにあったので、cycle.jsで処理したサンプルコードを紹介するよというお話

cycle.js

https://github.com/douglascrockford/JSON-js/blob/master/cycle.js

インストール

npm install json-cyclic

サンプルコード

//import
const decycle = require('json-decycle').decycle;
const retrocycle = require('json-decycle').retrocycle;
...

...
//文字列に変換
receiveNewAcString = JSON.stringify(receiveNewJson, decycle());

//JSONオブジェクトに変換
receiveNewAc = JSON.parse(receiveNewAcString, retrocycle()).data;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

toioとTwitterAPIを合わせて使ってみた!

toio.jsとTwitter APIを合わせて使ってみた

久しぶりの記事投稿。今回はtoioをJavascriptで制御するのとTwitterAPIを合わせて使っていく。

toioとは

toioとはソニーインタラクティブエンタテインメントより発売されているロボットトイである。詳しくは公式サイトを見てほしいが、子供から大人まで楽しめるモノになっている。公式からtoio.jsというNode.js(サーバサイドで動くJavaScript環境)のライブラリが公開されているので今回をそちらを利用していく。

今回やること

toioの最大の特徴は主役であるデバイスのキューブ(下図)の光学センサーを用いて、付属のマットやシールに施されている特殊印刷を読み取り、キューブの絶対座標やIDを取得できる点だ。

今回はその絶対座標や各シールのIDを取得した後、TwitterAPIを介してそれらをTweetするのを目標とする。
なおJavascriptを触るのは初めてなのであしからず。

環境構築

環境構築は以下を行った。今回は手順は省く。
- Node.js及びtoio.jsの環境構築(公式を参照)
- TwitterAPIの導入(参照記事)

なおTwitterのアプリケーション作成方法はアップデート毎に変更されているようだ。3年前に一度Androidアプリ開発で触ったことがあったが、開発者アカウントの作成などは審査などが追加されており少々面倒くさくなっていた。

できたもの

今回はクラフトファイターの技カードのIDを識別してツイートする内容とした。(マットを使った座標が今後考えていく・・・)
以下が機能である。

  • キューブはキーボードの矢印キーで走行可能
  • プログラム実行中は常にIDを取得し続ける
  • スペースキーを押すと現在のIDを利用してツイート文を判定・投稿

以下はオートタックルのカードを認識している。

スペースキーを押すと何やら詳細情報がたくさん吐き出されてTwitterに投稿される。
1.png

以下が投稿結果

2.png
ちゃんと投稿できてる。

投稿が完了するとプログラムは終了するようにした。
toioコンテンツ内の特殊印刷から得られるIDはこちらの技術情報から参照できる。

ちなみにもうひとつも(今度はタイフーン)
 
ツイート!
3.png
結果
4.png

ソースコード

twio.js
const twitter = require("twitter");
const fs = require("fs");
const client = new twitter(JSON.parse(fs.readFileSync("secret.json", "utf-8")));
const keypress = require('keypress')
const { NearestScanner } = require('@toio/scanner')

const DURATION = 700 // ms
const SPEED = {
    forward: [70, 70],
    backward: [-70, -70],
    left: [30, 70],
    right: [70, 30],
}

//tweet
function tweet(sentence) {
    client.post('statuses/update', { status:sentence }, function (error, tweet, response) {
        if (!error) {
            console.log(tweet);
            console.log('tweet complete & program end')
            process.exit(0);
        } else {
            console.log('error');
            process.exit(1);
        }
    });
}

//make sentences from id_data
function make_sentence(id_data){
    var today = new Date();
    if(id_data === 3670016){
        out = 'Typhoon!'+ '\n' + today
    }else{
        if(id_data === 3670054){
            out = 'Rush!'+ '\n' + today
        }else{
            if(id_data === 3670018){
                out = 'Auto Tackle!'+ '\n' + today
            }else{
                if(id_data === 3670056){
                    out = 'Random!'+ '\n' + today
                }else{
                    if(id_data === 3670020){
                        out = 'Stab Power Up!'+ '\n' + today
                    }else{
                        if(id_data === 3670058){
                            out = 'Slapping Power Up!'+ '\n' + today
                        }else{
                            if(id_data === 3670022){
                                out = 'Side Attack!'+ '\n' + today
                            }else{
                                if(id_data === 3670060){
                                    out = 'Easy Mode!'+ '\n' + today
                                }else{
                                    out = 'not defined ID, ' + '\n' + 'ID : ' + id_data + '\n' + today
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}


//main
async function main() {
    // start a scanner to find nearest cube
    const cube = await new NearestScanner().start()

    // connect to the cube
    await cube.connect()
    console.log('cube connected')

    //tweet data initialize
    var id = []

    //get id data
    cube
      .on('id:standard-id', data => {id.unshift(data.standardId)})

    //move and tweet
    keypress(process.stdin)
    process.stdin.on('keypress', (ch, key) => {
        // ctrl+c or q -> exit process
        if ((key && key.ctrl && key.name === 'c') || (key && key.name === 'q')) {
            process.exit()
        }

        switch (key.name) {
            //space is id tweet
            case 'space':
                var value = id[0]
                console.log('Data get : ', value)
                make_sentence(value)
                console.log('Tweet : ',out)
                tweet(out)
                break
            case 'up':
                cube.move(...SPEED.forward, DURATION)                
                break
            case 'down':
                cube.move(...SPEED.backward, DURATION)
                break
            case 'left':
                cube.move(...SPEED.left, DURATION)
                break
            case 'right':
                cube.move(...SPEED.right, DURATION)
                break
        }
    })

    process.stdin.setRawMode(true)
    process.stdin.resume()

}

main()

いかにもJavascript初心者っぽいコーディングだがあしからず・・・
IDを判別して文章を決める大量のif else文をなんとかしたいが、何かいい方法はないだろうか・・・

今後

初挑戦のNode.jsもといJavaScriptだったがtoioの整った環境と使いやすいデバイス、仕様のおかげで1つ作成することができた。
今回は利用するID(toio内の利用物)を絞ったが、次回はマットから取得できるX,Y座標やアングル等を利用して発展させたいと考えている。

※ソースコード更新

2020/01/19

  • 細かい修正
  • ツイート内容に日付を追加しツイート文かぶりによるエラーを解決
  • 技カード以外のIDを「not defined ID」としIDと一緒にツイートできるようelseを設定

8.png
タイフーンカードに日付追加

9.png
リズム&ゴーのひだり(ツイート文未定義)

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

Node.js で Redis のキーの一覧を取得

ライブラリーのインストール

sudo npm install -g redis
redis_list.js
#! /usr/bin/node
// ---------------------------------------------------------------
//  redis_list.js
//
//                  Jan/17/2020
//
// ---------------------------------------------------------------
console.error ("*** 開始 ***")
//
const redis = require("redis")
const client = redis.createClient(6379,'localhost')

client.on ("error", function (err)
    {
        console.log ("Redis connection error to "
        + client.host + ":" + client.port + " - " + err)
    })

client.keys ('*',function (err, reply)
    {
    if (err)
        {
        console.log("Get error: " + err)
            }
     else if (reply != null)
        {
        const keys = reply

        console.log (keys)
    console.log("keys.length = " + keys.length)
        console.log (keys[0])
        }

    client.quit()
    console.error ("*** 終了 ***")
    })

// ---------------------------------------------------------------

実行

$ export NODE_PATH=/usr/lib/node_modules
$ ./redis_list.js
*** 開始 ***
[
  't1853', 't1856',
  't1854', 't1852',
  't1855', 't1857',
  't1851', 't1858',
  't1859'
]
keys.length = 9
t1853
*** 終了 ***

確認したバージョン

$ node --version
v13.6.0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows 10へNode.jsをインストールする

概要

  • Node.jsをNode.jsのサイトからダウンロードしてインストールします。
  • Node.jsの利用方法を説明します。

Node.jsのインストール

  1. インストーラをNode.jsのダウンロードサイトを開きます。

    1. Node.js - ダウンロード
  2. 「LTS版」の《Windows Installer》をクリックしてダウンロードします。
    image.png

  3. ダウンロードしたインストールファイルをクリックしてインストーラーを開きます。
    image.png

  4. 《Next》ボタンをクリックします。
    image.png

  5. 《I accept the terms in the Licence Agreement》(ライセンス契約の条項に同意します)をチェックして、《Next》をクリックします。
    image.png

  6. 《Next》をクリックします。(必要であればインストールフォルダを指定する)
    image.png

  7. 《Next》をクリックします。(基本的にはデフォルトのまま)
    image.png

  8. 《Next》をクリックします。(ネイティブアドオンのビルドはしないのでデフォルトのまま)
    image.png

    1. チェックボックスをチェックするとNode.jsのネイティブアドオンをビルドするための設定をします。
      ネイティブアドオンについては下部の参考サイトを参照してください。
  9. 《Install》をクリックします。
    image.png

  10. ユーザーアカウント制御の画面が表示されるので《はい》をクリックします。

  11. 《Finish》をクリックし、インストールを完了します。
    image.png

Node.jsの利用とインストール確認

  1. Windowsのスタートボタンを右クリックします。
    image.png

  2. メニューが表示されるので「Windows PowerShell」をクリックします。
    image.png

  3. Windows PowerShellの画面が開くのでコマンドを入力してNode.jsがインストールされているか確認します。
    image.png

    1. node --version Node.jsのバージョン確認コマンド
  4. インストールしたバージョン番号が確認できれば正常にインストールされています。
    image.png

  5. Windows PowerShellやコマンドプロンプトからNode.jsは利用できます。

参考サイト

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

Slackからメールに自動送信してみた

はじめに

社内コミュツールとしてSlackが導入され、社内のコミュニケーションが多少なりとも活性化してきました。
SlackのAppやワークフロービルダーを使って既存プロセスを楽にしようと考える人も出てきて、ツールが変われば人も変わるなーと実感しています。

そんな中でも依頼は「社内メール」という文化は残っており、最後は誰かがメールを送らないといけません。。。
なのでSlackで簡素化した申請プロセスの申請内容をSlackから社内メールに自動送信するようにしてみました。

環境

今回は以下の環境を利用しました。

Slack(Outgoing Webhook)
Sendgrid
Google Apps Script(Node.js)

順番に設定内容を記載します。

1.Slack

チャンネルで特定のキーワードに対して反応するOutgoing Webhookを設定します。
Outgoing WebhookはSlackのApp管理ページから「App ディレクトリを検索」で検索できます。

1-1.設定内容

チャンネル:Outgoing Webhookを動かすチャンネルを指定します。
プライベートチャンネルは指定できませんでした。

引き金となる言葉:トリガーとなるキーワードを指定します。

URL:あとで作るGoogle Apps ScriptのCurrent web app URL:を指定します。

スクリーンショット 2020-01-17 11.39.50.png

2.Sendgrid

メール配送はSendgridを使いました。
https://sendgrid.kke.co.jp/

詳細は割愛しますが、必要となるのはAPIキーです。
ダッシュボートの「Settings」-「API Keys」でKeyを作成してください。
注意:Keyは作成時しか表示されません。

3.Google Apps Script

Slackの投稿を受け取ってメールを送信するスクリプトはGoogle Apps Scriptに構築しました。

3-1.環境変数

環境変数は以下を設定します。
環境変数の設定はGoogle Apps Scriptの「ファイル」-「プロジェクトのプロパティ」-「スクリプトのプロパティ」から設定できます。

■VERIFY_TOKEN
検証用トークンです。自身で設定したOutgoing WebhookからのPOSTかどうか検証します。
これを設定しないとどこからでもPOSTできるようになってしまいます。
設定値はOutgoing Webhookの設定ページにあるTokenを指定します。

■SEND_GRID_ENDPOINT
SendgridのURLを指定します。
https://api.sendgrid.com/v3/mail/send

■SEND_GRID_API_KEY
Sendgridのダッシュボードで取得したAPIキーを指定します。

3-2.スクリプト

doPost(POST、Verify処理)と、sendMail(メール送信処理)の2つに分けています。
メールのto,subject,from_name,fromはご自身の環境に合わせて設定してください。

PropertiesService.getScriptProperties().getProperty('XXX')で環境変数を取得しています。

code.gs
function doPost(e) {
  var verify_token = PropertiesService.getScriptProperties().getProperty('VERIFY_TOKEN');
  if (verify_token != e.parameter.token) {
    throw new Error("invalid token.");
  }

  var message = e.parameter.text;  
  sendEmail(message);
}

function sendEmail(message){
  var sendgrid_endpoint = PropertiesService.getScriptProperties().getProperty('SEND_GRID_ENDPOINT');
  var sendgrid_apikey = PropertiesService.getScriptProperties().getProperty('SEND_GRID_API_KEY');
  var to = "送信先メールアドレス";
  var subject = "メールタイトル"; 
  var from_name = "送信者名";
  var from = "送信元メールアドレス";

  var body = {
    "personalizations": [
      {
        "to": [
          {
            "email": to
          }
        ],
        "subject": subject
      }
    ],
    "from": {
      "email": from,
      "name" : from_name
    },
    "content": [
      {
        "type": "text/html",
        "value": message
      }
    ]
  }
  var payload = JSON.stringify(body);
  UrlFetchApp.fetch(sendgrid_endpoint, {
    method: 'POST',
    headers: { "Content-Type": 'application/json',
             "Authorization": "Bearer "+ sendgrid_apikey},
    payload: payload
  });
}

3-3.有効化

Google Apps Scriptのメニューの「公開」-「ウェブ アプリケーションを導入…」からスクリプトを有効化します。
Who has access to the app:Anyone, even anonymousを選択してください。

スクリーンショット 2020-01-17 13.31.29.png

こちらに出力されるCurrent web app URL:を 1-1.のURLに指定します。
これで設定は完了です。

4.動作確認

Outgoing Webhookで設定したチャンネルで引き金となる言葉を投稿して、内容がメールで送信されるか確認します。
うまく送信されない場合は各設定値と、Google Apps Scriptのログを確認してみてください。

最後に

Slack投稿をメールに自動送信してみました。
今回はVerifyのためにtokenを使いましたが、Verifyすら不要であれば変数なしでもいけそうです。
セキュリティには十分注意して使いましょう。

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

Slackの特定投稿をメールで自動送信してみた

はじめに

社内コミュツールとしてSlackが導入され、社内のコミュニケーションが多少なりとも活性化してきました。
SlackのAppやワークフロービルダーを使って既存プロセスを楽にしようと考える人も出てきて、ツールが変われば人も変わるなーと実感しています。

そんな中でも依頼は「社内メール」という文化は残っており、最後は誰かがメールを送らないといけません。。。
なのでSlackで簡素化した申請プロセスの申請内容をSlackから社内メールに自動送信するようにしてみました。

環境

今回は以下の環境を利用しました。

Slack(Outgoing Webhook)
Sendgrid
Google Apps Script(Node.js)

順番に設定内容を記載します。

1.Slack

チャンネルで特定のキーワードに対して反応するOutgoing Webhookを設定します。
Outgoing WebhookはSlackのApp管理ページから「App ディレクトリを検索」で検索できます。

1-1.設定内容

チャンネル:Outgoing Webhookを動かすチャンネルを指定します。
プライベートチャンネルは指定できませんでした。

引き金となる言葉:トリガーとなるキーワードを指定します。

URL:あとで作るGoogle Apps ScriptのCurrent web app URL:を指定します。

スクリーンショット 2020-01-17 11.39.50.png

2.Sendgrid

メール配送はSendgridを使いました。
https://sendgrid.kke.co.jp/

詳細は割愛しますが、必要となるのはAPIキーです。
ダッシュボートの「Settings」-「API Keys」でKeyを作成してください。
注意:Keyは作成時しか表示されません。

3.Google Apps Script

Slackの投稿を受け取ってメールを送信するスクリプトはGoogle Apps Scriptに構築しました。

3-1.環境変数

環境変数は以下を設定します。
環境変数の設定はGoogle Apps Scriptの「ファイル」-「プロジェクトのプロパティ」-「スクリプトのプロパティ」から設定できます。

■VERIFY_TOKEN
検証用トークンです。自身で設定したOutgoing WebhookからのPOSTかどうか検証します。
これを設定しないとどこからでもPOSTできるようになってしまいます。
設定値はOutgoing Webhookの設定ページにあるTokenを指定します。

■SEND_GRID_ENDPOINT
SendgridのURLを指定します。
https://api.sendgrid.com/v3/mail/send

■SEND_GRID_API_KEY
Sendgridのダッシュボードで取得したAPIキーを指定します。

3-2.スクリプト

doPost(POST、Verify処理)と、sendMail(メール送信処理)の2つに分けています。
メールのto,subject,from_name,fromはご自身の環境に合わせて設定してください。

PropertiesService.getScriptProperties().getProperty('XXX')で環境変数を取得しています。

code.gs
function doPost(e) {
  var verify_token = PropertiesService.getScriptProperties().getProperty('VERIFY_TOKEN');
  if (verify_token != e.parameter.token) {
    throw new Error("invalid token.");
  }

  var message = e.parameter.text;  
  sendEmail(message);
}

function sendEmail(message){
  var sendgrid_endpoint = PropertiesService.getScriptProperties().getProperty('SEND_GRID_ENDPOINT');
  var sendgrid_apikey = PropertiesService.getScriptProperties().getProperty('SEND_GRID_API_KEY');
  var to = "送信先メールアドレス";
  var subject = "メールタイトル"; 
  var from_name = "送信者名";
  var from = "送信元メールアドレス";

  var body = {
    "personalizations": [
      {
        "to": [
          {
            "email": to
          }
        ],
        "subject": subject
      }
    ],
    "from": {
      "email": from,
      "name" : from_name
    },
    "content": [
      {
        "type": "text/html",
        "value": message
      }
    ]
  }
  var payload = JSON.stringify(body);
  UrlFetchApp.fetch(sendgrid_endpoint, {
    method: 'POST',
    headers: { "Content-Type": 'application/json',
             "Authorization": "Bearer "+ sendgrid_apikey},
    payload: payload
  });
}

3-3.有効化

Google Apps Scriptのメニューの「公開」-「ウェブ アプリケーションを導入…」からスクリプトを有効化します。
Who has access to the app:Anyone, even anonymousを選択してください。

スクリーンショット 2020-01-17 13.31.29.png

こちらに出力されるCurrent web app URL:を 1-1.のURLに指定します。
これで設定は完了です。

4.動作確認

Outgoing Webhookで設定したチャンネルで引き金となる言葉を投稿して、内容がメールで送信されるか確認します。
うまく送信されない場合は各設定値と、Google Apps Scriptのログを確認してみてください。

まとめ

Slack投稿をメールに自動送信してみました。
これで「メールでしか申請を受け付けない!」プロセスをSlackで実行することができるようになりました。

今後はもっとポジティブな使い方がしたいです。笑

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

JSのプログラムでincludeするコンパイラ的な何かをかいたお話

どうも、フミです。
京都の上のほうから市内に向かう電車の中で書いているので、誤字はお許しください...

普段からC系の言語とJavascriptを二刀使いしている皆さん、皆さんはJavascriptをかいていて、あ~、include文使えたらいいのにな...
って思ったことありませんか?

いや、いやいや、シンキングフェイスをしたそこのあなた、あなたの気持ちはよ~くわかりますとも!ええ、ええ、そうでしょうね!importを使えばいいだろう!でしょうね!!

使いこなせるのであればいいのですが、importは少し書き方が特殊になる上に、スコープ的にめんどくさいんです(個人の感想です。)

そこで、JSでもinclude文が使えるようになるためのプログラムを作りました!!
5分くおりてぃなので悪しからず...

やったこと

Nodejsを使って既存のファイルを解析し、include文を適用したjsファイルをa.jsとしてカレントディレクトリに出力します。

多分コード読んだほうがわかるので...

cmp.js
const main_file=process.argv[2];
const fs = require('fs');
function include(fname){
    let code = String(fs.readFileSync(fname));
    console.log("include \n\n"+code);
    const analy=code.split("#include ");
    let program=analy[0];
    for(let i=1;i<analy.length;i++){
        program+="\n"+include(analy[i].split(/\r\n|\n|\r/)[0])+"\n";
    }
    program+=analy.pop().split(/\r\n|\n|\r/,2)[1];
    return program;
}
fs.writeFileSync("a.js", include(main_file));

以上!!

使い方

コンパイル()したいファイルとincludeしたいファイルの拡張子は何でもいいです。
コマンドラインで

node cmp.js [コンパイルしたいメインファイルのパス]

としてやるとa.jsに結果が出力されます。
includeしたいファイル内でさらにincludeしても大丈夫です。

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

Swagger-codegenを使おうと思ったが、エラーで使えなかった件

発生した問題

swagger-codegenでnodejs-serverを選択し、モックサーバーを立てようとしたら以下のエラーが出た。

Error: Cannot find module './middleware/swagger.router'

パッケージの中を確認すると、確かにswagger.routerがない。
issueが立ってた。パッケージに間違いがあるらしい。
https://github.com/bug-hunters/oas3-tools/issues/17

解決策

Swagger-codegenのバージョンを下げて、
swagger-codegen@2で対応した。

$ brew install swagger-codegen@2

学んだこと

パッケージも間違っていることがある。
npmのサイトにissuesが上がっていることがある。
Weekly downloadsとかが多いものは信頼性がちょっと高い。

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