Python で作る Facebook ページの「いいね!」ファン限定コンテンツ (ファンゲート)

最近ようやく Facebook を使い始めていろいろ遊んでいます。
今回は企業の Facebook ページなんかでよく見かける「いいね!」会員限定コンテンツを Python で実装してみます。

環境

今回は Dotcloud を使ってみますが、サーバーの設定が面倒だという理由からです。WSGI を利用できるサーバーがすでにあるならそちらで動かしても問題ないと思います。

コード

環境作成
$ mkdir fangate
$ cd fangate
$ touch wsgi.py
$ touch dotcloud.yml
wsgi.py

signed_request を POST してくるので送られてきたデータを parse する。

# coding: utf-8
# Ref: http://developers.facebook.com/docs/authentication/signed_request/
import json
import urlparse
import hmac
import hashlib
import base64


SECRET = 'アプリの秘訣を入れる'


def base64_url_decode(s):
    padding = 4 - len(s) % 4
    s += '=' * padding
    return base64.urlsafe_b64decode(s)


def parse_signed_request(signed_request, secret):
    encoded_sig, payload = signed_request.split('.', 2)
    sig = base64_url_decode(encoded_sig)
    data = json.loads(base64_url_decode(payload))

    if data['algorithm'].upper() != 'HMAC-SHA256':
        return None
    
    expected_sig = hmac.new(secret, payload, hashlib.sha256).digest()
    if sig != expected_sig:
        return None

    return data


def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-Type', 'text/html')]
    start_response(status, response_headers)
    if environ['REQUEST_METHOD'] == 'POST':
        post_data = urlparse.parse_qs(environ['wsgi.input'].read())
        if 'signed_request' in post_data:
            # post_data['signed_request'] の中身はリストになっている
            signed_request = parse_signed_request(post_data['signed_request'][0], SECRET)
            if signed_request['page']['liked']:
                # 限定コンテンツ!
                return ['Special Content!']
    # 通常コンテンツ
    return ['Hello']
dotcloud.yml
www:
  type: python
Dotcloud にデプロイ
$ dotcloud create fangate
$ dotcloud push fangate
...

Deployment finished. Your application is available at the following URLs
www: http://fangate-XXXXXXXX.dotcloud.com/

おしまい

これでファンゲートの完成です。あとは Facebook アプリの設定を済ませて、いいねを押してみたり取り消したりしてみましょう。
動かないときは dotcloud logs fangate.www としてみてログを確認してください。

MacBook Air 13inch (MacBookAir Late 2010) を買ったので画像で紹介

MacBook Air (Late 2010, 機種ID: MacBookAir3,2) を購入しました。標準モデルではなくメモリを 4GB、SSD を 256GB にしたマシンにしました。
JIS キーボードと US キーボード で option キーや control キーの位置が違ったり、かなキー、英数キーの有無などの違いがあるのでどちらにするか少し迷いましたが、option キーが左右にある US キーボードを選びました。
動作は噂通り快適で、ストレスは特に感じません。トラックパッドも使いやすくてタッチパネルで操作しているかのような便利さがあります。持ち運びにも便利なのでお勧めです。
画像はリンク先で「オリジナルサイズを表示」すると拡大できます。

開封







本体







初期設定

  • 言語選択
    • 主に日本語
  • ようこそ
    • 日本
  • キーボードの入力環境
  • すでに Mac をお持ちですか
    • 今すぐ転送しない
  • ワイヤレスネットワーク
    • 自宅の無線 LAN を選択
    • パスワードを入力
  • AppleID を入力
    • 入力しない
  • ユーザ登録の情報
    • Command + Q でスキップ
  • ローカルアカウントの作成
    • フルネーム
    • アカウント名
    • パスワード
    • パスワードの確認
    • パスワードのヒント

あとは好きなだけ遊ぶ

トラックパッドまわりの設定やファイアーウォールの設定などを自分の環境に合わせて設定してあとはひたすら遊びます!!

Python と pywinauto で Windows の GUI 操作を自動化する

GUI 操作の自動化は AutoItUWSC などを使うと可能ですが、選択肢として Python + pywinauto もありかもしれません。
Python はウェブ開発やスクリプト、PySide などを利用した GUI 開発にも使えます。そのため Python を使えば GUI の自動化以外にも様々な開発を行うことができるようになります。

インストール

  • Python 2.7.1
    • 公式の Python でも ActivePython でも OK。
      • 先々の面倒を考えると ActivePython が便利かもしれない
    • ctypes が利用できる Python 2.5 以上を使うこと
    • C:\Python27 にパスを通す
    • distribute か pip を入れておくと便利。しかし今回は使わない
  • pywinauto 0.4.0
    • easy_install だと古いバージョンが入ってしまうので注意
    • http://sourceforge.net/projects/pywinauto/files/pywinauto/0.4.0/
    • 上記 URL から pywinauto-0.4.0.zip をダウンロードして解凍
    • 解凍したフォルダを開いて python setup.py install を実行
    • インストール後、「SendKeys モジュールが無い」と言われたりするが、付属の SendKeysCtypes モジュールを使っているみたいなので必要ないと思われる
      • The following module has to be installed before running pywinauto...
      • No module named: SendKeys

