- 投稿日:2020-01-17T22:58:25+09:00
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.jsconst 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
参考
- 投稿日:2020-01-17T21:18:30+09:00
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をインストールしましょう(手順省略)。
サンプルのリポジトリは以下です。
今回は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 └ .gitignoref1メニューまたは左下に現れる緑色のアイコンをクリックして「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:3Docker 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 wincredsshでの認証では、ホストマシンで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を使い始めました。感謝!
- 投稿日:2020-01-17T21:14:39+09:00
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;
- 投稿日:2020-01-17T20:30:39+09:00
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に投稿される。
投稿が完了するとプログラムは終了するようにした。
toioコンテンツ内の特殊印刷から得られるIDはこちらの技術情報から参照できる。ソースコード
twio.jsconst 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を設定
- 投稿日:2020-01-17T17:37:16+09:00
Node.js で Redis のキーの一覧を取得
ライブラリーのインストール
sudo npm install -g redisredis_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
- 投稿日:2020-01-17T14:20:04+09:00
Windows 10へNode.jsをインストールする
概要
- Node.jsをNode.jsのサイトからダウンロードしてインストールします。
- Node.jsの利用方法を説明します。
Node.jsのインストール
インストーラをNode.jsのダウンロードサイトを開きます。
《I accept the terms in the Licence Agreement》(ライセンス契約の条項に同意します)をチェックして、《Next》をクリックします。
《Next》をクリックします。(ネイティブアドオンのビルドはしないのでデフォルトのまま)
- チェックボックスをチェックするとNode.jsのネイティブアドオンをビルドするための設定をします。
ネイティブアドオンについては下部の参考サイトを参照してください。ユーザーアカウント制御の画面が表示されるので《はい》をクリックします。
Node.jsの利用とインストール確認
Windows PowerShellの画面が開くのでコマンドを入力してNode.jsがインストールされているか確認します。
node --version
Node.jsのバージョン確認コマンドWindows PowerShellやコマンドプロンプトからNode.jsは利用できます。
参考サイト
- 投稿日:2020-01-17T13:59:50+09:00
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:
を指定します。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.gsfunction 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
を選択してください。こちらに出力される
Current web app URL:
を 1-1.のURLに指定します。
これで設定は完了です。4.動作確認
Outgoing Webhookで設定したチャンネルで
引き金となる言葉
を投稿して、内容がメールで送信されるか確認します。
うまく送信されない場合は各設定値と、Google Apps Scriptのログを確認してみてください。最後に
Slack投稿をメールに自動送信してみました。
今回はVerifyのためにtokenを使いましたが、Verifyすら不要であれば変数なしでもいけそうです。
セキュリティには十分注意して使いましょう。
- 投稿日:2020-01-17T13:59:50+09:00
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:
を指定します。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.gsfunction 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
を選択してください。こちらに出力される
Current web app URL:
を 1-1.のURLに指定します。
これで設定は完了です。4.動作確認
Outgoing Webhookで設定したチャンネルで
引き金となる言葉
を投稿して、内容がメールで送信されるか確認します。
うまく送信されない場合は各設定値と、Google Apps Scriptのログを確認してみてください。まとめ
Slack投稿をメールに自動送信してみました。
これで「メールでしか申請を受け付けない!」プロセスをSlackで実行することができるようになりました。今後はもっとポジティブな使い方がしたいです。笑
- 投稿日:2020-01-17T11:56:29+09:00
JSのプログラムでincludeするコンパイラ的な何かをかいたお話
どうも、フミです。
京都の上のほうから市内に向かう電車の中で書いているので、誤字はお許しください...普段からC系の言語とJavascriptを二刀使いしている皆さん、皆さんはJavascriptをかいていて、あ~、include文使えたらいいのにな...
って思ったことありませんか?いや、いやいや、シンキングフェイスをしたそこのあなた、あなたの気持ちはよ~くわかりますとも!ええ、ええ、そうでしょうね!importを使えばいいだろう!でしょうね!!
使いこなせるのであればいいのですが、importは少し書き方が特殊になる上に、スコープ的にめんどくさいんです(個人の感想です。)
そこで、JSでもinclude文が使えるようになるためのプログラムを作りました!!
5分くおりてぃなので悪しからず...やったこと
Nodejsを使って既存のファイルを解析し、include文を適用したjsファイルをa.jsとしてカレントディレクトリに出力します。
多分コード読んだほうがわかるので...
cmp.jsconst 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しても大丈夫です。
- 投稿日:2020-01-17T00:31:58+09:00
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とかが多いものは信頼性がちょっと高い。