<commit_before>package lila.push

import lila.common.LightUser
import lila.game.{ Game, GameRepo, Pov, Namer }
import lila.hub.actorApi.round.MoveEvent
import lila.user.User

import play.api.libs.json._

// https://aerogear.org/docs/specs/aerogear-unifiedpush-rest/index.html#397083935
private final class PushApi(
    aerogear: Aerogear,
    implicit val lightUser: String => Option[LightUser]) {

  def finish(game: Game): Funit =
    if (!game.isCorrespondence || game.hasAi) funit
    else game.userIds.map { userId =>
      Pov.ofUserId(game, userId) ?? { pov =>
        val result = pov.win match {
          case Some(true)  => "You won!"
          case Some(false) => "You lost."
          case _           => "It's a draw."
        }
        aerogear push Aerogear.Push(
          userId = userId,
          alert = s"Your game with ${opponentName(pov)} is over. $result",
          sound = "default",
          userData = Json.obj(
            "gameId" -> game.id,
            "color" -> pov.color.name,
            "win" -> pov.win)
        )
      }
    }.sequenceFu.void

  def move(move: MoveEvent): Funit = move.opponentUserId ?? { userId =>
    def filter(g: Game) = g.isCorrespondence && g.playable && g.nonAi
    GameRepo game move.gameId flatMap {
      case Some(game) if filter(game) =>
        Pov.ofUserId(game, userId) ?? { pov =>
          aerogear push Aerogear.Push(
            userId = userId,
            alert = s"${opponentName(pov)} played ${move.move}, it's your turn!",
            sound = "default",
            userData = Json.obj(
              "gameId" -> game.id,
              "color" -> pov.color.name)
          )
        }
      case _ => funit
    }
  }

  private def opponentName(pov: Pov) = Namer.player(pov.opponent)
}<commit_msg>push notification: display SAN move in the alert<commit_after>package lila.push

import lila.common.LightUser
import lila.game.{ Game, GameRepo, Pov, Namer }
import lila.hub.actorApi.round.MoveEvent
import lila.user.User

import play.api.libs.json._

// https://aerogear.org/docs/specs/aerogear-unifiedpush-rest/index.html#397083935
private final class PushApi(
    aerogear: Aerogear,
    implicit val lightUser: String => Option[LightUser]) {

  def finish(game: Game): Funit =
    if (!game.isCorrespondence || game.hasAi) funit
    else game.userIds.map { userId =>
      Pov.ofUserId(game, userId) ?? { pov =>
        val result = pov.win match {
          case Some(true)  => "You won!"
          case Some(false) => "You lost."
          case _           => "It's a draw."
        }
        aerogear push Aerogear.Push(
          userId = userId,
          alert = s"Your game with ${opponentName(pov)} is over. $result",
          sound = "default",
          userData = Json.obj(
            "gameId" -> game.id,
            "color" -> pov.color.name,
            "win" -> pov.win)
        )
      }
    }.sequenceFu.void

  def move(move: MoveEvent): Funit = move.opponentUserId ?? { userId =>
    def filter(g: Game) = g.isCorrespondence && g.playable && g.nonAi
    GameRepo game move.gameId flatMap {
      case Some(game) if filter(game) =>
        game.pgnMoves.lastOption ?? { sanMove =>
          Pov.ofUserId(game, userId) ?? { pov =>
            aerogear push Aerogear.Push(
              userId = userId,
              alert = s"${opponentName(pov)} played $sanMove, it's your turn!",
              sound = "default",
              userData = Json.obj(
                "gameId" -> game.id,
                "color" -> pov.color.name)
            )
          }
        }
      case _ => funit
    }
  }

  private def opponentName(pov: Pov) = Namer playerString pov.opponent
}
{'fraction_non_alphanumeric': 0.12986659406479717, 'fraction_numerical': 0.004900626191124422, 'mean_word_length': 2.0413907284768213, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 34, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4805310', 'n_tokens_mistral': 1209, 'n_tokens_neox': 1217, 'n_words': 275}