メモ帳を開いて現在の日付と時刻を保存する

# coding: utf-8
from datetime import datetime
from pywinauto import application
app = application.Application.start("notepad.exe")

# Notepad クラス (Notepad のウィンドウ) を探して日時を入力
app.Notepad.Edit1.SetText(unicode(datetime.now()))
# メニューを選択
app.Notepad.MenuSelect(u"ファイル->名前を付けて保存")
# 「名前を付けて保存」のウィンドウを探す
dialog = app[u"名前を付けて保存"]
# ファイル名を設定
dialog.Edit1.SetText(u"datetime.txt")
# 保存ボタンをクリック
dialog.Button1.Click()

# すでにファイルが存在すれば上書きの確認が求められる
confirm = app[u"名前を付けて保存の確認"]
if confirm.Exists():  # 確認を求められたかどうか
    confirm.Button1.Click() # 上書きする

# キーストロークを使って終了させる
app.Notepad.TypeKeys("%FX") # 終了 (Alt+F X)

コードを書く際の注意点

さらに詳細な操作は...

pywinauto を使えば Python を使ってより詳細な GUI 操作を自動化できます。ドキュメントにかなり詳しく書かれていますので、以下を参照してください。
http://pywinauto.googlecode.com/hg/pywinauto/docs/contents.html

BitBucket と TortoiseHg で快適分散型バージョン管理生活

f:id:wwwcfe:20110201002717p:plain

分散型バージョン管理システムは Git と Github の組み合わせが人気ですが、個人的に BitBucket が気に入ったので基本的な設定や注意点などをメモしておきます。

対象

  • 個人開発でソースコードのバージョン管理をしたい人
  • プライベート開発したい人。
  • Windows環境で開発したい人など。

なぜ BitBucket か

  • プライベートレポジトリを無制限に作成できる
  • 5ユーザーまでは無料プランを利用できる
  • プロジェクト Wiki や問題追跡システム (Issue tracking system) が利用できる

などが主な理由です。Mercurial レポジトリしか選択できませんが、Git や Bazzar と比べても機能的ほとんど差が無いのであまりこだわっていません (大規模開発なら話が違ってくるかもしれませんが)。単純に BitBucket 使いやすいと感じたので利用しようと思い、必然的に Mercurial を選択したという感じです。
他の候補としては GithubAssembla などを考えていましたが、Github はプライベートレポジトリが有料で数も制限あり、Assembla プライベートレポジトリを作れますが Wiki や問題追跡システムが有料ですので、私個人的な用途では気軽に使えるという感じがしませんでした。

Mercurial の基本

  • レポジトリを作成するか、クローンする
  • 作業ディレクトリでソースコードを変更する
  • レポジトリに作業ディレクトリの内容をコミットする
  • コミットした内容を別レポジトリからプルするか、別レポジトリにプッシュする
    • BitBucket で使うので、最終的には BitBucket 上のレポジトリにプッシュする

BitBucket に登録

BitBucket にユーザー登録してレポジトリを作成します。このレポジトリがリモートレポジトリになります。プライベートレポジトリにするには「Private」をチェックします。後で変更することも可能です。レポジトリを作成すると Wiki の編集や Issue の登録ができます。


BitBucket にレポジトリを作成したら、TortoiseHg を使ってクローンするか、ローカルレポジトリを新たに作成して後で BitBucket 上のリモートレポジトリにプッシュします。

TortoiseHg の設定

ローカルにレポジトリを作成したらエクスプローラーの右クリックから「TortoiseHg」->「Repository Setting」でレポジトリの設定をします。
「同期ツール」にリートレポジトリを追加します。BitBucket のレポジトリ URL をコピーしてきて「URL」の欄にペーストします。パスワードの入力が面倒であればパスワードも設定します。「デフォルトにする」でデフォルトのリモートレポジトリに設定しておきます。

そして「コミット」->「ユーザー名」に BitBucket のユーザー名を入力します。ユーザー名は何でもいいですが、BitBucket のユーザー名にしておくと BitBucket のレポジトリブラウザで閲覧した際にコミッターのプロフィールページへリンクされます。(別の名前にしても後でBitBucket のレポジトリ管理画面から「Custom Username Aliases」を開いて BitBucket ユーザー名とコミット時のユーザー名を関連づけることができます)
次に「Issue Tracking」の設定で以下のように設定します (user_name と project_name を変更します)

