Bulknews::Subtech RSSフィード

2006/10/31 (火)

Test::Base でテストコードとデータの分離 00:11  Test::Base でテストコードとデータの分離 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Test::Base でテストコードとデータの分離 - Bulknews::Subtech

Test::Base driven Development - Bulknews::Subtech - subtech で Test::Base でテストコードとデータの分離を! という話をかいたけど、実際 Test::Base にはファイル自体を分離する方法も用意されていた。

selector.t

#!/usr/bin/perl
use strict;
use warnings;
use HTML::Selector::XPath 'selector_to_xpath';
use Test::Base;

filters {
    selector => 'selector_to_xpath',
};

spec_file('selector.tb');
run_compare;

spec_file('selector.tb') でテストデータを書き込むファイルを指定。selector.tb は以下のようになる。

===
--- selector: *
--- xpath:    //*

===
--- selector: E
--- xpath:    //E

===
--- selector: E F
--- xpath:    //E//F

===
--- selector: E > F
--- xpath:    //E/F

てな具合。

spec_string($test_data) というメソッドも用意されているので、データベースにテストデータを格納して DBI で引っ張ってもいいし、Excel でテスト仕様書かいて Spreadsheet::ParseExcel なんてのもできるかも。素敵だ。

2006/10/30 (月)

Pootle 00:20  Pootle - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Pootle - Bulknews::Subtech

.po ファイルをWeb上で編集したりアサインしたりできるツールはないかと調べていたら BitTorrent でもつかってる Pootle がよさげ。ということで導入してみようかと。

しかし依存多し。apt で python2.3-setuptools いれたところ kid-0.9.3 で obsolete version of setuptools といわれたので apt-get remove。

が、ez_setup.py で http://cheeseshop.python.org/packages/s/setuptools/setuptools-0.6c3-py2.3.egg をとりにいこうとしてcheeseshop.python.org がタイムアウト。ネットワークインストールの肝なサーバが落ちてるなんて。

ミラーがみつからないので http://files.turbogears.org/eggs/ から 0.6c2 を持ってきて、ez_setup.py を手で書き換え。これでやっと kid-0.9.3 が入ったのだけど、今度は

Installed /usr/lib/python2.3/site-packages/kid-0.9.3-py2.3.egg
Processing dependencies for kid==0.9.3
Searching for elementtree
Reading http://www.python.org/pypi/elementtree/
No local packages or download links found for elementtree
Could not find suitable distribution for Requirement.parse('elementtree')

とかいわれる。たしかに python.org/pypi/ は Bad Gateway だ。こんな脆弱なインフラでいいのか Python

とまあよくわからないが http://effbot.org/downloads/cElementTree-1.0.5-20051216.tar.gz あたりからもってきてインストール。ログをみると /usr/lib/python2.3/site-packages/cElementTree.so はちゃんとできてるのだけど、肝心の PootleServer を走らせると

> PootleServer
Traceback (most recent call last):
  File "/usr/bin/PootleServer", line 23, in ?
    from Pootle import pootle
  File "/usr/lib/python2.3/site-packages/Pootle/pootle.py", line 31, in ?
    from Pootle import indexpage
  File "/usr/lib/python2.3/site-packages/Pootle/indexpage.py", line 31, in ?
    from elementtree import ElementTree
ImportError: No module named elementtree

でロードできない。って elementtree-1.2.6-20050316.tar.gz と cElementTree-1.0.5 は別物でした。。というわけで再度、http://effbot.org/downloads/elementtree-1.2.6-20050316.tar.gz からもってきて sudo python setup.py install

> PootleServer
2006-10-30 00:31:46: Listening on port 8080
2006-10-30 00:31:46: To use the server, open a web browser at http://127.0.0.1:8080/

うごいた!

2006/10/29 (日)

CPAN 01:50  CPAN - Bulknews::Subtech を含むブックマーク はてなブックマーク -  CPAN - Bulknews::Subtech

【備忘録】CPAN Author の登録手順とモジュールの登録手順 - drk7jp

pmsetup のリンクが古いほうになってますが、僕の最新は http://svn.bulknews.net/repos/public/misc/pmsetup にあります。Test::Base デフォルト。ちなみに h2xs は古いので、Module::Starter がいいかな。

アップロードをブラウザでやるのはだるいので、

あたりを使うとよいです。

kdaibakdaiba2006/10/29 19:56use_test_base;としてTest::Baseを使うときには,Test::Moreは使わないのかと思ってたんですが,そういうものではないですか?

miyagawamiyagawa2006/10/30 11:17Test::BaseはTest::Moreを継承してるので、Test::Baseは必要です。というか use_test_base すればいらないですけど。

2006/10/25 (水)

Test makes hackers also happy 21:04  Test makes hackers also happy - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Test makes hackers also happy - Bulknews::Subtech

no title

TDDはハッカーのための技術ではない。ハッカーにTDDは要らない。ただただハックすればよい。偉大なプログラマは偉大なプログラミングをすればよい。だが、ハッカーならぬ凡百たる私のような"普通の"プログラマはそうはいかない。TDDは我々が日々の仕事に自信を持ち、誇りを持って定時に帰るための思想だ。

言わんとすることは理解できる(つもりだ)けど、TDD こそハッカーのための技術(でもある)、という気がしないでもない。

Pugs (Perl6) も JSAN も Perl ハッカーのはじめた新しい言語・ライブラリのレポジトリなんだけど、そこで一番最初にポーティングされたモジュールが Test::Simple (Test::More) だった、という事実に注目しないと。

#perl6 や Pugs のMLで「このコードはこういう挙動でいいの?」と質問すれば「commit bit あげるから .t (テストコード)にしてコミットしておいてよ」といわれる。

