ハイクに時報を自動投稿するスクリプト

ハイクに時報を投稿するだけのごく簡単なbotが生まれました。h:id:kalen_tにて喋っています。今後喋ることのバリエーションを増やすかどうかは未定。

紹介を兼ねて、現状のソーススクリプトを掲載します。Ruby初心者が見よう見まねで書いたものなので、変なところがあるかもしれませんし、あまり詳しい説明も付けていませんが、ご了承ください。

誤投稿を防ぐため、コマンドラインオプションを付けて起動しない限り実際にはハイクに投稿しないようになっています。

#!/usr/local/bin/ruby -Ks

#※開発環境はWindows XPです。

=begin
■開発日誌
◆2009-03-13
kalen_t の投稿テストを経て、時報としてとりあえず動きそう。

◆2009-03-14
起動・終了時メッセージと時報を投稿。
メニューから制作者による告知を投稿することもできる。
不意な投稿を避けるため、実際にハイクに投稿するかどうかを
コマンドラインオプションで指定できる(無指定だと投稿しない)。
=end

require "kconv"
require 'net/http'
require 'uri'
require 'cgi'
Net::HTTP.version_1_2

username = '(はてなID)'  #はてなのIDを入れます。
password = '(パスワード)'  #投稿用メールアドレスを入れます。ハイクAPIを参照のこと。
bot_name = 'nanashino_bot'

#コマンドライン引数を見て、実際にハイクに投稿するかどうか決める
if ARGV[0] == "p" then
  post_flag = true
  puts "■★★★投稿モードで起動します。★★★"
else
  post_flag = false
  puts "■投稿しないモードで起動します。"
end

#ハイクに投稿する関数
def post_haiku(username, password, message, bot_name, reply_id, post_flag)
  #投稿プレビュー
  puts " ◆投稿プレビュー\n" + message + "\nsource: " + bot_name + "\n"
  if reply_id != nil then
    puts "reply_id: " + reply_id
  end

  #パラメータをURLエンコードする
  params = 'status=' + CGI.escape(message.toutf8)
  params += '&source=' + CGI.escape(bot_name.toutf8)
  if reply_id != nil then
    params += '&in_reply_to_status_id=' + CGI.escape(reply_id.toutf8)
  end

  puts " ◆投稿プレビュー(URLエンコード後)\n" + params + "\n"

  #BASIC認証してはてなハイクにPOST
  if post_flag then
    puts ' ◆投稿中……'
    req = Net::HTTP::Post.new("http://h.hatena.ne.jp/api/statuses/update.xml")
    req.basic_auth(username, password)
    Net::HTTP.start('h.hatena.ne.jp', 80) {|http|
      response = http.request(req, params)
      #puts response.body.tosjis
    }
    puts ' ◆投稿が完了しました'
  else
    puts " ◆投稿しないモードなのでスキップします。"
  end
end

#起動時刻を取得
startup_day = Time.now

#起動時にメッセージを投稿
puts '■起動メッセージを投稿します。'
message  = "おはようございます。\n時報投稿スクリプトの試運転を始めます。"
post_haiku(username, password, message, bot_name, nil, post_flag)

#毎時0分に時報を投稿するスレッドを作成
#(メインメニューの処理と並行して裏で動き続けます)
t = Thread.new do
  puts '■0分待ち中……。'
  day = Time.now
  hour_prev = day.hour
  while true
    sleep(1)
    day = Time.now
    #puts day
    if day.hour != hour_prev then
      puts '■0分になりました。投稿します。'
      message  = day.hour.to_s + '時になりました。'
      post_haiku(username, password, message, bot_name, nil, post_flag)
      hour_prev = day.hour
      puts '■0分待ち中……。'
    end
  end
end

#メインメニュー
puts "■コマンド待機に入ります。"
puts " hコマンドでメニューを表示します。"

while true
  print ">"
  input_str = STDIN.gets  #ただのgetsだとコマンドライン引数を拾ってしまうので

  case input_str.chomp
  when "h"
    puts '■メニュー'
    puts ' h: このメニューを表示'
    puts ' q: プログラムの終了'
    puts ' m: ハイクに制作者からの告知を投稿'

  when "q"
    puts '■プログラム終了メッセージを投稿します。'
    
    #稼働時間を取得
    day = Time.now
    run_day = (day - startup_day).divmod(24*60*60)
    run_hour = run_day[1].divmod(60*60)
    run_min = run_hour[1].divmod(60)

    run_time = ""
    if run_day[0] != 0 then
      run_time += run_days[0].to_s + ""
    end
    if run_hour[0] != 0 then
      run_time += run_hour[0].to_s + "時間"
    end
    if run_min[0] != 0 then
      run_time += run_min[0].to_s + ""
    end
    run_time += run_min[1].truncate.to_s + ""

    message  = "そろそろ落ちます。\n今回の稼働時間は" + run_time + "でした。-"
    message  += "ありがとうございましたー。"
    post_haiku(username, password, message, bot_name, nil, post_flag)

    puts '■プログラムを終了します。'
    break

  when "m"
    puts "■制作者からの告知メッセージを投稿します。"
    puts "■メッセージを入力してください。"
    puts " 「-」のみの行を入力すると入力を終了します。"
    input_mes = ""
    while true
      input = STDIN.gets.chomp
      if input == "-" then
        break
      end
      input_mes += input + "\n"
    end

    #制作者という単語が出てくるとbotっぽくなるので「ますっ」とか言ってごまかす
    post_mes = "制作者より投稿されたメッセージを読み上げますっ。\n \n"
    input_mes.each_line { |line|
      post_mes += ">" + line
    }

    puts " ◆告知メッセージプレビュー\n" + post_mes
    puts "■yコマンドで投稿、それ以外でキャンセルします。"
    if STDIN.gets.chomp == "y" then
      message  = post_mes
      post_haiku(username, password, message, bot_name, nil, post_flag)
    else
      puts "■投稿をキャンセルしました。"
    end

  else
    puts "■未定義のコマンド: " + input_str
  end
end

参考にさせていただいたページのメモ。