Monthly Archive for November, 2007

TwitterBot by Ruby

This tutorial describes how to write your own Twitter bot by Ruby.

Plan

  • Recieves DirectMessages, parses them and sends back responses.
  • Keeps on being connected in Twitter via Jabber protocol.
  • Written in Ruby !

Preparation

Twitter account

You need a twitter account for your bot.

Jabber ID

You need a Jabber ID for your bot to sit in Twitter. I use Jabber.JP service (free!), but you can choice whatever Jabber service you like.

If you use a GMail address for your bot, you can skip above step. (I could not connect to GTalk by GMail sub account, so took a different way)

Requirements

Code

#  Tiny Twitter Bot.
#
require 'rubygems'
require 'xmpp4r'
require 'kconv'
 
class Reciever
  attr_accessor :client
 
  # user : Jabber ID
  # pass : Password
  def initialize(user, pass)
    @end = false
    Jabber::debug = true
 
    # connect Jabber client to the Server
    @client = Jabber::Client.new(Jabber::JID.new(user), false)
    @client.connect
    @client.auth(pass)
    @client.send(Jabber::Presence::new)
 
    thread = Thread.current
 
    # a callback to parse recieved messages
    @client.add_message_callback do |message|
      unless message.type == :error
        if message.body =~ /Direct from (.*):/ # who sends DirectMessage ?
          sender = $1
          msg = message.body.split(/\r?\n/)
          msg.shift # cut Direct from ...
          msg.pop # cut last line, too
          body = msg.join
 
          #
          # do whatever you like in following lines :)
          #
          if body =~ /!abort/ # finish if told 'abort'
            @client.send(Jabber::Message::new(message.from, "d #{sender} aborting...").set_type(:chat))
            thread.wakeup
          else
            # it just echoes in this example
            xxx = Kconv.toutf8("d #{sender}\n#{message.body}")
            @client.send(Jabber::Message::new(message.from, xxx).set_type(:chat))
          end # if body
        end # if direct
      end # unless error
    end # callback
 
    @watcher = Thread.new do
      while not @end
        # saying "I'm alive!" to the Jabber server
        @client.send(Jabber::Presence::new)
        sleep 30
      end
    end
  end
 
  def close
    @client.close
    @end = true
    @watcher.join
  end
end # Reciever

After that, the only step remains is to create this Reciever class instance from main routine. To kill the bot, send Ctrl-C from the command line.

Let’s do some neat hacks at the lines parsing body by regexp.

Auto Follow

You need to follow your bot.

You may want your bot to counter-follow you automatically. I wrote a simple Procmail recipe and a tiny Ruby script. (original idea is にぽたん研究所::Twitter でイチイチ follow するのが面倒くさい

Procmail recipe

.procmailrc:

:0
* ^To:.your@bot.address
| counter_follow.rb

Ruby script to follow

counter_follow.rb:

#!/opt/local/bin/ruby
require 'open-uri'
 
ID = 'jabber bot ID'
PASSWORD = 'jabber bot password'
 
msg = ARGF.read
msg =~ /\s+http:\/\/twitter.com\/(\w+)$/
screen_name = $1
exit 1 unless screen_name
 
auth = {'Authorization' => 'Basic '+[ID+':'+PASSWORD].pack('m')}
open('http://twitter.com/friendships/create/'+screen_name+'.json', auth)

Usage

  1. Follow your bot from you Twitter account.

    follow bot_account

  2. Send a DirectMessage to your bot.

    d bot_account hello bot !

Conclusion

Wrapped up a recipe how to create a tiny Twitter bot.

There were some pitfalls (it can hang up if you don’t send messages in ‘chat type’, cannot get any responses if you send something periodically, or …) in creating Twitter bot. I hope this tutorial help someone creating their own Twitter bot.


Any feedbacks make me happy :)

WP CalendarCloud plugin

よくあるタグクラウドのカレンダー版をつくりました。 ただずらっと年月のリストがあるよりも、ちょっとばかりは見た目が楽しくなるんではないでしょうか。

WordPressのCustom Template Tag として実装してあります。 CodeReposに置いておきました

実際に動いているものが、このサイトのサイドバー、アーカイブのところにあります。 詳しくは、こちらをご覧ください。


明日以降に、WordPressのplugin レポジトリにも登録できないか調べてみます。今日はもう寝なきゃなので…

WordPress CalendarCloud plugin

What ?

A WordPress TemplateTag plugin that displays yearly calendars containing 12 months weighed by their post counts, like Tag Cloud.

Example

and, live demo is placed in the sidebar of this blog.

Download

calendar_cloud.zip (20KB)

Install

  1. Upload and unzip calendar_cloud.zip to the /wp-content/plugins/ directory
  2. Activate the plugin through the ‘Plugins’ menu in WordPress

Use css to customize look & feel. See an example in style.css.