Plagger も最初こそテストかかずにやってきたけど、いまやテストかかずにプラグインコミットするのは健康に悪い。tools/plugin-start.pl で勝手にテストの雛形がつくられるようにしたのもそういう理由。

たぶん。彼らは怠惰だ。短気だ。傲慢だ。だが、少なくとも私には怠惰が足りない。怠惰が足りないプログラマの仕事をドライブするものこそテストだ。私は毎日が不安だ。

ハッカーは怠惰だからこそ、自分で結果をチェックするなんて面倒くさいことをせず、テストコードにそのチェックをやらせるんじゃないかな? 「楽をするためならどんな苦労もいとわない」のがハッカーでしょ。

Test::Base driven Development 18:39  Test::Base driven Development - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Test::Base driven Development - Bulknews::Subtech

404 Blog Not Found:テキストエディタさえあればできるTDD

まあいわんとすることはわかるのだが、例がわるくて Perl のほうがぜんぜん簡単に見えないし、TDD のポイントは Test を書いてインタフェースを決め、fail させ、実装コードを書いて pass させるという点にある(と思う)から、コード使いでない人がかける云々というのはポイントではないはずだ。

それにいくら Perl を贔屓目に見たところで、実際の実装コードとテストコードを違う言語で書くことにメリットはほとんどないはずだから、ここでも Java は見にくくて云々は関係ない。

ついでなので、Test::Base でテストを書くとこのようになる。Lingua::JA::Hepburn::Passport (入力されたひらがな・カタカナをヘボン式ローマ字に変換)を例にすると、

use strict;
use Test::Base;

use Encode;
use Lingua::JA::Hepburn::Passport;

sub hepburn {
    Lingua::JA::Hepburn::Passport->new->romanize( decode_utf8($_[0]) );
}

filters {
    input => [ 'chomp', 'hepburn' ],
    expected => [ 'chomp' ],
};

run_is 'input' => 'expected';

__END__

===
--- input
なんば
--- expected
NAMBA

===
--- input
ほんま
--- expected
HOMMA

===
--- input
さんぺい
--- expected
SAMPEI

===
--- input
はっとり
--- expected
HATTORI

===
--- input
きっかわ
--- expected
KIKKAWA

===
--- input
ほっち
--- expected
HOTCHI

===
--- input
はっちょう
--- expected
HATCHO

===
--- input
こうの
--- expected
KONO

===
--- input
おおの
--- expected
ONO

===
--- input
ひゅうが
--- expected
HYUGA

===
--- input
ちゅうま
--- expected
CHUMA

===
--- input
おーの
--- expected
ONO

=== Katakana
--- input
チュウマ
--- expected
CHUMA

真ん中にある __END__ の上がテストコード、下がそれに食わせるデータである。いわゆる MVC とかでデザインとロジックの分離!とか言うが、テストにおけるテストコードとテストデータの分離、といってもいいかもしれない。

Test::More では .t にのっぺり書いていくのがいや、という人も Test::Base ならこのようにかけて安心。「結局__END__ 上のテストコード(フィルタとか)は .t ごとに書くんじゃねえの」という方は、t/MyTest.pm とか書いて .t からは use t::MyTest; と呼び出せば再利用できる。

というわけで自分が CPAN モジュールを書くときは、

  • モジュール名決める
  • pmsetup で雛形作成
  • APIを決めて、POD を書く
  • t/01_module.t にテストコードとテストデータを書く
  • make test こける
  • 実装
  • make test OK
  • コーナーケースのデータを .t に追加

というようなサイクルで実装してます。

コーナーケースの発見がたまに難しいわけだけど、それに注目しているのが LectroTest という仕組み。Haskell では QuickCheck, CPAN には Test::LectroTest とかあるが、ちょっと test spec の作り方が難しそう。うまいこと Test::Base にフィードするデータをこんな感じでつくれると回帰テストに役立ちそうだなんだけど。

register.com down 16:11  register.com down - Bulknews::Subtech を含むブックマーク はてなブックマーク -  register.com down - Bulknews::Subtech

register.com が全体的にダウンしている模様。その影響で自分のいくつかのドメイン (bulknews.net など)がDNS解決できなくなっています。復旧を待つしかないですが。。

コンテンツをみたい、という方は plagger.org などと同じ 202.181.96.213 を hosts に追加してもらえれば。

UPDATE: 17:37 復帰した。

2006/10/24 (火)

SSL の更新期限を iCal へ 17:28  SSL の更新期限を iCal へ - Bulknews::Subtech を含むブックマーク はてなブックマーク -  SSL の更新期限を iCal へ - Bulknews::Subtech

サーバ証明書数百枚を管理している人が身近にいる。

それPla」とされているように、Plaggerと連動させれば期限管理ツールとして使える。

CPANに登録されるのが待ち遠しい。

CustomFeed::Script と openssl コマンドでやってみよう。


#!/usr/bin/perl
use strict;
use warnings;
use YAML;

my @hosts = @ARGV
    or die "Usage: ssl-expire.pl host1 host2 ...\n";

my $output = {
    title => "SSL expire dates",
    entry => [],
};

for my $host (@hosts) {
    my $expires = expire_date($host);
    push @{$output->{entry}}, {
        title => $host,
        date  => $expires,
    };
}

sub expire_date {
    my $host = shift;

    my $res = `echo '' | openssl s_client -connect $host:443 2>/dev/null | openssl x509 -enddate -noout`;
    if ($res =~ /notAfter=(.*)/) {
        return $1;
    }
}

print YAML::Dump $output;

として、

plugins:
  - module: Subscription::Config
    config:
      feed:
        - script:assets/plugins/CustomFeed-Script/ssl-expire.pl ssl.example.jp ssl2.example.jp
  - module: CustomFeed::Script
  - module: Publish::iCal
    config:
      dir: .
      filename: ssl.ics

