Facebook C# SDK を使用して F# からFacebook API を叩いてみた。
最初にコードを示しておくと、こんな感じになった。
…うーん、ダウンキャストしたりボクシングしたりミュータブルな Dictionary を使ったりと、
あんまり F# らしいイケてるコードに見えない…。
これは僕がもっと良い書き方を知らないからなのだろうか…。
SDK の入手
NuGetを使用する。
Visual Studio の拡張機能としてインストールするのが一般的(?)なようだけど、
普段 Visual Studio を使っていないのでスタンドアローン版
(っていうのかな、コマンドラインで実行できるexeファイル)を使用した。
nuget install Facebookを実行すると、まず NuGet 自体のアップデートが行われた。
NuGet bootstrapper 1.0.0.0
Found NuGet.exe version 2.5.0.
Downloading...
Update complete.
アップデート完了後、再度同コマンドを実行する。
Installing 'Facebook 6.4.0'.
Successfully installed 'Facebook 6.4.0'.
ライブラリのロード
NuGetで取得した Facebook.dll と ZaneliFacebook.fs を F# interactive にロードする。
(ついでにモジュールのインポートも)
#r "Facebook.dll";;
#load "AccessToken.fs";;

open Zaneli.Facebook;;
アプリ認証のためのcodeを取得
let url = getLoginUrl;;
で取得したURLにブラウザアクセスして、code を取得する。

code はアプリ認証後、redirectUri に指定した URI に Get パラメータとして付いてくる。
パラメータに指定している appId は Facebook アプリ設定画面で確認できる「アプリID」。
redirectUri はアプリ設定画面で設定したURLと一致、もしくは App Domains で指定したドメインのサブドメインにする必要がある。
パラメータをボクシングしているのは、FacebookClient の GetLoginUrl に
IDictionary<string, string> ではなく IDictionary<string, obj> を渡す必要があるため。
(これはボクシングではなくてもっと良いやり方があるように思う…)
アクセストークンを取得
先ほど取得したcodeを引数に使用する。
let token = getAccessToken <取得したcode>;;
この token を使用して各 API を実行する。
自分のプロフィールを取得
let profile = getProfile <取得したtoken>;;
独自で定義した Profile レコードを返すようにした。 パラメータは、dict[("access_token", box token)] としたかったが、以下のエラーが発生した。
System.NotSupportedException: 種類 'System.NotSupportedException' の例外がスローされました。
   場所 Microsoft.FSharp.Core.ExtraTopLevelOperators.CreateDictionary@45.Remove(TKey key) 場所 f:\dd\fsharp\devdiv\src\fsharp\FSharp.Core\fslib-extra-pervasives.fs:行 74
   場所 Facebook.FacebookClient.PrepareRequest(HttpMethod httpMethod, String path, Object parameters, Type resultType, Stream& input, Boolean& containsEtag, IList`1& batchEtags)
   場所 Facebook.FacebookClient.Api(HttpMethod httpMethod, String path, Object parameters, Type resultType)
   場所 Facebook.FacebookClient.Get(String path, Object parameters, Type resultType)
   場所 Facebook.FacebookClient.Get(String path, Object parameters)
どうも内部で要素を除去しているらしく、イミュータブルな IDictionary では駄目なようだ。
これも Dictionary に要素をセットするのではなく、
もう少し F# 的にスマートなやり方がある気がする。
投稿
let result = post <取得したtoken> <投稿内容>;;
レスポンスには投稿した ID が返ってくるようだ。
パラメータとしては
  • picture
  • link
  • message
  • name
  • caption
  • description
  • category
が指定できるらしいが、今回は単純にメッセージのみ指定するようにした。


こちらも dict 関数でパラメータを作って渡すと以下のエラーが発生した。
System.NotSupportedException: 種類 'System.NotSupportedException' の例外がスローされました。
   場所 Microsoft.FSharp.Core.ExtraTopLevelOperators.CreateDictionary@45.set_Item(TKey key, TValue value) 場所 f:\dd\fsharp\devdiv\src\fsharp\FSharp.Core\fslib-extra-pervasives.fs:行 48
   場所 Facebook.FacebookClient.PrepareRequest(HttpMethod httpMethod, String path, Object parameters, Type resultType, Stream& input, Boolean& containsEtag, IList`1& batchEtags)
   場所 Facebook.FacebookClient.Api(HttpMethod httpMethod, String path, Object parameters, Type resultType)
   場所 Facebook.FacebookClient.Post(String path, Object parameters)
こちらは内部で要素の追加をしているようだ。

色々改善点は残っているように思うが、とりあえず動くのを確認できたので良しとしておこう。

Copyright© 2011-2021 Shunsuke Otani All Right Reserved .