Issue Regex #(\d+)\b
Issue Link http://bitbucket.org/user_name/project_name/issue/{1}/

これによってコミットメッセージに #1 などと書くと、BitBucket の Issue Tracker にリンクされます。

基本的な設定はこれくらいで OK です。

注意点

ソースコードUTF-8 で保存します。Shift_JIS などは BitBucket のレポジトリブラウザからは正常に閲覧できません。
マージで KDiff3 を使うならあらかじめ KDiff の設定でファイルのエンコーディングを指定しておく。TortoiseMerge や WinMerge を使った方がいいかも。

コードを書く

あとはひたすらコードを書いてコミットして、最終的に BitBucket 上のレポジトリにプッシュしていきます。プルやプッシュするときは、レポジトリをエクスプローラーで開いて右クリックから「TortoiseHg」->「Synchronize」を開き、「同期ツール」で設定したリモートレポジトリを選択します。

最後に

個人でプライベートな開発するなら今のところ BitBucket が優秀だと思います。プライベートレポジトリで Wiki や問題追跡システムが利用できるのは本当にありがたいです。
もちろんパブリックな開発でも十分に強力なサービスですので、BitBucket の選択は「あり」だと思います。

エクスプローラーからレジストリにアクセスする方法


Windows Registry shell extension というシェル拡張プログラムをインストールすると regedit.exe を起動せずエクスプローラーからファイルを操作するかのようにレジストリを操作できます。

インストール

インストールはとても簡単で、こちらから「Installation file」をダウンロードしてきて、ダウンロードしたインストーラを実行するだけです。

使ってみる

Windows7 にインストールしてみました。

ルートキーを表示する

インストールが終わり、「コンピューター」を開くと「Windows Registry」というアイコンが追加されています。
アイコンをダブルクリックするとルートキーがフォルダとして表示されています。ここから目的の場所へと辿っていくことができます。

値を編集する

目的のキーへと辿り、値を編集するには、変更したいレジストリ値を選択してエクスプローラーの下部に表示される「Value」という項目を変更します。変更した値は自動保存されないのでしっかりと「保存」ボタンを押しておきます。

値を追加する

ファイルを作成するように右クリックから値を作成できます。

デフォルトでは項目の値やレジストリ値の種類が表示されておらず一覧性が悪いので、列を右クリックして「その他...」から「Value」と「Value Type」を選択しておくと便利です。

使用は自己責任で

レジストリというデリケートな場所を扱うため、ソフトウェアの不具合などにより予期せぬ結果を招くかもしれません。くれぐれもご注意を。

Ruby 1.9 で日本語 (UTF-8 の文字列) を正しく表示させる方法


Windows 環境でコマンドプロンプトを使って日本語を表示させようとして躓いたのでメモ。ソースコードUTF-8 で書きたい人を対象にしています。

環境

まとめ

先にまとめを書いておきます。

ソースコード

以下のソースコードを使ってテストしてみます。ソースコードは encoding_test.rb として、UTF8 (BOM 無し) で保存しました。

# -*- encoding: utf-8 -*-

# 外部エンコーディング
p Encoding.default_external
p $stdout.external_encoding
# 内部エンコーディング
p Encoding.default_internal
p $stdout.internal_encoding

str = "こんにちは世界"
# 文字列のエンコーディング。ソースコードと同じになる。
p str.encoding
# 文字列を表示
puts str

オプションなし

ruby encoding_test.rb
結果
#
nil
nil
nil
#
縺薙s縺ォ縺。縺ッ荳也阜

文字化けしてしまいました。デフォルトの外部エンコーディングWindows-31J になっていますが、内部エンコーディングと $stdout の外部エンコーディングnil になってしまってます。文字列自体は UTF-8 であることが分かります。

オプション -E を使う

  • Eexternal_encoding と指定します。デフォルトの外部エンコーディングを指定するオプションです。
ruby -EWindows-31J encoding_test.rb
結果
#
nil
nil
nil
#
縺薙s縺ォ縺。縺ッ荳也阜

オプションなしと同じ結果になりました。

オプション -U を使う

ruby -U encoding_test.rb
結果
#
#
#
#
#
こんにちは世界

正しく表示できました。デフォルトの外部・内部エンコーディングだけでなく、$stdout の外部・内部エンコーディングに適切なエンコーディングが指定されています。

オプション -E で内部エンコーディングも指定する

-Eexternal_encoding:internal_encoding とすることで、デフォルトの外部・内部エンコーディングを指定できます。

ruby -EWindows-31J:UTF-8 encoding_test.rb
結果
#
#
#
#
#
こんにちは世界

こちらも正しく表示できました。環境によって外部エンコーディングの指定を適切に書き換える必要があります。また、ソースコードエンコーディングUTF-8 でなければ内部エンコーディングの指定も書き換える必要があります。

Xion Audio Player 日本語化