できた。


DateTime::TimeZone 0.52 01:26  DateTime::TimeZone 0.52  - Bulknews::Subtech を含むブックマーク はてなブックマーク -  DateTime::TimeZone 0.52  - Bulknews::Subtech

Plagger を DateTime::TimeZone 0.52 で動かし、SmartFeed を使う(Planet とかは内部で使ってる)と、

The following parameter was passed in the call to DateTime::TimeZone::OffsetOnly::new but was not listed in the validation options: name
at /home/miyagawa/svn/plagger/lib/Plagger/Thing.pm line 24

で死ぬ。DateTime::TimeZone 0.52 のバグのようなので、とりあえず 0.51 以下にもどせばOK。datetime@ にはレポートずみ。

UPDATE: 0.53 で修正された。...とおもったけど DateTime の .t がこけたり、Format が動かなくなったりまだ問題おおし。

2006/10/22 (日)

Test::Base のフィルタで数値返す 13:42  Test::Base のフィルタで数値返す - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Test::Base のフィルタで数値返す - Bulknews::Subtech

           if (defined &$function) {
               $_ = join '', @value;
               @value = &$function(@value);
               if (not(@value) or
                   @value == 1 and $value[0] =~ /\A(\d+|)\z/
               ) {
                   @value = ($_);
               }
           }

Test::Base の filter まわりにこんなコードがあって、main:: に書いたサブルーチンをフィルタとして使うとき、数値を返すことができない。なんで?と聞いてみたら、

There are two calling conventions. Filters defined in the main:: namespace can
look like:

   sub filter9 {
       s/foo/bar/;
   }

Since a regexp match always returns a number or undef, we look for that.

If you must define a filter that returns just a single number, do it in a
different namespace. For instance, if you subclass Test::Base with Foozle,
then define filters in Foozle::Filter. These filters don't allow the
simplistic $_ munging.

ということで s/// が $_ に使えるようにしてあるので、数値が帰ってきた場合は $_ が返り値になる、ってことだった。t::Foo::Filter とかに定義する場合はOK。

2006/10/20 (金)

[Plagger] Becky! Tips 15:45  [Plagger] Becky! Tips - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Becky! Tips - Bulknews::Subtech

Becky! を使って Plagger メールをオフラインで読むとき、画像がたくさん入っているエントリが出てくると表示がふんづまる(画像がタイムアウトするまで待つ)問題があったのだけど、IE や Donut などを開いてオフライン作業モードにしてやればタイムアウトすることなくN/A画像が表示されてストレスフリーに。

2006/10/19 (木)

[Perl] Encode.pm の fallback が iso-2022-jp できかない 16:32  [Perl] Encode.pm の fallback が iso-2022-jp できかない - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Perl] Encode.pm の fallback が iso-2022-jp できかない - Bulknews::Subtech

iso-2022-jp でHTMLメールを送るときに範囲外を HTML 数値参照にしようと、

use strict;
use Encode;
my $u = "\x{0647}";
print encode("iso-2022-jp", $u, Encode::FB_HTMLCREF);

としても、

\x{0647}

となってしまう。iso-2022-jp は ucm ベースでなくて Encode::JP::JIS7 でもって変換をしてるからかな? とりあえずの workaroud としては Shift_JIS とか euc-jp を一度経由すれば OK。

これ Known bug?>Dan さん

2006/10/18 (水)

[Plagger] Summary::GetSen 15:56  [Plagger] Summary::GetSen - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Summary::GetSen - Bulknews::Subtech

no title, no title あたりにある自動要約生成サービス GetSen にサマリ生成を投げるプラグイン Summary::GetSen を書いた。

http://plagger.org/trac/ticket/432

OSX の SummaryService を Mac::Glue から呼び出す のはだれPla。>otsuneさんがやってくれそう

GetSen 自体のアルゴリズムも Text::MeCab とかつかって出来そうなので、GetSen のサービスに依存せずに自前実装もできそう>Yappoさんがやってくれそう

[Plagger] Filter::Kansai 15:54  [Plagger] Filter::Kansai - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Filter::Kansai - Bulknews::Subtech

f:id:miyagawa:20061017013140g:image

関西弁にするフィルタが http://kansai.pm.org/ にあったので 5.8 で使えるようにして Plagger::Plugin 化。アツイ。

Lingua::JA::Dialect::Kansai にしたいな。

2006/10/17 (火)

Kansai.pm 終了 23:51  Kansai.pm 終了 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Kansai.pm 終了 - Bulknews::Subtech

つかれたー。ノドがからからにかわきました。スライドはこちらにアップしました。

http://plagger.org/trac/attachment/wiki/PlaggerPresentations/Plagger-Kansaipm.pdf?format=raw

飲み会でもいろんなひとと話せて楽しかったです。感想とかのタグは [kansai.pm] でよろしくおねがいします。

飲み会で出たアイデア:

  • フィードを読んだかどうかをメーラの開封通知プロトコルを使うのはどうか
  • ていうかWidget::Simple でWebバグ埋め込めばいいんじゃね?


Trac の Zip download 10:52  Trac の Zip download - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Trac の Zip download - Bulknews::Subtech

Plagger中級

Changeset 1730の Zip Archiveが…、取れない…。

日ごろの行いが悪いからだろうか…。空のZipファイルが送られてくる…。

svn copy な changeset はダウンロードしようとしてもそれ全体がとれるわけではない、とおもう。svn において cp はただのマークにすぎないわけで。素直に svn export あたりを使うが吉。

2006/10/16 (月)

Plagger Slides 23:13  Plagger Slides - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Plagger Slides - Bulknews::Subtech

