lila/modules/study/src/main/StudyInvite.scala

72 lines
2.7 KiB
Scala
Raw Normal View History

2016-05-03 14:52:30 -06:00
package lila.study
2019-08-02 07:03:37 -06:00
import scala.concurrent.duration._
2016-05-03 14:52:30 -06:00
2019-12-13 07:30:20 -07:00
import lila.notify.{ InvitedToStudy, Notification, NotifyApi }
import lila.pref.Pref
2017-10-21 14:01:50 -06:00
import lila.relation.{ Block, Follow }
2019-12-03 17:55:45 -07:00
import lila.user.User
2016-05-03 14:52:30 -06:00
2019-12-13 07:30:20 -07:00
final private class StudyInvite(
studyRepo: StudyRepo,
2019-12-03 17:55:45 -07:00
userRepo: lila.user.UserRepo,
notifyApi: NotifyApi,
2019-12-03 17:55:45 -07:00
prefApi: lila.pref.PrefApi,
relationApi: lila.relation.RelationApi
)(implicit ec: scala.concurrent.ExecutionContext) {
2016-05-03 14:52:30 -06:00
2019-08-02 07:03:37 -06:00
private val notifyRateLimit = new lila.memo.RateLimit[User.ID](
credits = 500,
duration = 1 day,
name = "Study invites per user",
key = "study.invite.user"
)
2017-05-06 04:30:58 -06:00
private val maxMembers = 30
2019-12-13 07:30:20 -07:00
def apply(
byUserId: User.ID,
study: Study,
invitedUsername: String,
getIsPresent: User.ID => Fu[Boolean]
): Funit =
for {
_ <- !study.isOwner(byUserId) ?? fufail[Unit]("Only study owner can invite")
_ <- (study.nbMembers >= maxMembers) ?? fufail[Unit](s"Max study members reached: $maxMembers")
inviter <- userRepo.named(byUserId) orFail "No such inviter"
invited <- userRepo
.named(invitedUsername)
.map(_.filterNot(_.id == User.lichessId)) orFail "No such invited"
_ <- study.members.contains(invited) ?? fufail[Unit]("Already a member")
relation <- relationApi.fetchRelation(invited.id, byUserId)
_ <- relation.has(Block) ?? fufail[Unit]("This user does not want to join")
isPresent <- getIsPresent(invited.id)
_ <- if (isPresent) funit
else
prefApi.getPref(invited).map(_.studyInvite).flatMap {
case Pref.StudyInvite.ALWAYS => funit
case Pref.StudyInvite.NEVER => fufail("This user doesn't accept study invitations")
case Pref.StudyInvite.FRIEND =>
if (relation.has(Follow)) funit
else fufail("This user only accept study invitations from friends")
}
_ <- studyRepo.addMember(study, StudyMember make invited)
shouldNotify = !isPresent && (!inviter.marks.troll || relation.has(Follow))
2019-12-13 07:30:20 -07:00
rateLimitCost = if (relation has Follow) 10
else if (inviter.roles has "ROLE_COACH") 20
else if (inviter.hasTitle) 20
else if (inviter.perfs.bestRating >= 2000) 50
else if (invited.hasTitle) 200
else 100
_ <- shouldNotify ?? notifyRateLimit(inviter.id, rateLimitCost) {
val notificationContent = InvitedToStudy(
InvitedToStudy.InvitedBy(inviter.id),
InvitedToStudy.StudyName(study.name.value),
InvitedToStudy.StudyId(study.id.value)
)
val notification = Notification.make(Notification.Notifies(invited.id), notificationContent)
notifyApi.addNotification(notification)
}
} yield ()
2016-05-03 14:52:30 -06:00
}