Usage

put following line in your template:

<?php calendar_cloud(); ?>

ChangeLog

  • 0.2 : accordance with WordPress Coding Standard.
  • 0.1 : initial release.

Feel free to send any feedbacks.

cmd2twitter

コマンドラインの入力をすべてTwitterにpostするコマンドを、思いつきで作りました。 chatty を改造しています。

コード

に置いてあります。

使い方

make して、

./cmd2twitter <twitterのユーザ名> <パスワード>

として、あとは、ふつうにlsとかcdとか打ち込んでると、自分のTimelineに同じものがpostされてます。 終わるときは、Ctrl-Dとかで。

必要なもの

  • cURL : 最近のUnixなシステムには付いていると思います。

ToDo

  • TwitterにpostしたあとのJSON出力がうっとうしいので消す (> /dev/nullすればよいかな)
  • curlでpostするときに待たされる遅延がうっとうしいので非同期化する
  • 自分のTimelineに出てくるのはうっとうしいので、Twitter botをたててDirectMessageする

詳しくは CodeRepos::Share::cmd2twitterにて。

Mac miniな自宅サーバでのApacheとメモリ

RubyでTwitter bot を書くがプチ人気になって、突発的にアクセス数が増えました。ありがたいことです。

そうこうしてるうちに、Mac miniで動かしてるサーバからの応答がぷっつりになってしまいました。リビングに行ってみると、HDDがガリガリガリと鳴り続けてます。ああ、いつものスラッシングか、と。ApacheLogPatchをつくったときなんかも、同じことが起こってました。でもあきらめて電源ブチっとしてました。なんという…

今日は一念発起して、なんとかすることにしました。いつまでも電源ブチでは壊れてしまいます。

状況確認

なにが起こってるかをtopで確認してみます。

slashing Mac OS X

512MBしかメモリのないMac miniで、504MBが使用中になっており、いかにもslashingです。

Apache restart

ひとまず、止めてしまおうと

% apachectl restart

と打ってみたのですが、いっこうに返ってきません…

状況確認 2

% ps xa |grep httpd | wc

してみたら、60くらいのhttpdがいることが分かりました。

1つのhttpdが使うメモリが8〜10MBだとすると、合計で480〜600MBのメモリが必要になってしまい、総容量を越えてしまう、というわけでした。

Apacheの設定を見直す

同時接続プロセス数が多いのが原因だと分かったので、制限してみます。

@IT::httpd.confによるWebサーバの最適化 という記事を読んで、MaxClientsというものを指定すればよいことを知りました。なるほど。 うちの場合は、だいたいhttpdにさける総メモリを450MB、1つのhttpdが使うメモリを10MBと見積もって、450/10 = 45 clients と算出しました。

MacPortsで入れているApache2の設定ファイルで、conf/extra/httpd-mpm.conf というものをincludeするようにして、

<ifModule mpm_prefork_module>
    ....
    MaxClients           45
    MaxRequestsPerChild   4098
</ifModule>

としておきました。

まとめ

自宅サーバはラクじゃないね。

おまけ

Mac OS Xで、コマンドラインから動いているプロセスの使用メモリを見る方法を、top以外にこれまで知らなかったのですが、man psしてみたところ -vとか-uをつければよいと知りました。メモリ消費量でソートするには-mをつけると。

無理なく続けられる 年収10倍アップ勉強法

無理なく続けられる 年収10倍アップ勉強法

最近気づいたのですが、僕はどうもでっぷり太ったガリ勉くんのようです。 本はたくさん読むし、feedも日々読み流してる (LDRの購読feed数は191) んだけど、どうも身についてる気がしない。読み終わって、再読reviewのキューに突っ込んでる本は、どう見てももう50冊は下りません。

そんなわけで勉強法に困ってはいないのですが、話題だったので無理なく続けられる 年収10倍アップ勉強法 を読んでみました。話題とか流行とかに弱すぎる自分。 で、感想とかはすっとばして、この本の影響で自分が変わったことを書いてみます。

AudioBook

耳からの積極的なinputを試してみることにしました。 今ぼくのiPod shuffleには、Who Moved My Cheese ?The 7 Habits of Highly Effective People、そして音簿記三級入門 しか入っていません。No Music, More Study なのです。

会計の勉強

ちょうど、家計簿Webアプリをつくろうとしていることもあり、簿記の勉強を始めました。 妻が三級を持っており、参考書はたくさんあるのではじめやすかった。

自分の言葉で語る

inputはoutputのためにあると。むしろ、output drivenなinputをすることにします。 ウェブ時代をゆくにもありましたが、知的生産はoutputしてはじめて完結するのです。


ということで、読んで感じたことをできるだけ自分の言葉で語ってみました。

RubyでTwitter bot を書く