明日のスライド作成中。YAPC::EU のをベースに、サンプルをかなり増やした感じ。http://kansai.pm.org/cgi-bin/jenq.cgi?enq=7thmeeting を見た感じでどれくらいの客層なのか想像がつかないんだけど、70 のうち

  • Plagger 聞いたことあるけどよくわからない: 25人
  • Plagger やってみたいけどどう使うのか?: 25人
  • 基本的な設定だけつかってます: 15人
  • プラグイン自分で書いてます: 5人

ぐらいなのかなぁと思ってますが、あってるかな?

hatenagraph.pl 19:32  hatenagraph.pl - Bulknews::Subtech を含むブックマーク はてなブックマーク -  hatenagraph.pl - Bulknews::Subtech

はてなグラフAPIリリースということでいまブームのCLIツールを書いてみた。

http://svn.bulknews.net/repos/public/misc/hatenagraph.pl

ほとんど 30boxes.pl のコピペ。

> hatenagraph.pl
Hatena username:  miyagawa
Hatena password:  ********
Graph names (Comma separated): 体重,体脂肪率

として初期化。(あとからやるときは hatenagraph.pl setup)

> hatenagraph.pl
体重 on 2006-10-16: ***
体脂肪率 on 2006-10-16: ***

のようにして日々実行する。日付指定は --date=2006-10-12 のように。

Plagger on Kansai.pm 12:34  Plagger on Kansai.pm  - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Plagger on Kansai.pm  - Bulknews::Subtech

no title

そういえば明日です。申し込みまだの方はぜひ。関西でしゃべることはあと数年はないと思います。。

[Plagger] テレビ番組表を Plagger で #2 11:50  [Plagger] テレビ番組表を Plagger で #2 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] テレビ番組表を Plagger で #2 - Bulknews::Subtech

エラー - キャバクラで働くQ&A

ライブドアの番組表で検索結果フィードを出してくれるんだからカレンダーを出してくれてもいいのに。

たしかにそれは盲点だった。

livedoor から livedoor にいくと、カテゴリやら出演者で検索して RSS がつくれるので、ここから iCal つくれますね。WOWOW とかもちゃんと出てるし。。スクレイプする必要なかったな(WOWOW のリーガとかはカードが決まるのが直近なのでサイトのほうが情報は早そうですが)

ただ検索したフィードは Livedoor TV 独自の namespace 拡張で gcode とか iEPG、開始・終了時刻とか入ってるので、これをパースしないとだめですね。

<tv:feed rdf:parseType="Resource">
  <tv:genre>スポーツ/サッカー</tv:genre> 
  <tv:startDatetime>2006-10-16T00:45:00+09:00</tv:startDatetime> 
  <tv:endDatetime>2006-10-16T02:40:00+09:00</tv:endDatetime> 
  <tv:gcode>96433581</tv:gcode> 
  <tv:iepgUrl>http://tv.livedoor.com/tvpi.epg?pid=20510940</tv:iepgUrl> 
  <tv:performer>風間八宏,西岡孝洋</tv:performer> 
</tv:feed>

ってよく見たら上に dc:date は普通についてた。Namespace::LivedoorTV 書くところだったよ。。。まあ、Event Schedule API ができたら終了時刻とかもとれる、ということで今度また書くことにしよう。

というわけで、「サッカー」カテゴリの検索結果を iCal 化してみた。

ちなみに Namespace::LivedoorTV でIEPG とって Publish::Netnavi とか書くと勝手に予約とかできるよね。

2006/10/15 (日)

Publish::iCal とタイムゾーン 22:27  Publish::iCal とタイムゾーン - Bulknews::Subtech を含むブックマーク はてなブックマーク -  Publish::iCal とタイムゾーン - Bulknews::Subtech

Publish::iCal のスケジュールは全部 localtime で出していたので、修正中。RDFカレンダー -- iCalendarとRSSによるイベント情報の公開と活用 に iCal の日付仕様があり、Olson の名前 ("Asia/Tokyo" とか)を TZID= でつければいいっぽいので、こういうパッチを書いたんだけど、

=== lib/Plagger/Plugin/Publish/iCal.pm
==================================================================
--- lib/Plagger/Plugin/Publish/iCal.pm  (revision 5590)
+++ lib/Plagger/Plugin/Publish/iCal.pm  (local)
@@ -40,12 +40,16 @@
         my $event = Data::ICal::Entry::Event->new;

         my($dtstart, $dtend);
+        my %param;
+        if (!$date->time_zone->is_floating && $date->time_zone->name ne 'UTC') {
+            $param{TZID} = $date->time_zone->name;
+        }
         if ($date->hms eq '00:00:00') {
-            $dtstart = [ $date->strftime('%Y%m%d'), { VALUE => 'DATE' } ];
-            $dtend   = [ $date->strftime('%Y%m%d'), { VALUE => 'DATE' } ];
+            $dtstart = [ $date->strftime('%Y%m%d'), { %param, VALUE => 'DATE' } ];
+            $dtend   = [ $date->strftime('%Y%m%d'), { %param, VALUE => 'DATE' } ];
         } else {
-            $dtstart = $date->strftime('%Y%m%dT%H%M%S');
-            $dtend   = $date->strftime('%Y%m%dT%H%M%S');
+            $dtstart = [ iso8691_full($date), \%param ];
+            $dtend   = [ iso8691_full($date), \%param ];
         }

         $event->add_properties(
@@ -70,6 +74,12 @@
     $context->log(info => "Wrote iCalendar file to $path");
 }

+sub iso8691_full {
+    my $date = shift;
+    my $iso  = $date->strftime('%Y%m%dT%H%M%S');
+    $iso .= $date->time_zone->name eq 'UTC' ? 'Z' : '';
+    $iso;
+}

 1;
 __END__

