Facebookの「いいね!」ボタンからコメント投稿できるようにする方法

分からない人結構いそうなので書く.


XFBMLを使っていいねボタンを設置している場合は何もしなくてOK.
Iframeでいいねボタンを設置している場合は,Layout Styleを'standard'にして,Widthを400px以上にすればOK.
って公式ドキュメントに書いてます.


http://developers.facebook.com/docs/reference/plugins/like/

クラウド時代の新しいソートアルゴリズムTask Queue Sortを発明しました.

Task Queue Sortは,

Google App Engineの並列処理の仕組みTaskQueueを使ってソート処理を行う,クラウド時代の新しいソートアルゴリズムです.
クラウドソートとも言う)


ネタ元

重要な仕様

  • ソートした結果のソート順は保証されない.
  • たまにソート対象の要素が増える事がある.

Java(slim3)での実装例

TaskQueueを投げる側

public class IndexController extends Controller {

	@Override
	public Navigation run() throws Exception {

		addToQueue(4);
		addToQueue(1);
        addToQueue(3);
        addToQueue(8);
		addToQueue(10);
		addToQueue(5);
		addToQueue(9);
        addToQueue(6);
        addToQueue(7);
		addToQueue(2);

		return forward("index.jsp");
	}

	private void addToQueue(int value) {
		Queue queue = QueueFactory.getDefaultQueue();
		queue.add(withUrl("/log").countdownMillis(value * 1000).param("value", String.valueOf(value)));
	}
}

TaskQueueを処理する側

public class LogController extends Controller {

	@Override
	public Navigation run() throws Exception {

		Logger.getLogger(this.getClass().getName()).info(asString("value"));
		return null;
	}
}

mogli(RubyのFacebookライブラリ)から作成するフィードにカスタムプライバシー設定する方法

2011/06/14追記
mogliにコミットさせてもらいました。
https://github.com/mmangino/mogli/commit/9f63d1356bffc823e0060ce64f486b37fbcfed9f


mogli
mogliは現在のところfeed作成でprivacy設定をサポートしていないようです。

ということで、

ソースを修正します。
/lib/mogli/post.rb

require 'json'

module Mogli
  class Post < Model

    define_properties :id, :to, :message, :picture, :link, :name, :caption,
      :description, :source, :icon, :attribution, :actions, :likes,
      :created_time, :updated_time, :privacy, :type

    #↓ここに、:privacyを追加する
    creation_properties :message, :picture, :link, :name, :description, :caption, :source, :actions, :privacy

    hash_populating_accessor :actions, "Action"
    has_association :comments, "Comment"
    hash_populating_accessor :from, "User"
    hash_populating_accessor :application, "Application"

    def likes_create
      client.post("#{id}/likes",nil,{})
    end
  end
end

Facebookアプリ作ってて困った事というか、IEでiframe内の別ドメインのページでもクッキーを有効にする方法とか、セキュリティレベルを下げずにCookieを有効にする方法とか

なんか最近のXSSネタとか見てるとWeb開発者には常識なのかもしれない気がしているけど、
自分は全然知らなかったし、検索してもなかなか出てこないので書いてみる。*1

1.FacebookIEで動かす為というか、IEのセキュリティレベルを下げずに(デフォルトのままで)クッキーを有効にする為にやること

サイトにプライバシーポリシーの設定をしないといけない
これは超面倒くさい作業でした。
もし私同様に知らなかった人は「p3p.xml」とかで検索して自分で調べてください。


役立ちそうなツールとか
http://www.nmda.or.jp/enc/privacy/

2.FacebookIEで動かす為というか、IEのiframe内の別ドメインのページでクッキーを有効にする為にやること

プライバシーポリシー情報をHTTPヘッダで設定しないといけない
これは超意味不明な作業でした。
もし私同様に知らなかった人は「P3P コンパクトポリシー」とかで検索して自分で調べてください。


役立ちそうなツールとか
http://www.alphaworks.ibm.com/tech/p3peditor

という事で、

Facebookアプリを作る時もやはりIEは大きな敵でした
まぁこれが仕様どおりの正しい動作なのかもしれないですが、なんで標準化してほしいところはしてくれないのに、こういうめんどくさい事だけ標準化してくれるのか

*1:検索の仕方にもよるが、「IE クッキー」とかで検索しても、「IEのセキュリティレベルを下げればクッキーが有効になります」的なページによって本質的な解説ページが埋もれてしまっている