TwitterTimeTrackというものをちょっと前につくって、 自分ではけっこう便利に使っています。 Twitterからbotに対してメッセージを投げると、あとでiCalendar形式で取ってこれる、というものなのですが、 今回はここでも使っているTwitterのbotを書く方法を書いてみます。

方針

  • ダイレクトメッセージを受けとり、内容をパースして応答を返す
  • botはJabberでTwitterに接続して常駐
  • Rubyで

準備

Twitter アカウント

bot用のTwitterアカウントを用意します。

Jabber ID

botがTwitterに常駐するために、Jabber IDが必要です。 ここでは、Jabber.JPを使わせてもらうことにしました。

GMailのメールアドレスが使える場合には、Jabber IDを別にとる必要がないのでお手軽です。 しかしGMailのサブアカウントではGTalkに接続できなかったので、今回は別の方法をとりました。

ライブラリ

コード

# 簡単なTwitter bot
#
require 'rubygems'
require 'xmpp4r'
require 'kconv'
 
class Reciever
  attr_accessor :client
 
  # user : Jabber ID
  # pass : パスワード
  def initialize(user, pass)
    @end = false
    Jabber::debug = true
 
    # Jabber クライアントをサーバに接続
    @client = Jabber::Client.new(Jabber::JID.new(user), false)
    @client.connect
    @client.auth(pass)
    @client.send(Jabber::Presence::new)
 
    thread = Thread.current
 
    # 受信メッセージをパースするコールバック
    @client.add_message_callback do |message|
      unless message.type == :error
        if message.body =~ /Direct from (.*):/ # DirectMessage が誰からのものか
          sender = $1
          msg = message.body.split(/\r?\n/)
          msg.shift # Direct from ... を削る
          msg.pop # 末尾の行も削る
          body = msg.join
 
          #
          # ここからあとで、自分の好きなことをする :)
          #
          if body =~ /!abort/ # abort といわれたら終わる
            @client.send(Jabber::Message::new(message.from, "d #{sender} aborting...").set_type(:chat))
            thread.wakeup
          else
            # ここでは単にechoするだけ
            xxx = Kconv.toutf8("d #{sender}\n#{message.body}")
            @client.send(Jabber::Message::new(message.from, xxx).set_type(:chat))
          end # if body
        end # if direct
      end # unless error
    end # callback
 
    @watcher = Thread.new do
      while not @end
        # 自分の生存をJabberサーバにアピール
        @client.send(Jabber::Presence::new)
        sleep 30
      end
    end
  end
 
  def close
    @client.close
    @end = true
    @watcher.join
  end
end # Reciever

このRecieverクラスをmain側からつくってやればできあがり。 終了するときは、Ctrl-Cとかで。

bodyを正規表現でパースしてるとこで、自分の好きなことを書いてやればよいでしょう。

自動Follow

botにメッセージを送るためには、自分のアカウントから

にぽたん研究所::Twitter でイチイチ follow するのが面倒くさい のRuby版を書き、.procmailrc に

:0
* ^To:.*2c@deadbeaf.org
| counter_follow.rb

とかしています。

Ruby版

#!/opt/local/bin/ruby
require 'open-uri'
 
ID = 'jabber bot ID'
PASSWORD = 'jabber bot password'
 
msg = ARGF.read
msg =~ /\s+http:\/\/twitter.com\/(\w+)$/
screen_name = $1
exit 1 unless screen_name
 
auth = {'Authorization' => 'Basic '+[ID+':'+PASSWORD].pack('m')}
open('http://twitter.com/friendships/create/'+screen_name+'.json', auth)

使い方

  1. いまつくったbotアカウントをfollowします。

    follow bot_account

  2. botアカウントに対してダイレクトメッセージを投げます。

    d bot_account hello bot !

まとめ

簡単なTwitter botづくりのレシピをまとめました。

つくってみると、いろんなバッドノウハウ (送信するメッセージはchat typeじゃないとおかしくなる場合がある、 定期的に何かメッセージを投げないと、応答しなくなる) にぶちあたるので、自分で何かbotをつくてみようかと考えている方の参考になれば幸いです。

もっと良い方法があるよ! とか、分かんないよ! とか、添削してやるぞ! とかあればよろしくお願いします。

Real UNIX MAGAZINE Day

REAL UNIX Magazine day Real UNIX MAGAZINE Day に行ってきました。


和田さん

Keynote Speech その1 : 私のプログラム書法

といいつつ、数学的な問題をLispで解く90分。 モチーフは、

  • howmany0s : 東大の研究室内でやってるプログラミングコンテストからの話題
  • 多面体 : TAOCP ex 7.2.1.2-60