うまく TZID=Asia/Tokyo にはならなくて、TZID=+0900 になってしまう。CustomFeed::Script で日付をやりとりするときに W3CDTF 形式をつかっているので、現在の時差 (+0900) しかやりとりできないのだ。 JST みたいな名前で渡せればいいんだけど、Date::Parse::strptime() する段階 (Plagger::Date->parse_dwim) でタイムゾーン情報は落ちてしまう。悩ましい。。

いっそ CustomFeed::Script の段階では floating のままでやりとりしておいて、Filter::GuessTimeZoneByDomain とか Filter::FloatingDateTime で Asia/Tokyo にしてしまう、という手もある。そのほうがシンプルかなあ。

http://plagger.org/trac/changeset/1761

というわけで、そのようにした。新しく Filter::ForceTimeZone というプラグインを追加。TZ があるなし、UTC かどうかにかかわらず、すべての日付をシステムで設定した timezone にセットする。Filter::FloatingDateTime は floating のものだけをするのに対し、こちらはすべて。

これで、

- module: Filter::ForceTimeZone
  config:
    timezone: Asia/Tokyo

を追加して (timezone は global: の下でもよいし、なければ local の tzinfo を見る)、iCal に

DTSTART;TZID=Asia/Tokyo:20061015T180000

が追加された。

と、思ったんだけど +0900 みたいに時差しかないときは、UTC に変換して Z つければいいんだな。Google Calendar の場合、floating だと PST と仮定、UTC ならちゃんとハンドルしてくれるはず。この辺の処理は DateTime::Format::ICal がこれやってくれるっぽい。もちろん UTC がやなら Filter::ForceTimeZone とかで。

[Plagger] TV 番組表を iCal で 16:29  [Plagger] TV 番組表を iCal で - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] TV 番組表を iCal で - Bulknews::Subtech

WOWOW の HV/5.1ch 番組表リーガエスパニョーラ, JSPORTS の海外サッカーPlagger で iCal にしてみた。

スクリプトはとりあえず svn の assets/plugins/CustomFeed-Script 以下にいれてある。

plugins:
  - module: Subscription::Config
    config:
      feed:
        - script:assets/plugins/CustomFeed-Script/wowow-hv-51ch.pl
        - script:assets/plugins/CustomFeed-Script/wowow-liga-espanola.pl
        - script:assets/plugins/CustomFeed-Script/jsports-football.pl
  - module: CustomFeed::Script
  - module: Filter::TagsToTitle
    config:
      add_to: right
  - module: Publish::iCal
    config:
      dir: /home/miyagawa/public_html/ical
      filename: %t.ics

出来上がった ics ファイルは http://plagger.org/ical/ においてある。URL は変わるかもだけど、Google Calendar にも入れてあります。

f:id:miyagawa:20061015162441g:image

いくつかメモ。

  • Publish::iCal の現在の仕様上、終了時間がいれられないので Day View とかで見にくい。body に microformats の hCalendar でいれるようにしたい。00:00開始の番組が終日イベント扱いになっているのも同様の制約。
  • %t.ics ではいているが、生成されるファイル名が UTF-8 になっている。UNIX でつくって Apache でサーブする分には問題ないみたいだけど、あまりよくはなさそう。filename_for の \w が utf-8 のマルチバイトにもマッチするのが問題か。
  • チャンネルや "HV", "5.1ch", リーグ名などは tags に入れるようにして、Filter::TagsToTitle でタイトルに追加するようにした。こうすれば Rule を書いて「チャンピオンズリーグだけのカレンダー」とかつくることができる、はず。
  • 2ch のスレでも EFT/CustomFeed::Config の管理が話題になっているけど、こういう野良っぽいスクレイプツールをどうやって管理するかは今後の課題。
  • JSPORTS フィードのタグが化けているがこれは修正済み。Google Calendar に強制的にリフェッチさせるのはどうしたらいいんだろ。

2006/10/14 (土)

DateTime::TimeZone 0.51 11:42  DateTime::TimeZone 0.51 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  DateTime::TimeZone 0.51 - Bulknews::Subtech

countries() と names_in_country() が追加された。

use DateTime::TimeZone;
@names = DateTime::TimeZone->names_in_country('US');

変更点は ISO 3166 コードしか受け付けない。スカラコンテキストでは1個目ではなく、array ref を返す(これは他のメソッドと共通化したんだろう)。これで Filter::GuessTimeZoneByDomain が書ける。

と、思ったら返ってくる names が sort されている。これじゃ使いにくいんだよなあ。ということで sort しないように要望なげた。

[perl] DateTime::TimeZone::FromCountry 04:06  [perl] DateTime::TimeZone::FromCountry - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [perl] DateTime::TimeZone::FromCountry - Bulknews::Subtech

#plagger-ja より。Floating な DateTime (たとえば d.hatena.ne.jp/rss/keyword みたいにタイムゾーンがついていないフィードとか、EFT で抜き出した日付とか)について、ドメイン名 (ccTLD) から推測できないかな、という話題。

ccTLD と ISO 3166 は一部の例外 (.uk, .eu など)を除き同一なので、ISO 3166 からタイムゾーンをひっぱってくる方法を調査。Olson には zone.tab という名前で入っているのだけど、DateTime::TimeZone ではとれない。というわけでモジュールかいた。

http://svn.bulknews.net/repos/public/DateTime-TimeZone-FromCountry/trunk/

$tz = DateTime::TimeZone->from_country('JP'); # Asia/Tokyo

という感じに DT::TZ オブジェクトがとれる。リストコンテキストなら複数、スカラなら1個目。日本とかは1個しかないので当然1個しかどちらでも1個だけしか返ってこない。

datetime MLに出したら Rolsky が取り込みたいみたいなのでそれ待ち。

