ひとりぶろぐ

価値ある情報をユーザー視点で発信するブログ

これは面白いぞ!Ruby/Python/PerlでWebプッシュ通知サービスPush7のAPIを使ってプッシュ通知を送ってみる

      2016/04/07

実は汎用性に富んだWebプッシュ通知サービスPush7

ブログやWebサイトの更新をプッシュ通知で知らせるためのWebサービス、Push7が最近人気を集めていますね。

Push7は最近のWebブラウザが持っているプッシュ通知の機構や、スマートフォンのプッシュ通知の機構に対応していて、家でも外でもプッシュ通知を受け取れる環境を提供してくれます。

環境別対応状況
iOS Push7アプリ
Android Chrome(Android用のPush7アプリがあるわけではない)
Webブラウザ Chrome、Firefox(Safariは現時点では未対応)

これまでもプッシュ通知を送るためのAPIを提供するサービスはありましたが、1対1の通知しか送れず、自分自身のために送るプッシュ通知という利用形態に限られました。

Push7は購読してくれた人全員にプッシュ通知を送ることができる1対多のサービスであるところが画期的です。それでいて無料で使えるのですから素晴らしいものです。

Push7 figure 01

ブログを運営していれば、興味を惹かれるサービスであるのは間違いありません。

弊ブログも遅ればせながらPush7対応をしてみました。ぜひ購読をお願い致します。


WordPress用のプラグインがあるので、WordPressなら導入は簡単です。ちなみに、弊ブログの環境(sixcore)ではSSLの「SSLの検証を無効化する」で「する(必要のない場合には選択しないでください。)」を選択しないとプッシュ通知が送られませんでした。

Push7 figure 04

ただ、公式のWordPress用プラグインを導入すると、最初の公開時はもちろんのこと記事に修正を加えるなどの更新毎にプッシュ通知が送られるので、修正が多いと迷惑ですし、月5,000回に定められた送信限度回数を使い切ってしまいそうです。

さて、Push7は何もブログやWebサイトの更新のためだけにしか使えないわけではありません。

Push7は「Webサイト運営者のための」と前置きがありますが、その実、不特定多数の人に知らせたいことを送信するために汎用的に使えるメッセージングサービスです。

「更新通知」にとらわれない利用を考えたいところです。

Push7へのアプリケーション登録と制約

Push7を利用開始するには、アカウントを取得してアプリケーションを登録するところから始めます。

一つのアプリケーションにつき、月5,000回のプッシュ送信に限られるという制約があります。

アプリケーションは複数登録することができ、4つまでの登録を確認しました。これ以上も登録が可能のようです。

Push7 figure 02

プッシュ送信月5,000回の制約はアプリケーションごとに別勘定なので、4つ登録すれば合計20,000回プッシュ送信できることになります。

複数のアプリケーションを購読してもらうことのハードルは高そうですが、それが問題にならない場合は、制約は簡単に突破できますね。

登録したアプリケーションをだれにも公開せずにおけば、在来の1対1のプッシュ通知サービスのように、自分のためにだけに使うこともできます。

APIの利用

Push7はAPIが公開されていて、これを通して利用することができます。

現状、APIは二つあります。利用状況を確認するHead APIと、プッシュ通知を送信するためのSend API。

  • Head API(アプリケーションの各種データをログインしていない状態で取り出すAPI)
  • Send API(プッシュ通知を購読者全員に送信するAPI)

Head APIの利用は、URLを組み立ててアクセスするだけ。

https://api.push7.jp/api/v1/[APPNO]/head

URLの途中に[APPNO]がありますが、これはPush7に登録したアプリケーションのアプリケーション設定から取得が可能です。

  • ダッシュボードの「登録アプリケーション > アプリケーション設定 > 自動プッシュ設定 > WordPress」

Push7 figure 03

ひとりぶろぐのAPPNOは b12ed56a2b1642febc36c4c6cd1a0313 なので、アクセスすべきURLは以下のようになります。

https://api.push7.jp/api/v1/b12ed56a2b1642febc36c4c6cd1a0313/head

