【Lifehacks】はてなブックマークの操作内容をログに出力する

■タスク
 はてなブックマークで操作した内容を、外部プログラムで処理してログに書き込む。


■背景
・著名なSBS(ソーシャルブックマークサービス)の一つであるはてなブックマークに、6/3、新機能「WebHook」が追加されました。
・WebHookは、ブックマークの追加、更新、削除等の操作時に、あらかじめ指定した外部プログラムを呼び出し情報を渡すことを可能とするインタフェースです。
・外部プログラムとのインタフェースはCGIに基づくため簡単に利用可能です。
・色々と使えそうなので、サンプルを参考に外部プログラムの雛形を作ってみることにしました。


■仕様
▼呼び出し
CGI準拠のプログラムを記述し、はてなサーバから呼び出し可能なウェブサーバに設置します。
・WebHookからの呼び出しは、HTTPリクエストによります。


▼認証
・外部プログラム登録時に、あらかじめ認証用のキー文字列を設定しておきます。
・WebHookで外部プログラム呼び出し時に、認証キーがHTTPリクエストのクエリ情報として送付されます。
・外部プログラム側では、文字列内容が登録した文字列と一致するかを確認します。


▼情報形式
・操作したブックマークの情報(タイトル、URL、コメント、操作日時等)が送付されてきます。
・操作日時は、IS0 8601のサブセットとして定義されたW3CDTF形式となっています。
文字コードUTF-8となっています。


▼本プログラムの注意事項
・操作日時・文字コードは特に加工せず、そのままログに記録します。
・ログは単一ファイル・追記型とし、世代管理・循環管理は行わないものとします。


■プログラム

#!/usr/bin/perl
#
# SgHatenaBookmarkToLog.pl
# はてなブックマークの操作内容をログに出力する。
#
# Author: Orihika Ikuo
# Create: 2009.06.06
# Update: 2009.06.15
#

##### Pragma
use strict;
use warnings;
use CGI qw/:standard/;

##### Setting
our $HBWH_KEY                = "XXXXXXXXXXXXXXXX";
our $LOG                     = "./SgHbwhLog.txt";

##### Constant
our $ERR_CANNOT_AUTH         = "ERR: Cannot authenticate.";
our $ERR_OO_OPE              = "ERR: Out of operation.";
our $ERR_ILL_STAT            = "ERR: Illegal status.";
our $ERR_FOPEN               = "ERR: Cannot open file.";

our $CGI_OK                  = "CGI: OK";
our $CGI_NG                  = "CGI: NG";

##### Main routine
&main();

sub main {
  my $req = CGI->new;
  $req->charset('utf-8');

  # 登録キーとの認証
  &SgHbwhAuthenticate($req->param('key'), $HBWH_KEY);

  # ステータスの確認
  &SgHbwhChkStatus($req->param('status'));

  # ユーザーの情報を取得
  my $username   = $req->param('username');

  # エントリーの情報を取得
  my $title      = $req->param('title');
  my $url        = $req->param('url');
  my $count      = $req->param('count');

  # ブックマークの情報を取得
  my $comment    = $req->param('comment');
  my $timestamp  = $req->param('timestamp');
  my $is_private = $req->param('is_private');

  # ログ出力
  &SgHbwhWriteLog($title, $url, $comment, $timestamp);

  # 処理成功の返答
  &SgHbwhResponce($CGI_OK);
}

##### Sub routine

# 登録キーとの認証
sub SgHbwhAuthenticate {
  my ($req_key, $fixed_key) = @_;

  if ($req_key ne $fixed_key) {
    die $ERR_CANNOT_AUTH;
  }
}

# ステータスの確認
sub SgHbwhChkStatus {
  my ($status) = @_;

  if      ($status eq 'add') {
    return;
  } elsif ($status eq 'update') {
    die $ERR_OO_OPE;
  } elsif ($status eq 'delete') {
    die $ERR_OO_OPE;
  } else {
    die $ERR_ILL_STAT;
  }
}

# CGI処理結果の返答
sub SgHbwhResponce {
  my ($msg) = @_;

  print header('text/plain');
  print $msg;
}

# ログファイルへの書き込み
sub SgHbwhWriteLog {
  my ($title, $url, $comment, $timestamp) = @_;

  open(my $fh, ">>$LOG") or die $ERR_FOPEN;
  print $fh $timestamp, "\n";
  print $fh $title,     "\n";
  print $fh $url,       "\n";
  print $fh $comment,   "\n";
  print $fh "\n";
  close $fh;
}