tag:crieit.net,2005:https://crieit.net/tags/Onesignal/feed 「Onesignal」の記事 - Crieit Crieitでタグ「Onesignal」に投稿された最近の記事 2019-05-10T23:08:59+09:00 https://crieit.net/tags/Onesignal/feed tag:crieit.net,2005:PublicArticle/14977 2019-05-10T23:08:59+09:00 2019-05-10T23:08:59+09:00 https://crieit.net/posts/Onesignal-NodeJS-push Onesignalを使ってNodeJSでpush通知 <h1 id="背景"><a href="#%E8%83%8C%E6%99%AF">背景</a></h1> <p><strong>手軽にプッシュ通知を実装したい!</strong></p> <h2 id="何を使おうか?"><a href="#%E4%BD%95%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86%E3%81%8B%EF%BC%9F">何を使おうか?</a></h2> <ul> <li>pushbullet</li> </ul> <p>push通知アプリ。プラットフォームに依存しない。<br /> android 8に変えたらバックグラウンドタスクがkillされてるのか通知がこない。</p> <ul> <li>slack</li> </ul> <p>最近のトレンド。チームに加入してない人には通知がいかないのがデメリット。</p> <ul> <li>onesignal</li> </ul> <p>日本語対応が後手の印象。登録画面が怪しい。<br /> プッシュ通知が手軽に実装できる。</p> <p><strong>過去、slackとpushbulletは実装したことがある(※ただしJava)ので、今回はNodeJSでonesignalの実装に挑んでみました。</strong></p> <h1 id="使うライブラリ"><a href="#%E4%BD%BF%E3%81%86%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA">使うライブラリ</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/onesignal-node">onesignal-node</a></li> </ul> <p>NodeJSでonesignalのAPIにアクセスできるライブラリ。</p> <h1 id="実装"><a href="#%E5%AE%9F%E8%A3%85">実装</a></h1> <h2 id="概要"><a href="#%E6%A6%82%E8%A6%81">概要</a></h2> <p>4時間ごとに00分ちょうどに掲示板の書き込みがあるかヘッダを確認して更新があればプッシュ通知を出すというジョブを実装する。</p> <h2 id="毎日4時間ごと(00分00秒)にジョブを実行する"><a href="#%E6%AF%8E%E6%97%A54%E6%99%82%E9%96%93%E3%81%94%E3%81%A8%2800%E5%88%8600%E7%A7%92%29%E3%81%AB%E3%82%B8%E3%83%A7%E3%83%96%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B">毎日4時間ごと(00分00秒)にジョブを実行する</a></h2> <pre><code class="javascript">let cronTime:string = "0 0 */4 * * *"; </code></pre> <h2 id="即時関数"><a href="#%E5%8D%B3%E6%99%82%E9%96%A2%E6%95%B0">即時関数</a></h2> <p>この中ではawaitを使用できる。<br /> 戻り値がPromiseの処理を1行で記述できるのがasync/awaitの強み。<br /> (コールバック地獄とthen地獄はもう嫌だ)</p> <pre><code class="javascript">(async()=>{ })().catch(...) </code></pre> <h2 id="レスポンスヘッダから最終更新日時を取得する"><a href="#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%83%98%E3%83%83%E3%83%80%E3%81%8B%E3%82%89%E6%9C%80%E7%B5%82%E6%9B%B4%E6%96%B0%E6%97%A5%E6%99%82%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B">レスポンスヘッダから最終更新日時を取得する</a></h2> <pre><code class="javascript">let data = await response.headers.get('last-modified') </code></pre> <h2 id="REST API keyとAUTH KEYを指定する"><a href="#REST+API+key%E3%81%A8AUTH+KEY%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B">REST API keyとAUTH KEYを指定する</a></h2> <p>メニューから「ACCOUNT & API KEYS」のページを参照する。<br /> <a href="https://crieit.now.sh/upload_images/b08b548caec5795ad40e35af9c85f4c95cd58244524ac.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/b08b548caec5795ad40e35af9c85f4c95cd58244524ac.png?mw=700" alt="image" /></a></p> <pre><code class="javascript">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) </code></pre> <p>今回は最終更新日時はDBに格納せずテキストファイルで保持しています。</p> <h2 id="全体の実装"><a href="#%E5%85%A8%E4%BD%93%E3%81%AE%E5%AE%9F%E8%A3%85">全体の実装</a></h2> <pre><code class="javascript">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); </code></pre> ckoshien