APPNOは購読ボタンなどで公開されているので、Head APIはだれでも参照が可能です。

Send APIの方はPOSTメソッドでアクセスすることになるので、Ruby/Python/Perlで試してみました。

Push7のSend APIをRubyから利用する

Send APIのエンドポイントは以下。

https://api.push7.jp/api/v1/[APPNO]/send

[APPNO]の部分は、Push7のダッシュボード「登録アプリケーション > アプリケーション設定 > 自動プッシュ設定 > WordPress」で取得したAPPNOに置き換えます。

ひとりぶろぐの場合は、以下のようになります。

https://api.push7.jp/api/v1/b12ed56a2b1642febc36c4c6cd1a0313/send

ここへbodyに指定のJSONを置いてPOSTメソッドでリクエストを投げます。

[APPNO]と[APIKEY]はPush7のダッシュボード「登録アプリケーション > アプリケーション設定 > 自動プッシュ設定 > WordPress」から取得したもので置き換えます。

#!/usr/local/bin/ruby
# coding: utf-8

require 'net/http'
require 'uri'
require 'json'

APP_NO = "[APPNO]"
API_KEY = "[APIKEY]"
END_POINT = "https://api.push7.jp/api/v1/#{APP_NO}/send"

uri = URI.parse(END_POINT)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri.request_uri)
req["Content-Type"] = "application/json"

payload = {
	"title" => "テストタイトル", 
	"body" => "テスト本文", 
	"icon" => "https://dashboard.push7.jp/uploads/5f670282635746e38ce6b060ad495d2a.png",
	"url" => "http://hitoriblog.com/",
	"apikey": API_KEY
}.to_json

req.body = payload
res = http.request(req)

p res
p res.body

ポイントは、SSLを有効にしないと400エラーが返ってくるということです。

#<Net::HTTPBadRequest 400 Bad Request readbody=true>

購読者が0人の状態で投げると、リクエスト自体は正しくとも当然プッシュ通知は配信されず、405エラーが返ってきます。

ダッシュボードに記録は残ります。

非常に簡単に利用できるので、何かのbot的なものからの利用を考えてみようと思っています。

ブログの方も、購読者が増えたらリアルタイム性を前提とした取り組みもやりやすくなるでしょうし、ちょっとわくわくしますね。

#<Net::HTTPMethodNotAllowed 405 METHOD NOT ALLOWED readbody=true>

Push7のSend APIをPython2から利用する

今度はPython2でやってみました。

#!/usr/bin/python
# coding: utf-8

import json
import urllib2
import cookielib
from logging import getLogger,StreamHandler,DEBUG

logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(DEBUG)
logger.setLevel(DEBUG)
logger.addHandler(handler)

APP_NO = "[APPNO]"
API_KEY = "[APIKEY]"

END_POINT = "https://api.push7.jp/api/v1/{}/send".format(APP_NO)

payload = json.dumps({
    "title" : u"Python2テスト",
    "body" : u"テスト本文",
    "icon" : "https://dashboard.push7.jp/uploads/5f670282635746e38ce6b060ad495d2a.png",
    "url" : "http://hitoriblog.com/",
    "apikey" : API_KEY},
    sort_keys=True,
    indent=4)

req = urllib2.Request(END_POINT)
req.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(req, payload)

logger.debug(response)

OS Xで試したところ、以前HomebrewからインストールしたPython2のurllib2がhttpsを知らないというエラーが出ました。

urllib2.URLError: <urlopen error unknown url type: https>

以下でSSLがサポートされていないことが判断できました。

>>> import socket
>>> socket.ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ssl'

brewコマンドでOpenSSLのサポートを有効にしてインストールし直したところ、エラーが解消されました。

brew unlink python
brew remove python
brew install python --with-brewed-openssl
>>> import socket
>>> socket.ssl
<function ssl at 0x1072f31b8>

今度はPython2でrequestsを使ってやってみました。

requestsはeasy_installでインストール。

easy_install requests
#!/usr/local/bin/python
# coding: utf-8

