complete user activity feed API - closes #3473
parent
7d75dc4044
commit
42e8ffe9c3
|
@ -316,8 +316,6 @@ name | type | default | description
|
|||
|
||||
### `GET /api/user/<username>/activity` fetch recent user activity
|
||||
|
||||
This API is a work in progress
|
||||
|
||||
```
|
||||
> curl https://lichess.org/api/user/thibault/activityy
|
||||
```
|
||||
|
|
|
@ -62,12 +62,12 @@ final class ActivityReadApi(
|
|||
}
|
||||
}
|
||||
}
|
||||
simuls <- a.simuls ?? { simuls =>
|
||||
simuls <- a.simuls.?? { simuls =>
|
||||
simulApi byIds simuls.value.map(_.value) dmap some
|
||||
}
|
||||
studies <- a.studies ?? { studies =>
|
||||
}.map(_ filter (_.nonEmpty))
|
||||
studies <- a.studies.?? { studies =>
|
||||
studyApi publicIdNames studies.value map some
|
||||
}
|
||||
}.map(_ filter (_.nonEmpty))
|
||||
tours <- a.games.exists(_.hasNonCorres) ?? {
|
||||
val dateRange = a.date -> a.date.plusDays(1)
|
||||
tourLeaderApi.timeRange(a.id.userId, dateRange) map { entries =>
|
||||
|
|
|
@ -16,7 +16,8 @@ final class Env(
|
|||
studyApi: lila.study.StudyApi,
|
||||
lightUserApi: lila.user.LightUserApi,
|
||||
tourLeaderApi: lila.tournament.LeaderboardApi,
|
||||
getTourName: lila.tournament.Tournament.ID => Option[String]
|
||||
getTourName: lila.tournament.Tournament.ID => Option[String],
|
||||
getTeamName: lila.team.Team.ID => Option[String]
|
||||
) {
|
||||
|
||||
private val activityColl = db(config getString "collection.activity")
|
||||
|
@ -37,7 +38,8 @@ final class Env(
|
|||
|
||||
lazy val jsonView = new JsonView(
|
||||
lightUserApi = lightUserApi,
|
||||
getTourName = getTourName
|
||||
getTourName = getTourName,
|
||||
getTeamName = getTeamName
|
||||
)
|
||||
|
||||
system.lilaBus.subscribe(
|
||||
|
@ -75,6 +77,7 @@ object Env {
|
|||
studyApi = lila.study.Env.current.api,
|
||||
lightUserApi = lila.user.Env.current.lightUserApi,
|
||||
tourLeaderApi = lila.tournament.Env.current.leaderboardApi,
|
||||
getTourName = lila.tournament.Env.current.cached.name _
|
||||
getTourName = lila.tournament.Env.current.cached.name _,
|
||||
getTeamName = lila.team.Env.current.cached.name _
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,8 +5,12 @@ import play.api.libs.json._
|
|||
|
||||
import lila.common.Iso
|
||||
import lila.common.PimpedJson._
|
||||
import lila.game.JsonView.colorWrites
|
||||
import lila.game.Pov
|
||||
import lila.rating.PerfType
|
||||
import lila.simul.Simul
|
||||
import lila.study.JsonView.studyIdNameWrites
|
||||
import lila.team.Team
|
||||
import lila.tournament.JsonView._
|
||||
import lila.tournament.LeaderboardApi.{ Entry => TourEntry, Ratio => TourRatio }
|
||||
import lila.tournament.Tournament
|
||||
|
@ -18,7 +22,8 @@ import model._
|
|||
|
||||
final class JsonView(
|
||||
lightUserApi: lila.user.LightUserApi,
|
||||
getTourName: Tournament.ID => Option[String]
|
||||
getTourName: Tournament.ID => Option[String],
|
||||
getTeamName: Team.ID => Option[String]
|
||||
) {
|
||||
|
||||
private object Writers {
|
||||
|
@ -42,7 +47,8 @@ final class JsonView(
|
|||
implicit val variantWrites: Writes[chess.variant.Variant] = Writes { v =>
|
||||
JsString(v.key)
|
||||
}
|
||||
implicit val tourRatioWrites = intIsoWriter(Iso.int[TourRatio](r => TourRatio(r.toDouble), _.value.toInt))
|
||||
// writes as percentage
|
||||
implicit val tourRatioWrites = intIsoWriter(Iso.int[TourRatio](r => TourRatio(r.toDouble / 100), r => (r.value * 100).toInt))
|
||||
implicit val tourEntryWrites = OWrites[TourEntry] { e =>
|
||||
Json.obj(
|
||||
"tournament" -> Json.obj(
|
||||
|
@ -52,7 +58,7 @@ final class JsonView(
|
|||
"nbGames" -> e.nbGames,
|
||||
"score" -> e.score,
|
||||
"rank" -> e.rank,
|
||||
"rankRatio" -> e.rankRatio
|
||||
"rankPercent" -> e.rankRatio
|
||||
)
|
||||
}
|
||||
implicit val toursWrites = Json.writes[ActivityView.Tours]
|
||||
|
@ -66,14 +72,40 @@ final class JsonView(
|
|||
"score" -> Score(s.wins, s.losses, s.draws, none)
|
||||
)
|
||||
}
|
||||
implicit val playerWrites = OWrites[lila.game.Player] { p =>
|
||||
Json.obj()
|
||||
.add("aiLevel" -> p.aiLevel)
|
||||
.add("user" -> p.userId)
|
||||
.add("rating" -> p.rating)
|
||||
}
|
||||
implicit val povWrites = OWrites[Pov] { p =>
|
||||
Json.obj(
|
||||
"id" -> p.gameId,
|
||||
"color" -> p.color,
|
||||
"url" -> s"/${p.gameId}/${p.color.name}",
|
||||
"variant" -> p.game.variant,
|
||||
"speed" -> p.game.speed.key,
|
||||
"perf" -> lila.game.PerfPicker.key(p.game),
|
||||
"rated" -> p.game.rated,
|
||||
"opponent" -> p.opponent
|
||||
)
|
||||
}
|
||||
implicit val followListWrites = Json.writes[FollowList]
|
||||
implicit val followsWrites = Json.writes[Follows]
|
||||
implicit val teamsWrites = Writes[Teams] { s =>
|
||||
JsArray(s.value.map { id =>
|
||||
Json.obj("url" -> s"/team/$id", "name" -> getTeamName(id))
|
||||
})
|
||||
}
|
||||
implicit val patronWrites = Json.writes[Patron]
|
||||
}
|
||||
import Writers._
|
||||
|
||||
def apply(a: ActivityView, user: User): Fu[JsObject] = fuccess {
|
||||
Json.obj("interval" -> a.interval)
|
||||
.add("games", a.games map gamesWrites.writes)
|
||||
.add("puzzles", a.puzzles map puzzlesWrites.writes)
|
||||
.add("tournaments", a.tours map toursWrites.writes)
|
||||
.add("games", a.games)
|
||||
.add("puzzles", a.puzzles)
|
||||
.add("tournaments", a.tours)
|
||||
.add("practice", a.practice.map(_.toList.sortBy(-_._2) map {
|
||||
case (study, nb) => Json.obj(
|
||||
"url" -> s"/practice/-/${study.slug}/${study.id}",
|
||||
|
@ -82,5 +114,27 @@ final class JsonView(
|
|||
)
|
||||
}))
|
||||
.add("simuls", a.simuls.map(_ map simulWrites(user).writes))
|
||||
.add("correspondenceMoves", a.corresMoves.map {
|
||||
case (nb, povs) => Json.obj("nb" -> nb, "games" -> povs)
|
||||
})
|
||||
.add("correspondenceEnds", a.corresEnds.map {
|
||||
case (score, povs) => Json.obj("score" -> score, "games" -> povs)
|
||||
})
|
||||
.add("follows" -> a.follows)
|
||||
.add("studies" -> a.studies)
|
||||
.add("teams" -> a.teams)
|
||||
.add("posts" -> a.posts.map(_ map {
|
||||
case (topic, posts) => Json.obj(
|
||||
"topicUrl" -> s"/forum/${topic.categId}/${topic.slug}",
|
||||
"topicName" -> topic.name,
|
||||
"posts" -> posts.map { p =>
|
||||
Json.obj(
|
||||
"url" -> s"/forum/redirect/post/${p.id}",
|
||||
"text" -> p.text.take(500)
|
||||
)
|
||||
}
|
||||
)
|
||||
}))
|
||||
.add("patron" -> a.patron)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,11 +355,4 @@ object Event {
|
|||
"watchers" -> watchers
|
||||
)
|
||||
}
|
||||
|
||||
private implicit val colorWriter: Writes[Color] = Writes { c =>
|
||||
JsString(c.name)
|
||||
}
|
||||
private implicit val statusWriter: OWrites[Status] = OWrites { s =>
|
||||
Json.obj("id" -> s.id, "name" -> s.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ object JsonView {
|
|||
"rated" -> game.rated,
|
||||
"initialFen" -> (initialFen | chess.format.Forsyth.initial),
|
||||
"fen" -> (Forsyth >> game.toChess),
|
||||
"player" -> game.turnColor.name,
|
||||
"player" -> game.turnColor,
|
||||
"turns" -> game.turns,
|
||||
"startedAtTurn" -> game.startedAtTurn,
|
||||
"source" -> game.source,
|
||||
|
@ -26,12 +26,12 @@ object JsonView {
|
|||
).add("threefold" -> game.toChessHistory.threefoldRepetition)
|
||||
.add("boosted" -> game.boosted)
|
||||
.add("tournamentId" -> game.tournamentId)
|
||||
.add("winner" -> game.winnerColor.map(_.name))
|
||||
.add("winner" -> game.winnerColor)
|
||||
.add("lastMove" -> game.castleLastMoveTime.lastMoveString)
|
||||
.add("check" -> game.check.map(_.key))
|
||||
.add("rematch" -> game.next)
|
||||
|
||||
implicit val statusWriter: OWrites[chess.Status] = OWrites { s =>
|
||||
implicit val statusWrites: OWrites[chess.Status] = OWrites { s =>
|
||||
Json.obj(
|
||||
"id" -> s.id,
|
||||
"name" -> s.name
|
||||
|
@ -115,4 +115,8 @@ object JsonView {
|
|||
}
|
||||
|
||||
implicit val sourceWriter: Writes[Source] = Writes { s => JsString(s.name) }
|
||||
|
||||
implicit val colorWrites: Writes[Color] = Writes { c =>
|
||||
JsString(c.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,9 @@ object JsonView {
|
|||
|
||||
implicit val studyIdWrites: Writes[Study.Id] = stringIsoWriter(Study.idIso)
|
||||
implicit val studyNameWrites: Writes[Study.Name] = stringIsoWriter(Study.nameIso)
|
||||
implicit val studyIdNameWrites = OWrites[Study.IdName] { s =>
|
||||
Json.obj("id" -> s._id, "name" -> s.name)
|
||||
}
|
||||
implicit val chapterIdWrites: Writes[Chapter.Id] = stringIsoWriter(Chapter.idIso)
|
||||
implicit val chapterNameWrites: Writes[Chapter.Name] = stringIsoWriter(Chapter.nameIso)
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ object ApplicationBuild extends Build {
|
|||
libraryDependencies ++= provided(play.api, reactivemongo.driver)
|
||||
)
|
||||
|
||||
lazy val activity = project("activity", Seq(common, game, analyse, user, forum, study, pool, puzzle, tournament, practice)).settings(
|
||||
lazy val activity = project("activity", Seq(common, game, analyse, user, forum, study, pool, puzzle, tournament, practice, team)).settings(
|
||||
libraryDependencies ++= provided(play.api, reactivemongo.driver)
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue