- 投稿日:2019-07-16T20:26:27+09:00
Electron を Custom URL Scheme で起動する
やりたいこと
Custom URL Scheme から Electron を起動したい、値も渡したい
例えばブラウザで、
itmss://music.apple.com/jp/album/ignition-single/1378858551
にアクセスすると iTunes が起動し、特定のページに遷移するこれと同じことを実現したい
前提
- Electron version v5.0
- electron-builder v20.40.2
手順
Mac
package.json の build に以下を追記する
"build": { ... "protocols": { "name": "myApp IM URL", "schemes": [ "my-appname" ] }, ... }ビルド後に
.dmg
イメージからアプリケーションを Mac にインストールすることで、 URL Scheme から Electron を起動することができるWindows
package.json の build に以下を追記する
"build": { ... "nsis": { "include": "build/installer.nsh", "perMachine": true }, ... }
build/installer.nsh
ファイルを追加する!macro customHeader !system "echo '' > ${BUILD_RESOURCES_DIR}/customHeader" !macroend !macro preInit ; This macro is inserted at the beginning of the NSIS .OnInit callback !system "echo '' > ${BUILD_RESOURCES_DIR}/preInit" !macroend !macro customInit !system "echo '' > ${BUILD_RESOURCES_DIR}/customInit" !macroend !macro customInstall !system "echo '' > ${BUILD_RESOURCES_DIR}/customInstall" DetailPrint "Register My AppName URI Handler" DeleteRegKey HKCR "My AppName" WriteRegStr HKCR "My AppName" "" "URL:My AppName" WriteRegStr HKCR "My AppName" "URL Protocol" "" WriteRegStr HKCR "My AppName" "EveHQ NG SSO authentication Protocol" "" WriteRegStr HKCR "My AppName\DefaultIcon" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME}" WriteRegStr HKCR "My AppName\shell" "" "" WriteRegStr HKCR "My AppName\shell\Open" "" "" WriteRegStr HKCR "My AppName\shell\Open\command" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME} %1" !macroend !macro customInstallMode # set $isForceMachineInstall or $isForceCurrentInstall # to enforce one or the other modes. !macroendビルド後、 Setup ファイルからインストールすることで、 URL Scheme から Electron を起動することができる
Custom URI Scheme を Electron 側で取得する
メインプロセス
Mac OS と Windows で書き方が違う
// for Mac OS app.on('open-url', (e, url) => { // URL Scheme から開いたときにここが実行される webContents.send('customUri', url); }); // アプリの二重起動を防ぐ(for windows) const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { // すでにウィンドウを開いていた場合、新しい window は quit app.quit(); } else { // 2つめのウィンドウが開かれた時のイベントを定義する app.on('second-instance', (event, commandLine, workingDirectory) => { // mainWindow.webContents.send('log', 'second instance!!'); commandLine.forEach(cmd => { // URIスキームのみを探して、レンダラプロセスに送る if (/my-appname:\/\//.test(cmd)) { mainWindow.webContents.send('customUri', cmd); } }); // すでにメインウィンドウがある場合、それにフォーカスする if (mainWindow) { if (mainWindow.isMinimized()) { // 最小化してた場合 mainWindow.restore(); // restore } mainWindow.focus(); // フォーカス } }); }レンダラプロセス
/** * custom uri をメインプロセスから受け取る */ ipcRenderer.on('customUri', (event, uri) => { console.log('customUri:', uri); });参考
https://electronjs.org/docs/all#apprequestsingleinstancelock
- 投稿日:2019-07-16T17:47:39+09:00
Slackメッセージ 10000 件制限対応: 古いメッセージを一括で削除する
Slackのフリープランで10000件制限をやりくりする
Slackはフリープランだと、10000件しかメッセージを保存できません。
古いものが見えなくなっても困らないけど、中には残しておきたいメッセージもありますよね。
そこで、スター付きのメッセージと、ピン留めしたメッセージは、残して置けるようにしました。目次
- 結論
- 手順
- 2-1. 実行環境を用意
- 2-2. ソースをダウンロード
- 2-3. あなたのSlackチームへのアクセス情報を設定
- 2-4. (オプション) プロキシの設定
- 2-5. 実行
1. 結論
最古の1000件を削除するプログラムを定期的に実行する
プログラムは、JavaScriptで書く
実行は、コマンドプロンプトから、Node.jsで行う2. 手順
2-1. 実行環境を用意
Node.jsをインストール
下図の中央左のボタンをクリックしてダウンロード
全部デフォルト選択でインストール2-2. ソースをダウンロード
Gitをインストールしている人は、以下のコマンドを実行
git clone https://github.com/teraoka-k/SlackWebAPI-deleteOldChat.git
Gitをインストールしていない人は、ここからzip形式でダウンロードできます
2-3. あなたのSlackチームへのアクセス情報を設定
ここからSlackのトークンを発行
緑色の「Create token」ボタンを押す
※Slack Teamの管理者権限のユーザが望ましい(閲覧権限のあるメッセージしか削除できないため)
間違って普通のユーザで、トークンを発行してしまっても、
「Re-issue token」ボタンを押せば、何度でもトークンを発行できるので大丈夫トークンが発行されたら、全選択して、コピーする
(※上図のxoxp-68094...部分がトークンです)
2-2.でダウンロードしたソースの、deleteOldMsgButPinnedOrStarred.jsをお好きなエディターで開く
下記Stringの値を先ほどコピーしたトークンで置き換えdeleteOldMsgButPinnedOrStarred.jsconst token = 'paste your token here';2-4. (オプション) プロキシの設定
仕事先だと、プロキシを設定する必要あり
Chromeを立ち上げて、右上の三点リーダから設定を開く
proxyと検索ボックスに入力して、Open proxy setting をクリック
LANの設定をクリックすると、アドレスとポートが見れるので、それぞれコピーする
以下のコメントを解除deleteOldMsgButPinnedOrStarred.js// const proxiedRequest = request.defaults({'proxy': 'http://${your-address}:${your-port-number}'});
先ほどコピーしたアドレスとポートを設定
deleteOldMsgButPinnedOrStarred.jsconst proxiedRequest = request.defaults({'proxy': 'http://your-corp-address:8080'});deleteOldMsgButPinnedOrStarred.jsを保存して閉じる
2-5. 実行
deleteOldMsgButPinnedOrStarred.jsがあるディレクトリで、コマンドプロンプトを開く
下記コマンドを実行
node deleteOldMsgButPinnedOrStarred.js
削除対象のチャット一覧が出力される
削除してよければ、下記のコメントアウトを解除して、再度実行すれば削除されるdeleteOldMsgButPinnedOrStarred.js/** delete chat */ // top1000OldestChatList.forEach(chat => // deleteChat(chat.channel, chat.ts).then(msg => // console.log(msg) // ) // );備考
Node.jsは、プロキシ環境下で動かないので、以下の設定が、追加で必要かもです
コマンドプロンプトで下記コマンド実行cmd for proxy setting of npm call npm -g config set proxy http://your-corp-address.co.jp:8080 call npm -g config set https-proxy http://your-corp-address.co.jp:8080 call npm -g config set registry https://registry.npmjs.org/ call npm config list※なお上記コマンドの2行目と3行目は、各自のプロキシのアドレスとポートに置き換えてください
4行目は固定です(ただしhttpsかhttpかは、Node.jsのバージョンによって替わったことがあります)
- 投稿日:2019-07-16T17:47:39+09:00
Slack10000 件制限: スター&ピンどめ以外1000件削除
Slackのフリープランで10000件制限をやりくりする
Slackはフリープランだと、10000件しかメッセージを保存できません。
古いものが見えなくなっても困らないけど、中には残しておきたいメッセージもありますよね。
そこで、スター付きのメッセージと、ピン留めしたメッセージは、残しておけるようにしました。目次
- 結論
- 手順
- 2-1. 実行環境を用意
- 2-2. ソースをダウンロード
- 2-3. あなたのSlackチームへのアクセス情報を設定
- 2-4. (オプション) プロキシの設定
- 2-5. 実行
1. 結論
最古の1000件(スター&ピンどめ以外)を削除するプログラムを定期的に実行する
プログラムは、JavaScriptで書く
実行は、コマンドプロンプトから、Node.jsで行う2. 手順
2-1. 実行環境を用意
Node.jsをインストール
下図の中央左のボタンをクリックしてダウンロード
全部デフォルト選択でインストール2-2. ソースをダウンロード
Gitをインストールしている人は、以下のコマンドを実行
git clone https://github.com/teraoka-k/SlackWebAPI-deleteOldChat.git
Gitをインストールしていない人は、ここからzip形式でダウンロードできます
2-3. あなたのSlackチームへのアクセス情報を設定
ここからSlackのトークンを発行
緑色の「Create token」ボタンを押す
※Slack Teamの管理者権限のユーザが望ましい(閲覧権限のあるメッセージしか削除できないため)
間違って普通のユーザで、トークンを発行してしまっても、
「Re-issue token」ボタンを押せば、何度でもトークンを発行できるので大丈夫トークンが発行されたら、全選択して、コピーする
(※上図のxoxp-68094...部分がトークンです)
2-2.でダウンロードしたソースの、deleteOldMsgButPinnedOrStarred.jsをお好きなエディターで開く
下記Stringの値を先ほどコピーしたトークンで置き換えdeleteOldMsgButPinnedOrStarred.jsconst token = 'paste your token here';2-4. (オプション) プロキシの設定
仕事先だと、プロキシを設定する必要あり
Chromeを立ち上げて、右上の三点リーダから設定を開く
proxyと検索ボックスに入力して、Open proxy setting をクリック
LANの設定をクリックすると、アドレスとポートが見れるので、それぞれコピーする
以下のコメントを解除deleteOldMsgButPinnedOrStarred.js// const proxiedRequest = request.defaults({'proxy': 'http://${your-address}:${your-port-number}'});
先ほどコピーしたアドレスとポートを設定
deleteOldMsgButPinnedOrStarred.jsconst proxiedRequest = request.defaults({'proxy': 'http://your-corp-address:8080'});deleteOldMsgButPinnedOrStarred.jsを保存して閉じる
2-5. 実行
deleteOldMsgButPinnedOrStarred.jsがあるディレクトリで、コマンドプロンプトを開く
下記コマンドを実行
node deleteOldMsgButPinnedOrStarred.js
削除対象のチャット一覧が出力される(その間およそ1秒!)
削除してよければ、y & enter
備考
Node.jsのパッケージマネージャーnpmは、プロキシ環境下で動かないので、以下の設定が、追加で必要かもです
コマンドプロンプトで下記コマンド実行cmd for proxy setting of npm call npm -g config set proxy http://your-corp-address.co.jp:8080 call npm -g config set https-proxy http://your-corp-address.co.jp:8080 call npm -g config set registry https://registry.npmjs.org/ call npm config list※なお上記コマンドの2行目と3行目は、各自のプロキシのアドレスとポートに置き換えてください
4行目は固定です(ただしhttpsかhttpかは、npmのバージョンによって替わったことがあります)
- 投稿日:2019-07-16T11:42:04+09:00
VSCodeのRemote Developmentを使ってDocker上のNode.js、Redis環境で作業する
2019年5月に公開された、Visual Studio Code でリモートマシン、コンテナ、Windows Subsystem for Linux (WSL) 上のワークスペースを開くことができるようになる拡張機能群「Remote Development Extension Pack」を使ってみました。
この拡張パックを導入すると、手元の「Visual Studio Code」からリモート環境へ接続し、そこでアプリ開発等を行うことが可能になります。
今回は、Microsoftのレポジトリ VSCode Remote Try Nodeを元に、Node.jsからRedisを扱うDockerコンテナに接続する設定をやってみます。
1 Visual Studio Codeのバージョン確認
Stable 版では (version 1.35) リリース以降で Remote Development 拡張が利用可能です。
バージョンが古い場合は、Visual Studio Code の [ヘルプ]->[更新の確認] または https://code.visualstudio.com/updates 等から最新版にアップデートしてください。2 拡張機能Remote Developmentのインストール
Visual Studio Codeで拡張機能"Remote Development"を検索し、インストールしてください。
3 プロジェクトの構成
Microsoftのレポジトリ VSCode Remote Try Nodeをクローンし、最低限のディレクトリ構成を揃えた後、必要なファイルを加除していきます。
[Project Home] |_ .devcontainer | |_ devcontainer.json | |_ ubuntu-bionic-core-cloudimg-amd64-root.tar.gz | |_ .vscode | |_ launch.json | |_ build | |_ server.js |_ src | |_ server | |_ main.ts |_ store | |_ redis | |_ .gitkeep | |_ Dockerfile |_ docker-compose.yml |_ package.json |_ tsconfig.json |_ tslint.json |_ webpack.config.js公式ではDockerfileを .devcontainer 以下に配置していますが、 ホームディレクトリ上のローカルフォルダ store/redis とDockerコンテナ上のディレクトリを同期してデータ永続化したいので、ホームディレクトリ直下に配置しています。
また、公式では、node:10イメージをベースを使っていますが、 今回は、Linuxイメージ上に npm, node.jsをインストールしたコンテナを作成し、redis コンテナとリンクする構成をやってみたいと思います。
当初、軽量Linuxの代表格alpineをベースにしようとしましたが、どうやら Stable版のVSCode上で動くRemote Developmentではalpineをサポートしていないようなので、やむなくMinimum Ubuntuを使うことにしました。
MInimum Ubuntuのイメージファイルは以下のレポジトリからダウンロードし、.devcontainer以下に配置しました。
4 Remote Development の設定
devcontainer.json
devcontainer.json{ "name": "node.js and redis sample ", "dockerComposeFile": [ "../docker-compose.yml" ], "service": "node", "appPort": 3000, "extensions": [ "VisualStudioExptTeam.vscodeintellicode", "dbaeumer.vscode-eslint", "eg2.tslint" ], "settings": { "terminal.integrated.shell.linux": "/bin/bash" }, "shutdownAction": "none" }主要な設定項目としては、
- service で node.jsを稼働するコンテナのサービス名を指定
- appPort で node.js上でlistenするportを指定
- dockerComposeFileでdocker-compose.ymlの相対パスを指定
- extensions でリモート上のVSCodeで使う拡張機能を追加
ちなみに、普段使っているVSCodeの拡張機能一覧は
code --list-extensions | xargs -L 1 echo code --install-extensionで取得できます。
5 Docker の設定
Dockerfile
DokerfileFROM scratch ADD .devcontainer/ubuntu-bionic-core-cloudimg-amd64-root.tar.gz / RUN set -xe \ \ && echo '#!/bin/sh' > /usr/sbin/policy-rc.d \ && echo 'exit 101' >> /usr/sbin/policy-rc.d \ && chmod +x /usr/sbin/policy-rc.d \ \ && dpkg-divert --local --rename --add /sbin/initctl \ && cp -a /usr/sbin/policy-rc.d /sbin/initctl \ && sed -i 's/^exit.*/exit 0/' /sbin/initctl \ \ && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \ \ && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \ && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \ && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \ \ && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \ \ && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \ \ && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests RUN rm -rf /var/lib/apt/lists/* RUN sed -i 's/^#\s*\(deb.*universe\)$/\1/g' /etc/apt/sources.list RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container # Configure apt and install packages RUN apt-get update && \ yes | apt-get install \ curl \ git \ npm \ nodejs WORKDIR /home SHELL ["/bin/bash", "-c"]基本的に、https://github.com/tianon/docker-brew-ubuntu-core/blob/59aa7dfef17153ecc812adbf26516675ce67e8aa/bionic/Dockerfile のままです。追加項目として、#Configure apt and install packages以下で、必要なモジュールをインストールするようにします。
docker-compose.yml
docker-compose.ymlversion: '3' services: node: build: context: . dockerfile: Dockerfile container_name: node-container volumes: - .:/home ports: - 3000:3000 command: sh -c 'npm install & node build/server.js' links: - "redis" redis: restart: always container_name: redis-container image: redis:latest volumes: - ./store/redis:/data ports: - "6379:6379" command: redis-server --appendonly yes上記のDockerfileを走らせて作成するnodeイメージと、Official Imageのredis:latestイメージをリンクします。
特記事項として、redis側でローカルのstore/redisとコンテナ側のdataフォルダを同期し、データの永続化を行っています。6 package.jsonの設定
今回は、Webpackを使ってTypeScriptをトランスパイルする例です。
2019年7月現在の、webpackの最新バージョン 4.29.0 では Maximum Call Stackのエラーが出てしまうため、旧バージョンを指定しています。
package.json{ "name": "node.js and redis sample", "version": "1.0.0", "devDependencies": { "@types/app-root-path": "", "@types/express": "", "@types/node": "", "@types/redis": "", "path": "", "ts-loader": "", "tslint": "", "tslint-loader": "", "typescript": "", "webpack": "4.17.1", "webpack-cli": "", "webpack-node-externals": "" }, "dependencies": { "app-root-path": "", "express": "", "redis": "" }, "private": true }7 Node.jsによるサーバ設定
expressでWebサーバを立ち上げ、redisでPOSTの回数をカウントするという例です。
main.ts'use strict'; import * as root from 'app-root-path'; import * as express from 'express'; import * as redis from 'redis'; /** * Configure Redis */ const client: redis.RedisClient = redis.createClient(6379, 'redis'); client.on('connect', () => console.log('Connected to Redis')); client.set('visit', '0'); /** * Configure Web Server */ const app: express.Application = express(); app.use(express.static('.')); app.post('/api', (_req: express.Request, res: express.Response) => { client.get('visit', (_err: Error|null , visit: string) => { res.send('POST request received. Number of Visits:' + visit); client.set('visit', String(parseInt(visit, 10) + 1)); }); }); // tslint:disable-next-line:typedef const port = process.env.PORT || 3000; app.listen(port, () => console.log(`Server running on ${port}`));8 実行
F1で拡張機能の一覧を表示するか、Visual Studioコードの左下の緑色のブラケットマークからRemoteデスクトップの機能一覧を表示します。
docker-compose up --build
を既に一度走らせている場合は、「Attach to Running Container(水色)」を選択し、まだの場合は「Open Folder in Container(赤色)」で現在のホームディレクトリを指定すればdocker-compose up --build
が自動的に走ります。ビルドに成功すると、Remote Development用のVSCodeのウィンドウが起動します。後は開いたウィンドウ上で「フォルダを開く」から任意のフォルダを開くと、コンテナ上のファイルをVS Codeで編集することができます。
9 Redisの動作確認
Remote Developmentとは直接関係ありませんが、Redisがきちんと動作しているか確認するには、
curl -X POST
(ローカル、コンテナ側のどちらからでも結構です) で以下のAPIを叩き、curl -X POST http://localhost:3000/api
以下のようにPOSTの通算回数が返ってくれば成功です。
POST request received. Number of Visits:[POSTの回数]10 参考にさせていただいたサイト
下記のページを参考にさせていただきました。
https://code.visualstudio.com/updates/v1_35
https://qiita.com/yoskeoka/items/01c52c069123e0298660
https://qiita.com/mizuhof/items/7bc20538c9fe1edcba40
https://katsu-tech.hatenablog.com/entry/2017/10/11/233024
https://blog.manabusakai.com/2018/08/minimal-ubuntu-dockerfile/なお、今回の構成はGithubで公開していますので、ご指摘などあればよろしくお願いいたします
https://github.com/snst-lab/vscode-remote-try-node-typescript-redis
- 投稿日:2019-07-16T08:46:40+09:00
Nest.jsでSequelizeを使ってみる
前回、Nest.js を使ってみるでNest.js環境を構築しました。
今回はNode.js向けのORMであるSequelizeを導入してみます。
Sequelizeとは
Sequelize:http://docs.sequelizejs.com/
Nest.jsにSequelizeを組み込む
公式に手順が載っているため、それに従います
なお、今回使用するDBはPostgresです。
sequelize-typescriptのインストール
sequelize、sequelize-typescript、pg(postgres)、sequelizeの型定義パッケージをインストールします
$ npm install --save sequelize sequelize-typescript pg $ npm install --save-dev @types/sequelizeDB接続準備
公式だと接続情報はコードにべた書きですが、環境ごとにDBを切り替えられるように設定ファイルで外だしします。
src/database/database.config.tsexport const config = { development: { host: process.env.POSTGRES_HOST, port: process.env.POSTGRES_PORT, database: process.env.POSTGRES_DB_NAME, username: process.env.POSTGRES_USER, password: process.env.POSTGRES_PASSWORD, dialect: 'postgres', }, production: { // TODO 本番用 } }src/database/database.providers.tsimport { Sequelize } from 'sequelize-typescript'; import { Cat } from '../cats/cat.entity'; import { config } from 'src/config/database.config'; export const databaseProviders = [ { provide: 'SEQUELIZE', useFactory: async () => { const sequelize = new Sequelize( config[process.env.NODE_ENV || 'development'] ); sequelize.addModels([Cat]); await sequelize.sync(); return sequelize; }, }, ];database.module.tsimport { Module } from '@nestjs/common'; import { databaseProviders } from './database.providers'; @Module({ providers: [...databaseProviders], exports: [...databaseProviders], }) export class DatabaseModule {}Catsテーブルアクセス用ファイル作成
公式の手順に従って、Catsテーブルにアクセスするためのファイルを準備します。
src/cats/cats.entity.tsimport { Table, Column, Model } from 'sequelize-typescript'; @Table export class Cat extends Model<Cat> { @Column name: string; @Column age: number; @Column breed: string; }src/cats/cats.providers.tsimport { Cat } from './cat.entity'; export const catsProviders = [ { provide: 'CATS_REPOSITORY', useValue: Cat, }, ];src/cats/cats.module.tsimport { Module } from '@nestjs/common'; import { CatsController } from './cats.controller'; import { CatsService } from './cats.service'; import { catsProviders } from './cats.providers'; import { DatabaseModule } from '../database/database.module'; @Module({ imports: [DatabaseModule], controllers: [CatsController], providers: [ CatsService, ...catsProviders, ], }) export class CatsModule {}src/cats/cats.service.tsimport { Injectable, Inject } from '@nestjs/common'; import { Cat } from './cat.entity'; @Injectable() export class CatsService { constructor( @Inject('CATS_REPOSITORY') private readonly CATS_REPOSITORY: typeof Cat) {} async findAll(): Promise<Cat[]> { return await this.CATS_REPOSITORY.findAll<Cat>(); } }src/cats/cats.controller.tsimport { Controller, Get } from '@nestjs/common'; import { CatsService } from './cats.service'; import { Cat } from './cat.entity'; @Controller({ path: 'cats' }) export class CatsController { constructor(private readonly catsService: CatsService) {} @Get() getCats(): Promise<Cat[]> { return this.catsService.findAll(); } }起動してみる
以下のようなdocker-compose.ymlを用意し、
docker-compose up
で起動してみます。docker-compose.ymlversion: '2' services: nestjs-web: image: node:latest container_name: nestjs-web ports: - "3000:3000" links: - nestjs-db working_dir: /develop command: [sh, -c, 'npm install --unsafe-perm && npm run start:dev'] volumes: - "./:/develop:z" environment: - "POSTGRES_HOST=192.168.33.20" - "POSTGRES_PORT=15432" - "POSTGRES_DB_NAME=postgres" - "POSTGRES_USER=postgres" - "POSTGRES_PASSWORD=postgres" nestjs-db: image: postgres:latest container_name: nestjs-db ports: - "15432:5432" environment: - "POSTGRES_USER=postgres" - "POSTGRES_PASSWORD=postgres" volumes: - "/data/db:/var/lib/postgresql/data:z"ちゃんとCatsテーブルのCREATE文が発行されてますね。
DBにデータを投入
A5M2でDBにアクセスし、データを追加しておきます。
ブラウザでアクセス
http://192.168.33.20:3000/cats にアクセスします
追加した情報が取れました!
- 投稿日:2019-07-16T05:59:08+09:00
【最新サービス試用⑧】リクエスト管理やJSON出力結果整形等に便利なcurl拡張コマンドツールの「curlx」を試用。
- 日々輩出される素晴らしき最新サービスを素早く試して、不鮮明な先見性を堂々と誇示する記事第八弾。
- 歴史的偉人の集中力の記事の、収集作業に精を出している生活。
- 今回は、curlでの出力の際に、Terminal上であらゆる高機能な作業が可能な「curlx」を試用することにしよう。
概要
- レスポンス確認やAPI通信の際の際に用いる「curl」のリクエストの管理が捗るコマンドツール。
- 「JSONでの出力結果の整形」や「リクエストのコレクション(グループ化)」等の機能を、GUIツール等を利用せずに、ターミナル内のみで可能。
- GUIツールの「Postman」やJSON整形コマンドツールの「jq」の両方の機能を備えたようなツール。
- 公式サイト
- 公式Github
特徴
出力結果の整形
- 可読が容易ではないcurlでのJSON出力結果を、cxでは整形して、見やすく表示してくれる。
- jqを利用することなく、標準で整形してくれる。
リクエスト履歴の視覚化
- リクエスト履歴の確認が容易に可能であることに加え、ステータスや通信形式、時間等の詳細情報が表として、わかりやすく確認できる。
リクエストのコレクション(グループ)化
- リクエストをカテゴリごとにグループ化できるため、「よく投げるコマンドのエイリアス登録」や「内容別でのリクエストのグループ管理」が可能。
- Postmanでのコレクション機能を、ターミナル内で利用が可能。
結果
※テストAPIとして、LivedoorさんのWeather Hackを利用。
下記のように、curlでは見づらいjson形式や文字化けが、簡単なコマンドで見やすくなる。
- 通信形式やステータス結果等も含んだ、わかりやすい履歴の表示も可能。
- よく使う出力等を、グループ化で整理して、簡単なコマンドでリクエストが可能。
作業環境
- Amazon Linux 2
- Node.js v10.16.0
- npm 6.9.0
- ※Node.js環境が利用できれば、MacやWindowsでも可能。
インストール
curlxのインストールは、Nodejsのnpmやyarnで可能なため、未導入の場合は、下記を参考にインストールする。
Node.jsのインストール後、下記のコマンドをうち、バージョン確認をする。
# Node.jsのバージョン確認 $ node -v # npmのバージョン確認 $ npm -v
- 確認後、下記のコマンドをうち、「curlx」のインストールを行う。
# curlxのインストール $ sudo npm install curlx -g # バージョン確認 $ cx version基本操作
- curlxの基本操作は、下記。
- ※基本的にcurlコマンドをcxに置き換えるだけで可能。
内容 コマンド 通常リクエスト cx 接続先URL
※オプション指定なしで、ヘッダー出力やjson整形が可能。リクエスト(オプション付き) cx -オプション URL
※オプションは、curlと同様なため、curlをcxに置き換えるだけ。
例 :cx -X GET URL
リクエスト履歴確認 cx history
リクエストのグループ(コレクション)化 cx new collections
実行後、いくつかの質問に回答していく形で、作成していく
詳細は、下記の操作例を確認。作成コレクションへのリクエストの追加 cx new request
コレクション作成同様、質問形式で追加していく
詳細は、下記の操作例を確認。コレクション一覧 cx collections
idやコレクションリクエストでの実行 cx run <id or collection_id>
詳細は、下記の操作例を確認。リクエストやコレクションの削除 cx delete <id or collectionname>
詳細は、下記の操作例を確認。ヘルプページ確認 cx help
バージョン確認 cx version
操作例
通常リクエスト
- 下記のコマンドをうち、URLでの通常リクエストを行う。
- ※オプションは、curlと同様に扱えるため、cxに置き換えるだけでよい。
# 通常リクエスト $ cx http://weather.livedoor.com/forecast/webservice/json/v1?city=471010 # オプション指定でのリクエスト $ cx -X GET http://weather.livedoor.com/forecast/webservice/json/v1?city=471010コレクションの作成〜実行
- 下記のコマンドをうち、cxコマンドをグループ化することで、任意の名前とidでリクエストが可能。
# コレクション(グループ)を作成 $ cx new collection ✔ Name of your new collection … コレクション名(例:getWeather)入力 This collection already exists ✔ Would you like to add a new request to getWeather … リクエスト追加確認(例:yes) ✔ Enter complete request eg: cx -X GET https://httpbin.org/get … 実行コマンド入力(例:cx -X GET URL) ✔ Give a name for your request … リクエスト名(例:getOkinawa) # コレクション一覧確認 $ cx collections ┌────────────┬────────────────────┬────────┬──────────────────────────────┐ │ id │ name │ method │ url │ ├────────────┼────────────────────┼────────┼──────────────────────────────┤ │ y2Q9JCOjL │ getOkinawa │ get │ http://weather.livedoor.com… │ └────────────┴────────────────────┴────────┴──────────────────────────────┘ # id名でのリクエスト実行 # まず、history(履歴)内のid名での実行 $ cx history ┌────────────┬────────┬──────────────────────────────┬────────┬────────────┐ │ id │ method │ url │ status │ timestamp │ ├────────────┼────────┼──────────────────────────────┼────────┼────────────┤ │ H0yIigcQv │ get │ http://weather.livedoor.com… │ 200 │ 2019-7-13 │ │ │ │ │ │ 12:51 PM │ ├────────────┼────────┼──────────────────────────────┼────────┼────────────┤ $ cx run H0yIigcQv { "pinpointLocations": [ { "link": "http://weather.livedoor.com/area/forecast/4720100", "name": "那覇市" }, { # コレクション内のリクエストidでの実行 # ※コレクション内のidは、コレクション名も同時に明記する必要がある。 $ cx run getWeather y2Q9JCOjL { "pinpointLocations": [ { "link": "http://weather.livedoor.com/area/forecast/4720100", "name": "那覇市" },コレクションへのリクエスト追加
- 下記のコマンドをうち、既存コレクションに新規リクエストを追加
# コレクション確認 $ cx collections ┌────────────┬────────────────────┬────────┬──────────────────────────────┐ │ id │ name │ method │ url │ ├────────────┼────────────────────┼────────┼──────────────────────────────┤ │ y2Q9JCOjL │ getOkinawa │ get │ http://weather.livedoor.com… │ └────────────┴────────────────────┴────────┴──────────────────────────────┘ # リクエストの新規追加 $ cx new request ✔ Name of your new collection … コレクション名(getWeather)入力 ✔ Enter complete request eg: cx -X GET https://httpbin.org/get … 実行コマンド(例:cx URL) ✔ Give a name for your request … リクエスト名(getOsaka) # コレクション一覧再確認 $ cx collections ┌────────────┬────────────────────┬────────┬──────────────────────────────┐ │ id │ name │ method │ url │ ├────────────┼────────────────────┼────────┼──────────────────────────────┤ │ y2Q9JCOjL │ getOkinawa │ get │ http://weather.livedoor.com… │ ├────────────┼────────────────────┼────────┼──────────────────────────────┤ │ nG3nzD53k │ getOsaka │ get │ http://weather.livedoor.com… │ └────────────┴────────────────────┴────────┴──────────────────────────────┘リクエストidやコレクションidの削除
- 下記のコマンドをうち、リクエストidやコレクションの削除を行う。
# id名でのリクエスト削除 $ cx delete H0yIigcQv # コレクション内のid名でのリクエスト削除 $ cx delete getWeather:y2Q9JCOjL操作履歴やコレクション確認
- curlxの操作履歴やコレクション一覧は、下記のファイルで確認できる。
- ※curlxの履歴やコレクションといった情報は、ルートフォルダの「cxdb」というフォルダに保存されている。
- ※簡単な履歴やコレクション確認の際は、上記の操作例での操作方法で可能。
# 操作履歴格納ファイルの中身確認 $ less ~/cxdb/history.json { "history": [ { "id": "UsVI7Oq9Y", "method": "get", "command": "curl -i \"http://weather.livedoor.com/forecast/webservice/json/v1?city=471010\"", "url": "http://weather.livedoor.com/forecast/webservice/json/v1?city=471010", "status": "200", "ts": "2019-7-12 11:58 PM" }, { "id": "So_ybzFn3", "method": "get", "command": "curl -i \"http://weather.livedoor.com/forecast/webservice/json/v1?city=471010\"", "url": "http://weather.livedoor.com/forecast/webservice/json/v1?city=471010", "status": "200", "ts": "2019-7-13 12:01 AM" },# コレクション一覧ファイルの中身確認 $ less ~/cxdb/collection.json { "collections": { "getWeather": [ { "id": "y2Q9JCOjL", "name": "getWeather", "method": "get", "command": "curl -i \"-X\" \"GET\" \"http://weather.livedoor.com/forecast/webservice/json/v1?city=471010\"", "url": "http://weather.livedoor.com/forecast/webservice/json/v1?city=471010" }まとめ
- 今回は、curlでのAPI結果整形ということで、「Terminalのみでの利用幅の拡大」による「パソコンの容量削減」を感慨深く染みながら、記事を書く。
- 「利用機能による、GUIツールとCUIツールの併用」の誓いは、すぐさま「日毎の気分利用」に変化することを確信。
- しばらく、この賢人ツールとの付き合いが続くと感じたため、より一層開発者礼拝を強化。
参考
- https://curlx.dev/
→公式サイトです。大変お世話になりました。- https://github.com/shivkanthb/curlx
→公式Githubです。大変お世話になりました。- https://entry.anypicks.jp/product-curlx/
→こちらの記事で知りました。大変お世話になりました。
- 投稿日:2019-07-16T00:12:30+09:00
Node.jsでGoogle Drive内の特定のファイルが特定のフォルダの配下にいるかどうかを調べる (Google Drive API v3)
Google Drive APIをNode.jsから触る以下の記事たちの続きです
- Node.jsでGoogle Driveの指定フォルダからファイル一覧を取得メモ
- Node.jsでGoogle Drive上のファイルを複製(copy)する
- Node.jsでGoogle Drive上のファイルを指定フォルダに移動する
- Node.jsでGoogle Drive上のファイルをリネームする
- Node.jsでGoogle Drive上のファイルを削除する (Google Drive API v3)
GETメソッドを再帰的に使う
GETメソッドで
fields
にparents
を指定することで、親フォルダのIDを取得できます。
これを再帰的に繰り返していって、祖先を遡っていったときにフォルダ名が指定した名前のものが見つかったら終了です。ちなみにGETメソッドの返却値はFILESのリファレンスを見ると確認できますが、けっこうたくさんあるので把握するのは大変そうですね。
スコープ
https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.photos.readonlyなかなか多い。
簡単な実装
基本的な認証周りなどのコードは他の記事同様です。
get.js省略 //特定のファイル(fileId)が特定フォルダ(folderName)の配下にいるか確認 const folderName = `定期発生`; const fileId = `xxxxxxxxxxxxxxxxxxxx`; async function loop(drive, fileId, path = ''){ //STEP1: IDからファイル情報を取得 const params = { fileId: fileId, fields: 'parents,name,kind,mimeType,id,spaces' } const res = await drive.files.get(params); console.log('---',res.data); path = `/${res.data.name}${path}`; //STEP2: 親フォルダのIDをGET - ここが複数あるとうまく動かないときあるかも... const parentsFolderId = res.data.parents[0]; //STEP3: 親フォルダを再帰的に探していく try { if(res.data.name === folderName){ console.log(`このファイルは${folderName}の配下です。`, path); }else{ await loop(drive, parentsFolderId, path); } } catch (error) { console.log(`このファイルは${folderName}の配下ではありません。`) } } async function main(auth) { const drive = google.drive({version: 'v3', auth}); await loop(drive, fileId); }