Electron と enebular editor を使って デスクトップ に ツィート を表示させてみた。

こんにちは。野良ハックチーム ざっきーと申します。

IoTLT Advent Calendar 2018 の 12 日目の @pokiiio さんの記事「<A HREF="https://qiita.com/pokiiio/items/88a69143179c48e6612b">Electronで作った京浜急行運行情報監視ウィジェットを支えるクソコードたち</A>」の内容が素晴らしかったので Electron と enebular editor を使って 
<A HREF="https://enebular.connpass.com/event/106731/">LT 登壇中</A>に
 デスクトップに ツィート を表示させてみました。
以前書いた記事「<A HREF="https://qiita.com/kitazaki/items/82c4e7a1d59cd484559f">enebular を使って IoTLT の ツィート状況を可視化してみた。</A>」の発展形になります。

## 成果物
最初にゴール (成果物) を示します。画面上部に表示されているバナーです。ツィートの内容が表示されます。常に最上位に表示されて、マウスクリックは透過されます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/294aa44f-141f-dafd-843c-ca40cd0b1886.png" width="75%">
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/0b51bbef-3f4a-79b3-3783-c86967a0f936.png" width="75%">

すぐに試してみたい方は<A HREF="https://www.dropbox.com/sh/jgflsrwgt5a16ig/AAD6fOkxk9PTqR_JpH68x39Na?dl=0
">こちら</A>に macOS と Windows のビルド済みファイルを置いておきます。(勉強会などの時しか役に立たないかもしれませんが・・。)

## 構成
twitter 〜 Milkcocoa までは<A HREF="https://qiita.com/kitazaki/items/82c4e7a1d59cd484559f">以前</A>と同じ構成です。Milkcocoa からツィートの情報を取得して画面上に表示する部分が異なります。<A HREF="https://qiita.com/kitazaki/items/82c4e7a1d59cd484559f">以前</A>はブックマークレットを用いてブラウザ内から Javascript のプログラムを読み込む形でしたが、今回は Electron でデスクトップアプリケーション化している点が異なります。メリットはアプリケーション化しているので、表現の領域がブラウザ内からデスクトップ全体に広がった点です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/a0ea7d14-4778-5c29-adf8-c38d6d56da47.png">

### Electron
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/4243f900-e072-6071-5166-0ffc24ec3ed8.png" width="75%">

ソースコードはこちら。
https://github.com/kitazaki/electron_twitterwidget

src/twitter.js を編集して自分の情報を記入する必要があります。

- MilkCocoa.connectWithApiKey に host, api_key, api_secret を設定する。<br />
Milkcocoa の管理画面の認証タブから情報を取得します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/c6c65c4f-902f-ff4f-4248-d600dedc7569.png" width="75%">

```javascript
var milkcocoa = MilkCocoa.connectWithApiKey('[host]', '[api_key]', '[api_secret]');
```

 - milkcocoa.dataStore に path を設定する。 (例. comment) <br />
後述の Node-RED フローにも同じ path を設定します。

```javascript
var milkcocoaDS = milkcocoa.dataStore('[path]');
```

- watchword に キーワード を設定する。 (例. spospo) <br />
他の人と dataStore を共有する際にツィートを区別するために使用します。 <br />
後述の Node-RED フローにも同じキーワードを設定します。

```javascript
 var watchword = "[キーワード]";
```

### インストールと使用方法

```bash
# ソースコードをダウンロード または clone する。
$ git clone https://github.com/kitazaki/electron_twitterwidget

# 必要なファイルをダウンロードする。
$ cd electron_twitterwidget
$ npm install

#
# src/twitter.js を編集して自分の情報を記入する。
#

# 起動する。
$ npm start
```

※ Node のバージョンは v8.14.0 で動作確認しています。

#### npm audit で脆弱性を修正
npm v6.0.0 からセキュリティチェックができるコマンド npm audit が追加され、脆弱性の警告を受けた npm パッケージの依存関係を確認できるようになりました。また、v6.1.0 から脆弱性のある箇所を自動修正してくれるサブコマンド npm audit fix が追加されました。修正しなくても動作に影響はありませんが、もし気になるようであれば、修正されたパッケージをインストールし、問題のあるパッケージを削除し、npm dedupe コマンドで依存関係を修正します。

