標準入力をtwitterにpostするコマンドを書いた

未だスマートフォンではない携帯を持っているのですが、外出時に twitter をするためにちょっとしたツールを書いてみました。標準入力に入れられたメールの文面を twitter に post します。

sendmail の aliases に

yourstream2twittermailaccount: |/some/where/stream2twitter.pl

のように書いてメールを送ることを想定しています。なのでサーバを持っていない人には使い道がないかもしれません。

% ./stream2twitter.pl < mailbody

直接流し込むことも出来ます。


動作させるためには各種認証キーが必要なので
http://tech.bayashi.jp/archives/entry/perl/2010/003016.html
を参照してください。
# ここのスクリプトを元にしています


以下から取得できます。
http://github.com/masanorih/stream2twitter


添付がなければ普通に twitter に post、添付があればファイルを twitpic にアップロードします(それが画像かどうかはみていません)。が、WWW::Twitpic が生のパスワードを要求するので使用する場合は注意してください。twitpic の新しい認証に対応した CPAN module が見つからなかったので誰かあったら教えてください。

FreeBSD 7.2-RELEASE 時代の PPPoE 設定

FreeBSD マシンを PPPoE でブロードバンドルータにする手順。"FreeBSD PPPoE" とかで検索に引っかかるページは若干記述が古いのですが、FreeBSD 7.2-RELEASE ではこんなに簡単に(GENERIC kernel で)設定出来ます。ちなみに使っているモデムは NEC atermOEM です。
dhcpd は別途必要かも。

/etc/ppp/ppp.conf を設定

default:
 set log Phase Chat LCP IPCP CCP tun command
 set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
 set MRU 1454
 set MTU 1454
 enable dns
 set timeout 0

your_profile:
 set device PPPoE:your_interface
 set authname your_name@isp
 set authkey your_password
 set dial
 set login
 add default HISADDR

各設定項目ですが、以下のような意味です。

your_interface : NIC の認識名。if0 とか dc0 とか
your_profile   : プロファイル名はわかりやすければ何でも良い
                 ISP 名でとかで
your_name@isp  : ISP からもらってる接続ID
your_password  : ISP からもらっている接続IDのパスワード

あなたの接続環境にあわせて設定してください。

/etc/rc.conf に以下を追加

# config for PPPoE
ppp_enable="YES"
ppp_mode="ddial"
ppp_nat="YES"
ppp_profile="your_profile"

そして reboot して、/var/log/ppp.log を眺めて確認する。インターネットから直接パケットを受けとることになるので firewall とかフィルタの設定はちゃんとしましょうね。

AnyEvent::Socket で簡単な echo サーバを書く

AnyEvent の勉強がてら、簡単な echo サーバを書いてみた。只の echo サーバではつまらないので返事をする度に数値をインクリメントして付与するようにしてみる。

#!/usr/local/bin/perl

use warnings;
use strict;
use AnyEvent;
use AnyEvent::Socket;

tcp_server undef, 12345, sub {
    my( $fh, $host, $port ) = @_;
    warn "connect from $host:$port\n";
    add_client($fh);
};

sub add_client {
    my $fh = shift;
    my $i  = 0;
    my $poller; $poller = AnyEvent->io(
        fh   => $fh,
        poll => 'r',
        cb   => sub {
            my $r = sysread $fh, my $buf, 1024;
            # got EOF
            if ( 0 == $r ) {
                undef $poller;
                return;
            }
            $i++;
            syswrite $fh, "($i):$buf";
        }
    );
}

AnyEvent->condvar->recv;

サーバを起動して、繋いでみる。

% telnet localhost 12345
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
aaa
(1):aaa
bbb
(2):bbb
ccc
(3):ccc
ddd
(4):ddd
eee
(5):eee
^]close
telnet> close
Connection closed.

もう一回

% telnet localhost 12345
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
aaa
(1):aaa
ddd
(2):ddd
rrr
(3):rrr
qqq
(4):qqq
^]close
telnet> close
Connection closed.

AnyEvent のコード量の少なさと書きやすさは異常かも。

Notify::Gtk2Notify

Notify::Growl のほぼコピペで Gtk2::Notify で通知する plagger の plugin を書いてみました。手元の Ubuntu 9.04 jaunty では問題なく動きます。

package Plagger::Plugin::Notify::Gtk2Notify;
use strict;
use base qw( Plagger::Plugin );
use Gtk2::Notify -init, "plagger";

sub register {
    my($self, $context) = @_;

    $context->register_hook(
        $self,
        'publish.entry' => \&entry,
    );
}

sub entry {
    my($self, $context, $args) = @_;

    my $notify = Gtk2::Notify->new(
        $args->{entry}->title,
        $args->{entry}->body_text
    );
    $notify->show;
}

1;

DNS client を自作する

可能な限り CPAN mobule に依存する + rawsocket という条件付きで DNS client を Perl で書いてみた。

#!/usr/local/bin/perl

use strict;
use warnings;
use IO::Interface::Simple;
use IO::Socket::INET;
use Net::DNS::Packet;
use Net::RawIP qw(:pcap);
use App::Options(
    values => \%ARGV,
    option => {
        name => {
            type     => 'string',
            required => 1,
        },
        ns => {
            type     => 'string',
            required => 1,
        },
        type => {
            type    => 'string',
            default => 'A',
        },
        localport => {
            type    => 'int',
            default => 53,
        },
    },
);

# get local address from interface
my $saddr;
my @interfaces = IO::Interface::Simple->interfaces;
for my $if (@interfaces) {
    if ( not $if->is_loopback and $if->is_running and $if->is_broadcast ) {
        $saddr = $if->address;
        last;
    }
}

my $server = IO::Socket::INET->new(
    Proto     => 'udp',
    LocalPort => $ARGV{localport},
);
my $dns_query = Net::DNS::Packet->new( $ARGV{name}, $ARGV{type}, 'IN' );
my $udp = Net::RawIP->new( { udp => {} } );
$udp->set(
    {
        ip => {
            saddr => $saddr,
            daddr => $ARGV{ns},
        },
        udp => {
            source => $ARGV{localport},
            dest   => 53,
            data   => $dns_query->data,
        },
    }
);
$udp->send;

$server->recv( my $msg, 65535 ) or die "recv failed : $!\n";
my $dns_response = Net::DNS::Packet->new( \$msg );
print $dns_response->string;

実行するとこんな感じ

# ./dns_client.pl --name=d.hatena.ne.jp --ns=ns0.future-s.com
;; HEADER SECTION
;; id = 45073
;; qr = 1    opcode = QUERY    aa = 1    tc = 0    rd = 1
;; ra = 1    ad = 0    cd = 0    rcode  = NOERROR
;; qdcount = 1  ancount = 1  nscount = 2  arcount = 2

;; QUESTION SECTION (1 record)
;; d.hatena.ne.jp.      IN      A

;; ANSWER SECTION (1 record)
d.hatena.ne.jp. 86400   IN      A       59.106.108.77

;; AUTHORITY SECTION (2 records)
hatena.ne.jp.   86400   IN      NS      ns0.future-s.com.
hatena.ne.jp.   86400   IN      NS      ns1.future-s.com.

;; ADDITIONAL SECTION (2 records)
ns0.future-s.com.       600     IN      A       219.99.160.180
ns1.future-s.com.       600     IN      A       219.99.160.181

Ubuntu の mlterm を 256色にする

Ubuntu の mlterm を 256色にする、あるいは dpkg に patch をあてる方法

mlterm の 256color patch は http://d.hatena.ne.jp/shinichiro_h/20080313#1205334463 にあります。

source を展開して、patch をあてる

% apt-get source mlterm
% patch -p0 < /some/where/mlterm-2.9.4_256.patch

このまま install すると後で update-manager に未 patch のものを再 install されてしまう(正確には毎回 update 候補に出てくる)。それを回避する為には build する前に mlterm-2.9.4/debian/changelog の version を increment しておく必要がある。

% vi mlterm-2.9.4/debian/changelog
mlterm (2.9.4-2) unstable; urgency=medium

  * Apply 256 color patch
    http://d.hatena.ne.jp/shinichiro_h/20080313#1205334463

 -- Masanori Hara <hogehoge@hogehoge.hoge>  Tue, 17 Jun 2008 02:04:41 +0900

適当になんか書いておく。

build & install

% sudo apt-get build-dep mlterm
% apt-get --build source mlterm
% sudo dpkg -i mlterm*.deb

これで mlterm は 256color で使える。Ubuntu で source に patch をあてるのは簡単なんだけど、dpkg と共存するのはなんか大変。Debian とか知らなさすぎなだけかな。