Facebookアプリを作ってみましたシリーズ5 (Ruby on Rails + fgraph サーバーサイドでFQL)

今回はfgraphというライブラリを使ってみました

作ったアプリはこちら

http://apps.facebook.com/taianfriends/
Facebookの友達から、誕生日にさりげなくおごってもらう事を可能にする素敵なサービスです。

環境

Ruby1.9
Rials3
フェイスブックライブラリはfgraph https://github.com/jugend/fgraph

fgraphについて

このライブラリもとてもよくできている印象でした。
Railsのサポートがしっかりしていて、rakeコマンドで設定までやってくれます。(と思ったら、rakeやってもHelperが認識されない…リポジトリrails/init.rbをconfig/initializersに置けばOKです)

ただ、設計は良いと思いますが、FacebookのOpenGrapAPIに合わせたインターフェースになってないので、直感的には使えなかったです。
ドキュメントもきちんとしたものが無いのでソース確認しながらさぐりさぐり使っていく感じでした。
でもわかりやすいので特にストレスなく使えたと思います。


今回もソースそのまま貼っときますので必要であれば勝手に見てください。

こまった事

なんとfgraph はFQLサポートしてない…
一応今回はサーバーサイドFQLを使って作る事を目的としていたのでいきなり不意打ちくらった感じでしたが、
こちらの記事
http://jablko.biz/post/2184601874/fql-in-fgraph
を参考にして無事FQL動かすことができました。

いろいろ

  • Rails使っているとテーブル名は複数形だという癖がついているので、FQL書く時にとまどう
  • JavaScriptだとカラム名まちがってもエラーにならない(レスが無い)のに、サーバーサイドだとちゃんと詳細メッセージを返してくれた。
  • GraphAPIとFQLテーブルの命名規約がそろってないから、カラム名の間違いで結構な頻度でハマる(正確にはFQLテーブル同士でも統一感されてない気がする)。名称変換して統一してしまうようなライブラリを作るとかえって意味分からなくなるかな…
  • なんかFQLテーブルって設計がいろいろイケてない(詳細省略)
  • でもFQLのエラーメッセージは結構親切なのでとりあえず良く分からないFQLは実行してみるのがいいんじゃないかと

ソース

home_controller.rb

# encoding: utf-8
class HomeController < ApplicationController
  
  def index
    
    response.headers["P3P"] = 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"'
    
    if fgraph_logged_in?
      
      fg_client = FGraph::Client.new(:access_token => fgraph_access_token)
      
      @user = fg_client.me
      @user.symbolize_keys!
      @user[:birthday_date] = @user[:birthday]
      calc_rokuyou!(@user)
      
      @friends = fg_client.fql("SELECT uid, name, pic_square, sex, birthday_date FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me())")
      
      @friends.each do |friend|
        calc_rokuyou!(friend)
      end
      @friends.delete_if {|v| v[:birthday_date].nil?}
      @friends.sort!{|a, b| a[:next_birthday_date] <=> b[:next_birthday_date]}
      
      #大安じゃ無い人は5人まで
      not_taian_count = 0;
      @friends.delete_if do |v|
        if v[:next_rokuyou] != 0
          not_taian_count = not_taian_count+1
          not_taian_count > 5
        else 
          false
        end
      end
      
      render :main
    else
      render :index
    end
    
  end
  
  private 
  
  def calc_rokuyou!(user)
    user.symbolize_keys!
    if user[:birthday_date].nil? 
      user[:next_rokuyou] = nil
    else
      user[:birthday_date] = Date.strptime(user[:birthday_date], (user[:birthday_date] =~ /^\d{2}\/\d{2}$/) ? "%m/%d" : "%m/%d/%Y")
      user[:next_birthday_date] = get_next_birthday(user[:birthday_date])
      user[:next_rokuyou] = rokuyou kyureki(user[:next_birthday_date])
    end
  end
  
end


main.html.erb

<%= @user[:name]%>さんの次の誕生日は大安
<%= if @user[:next_rokuyou] == 0 then 'です。' else 'ではありません。' end %>
<br/>
<%= if @user[:next_rokuyou] == 0 then 'ハッピーなので、' else '悲しいので、' end %>
みんなにおごってもらいましょう!
<br/>
<a href="javascript:void(0);" onclick="feed(<%= if @user[:next_rokuyou] == 0 then 'true' else 'false' end %>);"><%= image_tag('btn_treat_me.png', :style => "border-style:none;")%></a>

