lila/app/controllers/User.scala
2014-06-02 01:01:39 +02:00

184 lines
6.4 KiB
Scala

package controllers
import play.api.mvc._, Results._
import lila.api.Context
import lila.app._
import lila.common.LilaCookie
import lila.db.api.$find
import lila.game.GameRepo
import lila.security.Permission
import lila.user.tube.userTube
import lila.user.{ User => UserModel, UserRepo }
import views._
object User extends LilaController {
private def env = Env.user
private def gamePaginator = Env.game.paginator
private def forms = lila.user.DataForm
private def relationApi = Env.relation.api
def show(username: String) = Open { implicit ctx =>
filter(username, none, 1)
}
def showMini(username: String) = Open { implicit ctx =>
OptionFuResult(UserRepo named username) { user =>
GameRepo nowPlaying user.id zip
(ctx.userId ?? { relationApi.blocks(user.id, _) }) zip
(ctx.userId ?? { relationApi.follows(user.id, _) }) zip
(ctx.isAuth ?? { Env.pref.api.followable(user.id) }) zip
(ctx.userId ?? { relationApi.relation(_, user.id) }) map {
case ((((game, blocked), followed), followable), relation) =>
Ok(html.user.mini(user, game, blocked, followed, followable, relation))
.withHeaders(CACHE_CONTROL -> "max-age=5")
}
}
}
def showFilter(username: String, filterName: String, page: Int) = Open { implicit ctx =>
filter(username, filterName.some, page)
}
def online = Open { implicit req =>
val max = 1000
UserRepo.byIdsSortRating(env.onlineUserIdMemo.keys, max) map { html.user.online(_, max) }
}
private def filter(
username: String,
filterOption: Option[String],
page: Int,
status: Results.Status = Results.Ok)(implicit ctx: Context) =
Reasonable(page) {
OptionFuResult(UserRepo named username) { u =>
(u.enabled || isGranted(_.UserSpy)).fold({
userShow(u, filterOption, page) map { status(_) }
}, UserRepo isArtificial u.id map { artificial =>
NotFound(html.user.disabled(u, artificial))
})
}
}
private def userShow(u: UserModel, filterOption: Option[String], page: Int)(implicit ctx: Context) = for {
info Env.current.userInfo(u, ctx)
filterName = filterOption | (if (info.nbWithMe > 0) "me" else "all")
filters = mashup.GameFilterMenu(info, ctx.me, filterName)
pag (filters.query.fold(Env.bookmark.api.gamePaginatorByUser(u, page)) { query =>
gamePaginator.recentlyCreated(query, filters.cachedNb)(page)
})
data <- GameRepo isNowPlaying u.id
relation <- ctx.userId ?? { relationApi.relation(_, u.id) }
notes <- ctx.me ?? { me =>
relationApi friends me.id flatMap { env.noteApi.get(u, me, _) }
}
followable <- ctx.isAuth ?? { Env.pref.api followable u.id }
blocked <- ctx.userId ?? { relationApi.blocks(u.id, _) }
} yield html.user.show(u, info, pag, filters, relation, notes, followable, blocked)
def list(page: Int) = Open { implicit ctx =>
Reasonable(page) {
val nb = 10
for {
progressDay env.cached topProgressDay nb
tourneyWinners Env.tournament.winners scheduled nb
toint <- env.cached topToints nb
rating env.cached topRating nb
ratingDay env.cached topRatingDay nb
ratingWeek env.cached topRatingWeek nb
online env.cached topOnline 30
bullet env.cached topBullet nb
blitz env.cached topBlitz nb
slow env.cached topSlow nb
active env.cached topNbGame nb map2 { (user: UserModel) =>
user -> user.count.game
}
activeDay Env.game.cached activePlayerUidsDay nb flatMap { pairs =>
UserRepo.byOrderedIds(pairs.map(_._1)) map (_ zip pairs.map(_._2))
}
activeWeek Env.game.cached activePlayerUidsWeek nb flatMap { pairs =>
UserRepo.byOrderedIds(pairs.map(_._1)) map (_ zip pairs.map(_._2))
}
} yield html.user.list(
progressDay = progressDay,
tourneyWinners = tourneyWinners,
toint = toint,
rating = rating,
ratingDay = ratingDay,
ratingWeek = ratingWeek,
online = online,
bullet = bullet,
blitz = blitz,
slow = slow,
nb = active,
nbDay = activeDay,
nbWeek = activeWeek)
}
}
def leaderboard = Open { implicit ctx =>
UserRepo topRating 500 map { users =>
html.user.leaderboard(users)
}
}
def mod(username: String) = Secure(_.UserSpy) { implicit ctx =>
me => OptionFuOk(UserRepo named username) { user =>
Env.evaluation.evaluator find user zip
(Env.security userSpy user.id) map {
case (eval, spy) => html.user.mod(user, spy, eval)
}
}
}
def evaluate(username: String) = Secure(_.UserEvaluate) { implicit ctx =>
me => OptionFuResult(UserRepo named username) { user =>
Env.evaluation.evaluator.generate(user, true) inject Redirect(routes.User.show(username).url + "?mod")
}
}
def writeNote(username: String) = AuthBody { implicit ctx =>
me => OptionFuResult(UserRepo named username) { user =>
implicit val req = ctx.body
env.forms.note.bindFromRequest.fold(
err => filter(username, none, 1, Results.BadRequest),
text => env.noteApi.write(user, text, me) inject Redirect(routes.User.show(username).url + "?note")
)
}
}
def opponents(username: String) = Open { implicit ctx =>
OptionFuOk(UserRepo named username) { user =>
lila.game.BestOpponents(user.id, 50) flatMap { ops =>
ctx.isAuth.fold(
Env.pref.api.followables(ops map (_._1.id)),
fuccess(List.fill(50)(true))
) flatMap { followables =>
(ops zip followables).map {
case ((u, nb), followable) => ctx.userId ?? { myId =>
relationApi.relation(myId, u.id)
} map { lila.relation.Related(u, nb, followable, _) }
}.sequenceFu map { relateds =>
html.user.opponents(user, relateds)
}
}
}
}
}
def autocomplete = Open { implicit ctx =>
get("term", ctx.req).filter(_.nonEmpty).fold(BadRequest("No search term provided").fuccess: Fu[Result]) { term =>
JsonOk(UserRepo usernamesLike term)
}
}
def export(username: String) = Open { implicit ctx =>
OptionFuResult(UserRepo named username) { u =>
Env.game export u map { url =>
Redirect(Env.api.Net.Protocol + Env.api.Net.AssetDomain + url)
}
}
}
}