관련지식
pushbullet, api, curl

요즘 보안때문에 회사PC에서 메신저를 사용하지 못하는 경우가 많죠. 하지만 주변 지인들과 채팅이 필요할때 마다 핸드폰 자판으로 메시지를 입력하는게 불편할때가 있습니다. 특히 파일전송이나 장문의 텍스트를 전달해야할 경우 PC만큼 편한것이 없죠. Pushbullet은 크롬 플러그인으로 동작하기 때문에 인터넷이 되는 환경이라면 대부분 사용할수 가 있습니다.

그런데 푸시불릿에는 3rd-party 프로그램에서도 메시지를 보낼수 있도록 API를 제공하고 있습니다. 이번엔 푸시불릿에 API를 이용해서 자기 자신에게 쪽지를 보내는 프로그램을 만들어 보겠습니다. 모니터링 프로그램에서 특정 상황이 발생했을때 자신에게 쪽지를 보내도록 하면 꽤 편리하겠죠?

준비

Pushbullet API는 OAuth2.0 스펙을 구현하였습니다. 하지만 본인 혼자만 사용할 용도라면 OAuth2.0 인증 과정을 굳이 따르지 않고 인증에 필요한 액세스 토큰을 만드는 것 만으로 간단하게 연동이 가능합니다. 푸시불릿의 메뉴를 통해 찾아가거나 아래 URL을 통해 액세스 토큰 설정 화면으로 이동하겠습니다.

액세스 토큰 설정 : https://www.pushbullet.com/#settings/account

액세스 토큰을 만드는 것은 매우 간단합니다 ‘Create Access Token’ 버튼을 한번 클릭하는 것 만으로 액세스 토큰은 만들어집니다. 그렇게 만들어진 토큰은 본인을 증명하는 키가 되므로 외부로 노출 시키면 안됩니다.

API 확인

나 자신에게 쪽지를 푸시 알림을 보내기 위해 Push API를 사용할 것입니다 . 상세 스펙은 아래 링크에서 볼수 있습니다.

전체 API : https://docs.pushbullet.com/
Push API : https://docs.pushbullet.com/#create-push

각 API별로 어떻게 사용하면 되는지 curl 을 이용한 호출 예시가 있어서 확인하기가 매우 용이합니다. 예시에서 <your_access_token_here> 부분만 위에서 생성한 토큰으로 대체하면 바로 테스트도 가능합니다.

  1. curl --header 'Access-Token: <your_access_token_here>' \
  2. --header 'Content-Type: application/json' \
  3. --data-binary '{"body":"Space Elevator, Mars Hyperloop, Space Model S (Model Space?)","title":"Space Travel Ideas","type":"note"}' \
  4. --request POST \
  5. https://api.pushbullet.com/v2/pushes

반드시 curl을 써야 하는것 만은 아닙니다. 이 방식은 결국 URL을 호출하는 것이기 때문에 헤더를 임의로 설정해서 URL을 호출할수 있는 환경이라면 모두 사용 가능합니다.

구현

만들려고하는 형태는 아래와 같습니다. 공통 푸시로직을 만들고 여러 코드에서 제목과 내용만 다른것으로 호출하고 싶습니다.

  1. var push = require('push');
  2. push.sendMe({
  3. title : '제목 텍스트',
  4. body : '본문 텍스트'
  5. });

이제 작업을 시작해 보겠습니다. URL을 호출하는 방법은 여러가지가 있지만 예제처럼 curl을 이용하도록 작업하겠습니다. node에서 외부 명령어를 실행하기 위해선 child_process를 사용해야 합니다.

  1. var exec = require("child_process").exec;

모든 메시지에 공통으로 적용할 header를 정의합니다.

  1. var headersBase = [];
  2. headersBase['Content-Type'] = 'application/json; charset=utf-8';

메시지를 발송하는 함수를 작성합니다. header 기본값을 재정의 할 수 있도록 msg 부분외에 headerOption 변수를 만들었습니다.

  1. function sendMsg(msg, headerOption) {
  2. }

header 의 기본값과 호출하는 쪽에서 재정의한 header 값을 머지 합니다. 그리고 헤더를 문자열로 변경합니다.

  1. var header = ' ';
  2. for ( var key in headersBase) {
  3. headerOption[key] = headerOption[key] || headersBase[key]; //헤더값 재정의
  4. }
  5. for ( var key in headerOption) {
  6. header += ' -H "' + key + ': ' + headerOption[key] + '"';
  7. }

발송할 메시지도 포맷에 맞춰 문자열로 변경합니다.

  1. msg.type = 'note';
  2. var data = ' --data-binary "' + JSON.stringify(msg).replace(/["]/g, '\\"') + '"';

이젠 curl 명령어를 완성해서 프로세스로 호출하면 됩니다.

  1. var cmd = 'curl -X POST ' + header + data + ' https://api.pushbullet.com/v2/pushes';
  2. var options = {
  3. maxBuffer : 500 * 1024,
  4. encoding : 'utf-8'
  5. };
  6. exec(cmd, options, function(err, stdout, stderr) {
  7. if(err) {
  8. console.error(err);
  9. }
  10. });

푸시발송 함수가 완성되었습니다. 이 함수를 다른 소스에서 사용할수 있도록 모듈화만 하면 작업이 끝납니다.(최종 소스는 맨밑에 있습니다.)

  1. sendMe : function(msg) {
  2. var option = [];
  3. option['Access-Token'] = myAccessToken;
  4. sendMsg(msg, option);
  5. }

정리

푸시불릿은 API를 굉장히 잘 정리해서 제공하고 있으며 그것을 활용한 다른 구독 채널을 제공할 수도 있습니다. 그러나 대단한 비즈니스를 사용하지 않더라도 웹 시스템에서 알림 서버의 구축없이도 크롬 푸시 알림을 쓸수 있다는 것 자체가 큰 메리트 인것 같습니다.
한번 사용해보세요.

최종 소스

윈도우 환경에선 한글이 깨질 수 있습니다.

  1. (function(global, factory) {
  2. module.exports = factory();
  3. }(this, (function() {
  4. 'use strict';
  5. var exec = require("child_process").exec;
  6. var myAccessToken = '<your_access_token_here>';
  7. var headersBase = [];
  8. headersBase['Content-Type'] = 'application/json; charset=utf-8';
  9. function sendMsg(msg, headerOption) {
  10. var header = ' ';
  11. for ( var key in headersBase) {
  12. headerOption[key] = headerOption[key] || headersBase[key];
  13. }
  14. for ( var key in headerOption) {
  15. header += ' -H "' + key + ': ' + headerOption[key] + '"';
  16. }
  17. msg.type = 'note';
  18. var data = ' --data-binary "' + JSON.stringify(msg).replace(/["]/g, '\\"') + '"';
  19. var cmd = 'curl -X POST ' + header + data + ' https://api.pushbullet.com/v2/pushes';
  20. var options = {
  21. maxBuffer : 500 * 1024,
  22. encoding : 'utf-8'
  23. };
  24. exec(cmd, options, function(err, stdout, stderr) {
  25. if(err) {
  26. console.error(err);
  27. }
  28. });
  29. }
  30. return {
  31. sendMe : function(msg) {
  32. var option = [];
  33. option['Access-Token'] = myAccessToken;
  34. sendMsg(msg, option);
  35. }
  36. }
  37. })));