-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
Handler.scala
96 lines (86 loc) · 3.16 KB
/
Handler.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package lila.socket
import akka.actor.ActorRef
import akka.pattern.{ ask, pipe }
import play.api.libs.iteratee.{ Iteratee, Enumerator }
import play.api.libs.json._
import scala.concurrent.duration._
import actorApi._
import lila.common.PimpedJson._
import lila.hub.actorApi.relation.ReloadOnlineFriends
import makeTimeout.large
object Handler {
type Controller = PartialFunction[(String, JsObject), Unit]
type Connecter = PartialFunction[Any, (Controller, JsEnumerator, SocketMember)]
val emptyController: Controller = PartialFunction.empty
lazy val AnaRateLimit = new lila.memo.RateLimit(90, 60 seconds)
def apply(
hub: lila.hub.Env,
socket: ActorRef,
uid: String,
join: Any,
userId: Option[String])(connecter: Connecter): Fu[JsSocketHandler] = {
def baseController(member: SocketMember): Controller = {
case ("p", _) => socket ! Ping(uid)
case ("following_onlines", _) => userId foreach { u =>
hub.actor.relation ! ReloadOnlineFriends(u)
}
case ("startWatching", o) => o str "d" foreach { ids =>
hub.actor.moveBroadcast ! StartWatching(uid, member, ids.split(' ').toSet)
}
case ("moveLat", o) => hub.channel.moveLat ! (~(o boolean "d")).fold(
Channel.Sub(member),
Channel.UnSub(member))
case ("anaMove", o) => AnaRateLimit(uid) {
AnaMove parse o foreach { anaMove =>
anaMove.step match {
case scalaz.Success(step) =>
member push lila.socket.Socket.makeMessage("step", Json.obj(
"step" -> step.toJson,
"path" -> anaMove.path
))
case scalaz.Failure(err) =>
member push lila.socket.Socket.makeMessage("stepFailure", err.toString)
}
}
}
case ("anaDrop", o) => AnaRateLimit(uid) {
AnaDrop parse o foreach { anaDrop =>
anaDrop.step match {
case scalaz.Success(step) =>
member push lila.socket.Socket.makeMessage("step", Json.obj(
"step" -> step.toJson,
"path" -> anaDrop.path
))
case scalaz.Failure(err) =>
member push lila.socket.Socket.makeMessage("stepFailure", err.toString)
}
}
}
case ("anaDests", o) => AnaRateLimit(uid) {
AnaDests parse o match {
case Some(req) =>
member push lila.socket.Socket.makeMessage("dests", Json.obj(
"dests" -> req.dests,
"path" -> req.path
))
case None =>
member push lila.socket.Socket.makeMessage("destsFailure", "Bad dests request")
}
}
case _ => // logwarn("Unhandled msg: " + msg)
}
def iteratee(controller: Controller, member: SocketMember): JsIteratee = {
val control = controller orElse baseController(member)
Iteratee.foreach[JsValue](jsv =>
jsv.asOpt[JsObject] foreach { obj =>
obj str "t" foreach { t =>
control.lift(t -> obj)
}
}
).map(_ => socket ! Quit(uid))
}
socket ? join map connecter map {
case (controller, enum, member) => iteratee(controller, member) -> enum
}
}
}