ちなみに CPANIP::Country は ARIN WHOIS の IP 割り当てつかって IP アドレスから国コードを出すことができるから、.com/.net みたいな ccTLD じゃないやつの場合はこっちを使うのもいいかも。この2つがコンフリクトしたとき(たとえば sixapart.jp は ccTLD が日本だけど、IP アドレスは US のものになる)にどっちを使うかのポリシーは config で決めるかなあ。

2006/10/13 (金)

[Plagger] Summary merge 17:08  [Plagger] Summary merge  - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Summary merge  - Bulknews::Subtech

ページが見つかりません。 - Plagger

Google グループ

hackathon-summary を trunk にマージ。マージでいくつかエラーが見つかったけどユニットテストで発見できた。svk++ Test++

というわけで、Summary 系のプラグインはもう使えるけど、肝心の「Publish プラグインの content を summary に変更する」といったことはまだできない。やりたければ Filter プラグインを書けばできるのだが、個人的には Publish/Notify/Search プラグインごとに localize してやりたいなと思っているので、ちょっと構造の改修が必要になるかも。アイデアとしては、

  • config.yaml で Publish/Notify のブロックの下に localized_plugins: として Filter を書いていく
  • $entry->body としているところを $entry->content として、content() の中で config: からどれを返すか判別する

のどちらかになると思う。

また、Plagger::Text というオブジェクトが導入されたので、

  $entry->title("Foo &amp; Bar") 
  $entry->title->is_html;    # true 
  $entry->title->type        # 'html' 
  $entry->title->plaintext;  # Foo & Bar 
  $entry->title->html;       # Foo &amp; Bar 
  print $entry->title;       # "Foo &amp; Bar" 

のようなことができる。author, body も同様。overload しているので普通のコードはそのまま動くが、リファレンスを渡されると特殊な動作をするモジュールなどを使っている場合は、明示的に ->plaintext を呼ぶなどしてスカラ文字列型にする必要あり。

2006/10/12 (木)

[Plagger] Webページの更新をチェック 16:40  [Plagger] Webページの更新をチェック - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Webページの更新をチェック - Bulknews::Subtech

単純に WWWC っぽくページの更新だけをチェック。

plugins:
  - module: CustomFeed::Debug
    config:
      title: Cellphone IP ranges
      entry:
        - title: Air H Phone
          link: http://www.willcom-inc.com/ja/service/contents_service/club_air_edge/for_phone/ip/
        - title: DoCoMo
          link: http://www.nttdocomo.co.jp/service/imode/make/content/ip/about/
        - title: EZWeb
          link: http://www.au.kddi.com/ezfactory/tec/spec/ezsava_ip.html
        - title: Softbank
          link: http://developers.softbankmobile.co.jp/dp/tech_svc/web/ip.php
  - module: Filter::EntryFullText
    config:
      store_html_on_failure: 1
  - module: Filter::ResolveRelativeLink
  - module: Filter::Rule
    rule:
      module: Deduped
      compare_body: 1
  - module: Publish::Gmail
    config:
      mailto: example@example.com

CustomFeed::Debug でダミーフィードをつくって、EntryFullText で全文抽出、Deduped で compare_body する。


hiveminder 01:56  hiveminder - Bulknews::Subtech を含むブックマーク はてなブックマーク -  hiveminder - Bulknews::Subtech

Hiveminder has been shut down がいい理由。それはオフラインでも(あるいはサイトが落ちてても) TODO がみれる!

todo.pl download とすればカレントの tasks.txt に保存され、エディタで編集・新規追加・削除して todo.pl upload で反映。もちろん todo.pl 使わなくても Web UI からダウンロード・アップロードできます。

DXPresentation 01:22  DXPresentation - Bulknews::Subtech を含むブックマーク はてなブックマーク -  DXPresentation - Bulknews::Subtech

DLしてきてデモをみてみた。

すごすぎるな。。

ただ実際に凝ったプレゼンを書くのは結構苦労しそう。エフェクトとかフォントとかを変えるマクロを書くのが、on/off の繰り返しなので DRY じゃない気がする。Template Toolkit で MACRO とか定義して Makefile で tpage とかするといいかも。

2006/10/11 (水)

[Plagger] EFT で日本語 13:15  [Plagger] EFT で日本語 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] EFT で日本語 - Bulknews::Subtech

Plagger中級

「日本語どうなってんだろ?」も何も、タイトルだって本文だって普通に日本語使える。YAML は utf-8 で書いて BOM なしで保存すればOK。

extract_after_hook: で日本語リテラルかいて title にセットする場合は、$args->{entry}->title( decode_utf8("日本語") ); とかしないとだめ。

「動かない」とか「化ける」とか書かれても具体的にどのサイトで起こるのかがないと指摘しようがない。最低限 config.yaml と EFT の YAML をペーストして。

2006/10/09 (月)

window.openNewTabWith() 19:44  window.openNewTabWith() - Bulknews::Subtech を含むブックマーク はてなブックマーク -  window.openNewTabWith() - Bulknews::Subtech

