/
Bot.scala
80 lines (66 loc) · 2.09 KB
/
Bot.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package org.conbere.irc
import java.net.InetSocketAddress
import com.typesafe.scalalogging.log4j.Logging
import akka.actor._
import akka.util.{ ByteString, ByteStringBuilder }
import Tokens._
import ControlChars._
import Messages._
object Bot extends Logging {
def start(serverName:String, port:Int, responder:BotResponder) = {
ActorSystem().actorOf(Props(new Bot(serverName, port, responder)))
}
}
class Bot(serverName:String, port:Int, responder:BotResponder)
extends Actor with Logging {
val state = IO.IterateeRef.Map.async[IO.Handle]()(context.dispatcher)
val address = new InetSocketAddress(serverName, port)
def utf8(bytes:ByteString) =
bytes.decodeString("UTF-8").trim
override def preStart {
println("Connecting to: " + address)
IOManager(context.system).connect(address)
}
def parseMessage(str:String) =
Parser.apply(str) match {
case Parser.Success(message, _) =>
println("Received: " + message)
Some(message)
case _ =>
logger.error("Could not parse: " + str)
None
}
def writeResponseSocket(socket:IO.SocketHandle)(response:Option[Response]) = {
response match {
case Some(response) =>
println("Response: " + utf8(response.byteString))
socket.write((new ByteStringBuilder ++= response.byteString ++= CRLF).result)
case _ =>
// no response
}
}
def receive = {
case IO.Connected(socket, address) =>
val writeResponse = writeResponseSocket(socket) _
writeResponse(responder.onConnect)
state(socket).flatMap(_ =>
IO.repeat {
IO.takeUntil(CRLF).map { in =>
parseMessage(utf8(in)) match {
case Some(message) =>
if (responder.respondTo.isDefinedAt(message)) {
writeResponse(responder.respondTo(message))
}
case None =>
// do nothing
}
}
}
)
case IO.Read(socket, bytes) =>
state(socket)(IO.Chunk(bytes))
case IO.Closed(socket, cause) =>
state(socket)(IO.EOF)
state -= socket
}
}