メモ

  • 数学の教授然としたたたずまい
  • if expression considered harmful : if文もgotoみたいなもんで、制御が飛んでしまうのでなるべく使わないこと。minとかmaxとかのハイレベルなものを使い、実際の条件分岐は見えないとこに押し込める
  • Knuth のプログラミングは goto-oriented
  • ベル研のJournalは、とてもいい匂いがする
  • Lispでエレガントに書くには? → 書き続け、考え続ける。こうやって書けるようになるのに、一生かかってる
  • 膨大なイディオムやライブラリを、どうやって探すのか、知るようになるのか? → 書き続けること。だれかの後ろにたって、やってるのを見る。人の仕事、コードを読む。どんどん交わること
  • Haskellや膨大なライブラリ : ドイツ語のようなもの。学習に多大な時間がかかるけど、一度できるようになればあとは天国が待ってる
  • 徒弟制度はいい → でもものすごい大変である。ケンブリッジやオックスフォードにはまだチュータ制度ってのがあって、あれは大したものだ。生しごき
  • エレガントで分かりにくい VS 愚直だけど分かりやすい → エレガントかつ分かりやすいのが理想で、Dijkstraはそれを実践しててすごい。分かりやすさのためには、identificationが重要。変数名、関数名が分かりやすいと、理解しやすい

岸田さん

哲学、思想から現在のソフトウェア開発事情を読み解く。 温故知新マッシュアップ。

いろんなジャンルの知識を貯め込んでおいて、自分の専門範囲に活かすのがだいじだと思った。

LT

  • 歌代さん : SL開発秘話。logoutせずに席を離れるとプロンプトを遊び倒されるのが流行った80年代について
  • 手塚さん : いろんな壁。どこにでも壁はあるもんだなぁと
  • 竹迫さん : GIF89a。会場のオールドタイプな面々からも感嘆の声が漏れていた
  • 半田さん : いまどきのEmacs。sliced imageおもしろい。15パズルとかに使えるんじゃないかな。GDBインターフェイスは、Eclipseみたいになっててすごかった。Vimでもできないもんかな。
  • 大江さん : 電波Hack。Pythonと電波は相性よいと。電波をそのままIPで流すとテラ帯域食われるわけなので、適材適所だよなーという気がする。電波で受けとったものをIPでリピートしなくても、みたいな
  • 石曽根さん : Luaについて。会場の80%が帰ってLuaに興味を持つことが1つの目的と。使ってみようと思います。以前に1度挫折してるんだよな
  • 高岡さん : 今回、すげえ感が1番あった人。gcc/binutilsが使えない状態で、toolchainがあるかのように上位をだましていくとか、すごすぎた。KMCは偉大だ。Linuxはぜんぜんportableじゃなくて,longとかtypeofとかつかうな、とか
  • 島さん : irobotd。掃除ロボットルンバのロボット部だけが売られてて、SDKもある。んじゃNetBSDな脳みそをボードでつけて無線で知的ラジコンみたいにしようぜ、みたいなガジェット話。inetdを見直した
  • 増井さん : 最近つくってるWebアプリをいくつか紹介。Leopardの一番の売りはモザイクスクリーンセイバー。今やってみたけど、たしかにすごすぎる
  • 首藤さん : プロプライエタリなライブラリをいかにしてうまく使うか。力技で%esp書き換えとかおもしろかったんだけど、真の解決編はomitted
  • 山口さん : なぜかスーツ。最近はPDFの脆弱性が、クロスプラットフォームだけに影響でかい、とか

やっぱしLTは盛り上がりますね。制約があるからこそなのかも。

パネルディスカッション (OS)

  • 大学教授は、まず160万用意しよう

佐藤さん@BSD

  • BSD is dying … but
  • BSDをいま使ってる人は、昔からの人で、手に馴染んでるからってのが大きい
  • これからは、GPLを嫌う組込み系にもアプローチ
  • クライアントOSとしてはちょっと。サポートの弱さがつらい。企業サポートがなかなか育ってない
  • サーバ性能は良いので、そっち方面でがんばっていきたい

鵜飼さん@Linux

  • Debianのこれまでについてあれこれ。
  • Hackできない環境が蔓延しないよう、フリーソフトを開発し続けよう

篠田さん

  • StarBED (インターネットシミュレータ) は、誰でも使えます。
  • 仮想化を駆使してます
  • BSDの安心感 : 裏で何が起こっているかが分かるとこ、かな

山口さん@セキュアOS

  • 書いていいか微妙
  • ハイパーバイザーのコストはどれくらいなんだろう?

全体

  • 年齢層高め。30歳未満は確かに少なそうでした。自分はギリそっち側ですが
  • IIJのオフィスがとてもきれいで羨んだ
  • 各自が好きなことを好きなように話すという、いつに増してギークな雰囲気。まとまらない感じがユニマガっぽいかも

自分の目的だった、「活字の向こうのひとびとのリアルな姿を知る」ということは達成できたので満足でした。みなさんパワーあるなあ。自分も見せれるものつくってかないと。