All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ilcali.capture-server_2.8.1.0.0.2.source-code.RobotTalk.scala Maven / Gradle / Ivy

The newest version!
package capture
package server

import control._

import unfiltered.Cookie
import unfiltered.netty.websockets._

class EventParsing(val ident: String) {
  def unapplySeq(text: String) = {
    if (!text.startsWith(ident)) None else
      Some(text.split("\\|").drop(1).toSeq)
  }
}

// Mouse-related
object MouseDown extends EventParsing("mousedown")
object MouseUp extends EventParsing("mouseup")
object MouseMove extends EventParsing("mousemove")

// Keyboard-related
object KeyUp extends EventParsing("keyup")
object KeyDown extends EventParsing("keydown")

// Other interaction
object RobotAuth extends EventParsing("auth")
object RobotRecord extends EventParsing("record")
object ClipboardRetrieve extends EventParsing("clipretrieve")
object ClipboardSet extends EventParsing("clipset")
object ImageControl extends EventParsing("image")

case class RobotTalk(secret: String, service: Option[ImageStream])
  extends Plan with CloseOnException {
  @volatile private var controller: Option[java.lang.Integer] = None

  // One per controller
  private var recorder = setupRecorder

  def setupRecorder() = {
    val name = "recording_%d" format System.currentTimeMillis
    val location = new java.io.File(System.getProperty("user.home"), name)

    new Record(location.getAbsolutePath) with PostOperation
  }

  def check(pred: java.lang.Integer => Boolean)(block: => Unit) {
    controller.map(i => if (pred(i)) block) 
  }

  // Extra protection
  def isController(socket: WebSocket) = {
    controller.map(_ == socket.channel.getId).getOrElse(false)
  }

  def intent = {
    case _ => {
      case Open(s) =>
        check(_ != s.channel.getId) {
          s.send("Already being controlled")
        }
      case Message(s, Text(msg)) => msg match {
        case RobotAuth(key) if controller.isEmpty =>
          if (key == secret) {
            controller = Some(s.channel.getId)
            s.send("auth|connect")
          } else {
            s.send("bad-key| - %s" format key)
          }
        case _ if isController(s) => RobotProtect.message(s, msg)
      }
      case Close(s) =>
        // Prevent runaways
        if (recorder.isRunning) recorder.stop()
        // Safely clear inputs on disconnect
        Robot.clearInputs()
        check(_ == s.channel.getId)(controller = None)
    }
  }
  def pass: Plan.PassHandler = (_.sendUpstream(_)) 

  object RobotProtect {
    def handleGeneral(s: WebSocket, msg: String) = msg match {
      case RobotRecord(value) => value match {
        case "record" if !recorder.isRunning =>
          recorder.start()
          s.send("record|started")
        case "stop" if recorder.isRunning =>
          recorder.stop()
          recorder = setupRecorder()
          s.send("record|stopped")
        case _ if recorder.isRunning => s.send("record|started")
        case _ => s.send("record|stopped")
      }
      case ImageControl(x, y, q, p) =>
        service.map(_ ! ImageProps(x.toDouble, y.toDouble, q.toFloat, p.toBoolean))
        s.send("image|success")
      case ClipboardRetrieve(value) =>
        s.send("clipboard|get|%s" format Clipboard.retrieve.getOrElse(""))
      case msg if msg.startsWith(ClipboardSet.ident) =>
        val value = ClipboardSet.unapplySeq(msg).map(_.mkString("|")).get
        if (Clipboard(value).isDefined) {
          s.send("clipboard|success")
        } else {
          s.send("clipboard|failure")
        }
      case _ =>
        handleInput(s, msg)
    }

    def handleInput(s: WebSocket, msg: String) = msg match {
      case KeyUp(KeyTranslate(keyCode)) =>
        Robot(_.keyRelease(keyCode))
      case KeyDown(KeyTranslate(keyCode)) =>
        Robot(_.keyPress(keyCode))
      case MouseUp(MouseTranslate(button)) =>
        Robot(_.mouseRelease(button))
      case MouseDown(MouseTranslate(button)) =>
        Robot(_.mousePress(button))
      case MouseMove(xStr, yStr) =>
        Robot(_.mouseMove(xStr.toInt, yStr.toInt))
      case _ =>
        println("[DEBUG]: Unknown msg: %s" format msg)
    }

    def message(s: WebSocket, msg: String) = handleGeneral(s, msg)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy