Skip to content

Instantly share code, notes, and snippets.

@thowitt
Created February 13, 2012 23:36
Show Gist options
  • Select an option

  • Save thowitt/1821480 to your computer and use it in GitHub Desktop.

Select an option

Save thowitt/1821480 to your computer and use it in GitHub Desktop.
package io.alien.scalabot
import org.jivesoftware.smackx.muc.MultiUserChat
import org.jivesoftware.smack.packet.{Packet, Message}
import actors.Actor
import tools.nsc.InterpreterLoop
import java.io._
import org.jivesoftware.smack.{PacketListener, XMPPConnection}
import scala.tools.nsc.Settings
import tools.nsc.util.ScalaClassLoader
// Use responsibly -- don't connect this to public chat servers!
case class ReplBot(nick: String, pw: String, service: String, room: String = "", prefix: String = ">")
extends Actor with PacketListener {
override def start() = {
super.start()
try {
log("Connecting to %s...".format(service))
conn = new XMPPConnection(service)
conn.connect()
room.isEmpty match {
case true =>
log("Room not specified, so not joining.")
case false =>
log("Entering room %s...".format(room))
chat = new MultiUserChat(conn, room)
chat.addMessageListener(this)
log("Joining with nick %s...".format(nick))
chat.join(nick, pw)
}
new ReplThread().start()
} catch {
case e: Throwable =>
log("Failed to start: %s".format(e.getMessage))
quit()
}
log("""Chatting.""".format(nick))
log("""You can send these commands to the ReplBot Actor:""")
log(""" ! "quit" Disconnect and quit""")
log(""" ! "status" Print current status""")
log(""" ! "debug [on|off]" Print realtime activity""")
this
}
def act() {
loop {
react {
case Command(cmd) => handleCommand(cmd)
case Result(rslt) => handleResult(rslt)
case "quit" => quit()
case "status" => logStatus()
case Debug(onoff) => onoff match {
case "on" => debugging = true; log("Debugging turned on")
case "off" => debugging = false; log("Debugging turned off")
case wtf => log("""Unexpected regex match in Debug: %s""".format(wtf))
}
case wtf => debug("Discarding unknown message %s".format(wtf))
}
}
}
def processPacket(packet: Packet) = packet match {
case message: Message if message.getBody.startsWith(prefix) => this ! Command(message.getBody.substring(prefix.length))
case _ =>
}
private def handleCommand(cmd: String) {
debug("Processing command: %s".format(cmd))
commandWriter.write(cmd.toArray)
commandCount = commandCount + 1
}
private def handleResult(rslt: String) {
debug("Sending result: %s".format(rslt))
if (!room.isEmpty) chat.sendMessage(rslt)
resultCount = resultCount + 1
}
protected def quit() = {
log("Bye bye.")
conn.disconnect()
exit()
}
protected def logStatus() = {
log("""
| Status
| ------
| Connected: %s
| Authenticated: %s
| Command Messages Processed: %s
| Result Messages Sent: %s
| Debugging: %s
|""".stripMargin.format(conn.isConnected, conn.isAuthenticated, commandCount, resultCount, debugging))
}
private class ReplThread extends Thread {
override def run() {
val loop = new InterpreterLoop(commandReader, resultWriter)
new ResultThread().start()
val settings = new Settings(s => log(s))
settings.classpath.value = classpath.distinct.mkString(java.io.File.pathSeparator)
loop.main(settings)
ReplBot.this ! "quit"
def classpath = urls map {_.toString}
def urls = Thread.currentThread.getContextClassLoader match {
case cl: java.net.URLClassLoader => cl.getURLs.toList
case cl: ScalaClassLoader => cl.get
case cl => error("Unsupported ClassLoader %s".format(cl))
}
}
private class ResultThread extends Thread {
override def run() {
while (true) try {
ReplBot.this ! Result(resultReader.readLine())
} catch { case _ => }
}
}
}
override def toString = "ReplBot[%s]".format(nick)
protected def log(s: String) = println("%s %s".format(this, s))
protected def debug(s: String) = debugging match { case true => log(s) case false => }
protected case class Command(string: String)
protected case class Result(string: String)
private val cos = new PipedOutputStream()
private val cis = new PipedInputStream(cos)
private val ros = new PipedOutputStream()
private val ris = new PipedInputStream(ros)
private val commandWriter = new PrintWriter(cos)
private val commandReader = new BufferedReader(new InputStreamReader(cis))
private val resultWriter = new PrintWriter(ros)
private val resultReader = new BufferedReader(new InputStreamReader(ris))
private var conn: XMPPConnection = _
private var chat: MultiUserChat = _
private var commandCount = 0
private var resultCount = 0
private val Debug = "debug (on|off)".r
private var debugging = true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment