<commit_before>package controllers

import org.joda.time.DateTime
import ornicar.scalalib.Zero
import play.api.libs.json._
import play.api.mvc._
import scala.concurrent.duration._

import lila.api.Context
import lila.app._
import lila.common.PimpedJson._
import lila.common.{ HTTPRequest, IpAddress, MaxPerPage }

object Api extends LilaController {

  private val userApi = Env.api.userApi
  private val gameApi = Env.api.gameApi

  private implicit val limitedDefault = Zero.instance[ApiResult](Limited)

  private lazy val apiStatusJson = {
    val api = lila.api.Mobile.Api
    Json.obj(
      "api" -> Json.obj(
        "current" -> api.currentVersion.value,
        "olds" -> api.oldVersions.map { old =>
          Json.obj(
            "version" -> old.version.value,
            "deprecatedAt" -> old.deprecatedAt,
            "unsupportedAt" -> old.unsupportedAt
          )
        }
      )
    )
  }

  val status = Action { req =>
    val appVersion = get("v", req)
    lila.mon.mobile.version(appVersion | "none")()
    val mustUpgrade = appVersion exists lila.api.Mobile.AppVersion.mustUpgrade _
    Ok(apiStatusJson.add("mustUpgrade", mustUpgrade)) as JSON
  }

  def index = Action {
    Ok(views.html.base.api())
  }

  def user(name: String) = ApiRequest { implicit ctx =>
    userApi.one(name, ctx.me) map toApiResult
  }

  private val UsersRateLimitGlobal = new lila.memo.RateLimit[String](
    credits = 1000,
    duration = 1 minute,
    name = "team users API global",
    key = "team_users.api.global"
  )

  private val UsersRateLimitPerIP = new lila.memo.RateLimit[IpAddress](
    credits = 1000,
    duration = 10 minutes,
    name = "team users API per IP",
    key = "team_users.api.ip"
  )

  def users = ApiRequest { implicit ctx =>
    val page = (getInt("page") | 1) atLeast 1 atMost 50
    val nb = (getInt("nb") | 10) atLeast 1 atMost 50
    val cost = page * nb + 10
    val ip = HTTPRequest lastRemoteAddress ctx.req
    UsersRateLimitPerIP(ip, cost = cost) {
      UsersRateLimitGlobal("-", cost = cost, msg = ip.value) {
        lila.mon.api.teamUsers.cost(cost)
        (get("team") ?? Env.team.api.team).flatMap {
          _ ?? { team =>
            Env.team.pager(team, page, MaxPerPage(nb)) map userApi.pager map some
          }
        } map toApiResult
      }
    }
  }

  def usersByIds = OpenBody(parse.tolerantText) { implicit ctx =>
    val usernames = ctx.body.body.split(',').take(300).toList
    val ip = HTTPRequest lastRemoteAddress ctx.req
    val cost = usernames.size / 4
    UsersRateLimitPerIP(ip, cost = cost) {
      UsersRateLimitGlobal("-", cost = cost, msg = ip.value) {
        lila.mon.api.users.cost(cost)
        lila.user.UserRepo nameds usernames map {
          _.map { Env.user.jsonView(_, none) }
        } map toApiResult map toHttp
      }
    }
  }

  def usersStatus = ApiRequest { implicit ctx =>
    val ids = get("ids").??(_.split(',').take(40).toList map lila.user.User.normalize)
    Env.user.lightUserApi asyncMany ids dmap (_.flatten) map { users =>
      val actualIds = users.map(_.id)
      val onlineIds = Env.user.onlineUserIdMemo intersect actualIds
      val playingIds = Env.relation.online.playing intersect actualIds
      toApiResult {
        users.map { u =>
          lila.common.LightUser.lightUserWrites.writes(u) ++ Json.obj(
            "online" -> onlineIds.contains(u.id),
            "playing" -> playingIds.contains(u.id)
          )
        }
      }
    }
  }

