「Facebook」と一致するもの

最近、Meteorの勉強中です。何かパッケージを作ってみたいと思ったのですが、多くのものはすでに誰かがやっています。 MeteorのパッケージはAtmosphereで探します。

今回、自分が使おうと思ったものにぴったりのものが見つからなかったので、作ってみました。 探したものはFacebookのAPIを呼び出すライブラリです。OAuthのライブラリはMeteorで提供されているのですが、Graph APIを使うものは3rt partyのものを探しことになります。

見つけたのはこれらです。

  • biasport:facebook-sdk mrt時代からあるパッケージでインストール数も多いです。ドキュメントを見るとクライアントライブラリのようです。
  • stevezhu:fbgraph fbgraphをラップしたパッケージです。サーバサイドのみで動きます。
  • mrt:facebook-sdk これがオリジナルっぽいですね。
  • jdrorrer:facebook-sdk
  • dcsan:facebook-sdk
  • dferber:graph-api
  • maxkferg:facebook-collections 少し趣向が変わった感じでおもしろそうです。クライアントから使うことがメイン。
  • borges:facebook-sdk
  • timbroddin:facebook-node-sdk ドキュメントがないのでどういうものか分からず。

いっぱいあるように見えますが、facebook-node-sdkはGitHubを見るとforkしているのが分かります。

https://github.com/jdrorrer/facebook-sdk/ ← https://github.com/dcsan/facebook-sdk ← https://github.com/biasport/facebook-sdk ← https://github.com/hugesuccess/facebook-sdk

ネットワーク図を見てもいいかもしれません。全部は表示されていないようですが。

さて、今回はサーバサイドのライブラリを探していたのでfbgraphとgraph-apiが候補なのですが、過去の検討で使っていたライブラリを使いたいという要求もありました。 そこで、そのライブラリをMeteorパッケージにラップしました。

作ったパッケージは、 https://atmospherejs.com/daishi/facebook-server-api です。

ソースコードは、GitHubにあります。 中身はなんと2行だけです。

一応、新規にFB.mapiというAPIを用意しました。Meteor流のfibersを使った同期的APIです。

fibersはあまり好まないのですが、Meteorでやっていくには仕方ないかと諦め気味です。

自分が興味あるものの一つにコミュニケーションツールがあります。 と言っても普通のコミュニケーションではないです。 例えば、見知らぬ人と一時的なつながりを感じられるようなそんなツールがいいと思います。言語も使わず、世界のどこかの誰かと。

FacebookのPokeはよかったです。1bitで行うコミュニケーションとでも呼びましょうか。日本では「あいさつ」となり、意味が分からなくなりました。 ちなみに、Pokeは一度機能が隠れてしまったのですが、また復活しました。 最近は、Yoが流行っているらしいです。これも1bitコミュニケーションだと思います。どこまで流行るのか、気になるところです。

流行っているついでに、Snapchatについても気になるところです。 実は使ったことありませんが、これは使い捨てコミュニケーションだと思っています。 使い捨てコミュニケーションができたら面白いだろうなぁとは思っていましたが、 まさかそんなものが流行るとは想像していませんでした。 写真だからうまくいったのでしょうか。

あとは、匿名コミュニケーションにも興味あります。 最近は実名指向で、あまり匿名を重視したコミュニケーションツールは登場していないのでしょうか。

と言うわけで、前置きが長くなりましたが、1bitで使い捨てで匿名のコミュニケーションツールを作ってみようと思いました。 1bitで伝えたいことはなんだろう、と考えたその日が暑い日だったので、「暑い」にしました。 「暑い」を伝え合うだけでは、どんどん暑苦しくなるだけですので、 ストレス発散をできるような「吹き飛ばし」機能をつけることにしました。

atsufut_title.png

これがタイトル画面です。

atsufut_main.png

これがメイン画面です。これだけです。 画面の上半分をクリック(タップ)すると、丸が落ちてきます。 何度も押すと、丸がたまってきます。 次に画面の下半分をクリックすると、丸を吹き飛ばします。 それだけです。

それでは、やってみましょう。

http://atsufut.axlight.com/

このURLをスマホで開きましょう。PCでも大丈夫です。モダンブラウザ必須です。

