読者です 読者をやめる 読者になる 読者になる

( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

java-ja温泉成果物 @で話しかけるとsayコマンドでしゃべるbot

java-ja温泉ではsayコマンドで盛り上がってました。
んで、"@saybot hogehoge"のように@をつけて話しかけると、sayコマンドでしゃべるbotscalaで書いてみました。


Runtime#execでsayコマンドを実行しているので、このbotが動いているマシンでしかしゃべらないです。
つまり、オレのマシンです。

import scala.actors._
import java.lang.Thread

import java.net.{Authenticator, PasswordAuthentication}
import java.net.{URL, HttpURLConnection}
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.Calendar

import scala.xml.XML 
import scala.util.matching._

object SayBot extends Application{

  // Replyを取得する間隔(millsec)
  val INTERVAL = 60 * 1000
  
  val twitterId = "saybot"
  val twitterPass = "******"
  
  Authenticator.setDefault(
    new Authenticator {
      override def getPasswordAuthentication = {
        new PasswordAuthentication(twitterId, twitterPass.toCharArray);
      }
    }
  )
  
  val url = "http://twitter.com/statuses/replies.xml"
  
  
  // Actor
  object SayActor extends Actor{    
    
    // 前回Replyを取得した時刻
    var cl:Calendar = Calendar.getInstance
    cl.add(Calendar.HOUR_OF_DAY , -9)
    var lastTime = cl.getTimeInMillis
    
    def act = {
      getReplies
      Thread.sleep(INTERVAL)
    }
    
    // Replyを取得する
    def getReplies(){
      val df = new SimpleDateFormat("EEE MMM dd HH:mm:ss +0000 yyyy", Locale.US)
      
      println( "getReplies " + lastTime + ":" + df.format(lastTime))

      val urlConn = new URL(url).openConnection.asInstanceOf[HttpURLConnection]
 
      urlConn.connect();
      urlConn.getResponseCode
      
 
      for (s <- XML.load(urlConn.getInputStream) \ "status" reverse ;
           created_at = s \ "created_at" text ;
           time = df.parse(created_at).getTime if(time>lastTime)) {
         
        var (text, user_name) = (s \ "text" text, s \ "user" \ "name" text)
        
        println( user_name + ":" + text )
        lastTime = time
        
        val r = new Regex("@" + twitterId + "\\s(.+)$")
        r.findAllIn(text).matchData.foreach( i=>{ 
          say( i.group(1) )} 
        )
      }
      
	}
	  
    // sayコマンドを実行する
	def say( message :String){
	  var rt:Runtime  = Runtime.getRuntime
      rt.exec( "say " + message)
      // とりあえず文字数×0.5secだけsleep
      Thread.sleep( message.length * 500)
	}
  }
  
  while( true ){
	  SayActor.act
  }
  
}


idとpasswordをちがうアカウントにすれば使えるようになるはずです。

まぁ、ぶっちゃけかなりショボいコードです。
まず日本語はダメです。そのうちyahoo日本語係り受け解析とかでヨミを解析してしゃべるようにするかも。


ホントはActorライブラリの勉強だったんだど、まったくActorを使う意味がないコードになっています。
あと、Replyが複数あると声がかぶるとか。例外処理ちゃんとやってねぇとか。