<br/><br/>
<p>友達の誕生日一覧<br/>ハッピーな人達からおごってもらいましょう!</p>
<% if @friends.size == 0 %>
	友達の誕生日が取得できませんでした。友達をさそってからまらアクセスしてみてください。<br/>
<% else %>
	<table border="1">
	<% @friends.each do |friend| %>
	<tr <%= if friend[:next_rokuyou] == 0 then "bgcolor='#ffc0cb'" end %> >
		<td><img src="<%= friend[:pic_square] %>"/></td>
		<td><%= friend[:name] %></td>
		<td><%= friend[:next_birthday_date] %></td>
		<td><%= if friend[:next_rokuyou] == 0 then "大安" else "" end %></td>
		<td><a href="javascript:void(0);" onclick="wall('<%= friend[:name] %>','<%= friend[:uid] %>', <%= if friend[:next_rokuyou] == 0 then "true" else "false" end %>);"><%= image_tag('btn_treat_me.png', :style => "border-style:none;")%></a></td>
	</tr>
	<% end %>
	</table>
<% end %>

<script>
  function wall(name, toid, is_taian){
	if(is_taian){
		msg = name + 'さんの次の誕生日は大安です。ハッピーなのでおごってください!ありがとうございます!';
	} else {
		msg = name + 'さん、もうすぐ誕生日ですね!ハッピーなのでおごってください!ありがとうございます!';
	}
   FB.ui(
	   {
	     method: 'feed',
	     name: '誕生日なのでおごって!',
	     link: 'http://apps.facebook.com/taianfriends/',
	     picture: 'http://kissrobber.com/taianbirthday/images/logo.png',
		 to: toid,
	     description: msg,
	     actions: {'name':'powered by iq148.com', 'link':'http://iq148.com'}
	   });
  }
  function feed(is_taian){
	if(is_taian){
		msg = '<%= @user[:name]%>さんの次の誕生日は大安でハッピーなので、みんなおごってあげてください!ありがとう!';
	} else {
		msg = '<%= @user[:name]%>さんの次の誕生日は大安じゃなくて悲しいので、みんなおごってあげてください!ありがとう!';
	}
   FB.ui(
	   {
	     method: 'feed',
	     name: '誕生日なのでおごって!',
	     link: 'http://apps.facebook.com/taianfriends/',
	     picture: 'http://kissrobber.com/taianbirthday/images/logo.png',
	     description: msg,
		actions: {'name':'powered by iq148.com', 'link':'http://iq148.com'}
	   });
  }
</script>

FacebookのXFBMLがIEで表示されない場合に確認する事

htmlのhtmlタグにfb名前空間の宣言を忘れていないか

<html>

<html xmlns:fb="http://www.facebook.com/2008/fbml">


firefoxとかChromeだと宣言しなくても普通にXFBML表示される。

XenServerをiSCSIブートする設定のメモ

iSCSI SANからのXenServerのBOOTは正式には対応していませんが、技術的には可能です。

http://forums.citrix.com/thread.jspa?threadID=249734&tstart=0

って事でやってみた


XenServer5.5でも5.6でこの通りでいけました。

手順は、

ここのとおりやればOKです。
http://www.rienbroekstra.nl/?q=node/19


インストールCDからshellに入る


# Insert relevant kernel modules
modprobe scsi_transport_iscsi
modprobe iscsi_tcp


# Configure our initiator name, replace the name with whatever is correct for your organisation
iSCSIイニシエータ名
echo "InitiatorName=iqn.2010-01.com.example:whatever" > /etc/iscsi/initiatorname.iscsi


# Start the iscsi daemon
iscsid


# Configure the network interface which is to be used to access the iscsi target, and bring it up
XenServer側のIP
ip addr add 1.2.3.4/24 dev eth0
ifconfig eth0 up


# Discover the available targets on your iscsi filer (This step is necessary, even if you know what the correct target is)
iSCSI側のIP
iscsiadm -m discovery -t sendtargets -p 1.2.3.1


# Connect to the target
iSCSIのイニシエーター名とIP
iscsiadm -m node --targetname iqn.2006-01.com.openfiler:whatever -p 1.2.3.1 --login


# Kill and restart iscsid. I'm not sure that this is necessary, but it might write the correct configuration to /etc/iscsi/, so I guess it can't hurt.
psで確認するとiscsidのプロセスが2ついるのでkillしてもう一回iscsid


# Exit the shell in order to start the installer.
exit


Xenのインストールを進めていけば、インストール先の選択にiSCSIターゲットが出てくる