lila/modules/team/src/main/TeamApi.scala

181 lines
6.1 KiB
Scala
Raw Normal View History

2013-04-02 09:45:45 -06:00
package lila.team
2013-04-04 08:28:52 -06:00
import actorApi._
import akka.actor.ActorSelection
2016-04-01 11:50:57 -06:00
import lila.db.dsl._
2017-08-06 01:40:37 -06:00
import lila.hub.actorApi.team.{ CreateTeam, JoinTeam }
2013-05-24 14:37:27 -06:00
import lila.hub.actorApi.timeline.{ Propagate, TeamJoin, TeamCreate }
2016-04-01 22:57:54 -06:00
import lila.user.{ User, UserRepo, UserContext }
import org.joda.time.Period
import reactivemongo.api.Cursor
2013-04-02 09:45:45 -06:00
final class TeamApi(
2016-04-01 22:57:54 -06:00
coll: Colls,
cached: Cached,
notifier: Notifier,
2017-08-06 01:40:37 -06:00
bus: lila.common.Bus,
indexer: ActorSelection,
timeline: ActorSelection
) {
2013-04-02 09:45:45 -06:00
2016-04-01 22:57:54 -06:00
import BSONHandlers._
2014-11-15 06:53:01 -07:00
val creationPeriod = Period weeks 1
2013-04-02 09:45:45 -06:00
2016-04-01 22:57:54 -06:00
def team(id: String) = coll.team.byId[Team](id)
2013-05-06 14:49:12 -06:00
2016-04-01 22:57:54 -06:00
def request(id: String) = coll.request.byId[Request](id)
2013-05-06 14:49:12 -06:00
2013-04-04 08:28:52 -06:00
def create(setup: TeamSetup, me: User): Option[Fu[Team]] = me.canTeam option {
val s = setup.trim
val team = Team.make(
name = s.name,
location = s.location,
description = s.description,
open = s.isOpen,
createdBy = me
)
2016-04-01 22:57:54 -06:00
coll.team.insert(team) >>
2014-04-18 03:51:19 -06:00
MemberRepo.add(team.id, me.id) >>- {
2017-08-06 01:40:37 -06:00
cached invalidateTeamIds me.id
indexer ! InsertTeam(team)
timeline ! Propagate(
2014-04-18 03:51:19 -06:00
TeamCreate(me.id, team.id)
2017-08-06 01:40:37 -06:00
).toFollowersOf(me.id)
bus.publish(CreateTeam(id = team.id, name = team.name, userId = me.id), 'team)
2014-04-18 03:51:19 -06:00
} inject team
2013-04-04 08:28:52 -06:00
}
2014-02-17 02:12:19 -07:00
def update(team: Team, edit: TeamEdit, me: User): Funit = edit.trim |> { e =>
2013-04-04 08:28:52 -06:00
team.copy(
location = e.location,
description = e.description,
open = e.isOpen
) |> { team =>
coll.team.update($id(team.id), team).void >>- (indexer ! InsertTeam(team))
}
2013-04-04 08:28:52 -06:00
}
def mine(me: User): Fu[List[Team]] =
cached teamIds me.id flatMap { ids => coll.team.byIds[Team](ids.toArray) }
2013-04-04 08:28:52 -06:00
2017-02-05 04:11:03 -07:00
def hasTeams(me: User): Fu[Boolean] = cached.teamIds(me.id).map(_.value.nonEmpty)
2015-09-09 09:32:49 -06:00
2013-04-04 08:28:52 -06:00
def hasCreatedRecently(me: User): Fu[Boolean] =
TeamRepo.userHasCreatedSince(me.id, creationPeriod)
def requestsWithUsers(team: Team): Fu[List[RequestWithUser]] = for {
requests RequestRepo findByTeam team.id
users UserRepo usersFromSecondary requests.map(_.user)
2013-04-04 08:28:52 -06:00
} yield requests zip users map {
2014-02-17 02:12:19 -07:00
case (request, user) => RequestWithUser(request, user)
2013-04-04 08:28:52 -06:00
}
def requestsWithUsers(user: User): Fu[List[RequestWithUser]] = for {
teamIds TeamRepo teamIdsByCreator user.id
requests RequestRepo findByTeams teamIds
users UserRepo usersFromSecondary requests.map(_.user)
2013-04-04 08:28:52 -06:00
} yield requests zip users map {
2014-02-17 02:12:19 -07:00
case (request, user) => RequestWithUser(request, user)
2013-04-04 08:28:52 -06:00
}
2013-12-27 15:12:20 -07:00
def join(teamId: String)(implicit ctx: UserContext): Fu[Option[Requesting]] = for {
2016-04-01 22:57:54 -06:00
teamOption coll.team.byId[Team](teamId)
2013-04-04 08:28:52 -06:00
result ~(teamOption |@| ctx.me.filter(_.canTeam))({
2014-02-17 02:12:19 -07:00
case (team, user) if team.open =>
2013-04-04 08:28:52 -06:00
(doJoin(team, user.id) inject Joined(team).some): Fu[Option[Requesting]]
2014-02-17 02:12:19 -07:00
case (team, user) =>
2013-04-04 08:28:52 -06:00
fuccess(Motivate(team).some: Option[Requesting])
})
} yield result
def requestable(teamId: String, user: User): Fu[Option[Team]] = for {
2016-04-01 22:57:54 -06:00
teamOption coll.team.byId[Team](teamId)
able teamOption.??(requestable(_, user))
2014-02-17 02:12:19 -07:00
} yield teamOption filter (_ => able)
2013-04-04 08:28:52 -06:00
def requestable(team: Team, user: User): Fu[Boolean] = for {
belongs <- belongsTo(team.id, user.id)
requested <- RequestRepo.exists(team.id, user.id)
} yield !belongs && !requested
2013-04-04 08:28:52 -06:00
def createRequest(team: Team, setup: RequestSetup, user: User): Funit =
requestable(team, user) flatMap {
_ ?? {
val request = Request.make(team = team.id, user = user.id, message = setup.message)
2017-01-26 16:23:43 -07:00
coll.request.insert(request).void >>- (cached.nbRequests invalidate team.createdBy)
}
2013-04-04 08:28:52 -06:00
}
def processRequest(team: Team, request: Request, accept: Boolean): Funit = for {
2016-04-01 22:57:54 -06:00
_ coll.request.remove(request)
2017-01-26 16:23:43 -07:00
_ = cached.nbRequests invalidate team.createdBy
2016-04-01 22:57:54 -06:00
userOption UserRepo byId request.user
2014-02-17 02:12:19 -07:00
_ userOption.filter(_ => accept).??(user =>
doJoin(team, user.id) >>- notifier.acceptRequest(team, request))
} yield ()
2013-04-04 08:28:52 -06:00
def doJoin(team: Team, userId: String): Funit = !belongsTo(team.id, userId) flatMap {
_ ?? {
MemberRepo.add(team.id, userId) >>
TeamRepo.incMembers(team.id, +1) >>- {
cached invalidateTeamIds userId
timeline ! Propagate(TeamJoin(userId, team.id)).toFollowersOf(userId)
2017-08-06 01:40:37 -06:00
bus.publish(JoinTeam(id = team.id, userId = userId), 'team)
}
} recover lila.db.recoverDuplicateKey(_ => ())
}
2013-04-04 08:28:52 -06:00
2013-12-27 15:12:20 -07:00
def quit(teamId: String)(implicit ctx: UserContext): Fu[Option[Team]] = for {
2016-04-01 22:57:54 -06:00
teamOption coll.team.byId[Team](teamId)
2013-04-04 08:28:52 -06:00
result ~(teamOption |@| ctx.me)({
2014-02-17 02:12:19 -07:00
case (team, user) => doQuit(team, user.id) inject team.some
2013-04-04 08:28:52 -06:00
})
} yield result
def doQuit(team: Team, userId: String): Funit = belongsTo(team.id, userId) flatMap {
_ ?? {
MemberRepo.remove(team.id, userId) >>
TeamRepo.incMembers(team.id, -1) >>-
(cached invalidateTeamIds userId)
}
2014-04-18 03:51:19 -06:00
}
2013-04-04 08:28:52 -06:00
def quitAll(userId: String): Funit = MemberRepo.removeByUser(userId)
def kick(team: Team, userId: String): Funit = doQuit(team, userId)
def enable(team: Team): Funit =
2016-04-01 22:57:54 -06:00
TeamRepo.enable(team).void >>- (indexer ! InsertTeam(team))
2013-04-04 08:28:52 -06:00
def disable(team: Team): Funit =
2016-04-01 22:57:54 -06:00
TeamRepo.disable(team).void >>- (indexer ! RemoveTeam(team.id))
2013-04-04 08:28:52 -06:00
// delete for ever, with members but not forums
2013-04-04 08:28:52 -06:00
def delete(team: Team): Funit =
2016-04-01 22:57:54 -06:00
coll.team.remove($id(team.id)) >>
2013-05-06 07:48:05 -06:00
MemberRepo.removeByteam(team.id) >>-
2013-04-04 08:28:52 -06:00
(indexer ! RemoveTeam(team.id))
def syncBelongsTo(teamId: String, userId: String): Boolean =
cached.syncTeamIds(userId) contains teamId
def belongsTo(teamId: String, userId: String): Fu[Boolean] =
cached.teamIds(userId) map (_ contains teamId)
2013-04-09 12:58:34 -06:00
def owns(teamId: String, userId: String): Fu[Boolean] =
TeamRepo ownerOf teamId map (Some(userId) ==)
2013-04-09 12:58:34 -06:00
def teamName(teamId: String) = cached name teamId
2017-01-26 16:23:43 -07:00
def nbRequests(teamId: String) = cached.nbRequests get teamId
2015-04-12 00:18:47 -06:00
def recomputeNbMembers =
coll.team.find($empty).cursor[Team]().foldWhileM({}) { (_, team) =>
for {
nb <- MemberRepo.countByTeam(team.id)
_ <- coll.team.updateField($id(team.id), "nbMembers", nb)
} yield Cursor.Cont({})
}
}