Remove all mongodb objectids. They suck.
This commit is contained in:
parent
d0c41f3a33
commit
2adb874471
|
@ -22,7 +22,7 @@ object User extends LilaController {
|
|||
def show(username: String) = showFilter(username, "all", 1)
|
||||
|
||||
def showFilter(username: String, filterName: String, page: Int) = Open { implicit ctx ⇒
|
||||
IOptionIOk(userRepo byUsername username) { u ⇒
|
||||
IOptionIOk(userRepo byId username) { u ⇒
|
||||
u.enabled.fold(
|
||||
env.user.userInfo(u, ctx) map { info ⇒
|
||||
val filters = user.GameFilterMenu(info, ctx.me, filterName)
|
||||
|
@ -79,7 +79,7 @@ object User extends LilaController {
|
|||
_ ⇒
|
||||
IORedirect {
|
||||
for {
|
||||
uOption ← userRepo byUsername username
|
||||
uOption ← userRepo byId username
|
||||
_ ← uOption.filter(_.elo > UserModel.STARTING_ELO).fold(
|
||||
u ⇒ eloUpdater.adjust(u, UserModel.STARTING_ELO) flatMap { _ ⇒
|
||||
userRepo setEngine u
|
||||
|
@ -101,5 +101,5 @@ object User extends LilaController {
|
|||
def export(username: String) = TODO
|
||||
|
||||
private val onlineUsers: IO[List[UserModel]] =
|
||||
userRepo byUsernames env.user.usernameMemo.keys
|
||||
userRepo byIds env.user.usernameMemo.keys
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package lila
|
|||
package core
|
||||
|
||||
import com.mongodb.casbah.MongoConnection
|
||||
import com.mongodb.{ DBRef, Mongo, MongoOptions, ServerAddress ⇒ MongoServer }
|
||||
import com.mongodb.{ Mongo, MongoOptions, ServerAddress ⇒ MongoServer }
|
||||
|
||||
import akka.actor._
|
||||
|
||||
|
@ -26,8 +26,7 @@ final class CoreEnv private (application: Application, val settings: Settings) {
|
|||
lazy val user = new lila.user.UserEnv(
|
||||
settings = settings,
|
||||
mongodb = mongodb.apply _,
|
||||
gameRepo = game.gameRepo,
|
||||
dbRef = namespace ⇒ id ⇒ mongodb.ref(namespace, id))
|
||||
gameRepo = game.gameRepo)
|
||||
|
||||
lazy val forum = new lila.forum.ForumEnv(
|
||||
settings = settings,
|
||||
|
@ -57,14 +56,13 @@ final class CoreEnv private (application: Application, val settings: Settings) {
|
|||
userRepo = user.userRepo,
|
||||
timelinePush = timeline.push.apply,
|
||||
roundMessenger = round.messenger,
|
||||
ai = ai.ai,
|
||||
userDbRef = user.userRepo.dbRef)
|
||||
ai = ai.ai)
|
||||
|
||||
lazy val timeline = new lila.timeline.TimelineEnv(
|
||||
settings = settings,
|
||||
mongodb = mongodb.apply _,
|
||||
lobbyNotify = lobby.socket.addEntry,
|
||||
getUsername = user.cached.username)
|
||||
getUsername = user.cached.usernameOrAnonymous)
|
||||
|
||||
lazy val ai = new lila.ai.AiEnv(
|
||||
settings = settings)
|
||||
|
|
|
@ -3,7 +3,6 @@ package forum
|
|||
|
||||
import com.novus.salat._
|
||||
import com.novus.salat.dao._
|
||||
import com.mongodb.DBRef
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import com.mongodb.casbah.Imports._
|
||||
import scalaz.effects._
|
||||
|
|
|
@ -8,10 +8,10 @@ import play.api.templates.Html
|
|||
trait ForumHelper { self: UserHelper ⇒
|
||||
|
||||
def authorName(post: Post) =
|
||||
post.userIdString.fold(userIdToUsername, post.showAuthor)
|
||||
post.userId.fold(userIdToUsername, post.showAuthor)
|
||||
|
||||
def authorLink(post: Post, cssClass: Option[String] = None) =
|
||||
post.userIdString.fold(
|
||||
post.userId.fold(
|
||||
userId ⇒ userIdLink(userId.some, cssClass),
|
||||
Html("""<span class="%s">%s</span>"""
|
||||
.format(cssClass | "", authorName(post)))
|
||||
|
|
|
@ -3,7 +3,6 @@ package forum
|
|||
|
||||
import org.joda.time.DateTime
|
||||
import com.novus.salat.annotations.Key
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import ornicar.scalalib.OrnicarRandom
|
||||
|
||||
import user.User
|
||||
|
@ -12,14 +11,12 @@ case class Post(
|
|||
@Key("_id") id: String,
|
||||
topicId: String,
|
||||
author: Option[String],
|
||||
userId: Option[ObjectId],
|
||||
userId: Option[String],
|
||||
text: String,
|
||||
number: Int,
|
||||
createdAt: DateTime) {
|
||||
|
||||
def showAuthor = (author map (_.trim) filter ("" !=)) | User.anonymous
|
||||
|
||||
def userIdString: Option[String] = userId map (_.toString)
|
||||
}
|
||||
|
||||
object Post {
|
||||
|
@ -29,7 +26,7 @@ object Post {
|
|||
def apply(
|
||||
topicId: String,
|
||||
author: Option[String],
|
||||
userId: Option[ObjectId],
|
||||
userId: Option[String],
|
||||
text: String,
|
||||
number: Int): Post = Post(
|
||||
id = OrnicarRandom nextAsciiString idSize,
|
||||
|
|
|
@ -3,7 +3,6 @@ package forum
|
|||
|
||||
import com.novus.salat._
|
||||
import com.novus.salat.dao._
|
||||
import com.mongodb.DBRef
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import com.mongodb.casbah.Imports._
|
||||
import scalaz.effects._
|
||||
|
|
|
@ -4,8 +4,6 @@ package game
|
|||
import chess._
|
||||
import user.User
|
||||
|
||||
import com.mongodb.DBRef
|
||||
|
||||
case class DbPlayer(
|
||||
id: String,
|
||||
color: Color,
|
||||
|
@ -16,7 +14,7 @@ case class DbPlayer(
|
|||
isOfferingRematch: Boolean = false,
|
||||
lastDrawOffer: Option[Int] = None,
|
||||
isProposingTakeback: Boolean = false,
|
||||
user: Option[DBRef] = None,
|
||||
userId: Option[String] = None,
|
||||
elo: Option[Int] = None,
|
||||
eloDiff: Option[Int] = None,
|
||||
moveTimes: String = "",
|
||||
|
@ -34,23 +32,17 @@ case class DbPlayer(
|
|||
ps = encodePieces(allPieces)
|
||||
)
|
||||
|
||||
def withUser(user: User)(dbRef: User ⇒ DBRef): DbPlayer = copy(
|
||||
user = dbRef(user).some,
|
||||
def withUser(user: User): DbPlayer = copy(
|
||||
userId = user.id.some,
|
||||
elo = user.elo.some)
|
||||
|
||||
def isAi = aiLevel.isDefined
|
||||
|
||||
def isHuman = !isAi
|
||||
|
||||
def userId: Option[String] = user map (_.getId.toString)
|
||||
def hasUser = userId.isDefined
|
||||
|
||||
def hasUser = user.isDefined
|
||||
|
||||
def isUser(u: User) = user.fold(_.getId == u.id, false)
|
||||
|
||||
def withUser(u: User, ref: DBRef) = copy(
|
||||
elo = u.elo.some,
|
||||
user = ref.some)
|
||||
def isUser(u: User) = userId.fold(_ == u.id, false)
|
||||
|
||||
def wins = isWinner getOrElse false
|
||||
|
||||
|
@ -82,12 +74,12 @@ case class DbPlayer(
|
|||
aiLevel = aiLevel,
|
||||
w = isWinner,
|
||||
elo = elo,
|
||||
eloDiff = eloDiff,
|
||||
ed = eloDiff,
|
||||
isOfferingDraw = if (isOfferingDraw) Some(true) else None,
|
||||
isOfferingRematch = if (isOfferingRematch) Some(true) else None,
|
||||
lastDrawOffer = lastDrawOffer,
|
||||
isProposingTakeback = if (isProposingTakeback) Some(true) else None,
|
||||
user = user,
|
||||
userId = userId,
|
||||
mts = Some(moveTimes) filter ("" !=),
|
||||
blurs = Some(blurs) filter (0 !=)
|
||||
)
|
||||
|
@ -114,12 +106,12 @@ case class RawDbPlayer(
|
|||
aiLevel: Option[Int],
|
||||
w: Option[Boolean],
|
||||
elo: Option[Int],
|
||||
eloDiff: Option[Int],
|
||||
ed: Option[Int],
|
||||
isOfferingDraw: Option[Boolean],
|
||||
isOfferingRematch: Option[Boolean],
|
||||
lastDrawOffer: Option[Int],
|
||||
isProposingTakeback: Option[Boolean],
|
||||
user: Option[DBRef],
|
||||
userId: Option[String],
|
||||
mts: Option[String],
|
||||
blurs: Option[Int]) {
|
||||
|
||||
|
@ -132,12 +124,12 @@ case class RawDbPlayer(
|
|||
aiLevel = aiLevel,
|
||||
isWinner = w,
|
||||
elo = elo,
|
||||
eloDiff = eloDiff,
|
||||
eloDiff = ed,
|
||||
isOfferingDraw = isOfferingDraw | false,
|
||||
isOfferingRematch = isOfferingRematch | false,
|
||||
lastDrawOffer = lastDrawOffer,
|
||||
isProposingTakeback = isProposingTakeback | false,
|
||||
user = user,
|
||||
userId = userId,
|
||||
moveTimes = mts | "",
|
||||
blurs = blurs | 0
|
||||
)
|
||||
|
|
|
@ -71,16 +71,16 @@ class GameRepo(collection: MongoCollection)
|
|||
update(idSelector(id), $set("players.0.eloDiff" -> white, "players.1.eloDiff" -> black))
|
||||
}
|
||||
|
||||
def setUser(id: String, color: Color, dbRef: DBRef, elo: Int) = io {
|
||||
def setUser(id: String, color: Color, user: User) = io {
|
||||
val pn = "players.%d".format(color.fold(0, 1))
|
||||
update(idSelector(id), $set(pn + ".user" -> dbRef, pn + ".elo" -> elo))
|
||||
update(idSelector(id), $set(pn + ".userId" -> user.id, pn + ".elo" -> user.elo))
|
||||
}
|
||||
|
||||
def finish(id: String, winnerId: Option[String]) = io {
|
||||
update(
|
||||
idSelector(id),
|
||||
winnerId.fold(userId ⇒
|
||||
$set("positionHashes" -> "", "winnerUserId" -> userId),
|
||||
$set("positionHashes" -> "", "winId" -> userId),
|
||||
$set("positionHashes" -> ""))
|
||||
++ $unset(
|
||||
"players.0.previousMoveTs",
|
||||
|
@ -157,22 +157,6 @@ class GameRepo(collection: MongoCollection)
|
|||
find("_id" $in ids).toList.map(_.decode).flatten sortBy (_.id)
|
||||
}
|
||||
|
||||
def ensureIndexes: IO[Unit] = io {
|
||||
collection.underlying |> { coll ⇒
|
||||
coll.ensureIndex(DBObject("status" -> 1))
|
||||
coll.ensureIndex(DBObject("userIds" -> 1))
|
||||
coll.ensureIndex(DBObject("winnerUserId" -> 1))
|
||||
coll.ensureIndex(DBObject("turns" -> 1))
|
||||
coll.ensureIndex(DBObject("updatedAt" -> -1))
|
||||
coll.ensureIndex(DBObject("createdAt" -> -1))
|
||||
coll.ensureIndex(DBObject("createdAt" -> -1, "userIds" -> 1))
|
||||
}
|
||||
}
|
||||
|
||||
def dropIndexes: IO[Unit] = io {
|
||||
collection.dropIndexes()
|
||||
}
|
||||
|
||||
private def idSelector(game: DbGame): DBObject = idSelector(game.id)
|
||||
private def idSelector(id: String): DBObject = DBObject("_id" -> id)
|
||||
}
|
||||
|
|
|
@ -29,19 +29,19 @@ object Query {
|
|||
|
||||
def clock(c: Boolean): DBObject = "clock.l" $exists c
|
||||
|
||||
def user(u: User): DBObject = DBObject("userIds" -> u.idString)
|
||||
def user(u: User): DBObject = DBObject("userIds" -> u.id)
|
||||
|
||||
def started(u: User): DBObject = user(u) ++ started
|
||||
|
||||
def rated(u: User): DBObject = user(u) ++ rated
|
||||
|
||||
def win(u: User): DBObject = DBObject("winnerUserId" -> u.idString)
|
||||
def win(u: User): DBObject = DBObject("winId" -> u.id)
|
||||
|
||||
def draw(u: User): DBObject = user(u) ++ draw
|
||||
|
||||
def loss(u: User): DBObject = user(u) ++ finished ++ ("winnerUserId" $ne u.idString)
|
||||
def loss(u: User): DBObject = user(u) ++ finished ++ ("winId" $ne u.id)
|
||||
|
||||
def playing(u: User): DBObject = user(u) ++ playing
|
||||
|
||||
def opponents(u1: User, u2: User) = "userIds" $all List(u1.idString, u2.idString)
|
||||
def opponents(u1: User, u2: User) = "userIds" $all List(u1.id, u2.id)
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ object Hook {
|
|||
increment = clock map (_.increment),
|
||||
mode = mode.id,
|
||||
color = color,
|
||||
userId = user map (_.idString),
|
||||
userId = user map (_.id),
|
||||
username = user.fold(_.username, User.anonymous),
|
||||
elo = user map (_.elo),
|
||||
eloRange = eloRange.toString,
|
||||
|
|
|
@ -8,7 +8,6 @@ import play.api.i18n.Lang
|
|||
import play.api.i18n.MessagesPlugin
|
||||
import scalaz.effects._
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import com.mongodb.DBRef
|
||||
|
||||
import user.{ User, UserRepo }
|
||||
import game.{ GameRepo, DbGame }
|
||||
|
|
|
@ -13,7 +13,7 @@ final class Messenger(
|
|||
private val urlRegex = """lichess\.org/([\w-]{8})[\w-]{4}""".r
|
||||
|
||||
def apply(text: String, username: String): IO[Valid[Message]] = for {
|
||||
userOption ← userRepo byUsername username
|
||||
userOption ← userRepo byId username
|
||||
message = for {
|
||||
user ← userOption toValid "Unknown user"
|
||||
msg ← createMessage(text, user)
|
||||
|
@ -35,7 +35,7 @@ final class Messenger(
|
|||
}
|
||||
|
||||
def ban(username: String): IO[Unit] = for {
|
||||
userOption ← userRepo byUsername username
|
||||
userOption ← userRepo byId username
|
||||
_ ← userOption.fold(
|
||||
user ⇒ for {
|
||||
_ ← userRepo toggleChatBan user
|
||||
|
|
|
@ -26,7 +26,7 @@ final class DataForm(userRepo: UserRepo) {
|
|||
))
|
||||
|
||||
private def fetchUser(username: String) =
|
||||
(userRepo byUsername username).unsafePerformIO
|
||||
(userRepo byId username).unsafePerformIO
|
||||
|
||||
private def usernameExists(username: String) =
|
||||
fetchUser(username).isDefined
|
||||
|
|
|
@ -2,7 +2,6 @@ package lila
|
|||
package message
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import ornicar.scalalib.OrnicarRandom
|
||||
|
||||
case class Post(
|
||||
|
|
|
@ -5,7 +5,6 @@ import user.User
|
|||
|
||||
import org.joda.time.DateTime
|
||||
import com.novus.salat.annotations.Key
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import ornicar.scalalib.OrnicarRandom
|
||||
|
||||
case class Thread(
|
||||
|
@ -14,9 +13,9 @@ case class Thread(
|
|||
createdAt: DateTime,
|
||||
updatedAt: DateTime,
|
||||
posts: List[Post],
|
||||
creatorId: ObjectId,
|
||||
invitedId: ObjectId,
|
||||
visibleByUserIds: List[ObjectId]) {
|
||||
creatorId: String,
|
||||
invitedId: String,
|
||||
visibleByUserIds: List[String]) {
|
||||
|
||||
def +(post: Post) = copy(
|
||||
posts = posts :+ post,
|
||||
|
|
|
@ -26,19 +26,19 @@ final class ThreadRepo(
|
|||
|
||||
def userNbUnread(user: User): IO[Int] = userNbUnread(user.id)
|
||||
|
||||
def userNbUnread(userId: ObjectId): IO[Int] = io {
|
||||
def userNbUnread(userId: String): IO[Int] = io {
|
||||
val result = collection.mapReduce(
|
||||
mapFunction = """function() {
|
||||
var thread = this, nb = 0;
|
||||
thread.posts.forEach(function(p) {
|
||||
if (!p.isRead) {
|
||||
if (thread.creatorId.equals(ObjectId("%s"))) {
|
||||
if (thread.creatorId == "%s") {
|
||||
if (!p.isByCreator) nb++;
|
||||
} else if (p.isByCreator) nb++;
|
||||
}
|
||||
});
|
||||
if (nb > 0) emit("n", nb);
|
||||
}""" format userId.toString,
|
||||
}""" format userId,
|
||||
reduceFunction = """function(key, values) {
|
||||
var sum = 0;
|
||||
for(var i in values) { sum += values[i]; }
|
||||
|
@ -81,7 +81,7 @@ final class ThreadRepo(
|
|||
def visibleByUserQuery(user: User): DBObject =
|
||||
visibleByUserQuery(user.id)
|
||||
|
||||
def visibleByUserQuery(userId: ObjectId): DBObject =
|
||||
def visibleByUserQuery(userId: String): DBObject =
|
||||
DBObject("visibleByUserIds" -> userId)
|
||||
|
||||
def selectId(id: String) = DBObject("_id" -> id)
|
||||
|
|
|
@ -12,12 +12,12 @@ final class UnreadCache(threadRepo: ThreadRepo) {
|
|||
|
||||
def get(user: User): Int = get(user.id)
|
||||
|
||||
def get(userId: ObjectId): Int =
|
||||
def get(username: String): Int =
|
||||
cache.getOrElseUpdate(username.toLowerCase, {
|
||||
(threadRepo userNbUnread user).unsafePerformIO
|
||||
(threadRepo userNbUnread username).unsafePerformIO
|
||||
})
|
||||
|
||||
def invalidate(user: User) {
|
||||
cache -= user.usernameCanonical
|
||||
cache -= user.id
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@ package lila
|
|||
package mongodb
|
||||
|
||||
import com.mongodb.casbah.MongoConnection
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import com.mongodb.{ DBRef, Mongo, MongoOptions, ServerAddress ⇒ MongoServer }
|
||||
import com.mongodb.{ Mongo, MongoOptions, ServerAddress ⇒ MongoServer }
|
||||
|
||||
import core.Settings
|
||||
|
||||
|
@ -14,9 +13,6 @@ final class MongoDbEnv(
|
|||
|
||||
def apply(coll: String) = connection(coll)
|
||||
|
||||
def ref(namespace: String, id: ObjectId): DBRef =
|
||||
new DBRef(connection.underlying, namespace, id)
|
||||
|
||||
lazy val cache = new Cache(connection(MongoCollectionCache))
|
||||
|
||||
lazy val connection = MongoConnection(server, options)(MongoDbName)
|
||||
|
|
|
@ -85,6 +85,6 @@ trait AuthImpl {
|
|||
def restoreUser(req: RequestHeader): Option[User] = for {
|
||||
sessionId ← req.session.get("sessionId")
|
||||
username ← env.securityStore.getUsername(sessionId)
|
||||
user ← (env.user.userRepo byUsername username).unsafePerformIO
|
||||
user ← (env.user.userRepo byId username).unsafePerformIO
|
||||
} yield user
|
||||
}
|
||||
|
|
|
@ -7,22 +7,20 @@ import user.User
|
|||
import round.{ Event, Progress, Messenger }
|
||||
import controllers.routes
|
||||
|
||||
import com.mongodb.DBRef
|
||||
import scalaz.effects._
|
||||
|
||||
final class FriendJoiner(
|
||||
gameRepo: GameRepo,
|
||||
messenger: Messenger,
|
||||
timelinePush: DbGame ⇒ IO[Unit],
|
||||
userDbRef: User ⇒ DBRef) {
|
||||
timelinePush: DbGame ⇒ IO[Unit]) {
|
||||
|
||||
def apply(game: DbGame, user: Option[User]): Valid[IO[(Pov, List[Event])]] =
|
||||
game.notStarted option {
|
||||
val color = game.invitedColor
|
||||
for {
|
||||
p1 ← user.fold(
|
||||
u ⇒ gameRepo.setUser(game.id, color, userDbRef(u), u.elo) map { _ ⇒
|
||||
Progress(game, game.updatePlayer(color, _.withUser(u, userDbRef(u))))
|
||||
u ⇒ gameRepo.setUser(game.id, color, u) map { _ ⇒
|
||||
Progress(game, game.updatePlayer(color, _ withUser u))
|
||||
},
|
||||
io(Progress(game)))
|
||||
p2 = p1 withGame game.start
|
||||
|
|
|
@ -8,14 +8,12 @@ import game.{ GameRepo, DbGame, DbPlayer, Pov }
|
|||
import round.{ Messenger, Progress }
|
||||
|
||||
import scalaz.effects._
|
||||
import com.mongodb.DBRef
|
||||
|
||||
final class HookJoiner(
|
||||
hookRepo: HookRepo,
|
||||
fisherman: Fisherman,
|
||||
gameRepo: GameRepo,
|
||||
userRepo: UserRepo,
|
||||
userDbRef: User ⇒ DBRef,
|
||||
timelinePush: DbGame ⇒ IO[Unit],
|
||||
messenger: Messenger) {
|
||||
|
||||
|
@ -51,7 +49,7 @@ final class HookJoiner(
|
|||
|
||||
def blame(color: DbGame ⇒ ChessColor, userOption: Option[User], game: DbGame) =
|
||||
userOption.fold(
|
||||
user ⇒ game.updatePlayer(color(game), _.withUser(user, userDbRef(user))),
|
||||
user ⇒ game.updatePlayer(color(game), _ withUser user),
|
||||
game)
|
||||
|
||||
def makeGame(hook: Hook) = DbGame(
|
||||
|
|
|
@ -8,7 +8,6 @@ import chess.{ Game, Board }
|
|||
import ai.Ai
|
||||
import lobby.{ Hook, Fisherman }
|
||||
|
||||
import com.mongodb.DBRef
|
||||
import scalaz.effects._
|
||||
|
||||
final class Processor(
|
||||
|
@ -17,8 +16,7 @@ final class Processor(
|
|||
gameRepo: GameRepo,
|
||||
fisherman: Fisherman,
|
||||
timelinePush: DbGame ⇒ IO[Unit],
|
||||
ai: () ⇒ Ai,
|
||||
userDbRef: User ⇒ DBRef) {
|
||||
ai: () ⇒ Ai) {
|
||||
|
||||
def ai(config: AiConfig)(implicit ctx: Context): IO[Pov] = for {
|
||||
_ ← ctx.me.fold(
|
||||
|
@ -27,7 +25,7 @@ final class Processor(
|
|||
)
|
||||
pov = config.pov
|
||||
game = ctx.me.fold(
|
||||
user ⇒ pov.game.updatePlayer(pov.color, _.withUser(user, userDbRef(user))),
|
||||
user ⇒ pov.game.updatePlayer(pov.color, _ withUser user),
|
||||
pov.game)
|
||||
_ ← gameRepo insert game
|
||||
_ ← gameRepo denormalizeStarted game
|
||||
|
@ -50,7 +48,7 @@ final class Processor(
|
|||
)
|
||||
pov = config.pov
|
||||
game = ctx.me.fold(
|
||||
user ⇒ pov.game.updatePlayer(pov.color, _.withUser(user, userDbRef(user))),
|
||||
user ⇒ pov.game.updatePlayer(pov.color, _ withUser user),
|
||||
pov.game)
|
||||
_ ← gameRepo insert game
|
||||
_ ← timelinePush(game)
|
||||
|
|
|
@ -89,7 +89,7 @@ final class Rematcher(
|
|||
game.player(color).userId.fold(
|
||||
userId ⇒ userRepo byId userId map { userOption ⇒
|
||||
userOption.fold(
|
||||
user ⇒ player.withUser(user)(userRepo.dbRef),
|
||||
user ⇒ player withUser user,
|
||||
player)
|
||||
},
|
||||
io(player))
|
||||
|
|
|
@ -10,7 +10,6 @@ import user.{ User, UserRepo }
|
|||
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import scalaz.effects._
|
||||
import com.mongodb.DBRef
|
||||
|
||||
final class SetupEnv(
|
||||
settings: Settings,
|
||||
|
@ -21,8 +20,7 @@ final class SetupEnv(
|
|||
userRepo: UserRepo,
|
||||
timelinePush: DbGame ⇒ IO[Unit],
|
||||
roundMessenger: Messenger,
|
||||
ai: () ⇒ Ai,
|
||||
userDbRef: User ⇒ DBRef) {
|
||||
ai: () ⇒ Ai) {
|
||||
|
||||
import settings._
|
||||
|
||||
|
@ -37,8 +35,7 @@ final class SetupEnv(
|
|||
gameRepo = gameRepo,
|
||||
fisherman = fisherman,
|
||||
timelinePush = timelinePush,
|
||||
ai = ai,
|
||||
userDbRef = userDbRef)
|
||||
ai = ai)
|
||||
|
||||
lazy val friendConfigMemo = new FriendConfigMemo(
|
||||
ttl = SetupFriendConfigMemoTtl)
|
||||
|
@ -52,15 +49,13 @@ final class SetupEnv(
|
|||
lazy val friendJoiner = new FriendJoiner(
|
||||
gameRepo = gameRepo,
|
||||
messenger = roundMessenger,
|
||||
timelinePush = timelinePush,
|
||||
userDbRef = userDbRef)
|
||||
timelinePush = timelinePush)
|
||||
|
||||
lazy val hookJoiner = new HookJoiner(
|
||||
hookRepo = hookRepo,
|
||||
fisherman = fisherman,
|
||||
gameRepo = gameRepo,
|
||||
userRepo = userRepo,
|
||||
userDbRef = userDbRef,
|
||||
timelinePush = timelinePush,
|
||||
messenger = roundMessenger)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ case class UserConfig(
|
|||
object UserConfig {
|
||||
|
||||
def default(user: User) = UserConfig(
|
||||
id = user.usernameCanonical,
|
||||
id = user.id,
|
||||
ai = AiConfig.default,
|
||||
friend = FriendConfig.default,
|
||||
hook = HookConfig.default)
|
||||
|
|
|
@ -19,7 +19,7 @@ class UserConfigRepo(collection: MongoCollection)
|
|||
} yield ()
|
||||
|
||||
def config(user: User): IO[UserConfig] = io {
|
||||
findOneByID(user.usernameCanonical) flatMap (_.decode)
|
||||
findOneByID(user.id) flatMap (_.decode)
|
||||
} except { e ⇒
|
||||
putStrLn("Can't load config: " + e.getMessage) map (_ ⇒ none[UserConfig])
|
||||
} map (_ | UserConfig.default(user))
|
||||
|
|
|
@ -48,7 +48,7 @@ abstract class HubActor[M <: SocketMember](uidTimeout: Int) extends Actor {
|
|||
setAlive(uid)
|
||||
member(uid) foreach { m ⇒
|
||||
m.channel push m.username.fold(
|
||||
u ⇒ pong ++ JsObject(Seq("m" -> env.message.unreadCache.get(u))),
|
||||
u ⇒ pong ++ JsObject(Seq("m" -> JsNumber(unreadMessages(u)))),
|
||||
pong)
|
||||
}
|
||||
}
|
||||
|
@ -83,4 +83,7 @@ abstract class HubActor[M <: SocketMember](uidTimeout: Int) extends Actor {
|
|||
def member(uid: String): Option[M] = members get uid
|
||||
|
||||
def usernames: Iterable[String] = members.values.map(_.username).flatten
|
||||
|
||||
private def unreadMessages(username: String): Int =
|
||||
env.message.unreadCache get username
|
||||
}
|
||||
|
|
|
@ -2,25 +2,17 @@ package lila
|
|||
package user
|
||||
|
||||
import scala.collection.mutable
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
|
||||
final class Cached(userRepo: UserRepo) {
|
||||
|
||||
// idString => username|Anonymous
|
||||
val usernameCache = mutable.Map[String, String]()
|
||||
|
||||
// username => Option[ObjectId]
|
||||
val idCache = mutable.Map[String, Option[ObjectId]]()
|
||||
// id => username
|
||||
val usernameCache = mutable.Map[String, Option[String]]()
|
||||
|
||||
def username(userId: String) =
|
||||
usernameCache.getOrElseUpdate(
|
||||
userId,
|
||||
(userRepo username userId).unsafePerformIO | "Anonymous"
|
||||
userId.toLowerCase,
|
||||
(userRepo username userId).unsafePerformIO
|
||||
)
|
||||
|
||||
def id(username: String): Option[ObjectId] =
|
||||
idCache.getOrElseUpdate(
|
||||
username.toLowerCase,
|
||||
(userRepo id username).unsafePerformIO
|
||||
)
|
||||
def usernameOrAnonymous(userId: String) = username(userId) | User.anonymous
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@ final class EloUpdater(
|
|||
def game(user: User, elo: Int, gameId: String): IO[Unit] = {
|
||||
val newElo = max(elo, floor)
|
||||
userRepo.setElo(user.id, newElo) flatMap { _ ⇒
|
||||
historyRepo.addEntry(user.usernameCanonical, newElo, Some(gameId))
|
||||
historyRepo.addEntry(user.id, newElo, Some(gameId))
|
||||
}
|
||||
}
|
||||
|
||||
def adjust(user: User, elo: Int): IO[Unit] =
|
||||
userRepo.setElo(user.id, elo) flatMap { _ ⇒
|
||||
historyRepo.addEntry(user.usernameCanonical, elo, entryType = HistoryRepo.TYPE_ADJUST)
|
||||
historyRepo.addEntry(user.id, elo, entryType = HistoryRepo.TYPE_ADJUST)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ package lila
|
|||
package user
|
||||
|
||||
import com.novus.salat.annotations.Key
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import org.joda.time.DateTime
|
||||
|
||||
case class User(
|
||||
@Key("_id") id: ObjectId,
|
||||
id: String,
|
||||
username: String,
|
||||
elo: Int,
|
||||
nbGames: Int,
|
||||
|
@ -18,8 +17,6 @@ case class User(
|
|||
bio: Option[String] = None,
|
||||
engine: Boolean = false) {
|
||||
|
||||
def usernameCanonical = username.toLowerCase
|
||||
|
||||
def disabled = !enabled
|
||||
|
||||
def usernameWithElo = "%s (%d)".format(username, elo)
|
||||
|
@ -29,8 +26,6 @@ case class User(
|
|||
def nonEmptyBio = bio filter ("" !=)
|
||||
|
||||
def hasGames = nbGames > 0
|
||||
|
||||
def idString = id.toString
|
||||
}
|
||||
|
||||
object User {
|
||||
|
@ -41,7 +36,7 @@ object User {
|
|||
|
||||
// the password is hashed
|
||||
def apply(username: String): User = User(
|
||||
id = new ObjectId,
|
||||
id = username.toLowerCase,
|
||||
username = username,
|
||||
elo = STARTING_ELO,
|
||||
nbGames = 0,
|
||||
|
|
|
@ -2,8 +2,6 @@ package lila
|
|||
package user
|
||||
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import com.mongodb.DBRef
|
||||
|
||||
import chess.EloCalculator
|
||||
import game.GameRepo
|
||||
|
@ -12,16 +10,14 @@ import core.Settings
|
|||
final class UserEnv(
|
||||
settings: Settings,
|
||||
mongodb: String ⇒ MongoCollection,
|
||||
gameRepo: GameRepo,
|
||||
dbRef: String ⇒ ObjectId ⇒ DBRef) {
|
||||
gameRepo: GameRepo) {
|
||||
|
||||
import settings._
|
||||
|
||||
lazy val historyRepo = new HistoryRepo(mongodb(MongoCollectionHistory))
|
||||
|
||||
lazy val userRepo = new UserRepo(
|
||||
collection = mongodb(MongoCollectionUser),
|
||||
dbRef = user ⇒ dbRef(MongoCollectionUser)(user.id))
|
||||
collection = mongodb(MongoCollectionUser))
|
||||
|
||||
lazy val paginator = new PaginatorBuilder(
|
||||
userRepo = userRepo,
|
||||
|
|
|
@ -4,7 +4,6 @@ package user
|
|||
import core.CoreEnv
|
||||
import controllers.routes
|
||||
|
||||
import com.mongodb.casbah.Imports.ObjectId
|
||||
import play.api.templates.Html
|
||||
|
||||
trait UserHelper {
|
||||
|
@ -14,20 +13,18 @@ trait UserHelper {
|
|||
private def cached = env.user.cached
|
||||
private def usernameMemo = env.user.usernameMemo
|
||||
|
||||
def userIdToUsername(userId: String): String = cached username userId
|
||||
def userIdToUsername(userId: String): String =
|
||||
cached usernameOrAnonymous userId
|
||||
|
||||
def userIdToUsername(userId: Option[String]): String =
|
||||
userId.fold(userIdToUsername, User.anonymous)
|
||||
|
||||
def isUsernameOnline(username: String) = usernameMemo get username
|
||||
|
||||
def isUserIdOnline(userId: String) =
|
||||
usernameMemo get userIdToUsername(userId)
|
||||
|
||||
def userIdLink(
|
||||
userId: Option[String],
|
||||
cssClass: Option[String]): Html = Html {
|
||||
(userId map userIdToUsername).fold(
|
||||
(userId flatMap cached.username).fold(
|
||||
username ⇒ """<a class="user_link%s%s" href="%s">%s</a>""".format(
|
||||
isUsernameOnline(username).fold(" online", ""),
|
||||
cssClass.fold(" " + _, ""),
|
||||
|
@ -38,8 +35,8 @@ trait UserHelper {
|
|||
}
|
||||
|
||||
def userIdLink(
|
||||
userId: ObjectId,
|
||||
cssClass: Option[String]): Html = userIdLink(userId.toString.some, cssClass)
|
||||
userId: String,
|
||||
cssClass: Option[String]): Html = userIdLink(userId.some, cssClass)
|
||||
|
||||
def userLink(
|
||||
user: User,
|
||||
|
|
|
@ -3,7 +3,6 @@ package user
|
|||
|
||||
import com.novus.salat._
|
||||
import com.novus.salat.dao._
|
||||
import com.mongodb.DBRef
|
||||
import com.mongodb.casbah.{ MongoCollection, WriteConcern }
|
||||
import com.mongodb.casbah.Imports._
|
||||
import scalaz.effects._
|
||||
|
@ -11,51 +10,38 @@ import com.roundeights.hasher.Implicits._
|
|||
import ornicar.scalalib.OrnicarRandom
|
||||
|
||||
class UserRepo(
|
||||
collection: MongoCollection,
|
||||
val dbRef: User ⇒ DBRef) extends SalatDAO[User, ObjectId](collection) {
|
||||
collection: MongoCollection
|
||||
) extends SalatDAO[User, String](collection) {
|
||||
|
||||
private val enabledQuery = DBObject("enabled" -> true)
|
||||
val enabledQuery = DBObject("enabled" -> true)
|
||||
def byIdQuery(id: String): DBObject = DBObject("_id" -> normalize(id))
|
||||
def byIdQuery(user: User): DBObject = byIdQuery(user.id)
|
||||
|
||||
private def byUsernameQuery(username: String) =
|
||||
DBObject("usernameCanonical" -> username.toLowerCase)
|
||||
def normalize(id: String) = id.toLowerCase
|
||||
|
||||
private def byIdQuery(id: String) = DBObject("_id" -> new ObjectId(id))
|
||||
def byId(id: String): IO[Option[User]] = io {
|
||||
findOneByID(normalize(id))
|
||||
}
|
||||
|
||||
def byId(userId: String): IO[Option[User]] = byId(new ObjectId(userId))
|
||||
|
||||
def byId(userId: ObjectId): IO[Option[User]] = io {
|
||||
findOneByID(userId)
|
||||
def byIds(ids: Iterable[String]): IO[List[User]] = io {
|
||||
find("_id" $in ids.map(normalize)).toList
|
||||
}
|
||||
|
||||
def username(userId: String): IO[Option[String]] = io {
|
||||
primitiveProjection[String](byIdQuery(userId), "username")
|
||||
}
|
||||
|
||||
def id(username: String): IO[Option[ObjectId]] = io {
|
||||
primitiveProjection[ObjectId](byUsernameQuery(username), "_id")
|
||||
}
|
||||
|
||||
def byUsername(username: String): IO[Option[User]] = io {
|
||||
findOne(byUsernameQuery(username))
|
||||
}
|
||||
|
||||
def byUsernames(usernames: Iterable[String]): IO[List[User]] = io {
|
||||
find("usernameCanonical" $in usernames).toList
|
||||
}
|
||||
|
||||
def rank(user: User): IO[Int] = io {
|
||||
count("elo" $gt user.elo).toInt + 1
|
||||
}
|
||||
|
||||
def setElo(userId: ObjectId, elo: Int): IO[Unit] = io {
|
||||
collection.update(
|
||||
idSelector(userId),
|
||||
$set("elo" -> elo))
|
||||
def setElo(id: String, elo: Int): IO[Unit] = io {
|
||||
collection.update(byIdQuery(id), $set("elo" -> elo))
|
||||
}
|
||||
|
||||
def incNbGames(userId: String, rated: Boolean): IO[Unit] = io {
|
||||
def incNbGames(id: String, rated: Boolean): IO[Unit] = io {
|
||||
collection.update(
|
||||
DBObject("_id" -> new ObjectId(userId)),
|
||||
byIdQuery(id),
|
||||
if (rated) $inc("nbGames" -> 1, "nbRatedGames" -> 1)
|
||||
else $inc("nbGames" -> 1))
|
||||
}
|
||||
|
@ -66,30 +52,26 @@ class UserRepo(
|
|||
}
|
||||
|
||||
def toggleChatBan(user: User): IO[Unit] = io {
|
||||
collection.update(
|
||||
idSelector(user),
|
||||
$set("isChatBan" -> !user.isChatBan))
|
||||
collection.update(byIdQuery(user), $set("isChatBan" -> !user.isChatBan))
|
||||
}
|
||||
|
||||
def saveSetting(user: User, key: String, value: String) = io {
|
||||
collection.update(
|
||||
idSelector(user),
|
||||
$set(("settings." + key) -> value))
|
||||
collection.update(byIdQuery(user), $set(("settings." + key) -> value))
|
||||
}
|
||||
|
||||
def exists(username: String): IO[Boolean] = io {
|
||||
count(byUsernameQuery(username)) != 0
|
||||
count(byIdQuery(username)) != 0
|
||||
}
|
||||
|
||||
def authenticate(username: String, password: String): IO[Option[User]] = for {
|
||||
userOption ← byUsername(username)
|
||||
userOption ← byId(username)
|
||||
greenLight ← authenticable(username, password)
|
||||
} yield userOption filter (_ ⇒ greenLight)
|
||||
|
||||
private def authenticable(username: String, password: String): IO[Boolean] = io {
|
||||
for {
|
||||
data ← collection.findOne(
|
||||
byUsernameQuery(username),
|
||||
byIdQuery(username),
|
||||
DBObject("password" -> true, "salt" -> true, "enabled" -> true)
|
||||
)
|
||||
hashed ← data.getAs[String]("password")
|
||||
|
@ -105,8 +87,8 @@ class UserRepo(
|
|||
io {
|
||||
val salt = OrnicarRandom nextAsciiString 32
|
||||
val obj = DBObject(
|
||||
"_id" -> normalize(username),
|
||||
"username" -> username,
|
||||
"usernameCanonical" -> username.toLowerCase,
|
||||
"password" -> hash(password, salt),
|
||||
"salt" -> salt,
|
||||
"elo" -> User.STARTING_ELO,
|
||||
|
@ -115,18 +97,18 @@ class UserRepo(
|
|||
"enabled" -> true,
|
||||
"roles" -> Nil)
|
||||
collection.insert(obj, WriteConcern.Safe)
|
||||
} flatMap { _ ⇒ byUsername(username) }
|
||||
} flatMap { _ ⇒ byId(username) }
|
||||
)
|
||||
} yield userOption
|
||||
|
||||
val countEnabled: IO[Int] = io { count(enabledQuery).toInt }
|
||||
|
||||
def usernamesLike(username: String): IO[List[String]] = io {
|
||||
val regex = "^" + username.toLowerCase + ".*$"
|
||||
val regex = "^" + normalize(username) + ".*$"
|
||||
collection.find(
|
||||
DBObject("usernameCanonical" -> regex.r),
|
||||
DBObject("_id" -> regex.r),
|
||||
DBObject("username" -> 1))
|
||||
.sort(DBObject("usernameCanonical" -> 1))
|
||||
.sort(DBObject("_id" -> 1))
|
||||
.limit(10)
|
||||
.toList
|
||||
.map(_.expand[String]("username"))
|
||||
|
@ -150,18 +132,14 @@ class UserRepo(
|
|||
def disable(user: User) = updateIO(user)($set("enabled" -> false))
|
||||
|
||||
def updateIO(username: String)(op: User ⇒ DBObject): IO[Unit] = for {
|
||||
userOption ← byUsername(username)
|
||||
userOption ← byId(username)
|
||||
_ ← userOption.fold(user ⇒ updateIO(user)(op(user)), io())
|
||||
} yield ()
|
||||
|
||||
def updateIO(user: User)(obj: DBObject): IO[Unit] = io {
|
||||
update(idSelector(user), obj)
|
||||
update(byIdQuery(user), obj)
|
||||
}
|
||||
|
||||
private def idSelector(user: User) = DBObject("_id" -> user.id)
|
||||
|
||||
private def idSelector(id: ObjectId) = DBObject("_id" -> id)
|
||||
|
||||
private def hash(pass: String, salt: String): String =
|
||||
"%s{%s}".format(pass, salt).sha1
|
||||
}
|
||||
|
|
7
bin/migrate
Executable file
7
bin/migrate
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
mongo lichess mongo_migration_user.js
|
||||
mongo lichess mongo_migration_forum.js
|
||||
mongo lichess mongo_migration_message.js
|
||||
mongo lichess mongo_migration_rest.js
|
||||
mongo lichess mongo_migration_game.js
|
||||
bin/cli forum-denormalize
|
|
@ -5,10 +5,4 @@ import scalaz.effects._
|
|||
|
||||
case class Games(gameRepo: GameRepo) {
|
||||
|
||||
def index: IO[Unit] = for {
|
||||
_ ← putStrLn("- Drop indexes")
|
||||
_ ← gameRepo.dropIndexes
|
||||
_ ← putStrLn("- Ensure indexes")
|
||||
_ ← gameRepo.ensureIndexes
|
||||
} yield ()
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ object Main {
|
|||
|
||||
val op: IO[Unit] = args.toList match {
|
||||
case "average-elo" :: Nil ⇒ infos.averageElo
|
||||
case "game-index" :: Nil ⇒ games.index
|
||||
case "trans-js-dump" :: Nil ⇒ TransJsDump(
|
||||
path = new File(env.app.path.getCanonicalPath + "/public/trans"),
|
||||
pool = env.i18n.pool,
|
||||
|
|
|
@ -18,7 +18,7 @@ case class Users(userRepo: UserRepo, securityStore: Store) {
|
|||
|
||||
def perform(username: String, action: String, op: User ⇒ IO[Unit]) = for {
|
||||
_ ← putStrLn(action + " " + username)
|
||||
userOption ← userRepo byUsername username
|
||||
userOption ← userRepo byId username
|
||||
_ ← userOption.fold(
|
||||
u ⇒ op(u) flatMap { _ ⇒ putStrLn("Success") },
|
||||
putStrLn("Not found")
|
||||
|
|
|
@ -3,8 +3,8 @@ mongo {
|
|||
port = 27017
|
||||
dbName = lichess
|
||||
collection {
|
||||
game = game
|
||||
user = user
|
||||
game = game2
|
||||
user = user2
|
||||
hook = hook
|
||||
entry = lobby_entry
|
||||
message = lobby_room
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
print("Hashing users")
|
||||
var users = {};
|
||||
var userHash = {};
|
||||
db.user2.find({},{oid:1}).forEach(function(user) {
|
||||
users[user.oid.toString()] = user._id;
|
||||
userHash[user.oid.toString()] = user._id;
|
||||
});
|
||||
function user(oid) {
|
||||
if(userHash[oid]) return userHash[oid];
|
||||
throw "Missing user " + oid;
|
||||
}
|
||||
|
||||
var categSlugs = {};
|
||||
var topicIds = {};
|
||||
|
@ -73,7 +77,7 @@ var topicIds = {};
|
|||
number: obj.number
|
||||
};
|
||||
if (obj.author) {
|
||||
post.userId = users[obj.author['$id'].toString()];
|
||||
post.userId = user(obj.author['$id'].toString());
|
||||
}
|
||||
coll.insert(post);
|
||||
}
|
||||
|
|
|
@ -10,11 +10,12 @@ function user(oid) {
|
|||
|
||||
print("Games");
|
||||
var batch = 10000;
|
||||
var max = 100000;
|
||||
var oGames = db.game;
|
||||
var nGames = db.game2;
|
||||
var it = 0, totalNb = oGames.count();
|
||||
nGames.drop();
|
||||
oGames.find().batchSize(batch).limit(100000).forEach(function(game) {
|
||||
oGames.find().batchSize(batch).limit(max).forEach(function(game) {
|
||||
delete game["positionHashes"];
|
||||
delete game["players.0.previousMoveTs"];
|
||||
delete game["players.1.previousMoveTs"];
|
||||
|
@ -45,5 +46,15 @@ oGames.find().batchSize(batch).limit(100000).forEach(function(game) {
|
|||
}
|
||||
nGames.insert(game);
|
||||
++it;
|
||||
if (0 == it % batch) print(it + "/" + totalNb);
|
||||
if (0 == it % batch)
|
||||
print(it + "/" + totalNb + " " + Math.round(100*it/totalNb) + "%");
|
||||
});
|
||||
|
||||
print("Indexes");
|
||||
nGames.ensureIndex({status:1});
|
||||
nGames.ensureIndex({userIds:1});
|
||||
nGames.ensureIndex({winId:1});
|
||||
nGames.ensureIndex({turns:1});
|
||||
nGames.ensureIndex({updatedAt:-1});
|
||||
nGames.ensureIndex({createdAt:-1});
|
||||
nGames.ensureIndex({userIds:1, createdAt:-1});
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
print("Hashing users")
|
||||
var users = {};
|
||||
var userHash = {};
|
||||
db.user2.find({},{oid:1}).forEach(function(user) {
|
||||
users[user.oid.toString()] = user._id;
|
||||
userHash[user.oid.toString()] = user._id;
|
||||
});
|
||||
function user(oid) {
|
||||
if(userHash[oid]) return userHash[oid];
|
||||
throw "Missing user " + oid;
|
||||
}
|
||||
|
||||
print("Threads and messages");
|
||||
var oThreads = db.message_thread;
|
||||
|
@ -16,7 +20,7 @@ oThreads.find().forEach(function(oThread) {
|
|||
name: oThread.subject,
|
||||
createdAt: oThread.createdAt,
|
||||
creatorId: creatorId(oThread),
|
||||
invitedId: users[invOid],
|
||||
invitedId: user(invOid),
|
||||
visibleByUserIds: visibleByUserIds(oThread)
|
||||
};
|
||||
var posts = [];
|
||||
|
@ -57,7 +61,7 @@ function invitedOid(oThread) {
|
|||
}
|
||||
|
||||
function userIds(oThread) {
|
||||
return [creatorId(oThread), users[invitedOid(oThread)]];
|
||||
return [creatorId(oThread), user(invitedOid(oThread))];
|
||||
}
|
||||
|
||||
function visibleByUserIds(oThread) {
|
||||
|
@ -69,8 +73,8 @@ function visibleByUserIds(oThread) {
|
|||
}
|
||||
|
||||
function username(obj) {
|
||||
if (typeof obj == "object") return users[objId(obj)];
|
||||
return users[obj];
|
||||
if (typeof obj == "object") return user(objId(obj));
|
||||
return user(obj);
|
||||
}
|
||||
|
||||
function objId(obj) {
|
||||
|
|
13
mongo_migration_rest.js
Normal file
13
mongo_migration_rest.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
print("Other collections");
|
||||
|
||||
db.lobby_room.drop();
|
||||
db.createCollection("lobby_room", {capped:true, max:1000})
|
||||
|
||||
db.lobby_entry.drop();
|
||||
db.createCollection("lobby_entry", {capped:true, max:50})
|
||||
|
||||
db.hook.drop();
|
||||
db.hook.ensureIndex({ownerId: 1});
|
||||
db.hook.ensureIndex({mode: 1});
|
||||
db.hook.ensureIndex({createdAt: -1});
|
||||
db.hook.ensureIndex({match: 1});
|
6
todo
6
todo
|
@ -22,12 +22,10 @@ http://codetunes.com/2012/05/09/scala-dsl-tutorial-writing-web-framework-router
|
|||
use POST instead of GET where it makes sense
|
||||
endgame sound http://en.lichess.org/forum/lichess-feedback/checkmate-sound-feature?page=1#1
|
||||
cached username option app/user/Cached.scala
|
||||
game.next dbref => string
|
||||
|
||||
next deploy:
|
||||
mongo lichess mongo_migration_user.js
|
||||
mongo lichess mongo_migration_forum.js
|
||||
mongo lichess mongo_migration_message.js
|
||||
bin/cli forum-denormalize
|
||||
bin/migrate
|
||||
new translations:
|
||||
-rematchOfferCanceled=Rematch offer canceled
|
||||
-rematchOfferDeclined=Rematch offer declined
|
||||
|
|
Loading…
Reference in a new issue