Firefox で MozRepl とか URL バーから window.open() を呼ぶと、シングルウィンドウモード如何にかかわらず新しいウィンドウを開いちゃうんだけど、IRC で質問したところ、そういう時用に window.openNewTabWith(() という関数が用意されているそうな。

もちろんプラットフォーム依存関数だとおもうけど、Notify::FirefoxRemote みたいな時にはこっちが使える。

[Plagger] Open Entries in a browser 19:33  [Plagger] Open Entries in a browser - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Open Entries in a browser - Bulknews::Subtech

Plagger::Plugin::Notify::Browser : blog.nomadscafe.jp を Notify::OpenBrowser としてコミット。ついでに MozRepl につなぐ Notify::OpenBrowser::FirefoxRemote もいれた。

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://b.hatena.ne.jp/{username}/favorite?mode=rss
        - http://del.icio.us/rss/network/{username}?private={private}
  - module: Filter::Rule
    rule:
      module: Deduped
  - module: Notify::OpenBrowser

とかで、はてブと del.icio.us の network/お気に入りから未読をとってきて一気にタブブラウザで開く、とかできる。

Plagger を VMWare で動かしている人は Firefox に MozRepl をいれて、SSH Port Forward しておいて、

  - module: Notify::OpenBrowser::FirefoxRemote

に変えてやればOK。

Wink で Screencast してみた。

2006/10/08 (日)

[Plagger] Deduped 23:05  [Plagger] Deduped - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Deduped - Bulknews::Subtech

コメントしたけどはじかれたので。

鈴鹿決勝, DXPresentation, スター・トレック ネメシス スペシャル・コレクターズ・エディション [DVD](ジョン・ローガン), plaggerでmixi→gmail, まるごとPerl! Vol.1(小飼 弾/宮川.. - 今日のなんでやねん(2006-10-08)

前回fetchした日記も次回のメールに含まれるんだね.前回fetchした日記を覚えてて次回のメールには載せないんだと思っていた.もしかしてどこかの設定で変えられるのだろうか. Mixi.pm見てもそんなオプションないみたい.

- module: Filter::Rule
  rule:
    module: Deduped

とします。Plagger では(現状)各プラグインで未読判定するのではなく、いったん全部あつめたあとフィルタフェーズでフィルタします。

鈴鹿決勝, DXPresentation, スター・トレック ネメシス スペシャル・コレクターズ・エディション [DVD](ジョン・ローガン), plaggerでmixi→gmail, まるごとPerl! Vol.1(小飼 弾/宮川.. - 今日のなんでやねん(2006-10-08)

実はplaggerでやりたいことがあるんだけど,自分でplugin書けないとそれが実現できないんだよねー. Rubyでplugin書けれると楽なんだけどなー.

perl勉強しないとな…

Perl勉強してもらうのは大歓迎ですがw、CustomFeed::Script, Filter::Pipe であれば任意のスクリプトが使えるので、Ruby/Python でプラグイン相当のことをすることもできますね。

美しい国 18:52  美しい国 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  美しい国 - Bulknews::Subtech

「憎いし苦痛」にはワロタが、「美国」は中国語でアメリカ合衆国のことなんですよね。以前サンフランシスコのチャイナタウンで Bank of America が「美国銀行」となっていて気づきました。

http://ja.wikipedia.org/wiki/%E7%BE%8E%E5%9B%BD

2006/10/07 (土)

[perl] use Smart::Comments 21:47  [perl] use Smart::Comments - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [perl] use Smart::Comments - Bulknews::Subtech


use Smart::Commentsはいらないと思う - ヒルズで働く@robarioの技ログ

ソース中にuse Smart::Commentsは書かなくていいんじゃないかなあと思います。

use Smart::Commentsを消したり、no Smart::Commentsに変えたりするよりも、

デバッグ中だけperl -MSmart::Commentsするとか、PerlSwitches -MSmart::Commentsにしておくとかすれば、

環境によるソースの修正(それが自動で行なわれるとしても)が不要になっていいんじゃないかと思ったり。

発想としては同意したいところだけど、残念ながらコレじゃ動かないケースも。e.g. foo.pl が

use Foo;
Foo->run;

で Foo.pm の中に ### ではじまる Smart Comments がある場合は、 perl -MSmart::Comments foo.pl では有効にならない。Smart::Comments はソースフィルタだから use したコンテキストでしかフィルタがきかない。というわけでこういうときは、やっぱり (Foo.pm の中で)use Smart::Comments が必要。

[Perl] Dumping variables Everywhere without use() 21:34  [Perl] Dumping variables Everywhere without use() - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Perl] Dumping variables Everywhere without use() - Bulknews::Subtech

no title

なんかいろいろやっているけど UNIVERSAL も CORE も CORE::GLOBAL もだめなんじゃないかという気がする。どれも perl -MP -e 'package XYZ; p "foo"' とすると

String found where operator expected at -e line 1, near "p "foo""

とか言われて怒られる。いっそのことこういうのはどうだ。

package P;
use strict;
use YAML;

*CORE::GLOBAL::dump = sub {
    warn YAML::Dump(@_);
};

1;

perl のコア関数 dump を上書き。dump なんて誰も使わないでしょ。これならどの名前空間からもいける。

[perl] debugging 02:44  [perl] debugging - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [perl] debugging - Bulknews::Subtech

P - #生存戦略 、それは - subtech

みんな use Data::Dumper; dumper $obj; って書いてるのかなぁ。めどいので

use P;p $obj;

とかしてるよ。。

最近は use YAML; warn Dump $obj が多いんだけど、よりラクにやるなら Damian 先生の Smart::Comments か Ingy の XXX.pm かなぁ。よりによって Damian と Ingy ってのが対極な感じで面白いけど。

Smart::Comments は ### でコメントしてくれれば Dump してくれる。他にも require: で assertion したり、for/while ループでダイアログだしたりいろいろ Cool。

use Smart::Comments;
$foo = some_complex_data;
### $foo

はずすときは use Smart::Comments の行だけコメントアウトすればいい、というのもいいですね。(またデバッグするときにラク)

XXX.pm は Spiffy から XXX/YYY/WWW/ZZZ だけ取り出したモジュール。なぜか cpan> install XXX できないので、install INGY/XXX-0.10.tar.gz するといけます。

use XXX;

$foo = some_complex_data;
XXX $foo;

だけど、XXX はサブルーチンなので式の途中とか先頭にいれてもいい。

use XXX;

XXX $foo = some_complex_data;

XXX は die, WWW は warn, YYY は print, ZZZ は stacktraceつき。この辺のセンスも ingy なんだよなー。

2006/10/06 (金)

[Plagger] Publish::iCal 18:09  [Plagger] Publish::iCal - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Publish::iCal - Bulknews::Subtech

http://plagger.org/trac/browser/trunk/plagger/lib/Plagger/Plugin/Publish/iCal.pm

↓ をやりたいがために、Publish::iCal をコミットした。kentaroたんがつくった http://antipop.gs/tmp/plagger/iCal.pm.txt をベースにして、Event API などはいれてないシンプルなもの。

フィードの date が 00:00 なら全日イベントにするとか、いろいろリファクタしてあります。



[Plagger] Domain 失効情報を RSS/iCal に 17:22  [Plagger] Domain 失効情報を RSS/iCal に - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Domain 失効情報を RSS/iCal に - Bulknews::Subtech

ドメイン失効のアラートに気付きにくいという話題。ドメイン管理者が、更新期限が迫っていることをRSS配信すると嬉しいかもと思いました。「たまにしか更新されないけど見落としたくない」情報を管理するのにRSSリーダーって向いてますよね。

それPla

plugins:
  - module: Subscription::Config
    config:
      feed:
        - script:/home/miyagawa/tmp/domain-expire.pl
  - module: CustomFeed::Script
  - module: Publish::Feed
    config:
      dir: /home/miyagawa/public_html
      filename: domains.rss
      format: RSS

さっそく CustomFeed::Script つかった。CustomFeed::DomainExpire つくろうとしたけど Subscription でどうマッピングさせるとかメンドウだったのでこっちのほうがいいね。

domain-expire.pl はこんなの。

use strict;
use warnings;
use Net::Domain::ExpireDate;
use YAML;

my @domains = (
    'bulknews.net',
    'plagger.org',
    # ...
);

my $output = {
    title => "Expire dates for my domains",
    entry => [],
};

for my $domain (@domains) {
    my $expires = expire_date($domain);
    push @{$output->{entry}}, {
        title => $domain,
        date  => "$expires",
    };
}

print YAML::Dump $output;

せっかくだから RSS だけじゃなくて iCal にしてしまえ。

  - module: Publish::iCal
    config:
      dir: /home/miyagawa/public_html
      filename: domain.ics

f:id:miyagawa:20061006172104g:image

サーバにリスト突っ込んで 30boxes にインポートしておこう。

2006/10/05 (木)

[Plagger] Youtube の新着動画を監視 02:03  [Plagger] Youtube の新着動画を監視 - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] Youtube の新着動画を監視 - Bulknews::Subtech

YouTube で「和田アキ子」「しょこたん」で検索した結果を "Date Added" でソートして新着動画を IRC に通知

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://www.youtube.com/results?search_type=search_videos&search_query=%E3%81%97%E3%82%87%E3%81%93%E3%81%9F%E3%82%93&search_sort=video_date_uploaded&search_category=0
        - http://www.youtube.com/results?search_type=search_videos&search_query=%E5%92%8C%E7%94%B0%E3%82%A2%E3%82%AD%E5%AD%90&search_sort=video_date_uploaded&search_category=0
  # XXX EFT has CustomFeed::Simple asset too!
  - module: Filter::EntryFullText
  - module: Filter::Rule
    rule:
      module: Deduped
  - module: Notify::IRC
    config:
      ...

CustomFeed::YouTube でもいいけど EFT に内蔵されてる CustomFeed::Simple の asset 使うほうが Plagger っぽいかな。EFT をロ-ドすると大量に .yaml をロードするのは何とかしたいところではある。。。assets 問題と一緒に解決か。

2006/10/04 (水)

[Plagger] CustomFeed::Script 21:36  [Plagger] CustomFeed::Script - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] CustomFeed::Script - Bulknews::Subtech