import json
import requests
from logging import getLogger,StreamHandler,DEBUG

logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(DEBUG)
logger.setLevel(DEBUG)
logger.addHandler(handler)

APP_NO = "[APPNO]"
API_KEY = "[APIKEY]"

END_POINT = "https://api.push7.jp/api/v1/{}/send".format(APP_NO)

headers = {"Content-Type":"application/json"}

payload = json.dumps({
    "title" : u"Python2テスト",
    "body" : u"テスト本文",
    "icon" : "https://dashboard.push7.jp/uploads/5f670282635746e38ce6b060ad495d2a.png",
    "url" : "http://hitoriblog.com/",
    "apikey" : API_KEY},
    sort_keys=True,
    indent=4)

response = requests.post(END_POINT, headers=headers ,data=payload)
logger.debug(response)

HomebrewからインストールしたPython2でrequestsを使おうとすると、以下のエラーが出ます。

"Symbol not found: __PyCodecInfo_GetIncrementalDecoder"

そこで、以下の対処をします。

Push7のSend APIをPython3から利用する

ついでにPython3から。Python2でのrequestsを使った例と変わりません。

requestsを使う分には文字列のリテラルが u’文字列’ から ‘文字列’ に変わるだけ(笑)。

Python3にはurllib2がなく、Python2とPython3だと事情が異なるのですが、大体のブログは2なのか3なのかが書いてなくて初心者的に困りますね。

#!/usr/local/bin/python3
# coding: utf-8

import json
import requests
from logging import getLogger,StreamHandler,DEBUG

logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(DEBUG)
logger.setLevel(DEBUG)
logger.addHandler(handler)

APP_NO = "[APPNO]"
API_KEY = "[APIKEY]"

END_POINT = "https://api.push7.jp/api/v1/{}/send".format(APP_NO)

headers = {"Content-Type":"application/json"}

payload = json.dumps({
    "title" : "Python3テスト",
    "body" : "テスト本文",
    "icon" : "https://dashboard.push7.jp/uploads/5f670282635746e38ce6b060ad495d2a.png",
    "url" : "http://hitoriblog.com/",
    "apikey" : API_KEY},
    sort_keys=True,
    indent=4)

response = requests.post(END_POINT, headers=headers ,data=payload)

logger.debug(response)

Homebrewで普通にPython3をインストールすると、OpenSSLのサポートが無効な状態でインストールされます。

>>> import socket
>>> socket.ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'socket' has no attribute 'ssl'

その場合は、OpenSSLのサポートを有効にしてインストールし直します。

brew unlink python3
brew remove python3
brew install python3 --with-brewed-openssl

Push7のSend APIをPerl5から利用する

Perl5です。cpanでJSONとMozilla::CAをインストールしました。

sudo cpan JSON Mozilla::CA
#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use Encode;
use JSON;
use Data::Dumper;

require HTTP::Request;
require LWP::UserAgent;

# sudo cpan JSON
# 以下のエラーが出る場合は、証明書をインストールする
# '_msg' => 'Can\'t verify SSL peers without knowing which Certificate Authorities to trust'
# ↓
# sudo cpan Mozilla::CA

binmode STDIN, ':encoding(utf8)';
binmode STDOUT, ':encoding(utf8)';
binmode STDERR, ':encoding(utf8)';

my $app_no = "[APPNO]";
my $api_key = "[APIKEY]";

my $end_point = "https://api.push7.jp/api/v1/${app_no}/send";

my $payload = {
	title => "Perlテスト",
	body => "テスト本文",
	icon => "https://dashboard.push7.jp/uploads/5f670282635746e38ce6b060ad495d2a.png",
	url => "http://hitoriblog.com/",
	apikey => $api_key
};

my $payload_json = encode_json($payload);

my $req = HTTP::Request->new( 'POST', $end_point );
$req->header( 'Content-Type' => 'application/json' );
$req->content($payload_json);

my $lwp = LWP::UserAgent->new;
print Dumper $lwp->request($req);

 - Webサービス・アプリ