```sh
$ npm install
...
...
found 3 vulnerabilities (1 low, 2 high)
  run `npm audit fix` to fix them, or `npm audit` for details

# npm audit で問題の箇所を確認
$ cd src
$ npm audit
 === npm audit security report ===                        
                                                                                
┌──────────────────────────────────────────────────────────────────────────────┐
│                                Manual Review                                 │
│            Some vulnerabilities require your attention to resolve            │
│                                                                              │
│         Visit https://go.npm.me/audit-guide for additional guidance          │
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Denial of Service                                            │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ ws                                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >= 1.1.5 <2.0.0 || >=3.3.1                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ milkcocoa                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ milkcocoa > mqtt-for-milkcocoa > websocket-stream > ws       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/550                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ DoS due to excessively large websocket message               │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ ws                                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=1.1.1                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ milkcocoa                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ milkcocoa > mqtt-for-milkcocoa > websocket-stream > ws       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/120                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Remote Memory Disclosure                                     │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ ws                                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >= 1.0.1                                                     │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ milkcocoa                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ milkcocoa > mqtt-for-milkcocoa > websocket-stream > ws       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/67                        │
└───────────────┴──────────────────────────────────────────────────────────────┘
found 3 vulnerabilities (1 low, 2 high) in 906 scanned packages
  3 vulnerabilities require manual review. See the full report for details.
```

milkcocoa > mqtt-for-milkcocoa > websocket-stream に含まれる ws に問題があることが分かる。

```bash
# 修正された ws パッケージをインストールする。
$ npm install ws
+ ws@6.1.2
added 3 packages from 2 contributors and audited 213 packages in 2.052s
found 3 vulnerabilities (1 low, 2 high)
  run `npm audit fix` to fix them, or `npm audit` for details

# 問題のある ws パッケージのディレクトリを確認する。
$ npm ls ws
TwitterWidget@1.0.0 ./electron_twitterwidget/src
├─┬ milkcocoa@0.7.0
│ └─┬ mqtt-for-milkcocoa@1.6.3
│   └─┬ websocket-stream@2.3.0
│     └── ws@0.8.1     # ← これが問題のある ws パッケージ
└── ws@6.1.2 

# 問題のある ws パッケージのディレクトリを削除する。
$ rm -rf node_modules/websocket-stream/node_modules/ws/

# 問題のある ws パッケージが削除されたことを確認する。
$ npm ls ws
TwitterWidget@1.0.0 ./electron_twitterwidget/src
├─┬ milkcocoa@0.7.0
│ └─┬ mqtt-for-milkcocoa@1.6.3
│   └─┬ websocket-stream@2.3.0
│     └── UNMET DEPENDENCY ws@0.8.1     # ← ws パッケージが削除されている。
└── ws@6.1.2 

npm ERR! missing: ws@0.8.1, required by websocket-stream@2.3.0

# npm dedupe コマンドで依存関係を修正する。
$ npm dedupe
audited 204 packages in 1.215s
found 0 vulnerabilities
 
# 脆弱性が修正されたことを確認する。
$ npm audit
                                                                                
                       === npm audit security report ===                        
                                                                                
found 0 vulnerabilities
 in 204 scanned packages
```

### enebular editor
<A HREF="https://docs.enebular.com/en/enebulareditor/">enebular editor</A> をダウンロード・インストール・実行し、enebular editor 起動後にデスクトップを選択すると、今までオンライン上で編集作業していた Node-RED フローを PC 上で操作できます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/63a8dfe9-7288-15c8-c4bb-68b51bea4123.png" width="45%"> <img src="https://qiita-image-store.s3.amazonaws.com/0/72479/ebca955f-f929-6670-62f0-0d838b855032.png" width="45%">

## まとめ
いまさらかもしれませんが、今回は Electron の "凄み" と enebular editor の "良さみ" を感じました。みなさんも 良き Electron ＆ enebular ライフを！

#### (追伸: デバッグ方法)
もし想定通りに動作しないな、と思った場合は main.js に
window.openDevTools()
を追加したり、BrowserWindow の フレーム表示オプションを有効化 (frame: true) したり、透過表示オプションを無効化 (transparent: false) したり、マウスクリックを有効化 (window.setIgnoreMouseEvents(true) → (false)) してデバッグすると良いと思います。

```bash
$ diff main_debug.js main.js 
59,60c59,60
<     frame: true,
<     transparent: false,
---
>     frame: false,
>     transparent: true,
66,67c66
<   window.setIgnoreMouseEvents(false);
<   window.openDevTools();
---
>   window.setIgnoreMouseEvents(true);
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/72479/53674a36-86de-3182-d6e8-ed84070b640c.png" width="75%">