転職しました。
超久方ぶりの更新です。もう誰も見てる人いないだろうなあ・・・
私事になりますが、タイトルの通り転職しました。
2月初めから新しい会社で働き始めています。
新しい会社は社員20名弱のベンチャーで、オープンソースのソフトウェアを開発したりしてるとこ。
残念ながら言語はPerlじゃなくPHPなんですが、憧れのwebの仕事ができ、
毎日ワクテカする日々を送っております。
今は結構忙しくてなかなか時間が取れませんが
隙を見てぼちぼち更新再開したいものですね。
■ベンチャー企業に入社して気づいたこと
ベンチャーの中の人はみんな暗黒面!暗黒面!とか言ってたり、
ライトセイバーを振り回してたりするのかと思ったらそうでもなかった。
でもバランスボールはある。
Plugin::Widget::CPAN
entryのbodyにPerlのモジュールらしきものがあったらCPANへの検索リンクをつけたすWidget。
package Plagger::Plugin::Widget::CPAN;
use strict;
use base qw( Plagger::Plugin );
use Encode;
use HTML::Entities;
use URI;
sub register {
my($self, $context) = @_;
$context->register_hook(
$self,
'publish.entry.fixup' => \&add,
);
}
sub add {
my($self, $context, $args) = @_;
$args->{entry}->add_widget($self);
}
sub html {
my($self, $entry) = @_;
return unless ( $entry->body =~ /([a-z]+?::[a-z]+)/i );
my $module = $1;
my $uri = URI->new('http://search.cpan.org/search');
$uri->query_form(
query => $module,
mode => $self->conf->{mode} || 'all',
);
my $url = HTML::Entities::encode($uri->as_string);
return qq(<a href="$url"><img src="http://search.cpan.org/favicon.ico" alt="$module" style="border:0;vertical-align:middle" /></a>);
}
1; - module: Widget::CPAN
config:
mode: all, module, dist or author # default all
Pluginとconfigの一覧
/\$self->conf->{(.+?)}/で抜き出しただけなんで
変なのも混じってるし全部取れてないしconfigとmoduleが上下逆で見にくいことこの上ないけど
まあ参考程度に。
plugins:
-
module: Aggregator::Null
-
module: Aggregator::Simple
-
config:
max_redirect: ~
timeout: ~
use_cache: ~
xango_args: ~
module: Aggregator::Xango
-
module: Bundle::Defaults
-
config:
$directive: ~
description: ~
dir: ~
duration: ~
extra_rule: ~
scrubber: ~
stylesheet: ~
theme: ~
title: ~
url: ~
module: Bundle::Planet
-
module: CustomFeed::2chSearch
-
module: CustomFeed::AmazonAssociateReportJP
-
module: CustomFeed::BloglinesCitations
-
config:
$_: ~
entry: ~
module: CustomFeed::Debug
-
config:
api_key: ~
method: ~
params: ~
size: ~
module: CustomFeed::FlickrSearch
-
config:
feed_type: ~
fetch_body: ~
fetch_body_interval: ~
fetch_items: ~
livedoor_id: ~
show_icon: ~
module: CustomFeed::Frepa
-
module: CustomFeed::GoogleNews
-
config:
aws_associate_id: ~
aws_developer_token: ~
aws_locale: ~
duration: ~
library_path: ~
title_format: ~
module: CustomFeed::iTunesRecentPlay
-
config:
fetch_items: ~
module: CustomFeed::Mailman
-
config:
email: ~
feed_type: ~
fetch_body: ~
fetch_body_interval: ~
fetch_items: ~
password: ~
show_icon: ~
module: CustomFeed::Mixi
-
config:
mixi_tos_paranoia: ~
module: CustomFeed::MixiDiarySearch
-
module: CustomFeed::PerlMonks
-
config:
delete: ~
host: ~
username: ~
module: CustomFeed::POP3
-
module: CustomFeed::Script
-
module: CustomFeed::Simple
-
config:
fetch_items: ~
link: ~
reverse: ~
revision_from: ~
revision_to: ~
target: ~
title: ~
module: CustomFeed::SVNLog
-
config:
page: ~
query: ~
sort: ~
module: CustomFeed::YouTube
-
module: CustomFeed::FriendDiary
-
module: CustomFeed::FriendStatus
-
module: CustomFeed::RecentComment
-
module: Filter::2chNewsokuTitle
-
module: Filter::2chRSSContent
-
module: Filter::AtomLinkRelated
-
config:
destination: ~
prepend_original: ~
service: ~
source: ~
module: Filter::Babelfish
-
config:
text_only: ~
module: Filter::Base
-
module: Filter::BloglinesContentNormalize
-
module: Filter::BlogPet
-
config:
use_entry_title: ~
module: Filter::BreakEntriesToFeeds
-
config:
apikey: ~
module: Filter::BulkfeedsTerms
-
config:
link: ~
title: ~
module: Filter::CompositeFeed
-
config:
interval: ~
scrape_big_numbers: ~
module: Filter::Delicious
-
module: Filter::DeliciousFeedTags
-
config:
driver: ~
option: ~
module: Filter::Emoticon
-
config:
force_upgrade: ~
store_html_on_failure: ~
module: Filter::EntryFullText
-
module: Filter::ExtractAuthorName
-
module: Filter::FeedBurnerPermalink
-
module: Filter::FeedFlareStripper
-
config:
dir: ~
fake_referer: ~
module: Filter::FetchEnclosure
-
module: Filter::FindEnclosures
-
config:
timezone: ~
module: Filter::FloatingDateTime
-
config:
timezone: ~
module: Filter::ForceTimeZone
-
config:
languages: ~
target: ~
module: Filter::GuessLanguage
-
config:
conflict_policy: ~
use_ip_country: ~
module: Filter::GuessTimeZoneByDomain
-
module: Filter::HatenaBookmarkTag
-
module: Filter::HatenaBookmarkUsersCount
-
module: Filter::HatenaDiaryKeywordLink
-
module: Filter::HatenaDiaryKeywordUnlink
-
module: Filter::HatenaFormat
-
module: Filter::HatenaKeywordTag
-
module: Filter::HEADEnclosureMetadata
-
module: Filter::HTMLScrubber
-
module: Filter::ImageInfo
-
module: Filter::Kansai
-
module: Filter::LivedoorClipUsersCount
-
module: Filter::LivedoorKeywordUnlink
-
module: Filter::Markdown
-
config:
command: ~
encoding: ~
text_only: ~
timeout: ~
module: Filter::Pipe
-
config:
encoding: ~
proxy: ~
tempdir: ~
training: ~
module: Filter::POPFile
-
module: Filter::Profanity
-
config:
regexp: ~
module: Filter::Regexp
-
module: Filter::ResolveRelativeLink
-
config:
rewrite: ~
module: Filter::RewriteEnclosureURL
-
module: Filter::Romanize
-
module: Filter::RSSLiberalDateTime
-
module: Filter::RSSTimeZoneString
-
module: Filter::Rule
-
config:
add_report: ~
new: ~
spam_tag: ~
module: Filter::SpamAssassin
-
module: Filter::StripRSSAd
-
module: Filter::StripTagsFromTitle
-
config:
add_to: ~
module: Filter::TagsToTitle
-
module: Filter::tDiaryComment
-
config:
set_per_entry: ~
module: Filter::Thumbnail
-
config:
follow_redirect: ~
module: Filter::TruePermalink
-
module: Filter::TTP
-
config:
form: ~
module: Filter::UnicodeNormalize
-
config:
dnsbl: ~
rate: ~
module: Filter::URLBL
-
config:
dir: ~
fake_referer: ~
module: Filter::Curl
-
config:
concurrency: ~
dir: ~
fake_referer: ~
max_requests_per_host: ~
module: Filter::ParallelUA
-
config:
dir: ~
fake_referer: ~
module: Filter::Wget
-
config:
dir: ~
fake_referer: ~
max_redirect: ~
timeout: ~
use_cache: ~
xango_args: ~
module: Filter::Xango
-
module: Filter::Japanese
-
module: Namespace::ApplePhotocast
-
module: Namespace::HatenaFotolife
-
module: Namespace::MediaRSS
-
config:
filename: ~
play_enclosures: ~
player: ~
module: Notify::Audio
-
config:
encoding: ~
module: Notify::Balloon
-
config:
music: ~
module: Notify::Beep
-
config:
email: ~
speak_interval: ~
module: Notify::Campfire
-
config:
command: ~
module: Notify::Command
-
module: Notify::Eject
-
module: Notify::Growl
-
config:
charset: ~
daemon_host: ~
daemon_port: ~
module: Notify::IRC
-
config:
animation: ~
character: ~
position: ~
voice: ~
module: Notify::MSAgent
-
config:
source_netbios_name: ~
target_ip: ~
target_netbios_name: ~
module: Notify::NetSend
-
module: Notify::OpenBrowser
-
config:
host: ~
options: ~
port: ~
module: Notify::SSTP
-
config:
channel: ~
charset: ~
send_interval: ~
sender: ~
socketname: ~
use_notice: ~
module: Notify::Tiarra
-
config:
extended_ping: ~
url: ~
module: Notify::UpdatePing
-
module: Notify::iTunesMac
-
module: Notify::iTunesWin32
-
module: Notify::MSWin32
-
module: Notify::darwin
-
module: Notify::freebsd
-
module: Notify::linux
-
module: Notify::mswin32
-
module: Notify::darwin
-
config:
host: ~
port: ~
module: Notify::FirefoxRemote
-
module: Notify::freebsd
-
module: Notify::linux
-
module: Notify::mswin32
-
config:
default_anonymous: ~
dir: ~
module: Publish::2chdat
-
config:
encoding: ~
title: ~
work: ~
module: Publish::CHTML
-
config:
column: ~
dir: ~
encoding: ~
filename: ~
mode: ~
module: Publish::CSV
-
config:
expression: ~
module: Publish::Debug
-
config:
interval: ~
password: ~
post_body: ~
username: ~
module: Publish::Delicious
-
config:
filename: ~
module: Publish::Excel
-
config:
dir: ~
filename: ~
full_content: ~
module: Publish::Feed
-
config:
filename: ~
module: Publish::FOAFRoll
-
config:
attach_enclosures: ~
mailfrom: ~
mailto: ~
pop3: ~
module: Publish::Gmail
-
config:
interval: ~
password: ~
post_body: ~
username: ~
module: Publish::HatenaBookmark
-
config:
dir: ~
filename: ~
module: Publish::iCal
-
config:
folder: ~
module: Publish::IMAP
-
config:
dir: ~
filename: ~
module: Publish::JavaScript
-
config:
dir: ~
filename: ~
jsonp: ~
varname: ~
module: Publish::JSON
-
config:
interval: ~
livedoor_id: ~
password: ~
post_body: ~
module: Publish::LivedoorClip
-
config:
attach_enclosures: ~
module: Publish::Maildir
-
config:
blog_id: ~
password: ~
rsd: ~
title: ~
username: ~
module: Publish::MT
-
config:
blog_id: ~
mt_path: ~
rebuild: ~
title: ~
module: Publish::MTWidget
-
config:
filename: ~
module: Publish::OPML
-
config:
encoding: ~
filename: ~
module: Publish::OutlineText
-
config:
medoc: ~
path: ~
prefix: ~
module: Publish::PalmDoc
-
config:
dir: ~
filename: ~
module: Publish::PDF
-
config:
command: ~
encoding: ~
module: Publish::Pipe
-
config:
dir: ~
template: ~
theme: ~
module: Publish::Planet
-
config:
password: ~
username: ~
module: Publish::Playlog
-
config:
dir: ~
module: Publish::PowerPoint
-
config:
output_file: ~
module: Publish::PSP
-
config:
dir: ~
filename: ~
option: ~
serializer: ~
module: Publish::Serializer
-
module: Publish::Speech
-
config:
bgcolor: ~
body_size: ~
color: ~
dir: ~
font: ~
height: ~
linefeed: ~
title_size: ~
width: ~
module: Publish::SWF
-
config:
dir: ~
module: Publish::Takahashi
-
config:
pitch: ~
speed: ~
voice: ~
module: Publish::MacOSX
-
config:
voice: ~
module: Publish::Win32
-
config:
debug: ~
password: ~
timeout: ~
url: ~
username: ~
module: Search::Estraier
-
config:
dir: ~
module: Search::Grep
-
config:
invindex: ~
module: Search::KinoSearch
-
config:
dir: ~
index: ~
mknmz_opt: ~
module: Search::Namazu
-
config:
dir: ~
encode: ~
replace: ~
module: Search::Rast
-
config:
add_comment: ~
dir: ~
module: Search::Spotlight
-
config:
description: ~
id: ~
link: ~
title: ~
module: SmartFeed::All
-
config:
description: ~
id: ~
link: ~
title: ~
module: SmartFeed
-
config:
url: ~
module: Subscription::2chThreadList
-
config:
fetch_meta: ~
mark_read: ~
no_sync_api: ~
password: ~
username: ~
module: Subscription::Bloglines
-
config:
browser: ~
path: ~
module: Subscription::Bookmarks
-
config:
feed: ~
module: Subscription::Config
-
config:
connect_info: ~
schema_class: ~
module: Subscription::DBI
-
config:
url: ~
module: Subscription::Feed
-
config:
file: ~
module: Subscription::File
-
config:
url: ~
module: Subscription::FOAF
-
config:
group: ~
module: Subscription::HatenaGroup
-
config:
password: ~
username: ~
module: Subscription::HatenaRSS
-
config:
mark_read: ~
password: ~
username: ~
module: Subscription::LivedoorReader
-
config:
account: ~
module: Subscription::Odeo
-
config:
url: ~
module: Subscription::OPML
-
config:
fetch_items: ~
servers: ~
module: Subscription::PingServer
-
config:
$key: ~
feed: ~
lang: ~
module: Subscription::Planet
-
config:
path: ~
module: Subscription::PlanetINI
-
config:
xpath: ~
module: Subscription::XOXO
-
config:
url: ~
xpath: ~
module: Subscription::XPath
-
module: Subscription::InternetExplorer
-
config:
url: ~
module: Subscription::Mozilla
-
config:
path: ~
module: Subscription::Safari
-
module: Summary::Auto
-
module: Summary::English
-
module: Summary::HatenaBookmark
-
module: Summary::Simple
-
module: Summary::TextOriginal
-
module: Summary::TrackbackRDF
-
config:
credentials: ~
module: UserAgent::AuthenRequest
-
config:
$header: ~
module: UserAgent::RequestHeader
-
module: Widget::BloglinesSubscription
-
module: Widget::BulkfeedsSpamReport
-
config:
one_click_post: ~
tags: ~
module: Widget::Delicious
-
module: Widget::HatenaBookmark
-
config:
image_size: ~
use_filter: ~
module: Widget::HatenaBookmarkUsersCount
-
config:
widget: ~
module: Widget::Simple
Plugin::PhaseNotifier(2)
AUTOLOAD使わずに書き直してみた。
これでいいのかなー。
package Plagger::Plugin::PhaseNotifier;
use strict;
use base qw( Plagger::Plugin );
sub register {
my($self, $context) = @_;
my @hooks;
for my $hook ( keys %{ $context->{hooks} } ) {
my @plugins = map {
my $plugin = ref $_->{plugin};
$plugin =~ s/^Plagger::Plugin:://;
$plugin;
} @{ $context->{hooks}->{$hook} };
my $callback = sub {
my($self, $context, $args) = @_;
my $msg = "Phase: $hook / Plugins: " . (join ', ', @plugins);
$context->log(info => $msg);
};
push @hooks, $hook => $callback;
}
$context->register_hook(
$self,
@hooks,
);
}
1;あとはAggregater::Simpleのcustomfeed.handleをどうやって取るかだなあ。
Plugin::PhaseNotifier
なんとなく作ってみた。
現在のフェーズとそのフェーズで使われるPluginを教えてくれるPlugin。
こういう風にconfig.yaml書くと、
- module: Subscription::Config
config:
feed:
- url: http://d.hatena.ne.jp/tayaya/rss
- module: Publish::Gmail
- module: Notify::YahooMessenger
- module: PhaseNotifier
下のようにフェーズとPlugin名が表示される。
Plagger [info] plugin Plagger::Plugin::Subscription::Config loaded. Plagger [info] plugin Plagger::Plugin::Publish::Gmail loaded. Plagger [info] plugin Plagger::Plugin::Notify::YahooMessenger loaded. Plagger [info] plugin Plagger::Plugin::PhaseNotifier loaded. Plagger::Plugin::PhaseNotifier [info] Phase: subscription.load / Plugins: Subscription::Config Plagger [info] plugin Plagger::Plugin::Aggregator::Simple loaded. ・ ・ ・ Plagger::Plugin::Publish::Gmail [info] Sending qw/Perる 日誌/ to xxx@example.com Plagger::Plugin::Notify::YahooMessenger [info] Notifying qw/Perる 日誌/ to Yahoo Messenger Plagger::Plugin::PhaseNotifier [info] Phase: publish.feed / Plugins: Publish::Gmail, Notify::YahooMessenger
ソースはこんな感じ。
package Plagger::Plugin::PhaseNotifier;
use strict;
use base qw( Plagger::Plugin );
sub register {
my($self, $context) = @_;
my @hooks;
for my $hook ( keys %{ $context->{hooks} } ) {
my @plugins = map {
my $plugin = ref $_->{plugin};
$plugin =~ s/^Plagger::Plugin:://;
$plugin;
} @{ $context->{hooks}->{$hook} };
push @{ $self->{hooks}->{$hook} }, @plugins;
push @hooks, $hook => \&$hook;
}
$context->register_hook(
$self,
@hooks,
);
}
sub AUTOLOAD {
my($self, $context, $args) = @_;
(my $phase = our $AUTOLOAD) =~ s/^Plagger::Plugin::PhaseNotifier:://;
my @plugins = @{ $self->{hooks}->{$phase} };
$context->log( info => "Phase: $phase / Plugins: " . (join ', ', @plugins) );
$context->dumper($context) if $self->conf->{context};
$context->dumper($args) if $self->conf->{args};
}
1;
Publish::OOoWriter
OpenOffice.org Writerに出力するPlugin。
つくりかけ。
package Plagger::Plugin::Publish::OOoWriter;
use strict;
use base qw(Plagger::Plugin);
our $Version = '0.01';
use OpenOffice::OODoc;
ooLocalEncoding('UTF-8');
sub register {
my ($self, $context, $args) = @_;
$context->register_hook(
$self,
'publish.feed' => \&feed,
);
}
sub feed {
my ($self, $context, $args) = @_;
my $body = $self->templatize('oo.tt', { feed => $args->{feed} });
Encode::_utf8_off($body) if Encode::is_utf8($body);
my $filename = $args->{feed}->title . '.odt';
my $oo = ooDocument(
file => $filename,
create => 'text'
);
$oo->appendParagraph(text => $body);
$oo->save;
$context->log(info => "Save $filename");
}
1;oo.tt
[% feed.title_text %]
[% FOREACH entry = feed.entries %]
[% entry.title_text %]
Link: [% entry.permalink %]
by [% entry.author %]
[% entry.body_text %]
Posted on [% entry.date.format('Mail') %]
[% END %]
TODO
OpenOffice::OODocの使い方を調べる。
文字コード関連の処理がよくわからんので調べる。
テンプレート使わずに出力できるようにする。