All Downloads are FREE. Search and download functionalities are using the official Maven repository.

im.actor.server.persist.UserRepo.scala Maven / Gradle / Ivy

The newest version!
package im.actor.server.persist

import java.time.{ LocalDateTime, ZoneOffset }

import im.actor.server.db.ActorPostgresDriver.api._
import im.actor.server.model.{ Sex, User, UserState }
import im.actor.util.misc.PhoneNumberUtils
import slick.dbio.Effect.Read
import slick.lifted.ColumnOrdered
import slick.profile.FixedSqlStreamingAction

import scala.concurrent.ExecutionContext

final class UserTable(tag: Tag) extends Table[User](tag, "users") {
  import SexColumnType._
  import UserStateColumnType._

  def id = column[Int]("id", O.PrimaryKey)
  def accessSalt = column[String]("access_salt")
  def name = column[String]("name")
  def countryCode = column[String]("country_code")
  def sex = column[Sex]("sex")
  def state = column[UserState]("state")
  def createdAt = column[LocalDateTime]("created_at")
  def nickname = column[Option[String]]("nickname")
  def about = column[Option[String]]("about")
  def deletedAt = column[Option[LocalDateTime]]("deleted_at")
  def isBot = column[Boolean]("is_bot")
  def external = column[Option[String]]("external")

  def * = (id, accessSalt, name, countryCode, sex, state, createdAt, nickname, about, deletedAt, isBot, external) <> (User.tupled, User.unapply)
}

object UserRepo {
  val users = TableQuery[UserTable]

  def byId(id: Rep[Int]) = users filter (_.id === id)
  def nameById(id: Rep[Int]) = byId(id) map (_.name)

  val byIdC = Compiled(byId _)
  val nameByIdC = Compiled(nameById _)

  private def byNickname(nickname: Rep[String]) =
    users filter (_.nickname.toLowerCase === nickname.toLowerCase)
  private def byNicknamePrefix(nickPrefix: Rep[String]) =
    users filter (_.nickname.toLowerCase.like(nickPrefix.toLowerCase))

  private val byNicknameC = Compiled(byNickname _)
  private val byNicknamePrefixC = Compiled(byNicknamePrefix _)

  def byPhone(phone: Rep[Long]) = (for {
    phones ← UserPhoneRepo.phones.filter(_.number === phone)
    users ← users if users.id === phones.userId
  } yield users).take(1)
  def idByPhone(phone: Rep[Long]) = byPhone(phone) map (_.id)

  val idByPhoneC = Compiled(idByPhone _)

  def idsByEmail(email: Rep[String]) =
    for {
      emails ← UserEmailRepo.emails filter (_.email.toLowerCase === email.toLowerCase)
      users ← users filter (_.id === emails.userId) map (_.id)
    } yield users
  val idsByEmailC = Compiled(idsByEmail _)

  private val activeHumanUsers =
    users.filter(u ⇒ u.deletedAt.isEmpty && !u.isBot)

  private val activeHumanUsersC = Compiled(activeHumanUsers)

  private val activeHumanUsersIdsC = Compiled(activeHumanUsers map (_.id))

  private def activeHumanUsersIds(createdAfter: Rep[LocalDateTime]) =
    Compiled {
      users.filter(u ⇒ u.deletedAt.isEmpty && !u.isBot && u.createdAt > createdAfter).sortBy(_.createdAt.asc).map(u ⇒ u.id → u.createdAt)
    }

  def activeUserIdsCreatedAfter(createdAfter: LocalDateTime): DBIO[Seq[(Int, LocalDateTime)]] = activeHumanUsersIds(createdAfter).result

  def fetchPeople = activeHumanUsersC.result

  def create(user: User) =
    users += user

  def setCountryCode(userId: Int, countryCode: String) =
    users.filter(_.id === userId).map(_.countryCode).update(countryCode)

  def setDeletedAt(userId: Int) =
    users.filter(_.id === userId).
      map(_.deletedAt).
      update(Some(LocalDateTime.now(ZoneOffset.UTC)))

  def setName(userId: Int, name: String) =
    users.filter(_.id === userId).map(_.name).update(name)

  def allIds = users.map(_.id).result

  def all = users.result

  def find(id: Int) =
    byIdC(id).result.headOption

  @deprecated("Duplicates ", "2016-07-07")
  def findName(id: Int) =
    nameById(id).result.headOption

  // TODO: #perf will it create prepared statement for each ids length?
  def findSalts(ids: Set[Int]) =
    users.filter(_.id inSet ids).map(u ⇒ (u.id, u.accessSalt)).result

  @deprecated("user GlobalNamesStorageKeyValueStorage instead", "2016-07-17")
  def findByNickname(query: String): DBIO[Option[User]] = {
    val nickname =
      if (query.startsWith("@")) query.drop(1) else query
    byNicknameC(nickname).result.headOption
  }

  @deprecated("user GlobalNamesStorageKeyValueStorage instead", "2016-07-17")
  def findByNicknamePrefix(query: String): DBIO[Seq[User]] = {
    val nickname: String =
      if (query.startsWith("@")) query.drop(1) else query
    byNicknamePrefixC(nickname).result
  }

  def findIdsByEmail(email: String) =
    idsByEmailC(email).result.headOption

  def findIds(query: String)(implicit ec: ExecutionContext) =
    for {
      e ← idsByEmailC(query).result
      p ← PhoneNumberUtils.normalizeStr(query)
        .headOption
        .map(idByPhoneC(_).result)
        .getOrElse(DBIO.successful(Nil))
    } yield e ++ p

  @deprecated("user GlobalNamesStorageKeyValueStorage instead", "2016-07-17")
  def setNickname(userId: Int, nickname: Option[String]) =
    byId(userId).map(_.nickname).update(nickname)

  def setAbout(userId: Int, about: Option[String]) =
    byId(userId).map(_.about).update(about)

  @deprecated("user GlobalNamesStorageKeyValueStorage instead", "2016-07-17")
  def nicknameExists(nickname: String) =
    users.filter(_.nickname.toLowerCase === nickname.toLowerCase).exists.result

  def findByIds(ids: Set[Int]) =
    users.filter(_.id inSet ids).result

  def findByIdsPaged(ids: Set[Int], number: Int, size: Int) = {
    val offset = (number - 1) * size
    users.
      filter(_.id inSet ids).
      sortBy(_.name).
      drop(offset).
      take(size).
      result
  }

  def activeUsersIds = activeHumanUsersIdsC.result

  def fetchPagedNewest(pageNumber: Int, pageSize: Int): DBIO[Seq[User]] =
    paged(pageNumber, pageSize, { ut ⇒ ut.createdAt.desc }).result

  def paged[A](pageNumber: Int, pageSize: Int, sorting: UserTable ⇒ ColumnOrdered[A]): Query[UserTable, User, Seq] = {
    val offset = (pageNumber - 1) * pageSize
    activeHumanUsers
      .sortBy(sorting)
      .drop(offset)
      .take(pageSize)
  }

  def isDeleted(userId: Int): DBIO[Boolean] =
    byIdC.applied(userId).filter(_.deletedAt.nonEmpty).exists.result
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy