京急線の運行情報をLINE Notifyする

(これは自分用に作成したものです。なぜならば完全にローカルネタだからです。)

京急線の運行情報をLINE Notifyを利用して、LINEアプリに通知してもらいます。
そうるすことで、電車に乗る前の心構えができるようになります。

私の場合、Xiaomiの「Mi Band 3」のリストバンドを付けていているので、LINEアプリに通知が来ると、バンドが震えて知らせてくれます。


# 京急のメンバーにメールアドレスを登録する

京急では、下記のKEIKYU WEBメンバーズに登録すると、登録したメールアドレスに京急線運行状況に変更があったことをお知らせしてくれます。

　https://www.keikyu.co.jp/login/index.html

正しくは、変更があるとメールが飛んでくるのですが、変更内容はメールに記載されいてるURLをブラウザから開くことで確認します。
確認する先のURLは、毎回同じでした。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/1597a8b7-9989-ea4b-0246-d26378ed6fb7.png)
 
登録メールアドレスとしてgmailを使いました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/2035e798-9959-8102-b70c-beb1a11cfeca.png)

仮登録完了のメールが届くので、メールにあるリンクをクリックすると、会員情報の入力画面が表示されるので、入力して送信すれば、登録完了です。
その時、忘れずに、「運行情報を配信する」にチェックを入れてください。
本登録完了のメールが届くはずです。

# LINE Notifyのパーソナルアクセストークンを発行する。

LINE Notifyを使って自分に通知するためには、パーソナルアクセストークンを払い出す必要があります。
まずブラウザで以下のページを開きます。

　https://notify-bot.line.me/ja/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/a5181808-7dd5-e0e3-686c-b67f94a5e333.png)

そうすると、友達追加のQRコードが表示されていますので、それをLINEアプリがインストールされたスマホのQRコードリーダでスキャンして、LINE Notifyという名前のお友達を追加します。
 
次に、同じページで、右上のログインをクリックしてログインします。
ログイン後、右上の名前のところから「マイページ」を選択します。
「トークンを発行する」ボタンを押下します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/77d5f2fc-7140-9c35-9541-9a94d688d013.png)

トークン名は適当でよいです。例えば、「通知用」とします。
トークルームは、「1:1でLINE Notifyから通知を受け取る」を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/cc00b37f-125d-1347-08d8-aa2e960e47f5.png)

トークンが払い出されます。後で使うので覚えておきます。

 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/0f8c20f9-6a9d-2754-79e1-d766d6b72e28.png)


# メールを受信したらLINEにNotifyする

あとは、実装するだけです。
以下のnpmモジュールを使います。

* cheerio
* inbox
* node-fetch

cheerioは、運行情報が表示されたHTMLページから、運行情報の文章を抜き出すために使います。
　https://github.com/cheeriojs/cheerio
inboxは、Gmailサーバに接続し、メール受信のイベントをフックします。
　https://github.com/ress/inbox
node-fetchは、京急の運行情報のHTMLページを取得したり、LINE Notifyに通知を依頼するときに使います。

```javascript:index.js
const cheerio = require('cheerio');
const fetch = require('node-fetch');
const { URLSearchParams } = require('url');
var inbox = require('inbox');

const LINE_PERSONAL_ACCESS_TOKEN = process.env.LINE_PERSONAL_ACCESS_TOKEN || 【パーソナルアクセストークン】;
const GMAIL_USER = process.env.GMAIL_USER || 【Gmailアドレス】;
const GMAIL_PASSWORD = process.env.GMAIL_PASSWORD || 【Gmailパスワード】;

var client = inbox.createConnection(false, 'imap.gmail.com', {
    secureConnection: true,
    auth: {
        user: GMAIL_USER,
        pass: GMAIL_PASSWORD
    }
});

client.on('connect', () => {
    console.log('connected');

    client.openMailbox('INBOX', (error) => {
        if (error){
            console.log(error);
            throw error;
        }
        console.log('opened');
    });
});

function do_get(url, qs){
    var params = new URLSearchParams();
    for( var key in qs )
        params.set(key, qs[key] );

    var p = params.toString();
    if( p )
        url += '?' + p;
    return fetch(url, {
        method : 'GET',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
    })
    .then((response) => {
        if( response.status != 200 )
            throw 'status is not 200';
        return response.text();
    });
}

function line_notify(message){
    var body = {
        message: message
    };
    return do_post_token('https://notify-api.line.me/api/notify', body, LINE_PERSONAL_ACCESS_TOKEN);
}

function do_post_token(url, body, token){
    var data = new URLSearchParams();
    for( var name in body )
        data.append(name, body[name]);

    return fetch(url, {
        method : 'POST',
        body : data,
        headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer ' + token }
    })
    .then((response) => {
        if( response.status != 200 )
            throw 'status is not 200';
        return response.json();
    });
}

client.on("new", (message) => {
    console.log('日時:' + message.date);
    console.log('送信者:' + message.from.name + '-' + message.from.address);
    console.log('タイトル:' + message.title);

    if( message.title == '京急線運行情報'){
        do_get('http://unkou.keikyu.co.jp/?from=mail')
        .then(text =>{
            const $ = cheerio.load(text);
            var message = $(".unko-panel").text().trim();
            console.log(message);
            return line_notify(message);
        })
        .catch(error =>{
            console.log(error);
        });
    }
});

client.connect();
```

以下の部分を環境に合わせて変更してください。

　【パーソナルアクセストークン】
　【Gmailアドレス】
　【Gmailパスワード】


流れとしてはこんな感じです。

1. inboxで、メールが受信されるのを待ち受ける
2. メールを受信したら、メールのタイトル(Subject)は「京急線運行情報」かを確認する。
3. 京急の運行情報のHTMLページを取得し、cheerioを使って運行情報を抜き出す。
4. LINE Notifyに運行情報を通知する。

メールが来ると、こんな感じでLINEに通知が来ます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/d7e436ae-768b-8712-9c34-1e9fc4b7a87b.png)

あとはこれを常時起動にするだけです。

以上です。