challenge push notifications

pull/1283/head
Thibault Duplessis 2016-02-07 23:19:13 +07:00
parent b8f9f78ad3
commit 48dbe6a63c
7 changed files with 75 additions and 8 deletions

View File

@ -69,7 +69,9 @@ object Challenge {
def apply(id: Int): Option[Status] = all.find(_.id == id)
}
case class Rating(int: Int, provisional: Boolean)
case class Rating(int: Int, provisional: Boolean) {
def show = s"$int${provisional.fold("?", "")}"
}
object Rating {
def apply(p: lila.rating.Perf): Rating = Rating(p.intRating, p.provisional)
}

View File

@ -15,7 +15,8 @@ final class ChallengeApi(
joiner: Joiner,
jsonView: JsonView,
socketHub: ActorRef,
userRegister: ActorSelection) {
userRegister: ActorSelection,
lilaBus: lila.common.Bus) {
import Challenge._
@ -24,7 +25,9 @@ final class ChallengeApi(
def create(c: Challenge): Funit = {
repo like c flatMap { _ ?? repo.cancel }
} >> (repo insert c) >> uncacheAndNotify(c)
} >> (repo insert c) >> uncacheAndNotify(c) >>- {
lilaBus.publish(Event.Create(c), 'challenge)
}
def byId = repo byId _
@ -48,8 +51,10 @@ final class ChallengeApi(
def accept(c: Challenge, user: Option[User]): Fu[Option[Pov]] =
joiner(c, user).flatMap {
case None => fuccess(None)
case Some(pov) => (repo accept c) >> uncacheAndNotify(c) inject pov.some
case None => fuccess(None)
case Some(pov) => (repo accept c) >> uncacheAndNotify(c) >>- {
lilaBus.publish(Event.Accept(c, user.map(_.id)), 'challenge)
} inject pov.some
}
def rematchOf(game: Game, user: User): Fu[Boolean] =

View File

@ -52,7 +52,8 @@ final class Env(
joiner = new Joiner(onStart = onStart),
jsonView = jsonView,
socketHub = socketHub,
userRegister = hub.actor.userRegister)
userRegister = hub.actor.userRegister,
lilaBus = system.lilaBus)
private lazy val repo = new ChallengeRepo(
coll = db(CollectionChallenge),

View File

@ -9,3 +9,8 @@ object Direction {
case object In extends Direction // I can accept this challenge
case object Out extends Direction // I created this challenge
}
object Event {
case class Create(c: Challenge)
case class Accept(c: Challenge, joinerId: Option[String])
}

View File

@ -9,6 +9,7 @@ final class Env(
config: Config,
db: lila.db.Env,
getLightUser: String => Option[lila.common.LightUser],
isOnline: lila.user.User.ID => Boolean,
roundSocketHub: ActorSelection,
system: ActorSystem) {
@ -29,16 +30,19 @@ final class Env(
private lazy val pushApi = new PushApi(
googlePush,
getLightUser,
isOnline,
roundSocketHub)
system.actorOf(Props(new Actor {
override def preStart() {
system.lilaBus.subscribe(self, 'finishGame, 'moveEvent)
system.lilaBus.subscribe(self, 'finishGame, 'moveEvent, 'challenge)
}
import akka.pattern.pipe
def receive = {
case lila.game.actorApi.FinishGame(game, _, _) => pushApi finish game
case move: lila.hub.actorApi.round.MoveEvent => pushApi move move
case lila.challenge.Event.Create(c) => pushApi challengeCreate c
case lila.challenge.Event.Accept(c, joinerId) => pushApi.challengeAccept(c, joinerId)
}
}))
}
@ -49,6 +53,7 @@ object Env {
db = lila.db.Env.current,
system = lila.common.PlayApp.system,
getLightUser = lila.user.Env.current.lightUser,
isOnline = lila.user.Env.current.isOnline,
roundSocketHub = lila.hub.Env.current.socket.round,
config = lila.common.PlayApp loadConfig "push")
}

View File

@ -3,6 +3,7 @@ package lila.push
import akka.actor._
import akka.pattern.ask
import chess.format.Forsyth
import lila.challenge.Challenge
import lila.common.LightUser
import lila.game.{ Game, GameRepo, Pov, Namer }
import lila.hub.actorApi.map.Ask
@ -14,6 +15,7 @@ import play.api.libs.json._
private final class PushApi(
googlePush: GooglePush,
implicit val lightUser: String => Option[LightUser],
isOnline: User.ID => Boolean,
roundSocketHub: ActorSelection) {
def finish(game: Game): Funit =
@ -32,6 +34,7 @@ private final class PushApi(
payload = Json.obj(
"userId" -> userId,
"userData" -> Json.obj(
"type" -> "gameFinish",
"gameId" -> game.id,
"fullId" -> pov.fullId,
"color" -> pov.color.name,
@ -58,6 +61,7 @@ private final class PushApi(
payload = Json.obj(
"userId" -> userId,
"userData" -> Json.obj(
"type" -> "gameMove",
"gameId" -> game.id,
"fullId" -> pov.fullId,
"color" -> pov.color.name,
@ -73,6 +77,51 @@ private final class PushApi(
}
}
def challengeCreate(c: Challenge): Funit = c.destUser.filterNot(u => isOnline(u.id)) ?? { dest =>
c.challengerUser ?? { challenger =>
lightUser(challenger.id) ?? { lightChallenger =>
googlePush(dest.id) {
GooglePush.Data(
title = s"${lightChallenger.titleName} (${challenger.rating.show}) challenges you!",
body = describeChallenge(c),
payload = Json.obj(
"userId" -> dest.id,
"userData" -> Json.obj(
"type" -> "challengeCreate",
"challengeId" -> c.id))
)
}
}
}
}
def challengeAccept(c: Challenge, joinerId: Option[String]): Funit = c.challengerUser.filterNot(u => isOnline(u.id)) ?? { challenger =>
val lightJoiner = joinerId flatMap lightUser
googlePush(challenger.id) {
GooglePush.Data(
title = s"${lightJoiner.fold("Anonymous")(_.titleName)} accepts your challenge!",
body = describeChallenge(c),
payload = Json.obj(
"userId" -> challenger.id,
"userData" -> Json.obj(
"challengeId" -> c.id))
)
}
}
private def describeChallenge(c: Challenge) = {
import lila.challenge.Challenge.TimeControl._
List(
c.mode.fold("Casual", "Rated"),
c.timeControl match {
case Unlimited => "Unlimited"
case Correspondence(d) => s"$d days"
case c: Clock => c.show
},
c.variant.name
) mkString " • "
}
private def IfAway(pov: Pov)(f: => Funit): Funit = {
import makeTimeout.short
roundSocketHub ? Ask(pov.gameId, IsOnGame(pov.color)) mapTo manifest[Boolean] flatMap {

View File

@ -231,7 +231,7 @@ object ApplicationBuild extends Build {
libraryDependencies ++= provided(play.api, RM, PRM)
)
lazy val push = project("push", Seq(common, db, user, game)).settings(
lazy val push = project("push", Seq(common, db, user, game, challenge)).settings(
libraryDependencies ++= provided(play.api, RM, PRM)
)