  private val UserGamesRateLimitPerIP = new lila.memo.RateLimit[IpAddress](
    credits = 10 * 1000,
    duration = 10 minutes,
    name = "user games API per IP",<commit_msg>add streaming flag to users status API<commit_after>package controllers

import org.joda.time.DateTime
import ornicar.scalalib.Zero
import play.api.libs.json._
import play.api.mvc._
import scala.concurrent.duration._

import lila.api.Context
import lila.app._
import lila.common.PimpedJson._
import lila.common.{ HTTPRequest, IpAddress, MaxPerPage }

object Api extends LilaController {

  private val userApi = Env.api.userApi
  private val gameApi = Env.api.gameApi

  private implicit val limitedDefault = Zero.instance[ApiResult](Limited)

  private lazy val apiStatusJson = {
    val api = lila.api.Mobile.Api
    Json.obj(
      "api" -> Json.obj(
        "current" -> api.currentVersion.value,
        "olds" -> api.oldVersions.map { old =>
          Json.obj(
            "version" -> old.version.value,
            "deprecatedAt" -> old.deprecatedAt,
            "unsupportedAt" -> old.unsupportedAt
          )
        }
      )
    )
  }

  val status = Action { req =>
    val appVersion = get("v", req)
    lila.mon.mobile.version(appVersion | "none")()
    val mustUpgrade = appVersion exists lila.api.Mobile.AppVersion.mustUpgrade _
    Ok(apiStatusJson.add("mustUpgrade", mustUpgrade)) as JSON
  }

  def index = Action {
    Ok(views.html.base.api())
  }

  def user(name: String) = ApiRequest { implicit ctx =>
    userApi.one(name, ctx.me) map toApiResult
  }

  private val UsersRateLimitGlobal = new lila.memo.RateLimit[String](
    credits = 1000,
    duration = 1 minute,
    name = "team users API global",
    key = "team_users.api.global"
  )

  private val UsersRateLimitPerIP = new lila.memo.RateLimit[IpAddress](
    credits = 1000,
    duration = 10 minutes,
    name = "team users API per IP",
    key = "team_users.api.ip"
  )

  def users = ApiRequest { implicit ctx =>
    val page = (getInt("page") | 1) atLeast 1 atMost 50
    val nb = (getInt("nb") | 10) atLeast 1 atMost 50
    val cost = page * nb + 10
    val ip = HTTPRequest lastRemoteAddress ctx.req
    UsersRateLimitPerIP(ip, cost = cost) {
      UsersRateLimitGlobal("-", cost = cost, msg = ip.value) {
        lila.mon.api.teamUsers.cost(cost)
        (get("team") ?? Env.team.api.team).flatMap {
          _ ?? { team =>
            Env.team.pager(team, page, MaxPerPage(nb)) map userApi.pager map some
          }
        } map toApiResult
      }
    }
  }

  def usersByIds = OpenBody(parse.tolerantText) { implicit ctx =>
    val usernames = ctx.body.body.split(',').take(300).toList
    val ip = HTTPRequest lastRemoteAddress ctx.req
    val cost = usernames.size / 4
    UsersRateLimitPerIP(ip, cost = cost) {
      UsersRateLimitGlobal("-", cost = cost, msg = ip.value) {
        lila.mon.api.users.cost(cost)
        lila.user.UserRepo nameds usernames map {
          _.map { Env.user.jsonView(_, none) }
        } map toApiResult map toHttp
      }
    }
  }

  def usersStatus = ApiRequest { implicit ctx =>
    val ids = get("ids").??(_.split(',').take(40).toList map lila.user.User.normalize)
    Env.user.lightUserApi asyncMany ids dmap (_.flatten) map { users =>
      val actualIds = users.map(_.id)
      val onlineIds = Env.user.onlineUserIdMemo intersect actualIds
      val playingIds = Env.relation.online.playing intersect actualIds
      val streamingIds = Env.streamer.liveStreamApi.userIds
      toApiResult {
        users.map { u =>
          lila.common.LightUser.lightUserWrites.writes(u)
            .add("online" -> onlineIds(u.id))
            .add("playing" -> playingIds(u.id))
            .add("streaming" -> streamingIds(u.id))
        }
      }
    }
  }

  private val UserGamesRateLimitPerIP = new lila.memo.RateLimit[IpAddress](
    credits = 10 * 1000,
    duration = 10 minutes,
    name = "user games API per IP",
{'fraction_non_alphanumeric': 0.11941104957449683, 'fraction_numerical': 0.009725786843171687, 'mean_word_length': 2.5906886517943746, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 38, 'https://': 0, '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': '2850964', 'n_tokens_mistral': 2468, 'n_tokens_neox': 2399, 'n_words': 559}