一人でやると、すぐに飽きます。 複数人で同時にやるとまあまあ面白いとは思います。 しかし、たまたま同時に開いている人がいることは稀です。 ここをどうするかが悩みどころです。

今回、開発に利用したライブラリは、 node.js, socket.io, angular.js, famo.us あたりです。

facebookはアプリを開発するときにテストユーザを作ることができます。これは非常に便利で、複数のユーザでの操作などもテストできます。

これまで、facebookアプリ(というかライブラリ)を自動でテストするときにテストユーザも自動で作っていました。過去記事を参照。他にも例えば、Qiitaの投稿に手順が載っています。

Facebookアプリのテストユーザーの作り方手順

ところが、このlogin_urlが使えなくなっているのに気づきました。404エラーになってしまうのです。Google検索すると、

http://stackoverflow.com/questions/22583963/404-error-trying-to-use-facebook-test-user-login-url

がヒットしました。今回は、stackoverflowでいい投稿を見つけました。すばらしい。stackoverflowは便利なときは便利です。facebookにバグ報告していて、

https://developers.facebook.com/bugs/276245435872240/

これによると、ポリシーが変わって使えなくなったと。「ドキュメントもアップデートしてくれ」と要望がでてますね。さて、stackoverflowのAnswerにはworkaroundも出ていて、簡単に回避できました。この方法が止められなければいいのですが。

参考までに、node.jsでのテストユーザのログインのコードの抜粋を載せておきます。

request.get('https://www.facebook.com', function() {
  request.post('https://www.facebook.com/login.php', {
    followAllRedirects: true,
    form: {
      email: facebook_user_email,
      pass: facebook_user_password
    }
  }, function(error, response) {
    //check response
  });
});

完全なコードはこちらです。

これまでにPassportでFacebook認証をやったことはありますが、OAuth2.0のプロバイダを提供するためにどんなライブラリがあるのか、というのが今回の話です。

OAuth2.0のクライアントライブラリは多くありますが、プロバイダライブラリはどうでしょうか。思ったよりは多かったです。条件は、express/connectのmiddlewareとして使えることです。

現時点でのStar数順に並べます。

今回は、一つずつコメントして行こうと思います。

まず、oauth2orizeですが、これはだいぶリッチな感じです。toolkitとあるように、色々な機能があります。connect middlewareにもなるようですが、standaloneでも動かすこともできる様子。testやexampleも豊富で信頼感あります。

node-oauth2-providerは歴史がある感じです。機能は多くなく、シンプルです。ストレージもコーディングしないといけませんが、個人的には一番好みのライブラリです。

oauth2_server_nodeは、最近更新されていません。oauth2の仕様もdraft10とのことです。

node-auth2-serverは、まだactive developmentということでドキュメントが追いついていないようです。しかし、ドキュメントを見る限りでは機能も豊富で、シンプルなmiddlewareとしても使えそうなので、stableになれば、oauth2orizeよりはexpressで使いやすそうです。

OAuthも、READMEによるとdraftの仕様を参照しており、その後メンテされていない様子です。

oauth2-expressは、READMEが空です。よく見たらコードも未完成でした。

connect-oauth2も、WIPとなっていて1年ほどコミットがないので、中断したプロジェクトでしょうか。いいパッケージ名なのに惜しい。

node-oauth20-providerは、StarもFolkもゼロというプロジェクトですが、見た感じはだいぶしっかりしています。最近コーディングを始めた様子。コミットログをよく見ると、node-oauth2-providerの存在を知らなかったようですね。node-oauth2-serverと比較すると、redis storageの対応が進んでいますが、全体的には劣る感じがします。また、コミュニティがついていないのが痛いですね。今後、作者の進め方次第では状況は変わることはあるでしょう。

以上、まとめると、現時点では、 シンプルで安定しているけど自分でコーディングしないといけないnode-oauth2-providerか、機能豊富でアクティブなnode-oauth2-serverがよさそうです。

でも、どっちも使ってみたわけではないので、ほんの参考程度です。

Railsより簡単にSNSを作れるようにすることを目指したライブラリ social-cms-backend を改良しました。

