2019-05-10に投稿

Onesignalを使ってNodeJSでpush通知

背景

手軽にプッシュ通知を実装したい!

何を使おうか?

  • pushbullet

push通知アプリ。プラットフォームに依存しない。
android 8に変えたらバックグラウンドタスクがkillされてるのか通知がこない。

  • slack

最近のトレンド。チームに加入してない人には通知がいかないのがデメリット。

  • onesignal

日本語対応が後手の印象。登録画面が怪しい。
プッシュ通知が手軽に実装できる。

過去、slackとpushbulletは実装したことがある(※ただしJava)ので、今回はNodeJSでonesignalの実装に挑んでみました。

使うライブラリ

NodeJSでonesignalのAPIにアクセスできるライブラリ。

実装

概要

4時間ごとに00分ちょうどに掲示板の書き込みがあるかヘッダを確認して更新があればプッシュ通知を出すというジョブを実装する。

毎日4時間ごと(00分00秒)にジョブを実行する

let cronTime:string = "0 0 */4 * * *";

即時関数

この中ではawaitを使用できる。
戻り値がPromiseの処理を1行で記述できるのがasync/awaitの強み。
(コールバック地獄とthen地獄はもう嫌だ)

(async()=>{

})().catch(...)

レスポンスヘッダから最終更新日時を取得する

let data = await response.headers.get('last-modified')

REST API keyとAUTH KEYを指定する

メニューから「ACCOUNT & API KEYS」のページを参照する。
image

var myClient = new OneSignal.Client({      
          userAuthKey: '*******',    
           app: { 
               appAuthKey: '*******',
               appId: '*******' 
          }    
        });
        var firstNotification = new OneSignal.Notification({      
          contents: {      
              ja: last_modified+"掲示板が更新されました。",
              en: "BBS is updated."     
          },    
          included_segments: ["All"] 
        });
        let response = await myClient.sendNotification(firstNotification) 

今回は最終更新日時はDBに格納せずテキストファイルで保持しています。

全体の実装

var server = http.createServer(app);


let cronTime:string = "0 0 */4 * * *";
let job = new cronJob({
  //実行したい日時 or crontab書式
  cronTime: cronTime

  //指定時に実行したい関数
  , onTick: ()=> {
    (async()=>{
      let response = await fetch('*****')
      let data = await response.headers.get('last-modified')
      let last_modified = moment(data).format('YYYY/MM/DD HH:mm:SS')
      let isExist:boolean
      try {
        fs.statSync('./logs/last-modified.txt')
        isExist = true
      } catch (error) {
        isExist = false
      }
      let stored_time
      if(isExist){
        stored_time = fs.readFileSync('./logs/last-modified.txt').toString()
      }
      console.log(stored_time,last_modified)
      if(stored_time === undefined || stored_time < last_modified){
        //onesignalで通知を出す
        var myClient = new OneSignal.Client({      
          userAuthKey: '*******',    
          app: { appAuthKey: '*******', appId: '*******' }      
        });
        var firstNotification = new OneSignal.Notification({      
          contents: {      
              ja: last_modified+"掲示板が更新されました。",
              en: "BBS is updated."     
          },    
          included_segments: ["All"] 
        });
        let response = await myClient.sendNotification(firstNotification)      
        console.log(response.data, response.httpResponse.statusCode);      
        console.log('send')

        //push通知の送信終了後にファイルを更新する
        fs.writeFileSync('./logs/last-modified.txt',last_modified)
      }

    })()
    .catch((err)=>{
        systemLogger.error(err)
      })
    console.log('onTick!');
  }

  //ジョブの完了または停止時に実行する関数 
  , onComplete: function() {
    console.log('onComplete!')
  }

  // コンストラクタを終する前にジョブを開始するかどうか
  , start: false

  //タイムゾーン
  //, timeZone: "Japan/Tokyo"
})
//ジョブ開始
job.start();

server.listen(port);
server.on('error', onError);

ckoshien

個人開発4年目。普段はアプリケーションエンジニア。 ReactJS/NodeJS/ReactNative/Java

Crieitは個人で開発中です。 興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!

ボードとは?

関連記事

コメント