1. raichoo
  2. sakura

Commits

raichoo  committed acf2f7c

code refactored and addtional features

* now sets XMPP topic to IRC topic
* removed bogus actors
* java keypass can now be set in config file
* regex rewrite

  • Participants
  • Parent commits a0f3c39
  • Branches default

Comments (0)

Files changed (13)

File .hgignore

View file
  • Ignore whitespace
 manifest.mf
 build/*
 config.xml
-start.sh
+*.sh
 testconfig.xml
 *.patch
+lib/*
 

File src/sakura/AnonConnector.scala

View file
  • Ignore whitespace
 import org.jivesoftware.smack.SASLAuthentication
 import org.jivesoftware.smack.XMPPConnection
 import org.jivesoftware.smackx.muc.MultiUserChat
-import scala.actors.TIMEOUT
 import scala.actors.Actor._
 import scala.collection.mutable.HashMap
-import scala.collection.mutable.SynchronizedStack
 import scala.collection.mutable.Stack
 
 /**
  * Connector that manages IRC users and maps them onto dummy XMPP users
  */
-object AnonConnector extends Connector {
+object AnonConnector {
 
   val service  = Main.config \ "connectors" \ "anon" \ "service" text
   val password = Main.config \ "connectors" \ "anon" \ "password" text
+  val keypass  = Main.config \ "java" \ "keypass" text
 
   private val users  = new HashMap[String, (XMPPConnection, MultiUserChat, Int)]
-  private val ids    = new SynchronizedStack[Int]
-  private val buffer = new Stack[String]
+  private val ids    = new Stack[Int]
 
   1 to 30 map (ids push _)
 
    * 
    */
   def join(name: String, room: String): Unit = {
-    if (name == IRCConnector.nick ||
-        XMPPConnector.room.occupants.contains(name))
+    if (name == IRCConnector.nick || XMPPConnector.room.occupants.contains(name))
       return
+
     val id = ids.pop
     val cf = new ConnectionConfiguration(service, 5222)
-    cf.setTruststorePassword("changeit")
+    
+    cf.setTruststorePassword(keypass)
     cf.setReconnectionAllowed(false)
+    
     val connection =  new XMPPConnection(cf)
+    
     SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 0)
+    
     connection.connect
+    
     try {
       connection.login("warpzone"+ id, password)
       connection.addConnectionListener(new SakuraConnectionListener)
     } catch {
       case e: Exception => {
           connection.disconnect
+          
           ids push id
-          return
       }
     }
     val muc = new MultiUserChat(connection, room + "@conference." + XMPPConnector.service)
    * @return true if user is a dummy
    *
    */
-  def isDummy(name: String): Boolean = {
-    users.contains(name)
-  }
+  def isDummy(name: String): Boolean = users.contains(name)
 
   /**
    * Quit a dummy
    * @param name Name of the dummy that has to leave
    *
    */
-  def leave(name: String): Unit = {
+  def leave(name: String): Unit =
     if (users.contains(name)) {
       users(name)._2.leave
       users(name)._1.disconnect
+      
       ids push users(name)._3
+      
       users -= name
     }
-  }
 
   /**
    * Make a dummy speak
    * @param msg Message to deliver
    *
    */
-  def sendMessage(from: String, msg: String): Unit = {
+  def sendMessage(from: String, msg: String): Unit =
     users(from)._2.sendMessage(msg)
-  }
-
-  /**
-   * Pushes user onto stack for later processing
-   *
-   * @param user User to stack
-   *
-   */
-  def pushUser(user: String): Unit = {
-    buffer.push(user)
-  }
-
-  /**
-   * Make all users on the stack join the room
-   *
-   * @param room Room to join
-   * 
-   */
-  def flushUsers(room: String): Unit = {
-    buffer map { x => join(x, room) }
-    buffer.clear
-  }
 
   /**
    * Rename a user
   def renameUser(from: String, to: String): Unit = {
     if (XMPPConnector.room.occupants contains to)
       leave(from)
+    
     val (connection, muc, id) = users(from)
+    
     users -= from
     users += to -> (connection, muc, id)
+    
     muc.changeNickname(to)
   }
-
-  def act(): Unit = {
-    loop {
-      receiveWithin(128000) {
-        case TIMEOUT => {}
-
-      }
-    }
-  }
   
 }

File src/sakura/ConnectionWatchdog.scala

  • Ignore whitespace
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package sakura
-
-import java.net.InetAddress
-import scala.actors.Actor
-import scala.actors.Actor._
-import scala.actors.TIMEOUT
-
-object ConnectionWatchdog extends Actor {
-
-  val service = Main.config \ "connectors" \ "anon" \ "service" text
-
-  val xmpp_server = InetAddress.getByName(service)
-
-  java.security.Security.setProperty("networkaddress.cache.ttl", "0")
-  System.setProperty("networkaddress.cache.ttl", "0")
-
-  def act(): Unit = {
-    loop {
-      receiveWithin(60000) {
-        case TIMEOUT =>
-          {
-            val check_addr = InetAddress.getByName(service)
-            println("XMPP:  " + xmpp_server.toString)
-            println("CHECK: " + check_addr.toString)
-
-            if (check_addr.toString != xmpp_server.toString) {
-              println("DISCONNECTED")
-              System.exit(0)
-            }
-            println("CONNECTED TO XMPP SERVER")
-          }
-      }
-    }
-  }
-
-}
-

File src/sakura/Connector.scala

  • Ignore whitespace
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package sakura
-
-import scala.actors.Actor
-
-trait Connector extends Actor {
-
-}

File src/sakura/IRCConnector.scala

View file
  • Ignore whitespace
  * a client. It processes messsages, replys to them if needed and provides
  * an interface that allows to send messages on demand
  */
-object IRCConnector extends Connector {
+object IRCConnector extends Actor{
   val user     = Main.config \ "connectors" \ "irc" \ "user" text
   val nick     = Main.config \ "connectors" \ "irc" \ "nick" text
   val realname = Main.config \ "connectors" \ "irc" \ "realname" text
 
   // regular expressions to parse irc input
   val Join    = new Regex("""(?i):(.+)!~?.+\s+JOIN\s+:#(.+)""")
-  val Part    = new Regex("""(?i):(.+)!~?.+\s+PART\s+#(\w+).*""")
+  val Leave   = new Regex("""(?i):(.+)!~?.+\s+(?:QUIT|PART)\s+(?:|#).*""")
   val PrivMSG = new Regex("""(?i):(.+)!~?.+\s+PRIVMSG\s+#(\w+)\s+:(.+)""")
   val Ping    = new Regex("""(?i)PING\s+:(.+)""")
-  val Pong    = new Regex("""(?i)PONG\s+:(.+)""")
-  val Quit    = new Regex("""(?i):(.+)!~.+\s+QUIT\s+:.*""")
   val Action  = new Regex("""\u0001ACTION\s+(.+)\u0001""")
   val Nick    = new Regex(""":(.+)!~?.+\s+NICK\s+:(.+)""")
-  val cmd352  = new Regex("""(?i):.+ 352 .+ #(\w+) .+ .+ .+ (.+) \w@? :0.*""")
-  val cmd315  = new Regex("""(?i):.+ 315 .+ #(\w+) :.*""")
-  val cmd353  = new Regex(""".+ 353 .+ = #(\w+) :(.*)""")
+  val Topic   = new Regex("""(?i):.+\s+(?:332\s+.+|TOPIC)\s+#.+\s+:(.+)""")
+  val Who     = new Regex("""(?i):.+\s+352\s+.+\s+#(\w+)\s+.+\s+.+\s+.+\s+(.+)\s+\w@?\s+:0.*""")
 
   // send necessary commands to login
   val room = login
     loop {
       receiveWithin(100) {
         case TIMEOUT =>
-          if(input.ready) {
+          if(input.ready)
             // try to avoid ending this thread at any cost
             try {
               println(processInput(input.readLine))
             } catch {
-              case e: Exception => {
-                  println(e.toString)
-              }
+              case e: Exception =>
+                println(e.toString)
             }
-          }
         case _ => {}
       }
     }
    * @return returns the input for further processing or debugging
    *
    */
-  def processInput(input: String): String = {
+  private def processInput(input: String): String = {
     input match {
-      case PrivMSG(nick, room, msg) => {
-          msg match {
-            case Action(action) =>
-              if (AnonConnector.isDummy(nick))
-                AnonConnector.sendMessage(nick, "/me " + action)
-              else
-                XMPPConnector.room.sendAction(nick, action)
-            case _ =>
-              if (AnonConnector.isDummy(nick))
-                AnonConnector.sendMessage(nick, msg)
-              else
-                XMPPConnector.room.sendMessage(nick, msg)
-          }
-        }
+      case PrivMSG(nick, room, msg) => 
+        decomposeMessage(nick,room,msg)
       case Ping(host) =>
         pong
-      case Part(nick, room) => {
-        AnonConnector.leave(nick)
-      }
+      case Leave(nick) =>
+          AnonConnector.leave(nick)
       case Join(nick, room) =>
         AnonConnector.join(nick, room)
-      case Quit(nick) => {
-        AnonConnector.leave(nick)
-      }
       case Nick(from, to) =>
         if (AnonConnector.isDummy(from))
           AnonConnector.renameUser(from, to)
         else
           AnonConnector.join(to, roomname)
-      case cmd352(room, nick) =>
+      case Topic(text) =>
+        ZoneStatusObserver ! text
+      case Who(room, nick) =>
         AnonConnector.join(nick, room)
-      case cmd353(room, nicks) => {
-          (nicks.split(' ').toList) map { nick => AnonConnector.join(nick, room) }
-      }
       case _ => {}
     }
     input
     output.flush
   }
 
-  def who(room: String): Unit = {
+  private def who(room: String): Unit = {
     output.println("WHO #" + room)
-    output.flush
+    output.flush()
   }
 
   /**
    */
   private def login(): IRCRoom = {
     output.println("USER " + user + " * * :" + realname)
-    output.flush
+    output.flush()
     output.println("NICK " + nick)
-    output.flush
+    output.flush()
 
     join(roomname)
   }
   private def getSocketStreams(s: Socket): (BufferedReader, PrintWriter) = {
     (new BufferedReader(
         new InputStreamReader(s.getInputStream)),
-     new PrintWriter(
+      new PrintWriter(
         new OutputStreamWriter(s.getOutputStream)))
   }
 
   private def join(room: String): IRCRoom = {
     output.println("JOIN #" + room)
     output.flush
+    
     who(room)
+    
     new IRCRoom(output, room)
   }
+  
+  
+  private def decomposeMessage(nick: String, room: String, msg: String): Unit =
+    msg match {
+      case Action(action) =>
+        if (AnonConnector.isDummy(nick))
+          AnonConnector.sendMessage(nick, "/me " + action)
+        else
+          XMPPConnector.room.sendAction(nick, action)
+      case _ =>
+        if (AnonConnector.isDummy(nick))
+          AnonConnector.sendMessage(nick, msg)
+        else
+          XMPPConnector.room.sendMessage(nick, msg)
+    }
 
 }

File src/sakura/IRCRoom.scala

View file
  • Ignore whitespace
    * @param msg The message to be send
    *
    */
-  def sendMessage(from: String, msg: String): Unit = {
-    if (AnonConnector.isDummy(from))
-      return
-    synchronized {
-
-      tokenizeText(msg) map ( 
-        x => { stream.println("PRIVMSG #" + room +
-                              " :[" + from +
-                              "]: " + x)
-        stream.flush }
-     )
-
-    }
-  }
+  def sendMessage(from: String, msg: String): Unit =
+    if (!AnonConnector.isDummy(from))
+      tokenizeText(msg) map { x => write("PRIVMSG #" + room +
+                                         " :[" + from +
+                                         "]: " + x) }
 
   /**
    * Send an action to this room
    * @param action The action that is happening
    *
    */
-  def sendAction(from: String, action: String): Unit = {
-    if (AnonConnector.isDummy(from))
-      return
-    synchronized {
-      stream.println("PRIVMSG #" + room +
-                     " :\u0001ACTION " + from +
-                     " "+ action +
-                     "\u0001")
-      stream.flush
-    }
-  }
+  def sendAction(from: String, action: String): Unit =
+    if (!AnonConnector.isDummy(from))
+      write("PRIVMSG #" + room +
+            " :\u0001ACTION " + from +
+            " "+ action +
+            "\u0001")
 
   /**
    * Split long text into tokens so IRC can swallow it
    * @param text Text to be tokenized
    * 
    */
-  private def tokenizeText(text: String): List[String] = {
+  private def tokenizeText(text: String): List[String] =
     if ((text size) < 480) {
       List(text)
     } else {
       val (left, right) = text splitAt(480)
       List(left + "…") ++ this.tokenizeText("…" + right)
     }
-  }
 
   /**
    * Send a message to this room that informs the occupants of a join
    * @param who Name of the user that has joined
    *
    */
-  def sendJoin(who: String): Unit = {
-    if (AnonConnector.isDummy(who))
-      return
-    synchronized {
-      stream.println("PRIVMSG #" + room +
-                     " :[" + who +
-                     " entered the channel]")
-      stream.flush
-    }
-  }
+  def sendJoin(who: String): Unit =
+    if (!AnonConnector.isDummy(who))
+      write("PRIVMSG #" + room +
+            " :[" + who +
+            " entered the channel]")
 
   /**
    * Send a message to this room that informs the occupants of a part that
    * @param who Name of the user that has left the room
    *
    */
-  def sendPart(who: String): Unit = {
-    if (AnonConnector.isDummy(who))
-      return
-    synchronized {
-      stream.println("PRIVMSG #" + room +
-                     " :[" + who +
-                     " left the channel]")
-      stream.flush
-    }
-  }
+  def sendPart(who: String): Unit =
+    if (!AnonConnector.isDummy(who))
+      write("PRIVMSG #" + room +
+                      " :[" + who +
+                      " left the channel]")
 
   /**
    * Leave this room
    * @todo Send a part message to the room
    *
    */
-  def leave(): Unit = {
-    IRCConnector.room.leave
+  def leave(): Unit = IRCConnector.room.leave
+  
+  /**
+   * Synchronizing writes to IRC
+   * 
+   * @param msg Message to be sent
+   * 
+   */
+  private def write(msg: String): Unit = synchronized {
+    stream.println(msg)
+    stream.flush()
   }
 
 }

File src/sakura/Main.scala

View file
  • Ignore whitespace
       println("usage example: sakura config.xml")
       System.exit(1)
     }
-    
+
     config = XML.loadFile(args(0))
-    XMPPConnector.start
+
     IRCConnector.start
     ZoneStatusObserver.start
-    AnonConnector.start
-    //ConnectionWatchdog.start
   }
 
 }

File src/sakura/SakuraConnectionListener.scala

View file
  • Ignore whitespace
 
 class SakuraConnectionListener extends ConnectionListener {
 
-  def connectionClosedOnError(e: Exception): Unit = {
+  def connectionClosedOnError(e: Exception): Unit =
     println("CONNECTION TERMINATED")
-//    System.exit(0)
-  }
 
   def connectionClosed(): Unit = {}
   def reconnectingIn(seconds: Int): Unit = {}

File src/sakura/SakuraPacketListener.scala

View file
  • Ignore whitespace
    *
    */
 
-  def processPacket(packet: Packet): Unit = {
+  def processPacket(packet: Packet): Unit =
     if (packet.getExtension("jabber:x:delay") == null) {
+      
       val message = packet.asInstanceOf[Message];
       val XMPPConnector.JID(room, host, nick) = message.getFrom;
-      if (nick != XMPPConnector.nick) {
+      
+      if (nick != XMPPConnector.nick)
         message.getBody match {
           case XMPPConnector.Action(action) =>
             IRCConnector.room.sendAction(nick, action)
           case _ =>
             IRCConnector.room.sendMessage(nick, message.getBody)
         }
-      }
     }
-  } 
 
 }

File src/sakura/SakuraStatusListener.scala

View file
  • Ignore whitespace
   override def joined(who: String): Unit = {
     if(AnonConnector.isDummy(who))
       return
+    
     val XMPPConnector.JID(room, host, nick) = who
+    
     IRCConnector.room.sendJoin(nick)
   }
 
    */
   override def left(who: String): Unit = {
     val XMPPConnector.JID(room, host, nick) = who
+    
     IRCConnector.room.sendPart(nick)
 
   }

File src/sakura/XMPPConnector.scala

View file
  • Ignore whitespace
 import org.jivesoftware.smackx.muc.MultiUserChat
 import scala.actors.Actor
 import scala.actors.Actor._
-import scala.actors.TIMEOUT
+//import scala.actors.TIMEOUT
 import scala.util.matching.Regex
 
-object XMPPConnector extends Connector {
+object XMPPConnector {
   val user     = Main.config \ "connectors" \ "xmpp" \ "user" text
   val service  = Main.config \ "connectors" \ "xmpp" \ "service" text
   val password = Main.config \ "connectors" \ "xmpp" \ "password" text
   val nick     = Main.config \ "connectors" \ "xmpp" \ "nick" text
+  val keypass  = Main.config \ "java" \ "keypass" text
 
   val JID     = new Regex("""(\w+)@(.+)/(.+)""")
   val Action  = new Regex("""/me (.+)""")
   private def login(): XMPPConnection = {
     val cf = new ConnectionConfiguration(service, 5222)
     cf.setReconnectionAllowed(false)
-    cf.setTruststorePassword("changeit")
+    cf.setTruststorePassword(keypass)
     val connection = new XMPPConnection(cf)
     connection.connect
     SASLAuthentication.supportSASLMechanism("PLAIN", 0)
     muc.join(nick)
     new XMPPRoom(muc)
   }
-
-  /**
-   * This is the loop of the XMPPConnector
-   *
-   * @todo Check if everything is still good
-   */
-  def act(): Unit = {
-    loop {
-      receiveWithin(60000) {
-        case TIMEOUT => {}
-      }
-    }
-  }
   
 }

File src/sakura/XMPPRoom.scala

View file
  • Ignore whitespace
    * @param action Content of the action
    *
    */ 
-  def sendAction(from: String, action: String): Unit = {
+  def sendAction(from: String, action: String): Unit =
     muc.sendMessage("*" + from + " " + action + "*")
-  }
   
   /**
   * Inform the room that someone on the IRC side has joined
   * @param who Name of the user that has joined
   *
   */
-  def sendJoin(who: String): Unit = {
+  def sendJoin(who: String): Unit =
     muc.sendMessage("[" + who + " entered the channel]")
-  }
 
  /**
   * Inform the room that someone on the IRC side has left
   * @param who Name of the user that has left
   *
   */
-  def sendPart(who: String): Unit = {
+  def sendPart(who: String): Unit =
     muc.sendMessage("[" + who + " left the channel]")
-  }
 
  /**
   * Inform the room that someone on the IRC side has quit
   * @param who Name of the user that has quit
   *
   */
-  def sendQuit(who: String): Unit = {
+  def sendQuit(who: String): Unit =
     muc.sendMessage("[" + who + " quit]")
-  }
 
  /**
   * Inform the room that someone on the IRC side has changed his nickname
   * @param to Name of the user after the change
   *
   */
-  def sendNickchange(from: String, to: String): Unit = {
+  def sendNickchange(from: String, to: String): Unit =
     muc.sendMessage("[" + from + " -> " + to +"]")
-  }
 
   /**
    * Leave this room
    */
-  def leave(): Unit = {
-    muc.leave
-  }
+  def leave(): Unit = muc.leave
 
   /**
    * Checks if a room is joined or not
    *
    * @return Returns true if joined
    */
-  def isJoined(): Boolean = {
-    muc.isJoined
-  }
+  def isJoined(): Boolean = muc.isJoined
 
   /**
    * Returns a list of users that are joined to this room
       var XMPPConnector.JID(msgroom, msghost, msgnick) = tmplistofusers.next
       listofusers = msgnick :: listofusers
     }
+    
     listofusers
   }
 

File src/sakura/ZoneStatusObserver.scala

View file
  • Ignore whitespace
   
   val provider = Main.config \ "plugins" \ "zonestatus" \ "provider" text
   val room     = Main.config \ "plugins" \ "zonestatus" \ "room"     text
-  val topic    = Main.config \ "plugins" \ "zonestatus" \ "topic"    text
 
+  var topic = ""
+  
   private var zonestatus = isOpen
 
   /**
     XMPPConnector.sendPacket(topicCreator)
     loop {
       receiveWithin(60000) {
+        case text: String => {
+            topic = text
+            XMPPConnector.sendPacket(topicCreator)
+        }
         case TIMEOUT => {
-            val tmp = isOpen
-            if (zonestatus != tmp) {
-              zonestatus = tmp
-              XMPPConnector.sendPacket(topicCreator)
+            try {
+              val tmp = isOpen
+              if (zonestatus != tmp) {
+                zonestatus = tmp
+                XMPPConnector.sendPacket(topicCreator)
+              }
+            } catch {
+              case e: Exception => println("EXCEPTION IN PLUGIN")
             }
           }
       }
    */
   def isOpen(): Boolean = {
     val wanker = new Socket
+    
     try {
       wanker.connect(new InetSocketAddress(provider, 8000))
     } catch {
       case e: ConnectException => return false
     }
+    
     val in  = new BufferedReader(new InputStreamReader(wanker.getInputStream))
     val out = new PrintWriter(new OutputStreamWriter(wanker.getOutputStream))
     
    */
   def topicCreator(): Message = {
     val msg = new Message
+    
     if (zonestatus)
       msg.setSubject(topic + " | [warpzone is open]")
     else
       msg.setSubject(topic + " | [warpzone is closed]")
+    
     msg.setTo(room)
     msg.setType(Message.Type.groupchat)
     msg