ページが見つかりません。 - Plagger

CustomFeed::Script をコミット。詳しくは ページが見つかりません。 - Plagger にあるとおりなのだけど、script:/path/to/script というURL を subscription に追加することによって、そのスクリプトを実行して結果をパースすることができる。結果は RSS/Atom もしくは CustomFeed::Debug 互換の YAML としてパース。

youpy さんの CustomFeed::Pipe とアイデアはほとんど同じだけど、結果をフィードとして丸ごと取り出す、というところが異なる。つまり、

  • 既存の hogehoge2rss みたいなツールを、(出力先を STDOUT にするだけで)そのまま利用できる。Netnewswire, endo, newspipe などでこうしたスクリプトが使えるらしい。
  • Python, Ruby など他の言語でスクレイプツールをつくって、RSS または YAML で出力することも可能

といった感じ、使い方は簡単で、

plugins:
  - module: Subscription::Config
    config:
      feed:
        - script:/path/to/scraper.pl
  - module: CustomFeed::Script

とするだけ、引数を渡したければ、

script:/path/to/scraper.pl 'argument one' arg2

のようにもできるし、Windows なら

script:perl.exe /path/to/script

のようにも。

サイトごとに CustomFeed::* を書く気力が若干失せる(というのは Plagger の方針としては歓迎)というウワサもありますが、スタンダロンのツールをそのまま利用できるのはかなりうれしいんじゃないかと。

[Plagger] EntryFullText 文字化け 17:53  [Plagger] EntryFullText 文字化け - Bulknews::Subtech を含むブックマーク はてなブックマーク -  [Plagger] EntryFullText 文字化け - Bulknews::Subtech

Plagger中級

WinのActivePerlなんだけど、Filter-EntryFullTextのプラグインで日本語がうまく使えない…。

どうすれば、うまく出来るようになるんだろうか…。

文字化けするサイトの例を書いてほしい。あと、Win32 なら Encode::Detect がインストールされているかどうかをチェック。なければ http://ppm.tcool.org/ から。