これまでは、認証機構はFacebook連携のみが実装されていたのですが、 Facebookに依存したくないアプリを作るケースも考え、 今回HTTP Digest認証も入れました。 Formによるパスワード認証も一応あったのですが、これは動作確認用で、not for production扱いです。 やはり生のパスワードがネット上を流れるのはよくないということで。 (SSLなしの想定)

Digest認証のサーバ側は passport-http を使いました。 Digest認証をそのまま使うのは不便なので、2つ工夫をしました。 一つは、RememberMeクッキーを併用することで、 もう一つは、JavaScriptでDigestを生成して認証することです。 Digest認証の最大の問題はUIがブラウザ依存だということです。 realmで指定する文字列しか指定できません。 また、ブラウザがパスワードを覚えてしまうので、アプリ側からログアウトできません。 そこで、DigestのヘッダーをJavaScriptで生成しました。 これは、完全な仕様通りではありません。細かい話は省きますが、 今回のサーバ実装ではたまたまnonceのサーバ側のチェックを省略していたのでできてしまったまでです。 ただ、もしチェックではじかれた場合でも通常のブラウザのDigest認証に fallbackするだけなので、リスクが増えるわけではないはずです。 逆に、パスワードを一回目で間違えた場合もfallbackしてしまいます。 このあたり、いい解決法がないようです。 (そもそもDigest認証の仕様に従わず、なんちゃってDigestにしてしまえばいいのかも)

Digest認証のクライアント側として request をunit testで使いました。使おうとしてから気づいたのですが、 Digest認証の実装が不十分だったので、直してPull Requestしておきました。 無事マージされました。

social-cms-backendはangular.jsでTwitterっぽいアプリを作るのに 便利なのですが、ちょっと使い方にくせがあります。 もっとチュートリアルを増やさないと使えるレベルにならないかも。

FacebookのGraph APIで写真を投稿する場合には、/ALBUM_ID/photosのエンドポイントにHTTP POSTするのですが、そのときにmultipart/form-data形式にする必要があります。

https://developers.facebook.com/docs/reference/api/publishing/

詳しくは上記公式ドキュメントを参照してください。

ところで、以前紹介したfacebook-node-sdkでは、form-dataがサポートされていません。

https://github.com/Thuzi/facebook-node-sdk/issues/28

このようにIssueにもなっていましたが、現時点ではサポートされていないようです。PRしてくれとか言っているので、ちょっとのぞいてみましたがrequestが奥の方に埋まっているので、ちょっと手間がかかりそうでした。

とりあえず、動くものを作ってみようと思ったので、上記ライブラリは使わずに普通にrequestだけでやってみたところ、簡単にできてしまいました。

コードを貼り付けておきます。

var request = require('request');

function postMyPhoto(accessToken, message, file, callback) {
  var form = request.post('https://graph.facebook.com/me/photos', function(err, res, data) {
    if (err) return callback(err);
    if (!data || data.error) return callback(data ? data.error : 'unknown error');
    callback(null, data);
  }).form();
  form.append('access_token', accessToken);
  form.append('message', message);
  form.append('source', fs.createReadStream(file));
}

実は、streamを初めて使いました。使ったとは言わないか。 しかし、フローが分かりにくいです。明示的にstreamの終了はないものなのでしょうか。 興味はあるのでまたの機会に勉強しようと思います。

以前書いた、 AngularJSを使ってRailsより簡単にTwitterクローンを作りたいと思って作ったnode.jsのライブラリ「social-cms-backend」をちょっとずつ改良しています。

今回は、通知機能です。通知機能というのは、例えば、自分のつぶやきに誰かが返信した場合にお知らせしてくれる機能です。今のところ、social-cms-backendはFacebookのみと連携しているので、通知機能もFacebook連携にしようと思いました。

Facebookアプリは何年か前にも一度作ったことがあって、そのときにapp requestsという機能で通知したのを覚えています。ところが、最近ではapp notificationsという機能もあるのですね。

http://developers.facebook.com/docs/games/notifications/

これです。このAPIの方がずっと素直で分かりやすい。難点は現状ではモバイルアプリに対応していないこと。また、通知先もCanvas対応アプリしか使えないようです。Betaとなっているので、将来的には使えることを期待してapp notificationsで行こうと思います。しかし、また数年後には使えなくなっていそう。Facebook依存はそのあたりがつらいので、social-cms-backendの通知機能としてはFacebook連携以外もサポートしていきたいところです。

APIは/<userid>/notificationsにHTTP POSTするだけです。

facebook-node-sdkを使った呼び出しサンプルコードは次のようになります。

FB.api(facebook_user_id + '/notifications', 'post', {
  href: href,
  template: template
}, function(res) { 
  //result handling
});

hrefはジャンプ先の相対URL、templateにはメッセージを入れます。これをちゃんと動かすにはapp access tokenが必要ですが、その方法は、

HerokuでFacebook APIを使う時の注意点

を参照してください。

いかがでしょうか、簡単でしょう?

久しぶりの記事です。

social-cms-backendのテストコードをMochaで書いていますが、Facebookのログイン周りのテストをするのに、Facebookのテストユーザを使いました。

Facebookのテストユーザについては、

http://developers.facebook.com/docs/test_users/

にドキュメントがあります。

手順は書いてある通りで、(1)アプリのアクセストークンを取得、(2)テストユーザを作成、(3)専用ログインURLを開いてログインする、だけです。

requestを使ってこれらのステップを実行していたのですが、たったこれだけのことをやるのに何時間もはまりました。

1と2は何の問題もなかったのですが、3がうまく行かず、Facebookのログインページにリダイレクトされてしまうという問題でした。

解決方法は、User-Agentを設定する、です。

ドキュメントには書かれていません。もし同様の問題を抱えている人に参考になればと思います。参考になるか分かりませんが、その時点でのテストコードは、

https://github.com/dai-shi/social-cms-backend/blob/c678043a2ad0ce45bc51b576d77e53c7eac658e5/test/80_facebook_login_test.js

です。

これまでnode.jsのアプリのデプロイにはHerokuを使っていたのですが、 無料アカウントでは上限があるらしいのと、そもそも一つのサービスに依存するのもよろしくないので、別の候補を探しました。

いくつかあるようなのですが、昔は無料でも今は終わっていたり、 今も無料だけどベータサービスなので期限があったりと、 あまりぱっとしません。ビジネスモデルとしてフリーミアムがちゃんと まわってないと持続性がないでしょう。

一番、有望かなと思ったのがRedHatの OpenShift です。

正式サービスしてからはまだ間もないですが、無料のアカウントがサポートなしという形で残っているので、今後も継続することが期待できます。 ただ、無料でホストできるアプリは2つだけのようで、厳しいですが。

さて、 NodeとAngularを使ってTwitterクローンを15分で作るスクリーンキャスト で作ったTwitterクローンをOpenShiftの上にのせることにしました。

まず、OpenShiftのアカウント登録。簡単でした。次に、sshの公開鍵の登録。これもコピペするだけ、簡単。

続いて、アプリの作成。 domainが空いてないと登録できないので、何度もトライしました。 動的にチェックしてくれればいいのに。このあたり、まだまだな感じですね。

続いて、ソースのアップロード。gitのURLが表示されるので、それを、リモートリポジトリとして登録します。

$ git remote add openshift <URL>

で、PUSHします。

$ git push openshift master

ここまで大きな問題なし。このあと大変でした。

まず、今回のアプリはFacebookと連携するのでその情報を入れないといけないのですが、それはリポジトリにはいれるものではありません。 Herokuでは環境変数を使っていました。 openshiftでも環境変数を使えるようで、

$ vi ~/app-root/data/.bash_profile

で追記すれば環境変数を設定できます。 しかし、このままだとnodeを起動するときにその設定は読み込まれないようです。

openshiftにはpre_startというスクリプトがあって、それを使って、 source .bash_profileするようにしたのですが、うまくいきませんでした。

調べているうちに別の方法を見つけました。nodeでしか使えないようなのですが、

$ vi ~/nodejs/configuration/node.env

で環境変数の設定をすることができます。中身は、.bash_profileでの環境変数の設定と同じです。 これは、うまく行きました。

次の問題は、EACCESエラーです。なぜか、webサーバの起動でエラーになるのです。これは、どんぴしゃの記事がありました。

https://www.openshift.com/forums/openshift/other-threads-didnt-help-503-service-unavailable

OpenShiftではINADDR_ANYでlistenできないようです。 app.jsを次のように変えて対処しました。

app.set('port', process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 3000);
app.set('ipaddr', process.env.OPENSHIFT_NODEJS_IP);
....
http.createServer(app).listen(app.get('port'), app.get('ipaddr'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

これで、アプリが正常に動作しました。

慣れてしまえば、OpenShiftでもHerokuと同様の使用感でnode.jsのアプリをデプロイできそうです。ただ、困りそうなことが一つだけあります。OpenShiftで用意されているのは、node v0.6なのです。現在の安定版がv0.10なので2世代も前です。Herokuではv0.10もv0.8も使えます。開発スピードが速いnode.jsエコシステムでは致命的かもしれません。npmとかパッケージによっては動かないケースがでてきそうです。

今回は試しませんでしたが、node.jsカートリッジとは別に、DIYカートリッジというのがあるらしく、それを使えば好きなバージョンを入れることができるそうです。そもそも、Herokuではできないsshができるのでいろいろ自由度は高そうですね。

もう一つ、Herokuと比べて不便を感じたのは、デプロイの遅さです。pushしてから待つこと数分かかったような気がします。Herokuってすごいんだなぁ、と思った瞬間。

実際に今回デプロイしたアプリはこちらです。

http://twitterclonesample-nodeangularapp.rhcloud.com/

なんにしてもPaaSの選択肢が増えることはよいことです。 興味ある方は試してみると良いでしょう。


9/10追記。 ~/nodejs/configuration/node.envのファイルですが、いつのまにか勝手に戻っていて、プロセスが8月後半から動いていなかったことが判明しました。とりあえず、再度書いておきましたが、また、勝手に上書きされてしまうかもしれません。もっといい方法があるのでしょうか。

昨日、 NodeとAngularを使ってTwitterクローンを15分で作るスクリーンキャスト を書いたのですが、ライブラリの紹介をし損ねたので紹介します。

そもそもの動機は、Twitterクローンを簡単に作りたいと思ったことが発端です。 そこで、なにかいいライブラリはないかと色々調べたら、Railsもどきのフルスタックフレームワークがいくつか見つかりました。

他にもいっぱいあるのですが、気になったのがこのあたりです。

ところが、なんと言うかAngularJSを使おうとするとこれらのライブラリはオーバースペックな感じがするのです。Ruby on Railsのようにデファクトが一つある状態であればいいですが、もどきがいっぱいある状態ではコンベンションも統一感がなさそうです。

Angularを前提とするのであれば、フレームワークではなくもっとシンプルなライブラリがあればいいのではないかと思いました。それでもって、面倒なことはそのライブラリが引き受けてくれるような。

そこで、TwitterやFacebookのようなSNSのサイトを作ることに限定したライブラリを作りました。node.jsではexpress.jsがほぼデファクトなのでexpressのmiddlewareとして作りました。middlewareにすることで、単一のフレームワークに依存することなく、他のアプリにアドオンする形で導入できます。

面倒な、認証や権限管理の機能はライブラリが面倒みてくれます。 現状では、Facebook認証と、標準的な権限管理(ownership based)の機能が用意されているだけですが、プラグインとして他の認証や権限管理の機能を追加できるようになっています。 また、通知(メールアラートなど)の機能も今後追加してきたいと考えています。

このライブラリを使うと、フロントエンドを作るだけですぐサービスできます。Railsのようにデフォルトがないので作らないとなにもできないのですが、Angularに慣れていればコンベンションを意識してコーディングするよりもずっと楽かもしれません。

まずは、 こちら からスクリーンキャストを見てみると雰囲気が分かるかもしれません。 もしかしたら、分からないかもしれません。

ソースコードは、

https://github.com/dai-shi/social-cms-backend

にあります。


8/7追記。

最近知ったのですが、http://sproute.io/というフレームワークもあるようですね。 こちらは比較的SNSに特化したようなフレームワークであるようです。 ほとんどコーディングなしでTwitterクローンが作れるようです。 でも、$99って。