131 lines
4.3 KiB
Scala
131 lines
4.3 KiB
Scala
package lila.api
|
|
|
|
import cats.implicits._
|
|
import scala.concurrent.ExecutionContext
|
|
|
|
import lila.chat.UserLine
|
|
import lila.common.config.NetDomain
|
|
import lila.hub.actorApi.shutup.PublicSource
|
|
import lila.simul.Simul
|
|
import lila.simul.SimulApi
|
|
import lila.swiss.Swiss
|
|
import lila.swiss.SwissApi
|
|
import lila.team.Team
|
|
import lila.team.TeamRepo
|
|
import lila.tournament.Tournament
|
|
import lila.tournament.TournamentRepo
|
|
import lila.user.User
|
|
import lila.study.Study
|
|
import lila.study.StudyRepo
|
|
|
|
/* Determine if a link to a lichess resource
|
|
* can be posted from another lichess resource.
|
|
* Owners of a resource can post any link on it (but not to it).
|
|
* Links to a team resource can be posted from another resource of the same team.
|
|
* Links to official resources can be posted from anywhere.
|
|
* */
|
|
final private class LinkCheck(
|
|
domain: NetDomain,
|
|
teamRepo: TeamRepo,
|
|
tournamentRepo: TournamentRepo,
|
|
simulApi: SimulApi,
|
|
swissApi: SwissApi,
|
|
studyRepo: StudyRepo
|
|
)(implicit ec: ExecutionContext) {
|
|
|
|
import LinkCheck._
|
|
|
|
def apply(line: UserLine, source: PublicSource): Fu[Boolean] = {
|
|
if (multipleLinks find line.text) fuFalse
|
|
else
|
|
line.text match {
|
|
case tournamentLinkR(id) => withSource(source, tourLink)(id, line)
|
|
case simulLinkR(id) => withSource(source, simulLink)(id, line)
|
|
case swissLinkR(id) => withSource(source, swissLink)(id, line)
|
|
case studyLinkR(id) => withSource(source, studyLink)(id, line)
|
|
case _ => fuTrue
|
|
}
|
|
}
|
|
|
|
private def withSource(
|
|
source: PublicSource,
|
|
f: (String, FullSource) => Fu[Boolean]
|
|
)(id: String, line: UserLine): Fu[Boolean] = {
|
|
source match {
|
|
case PublicSource.Tournament(id) => tournamentRepo byId id map2 FullSource.TournamentSource
|
|
case PublicSource.Simul(id) => simulApi find id map2 FullSource.SimulSource
|
|
case PublicSource.Swiss(id) => swissApi byId Swiss.Id(id) map2 FullSource.SwissSource
|
|
case PublicSource.Team(id) => teamRepo byId id map2 FullSource.TeamSource
|
|
case PublicSource.Study(id) => studyRepo byId Study.Id(id) map2 FullSource.StudySource
|
|
case _ => fuccess(none)
|
|
}
|
|
} flatMap {
|
|
_ ?? { source =>
|
|
// the owners of a chat can post whichever link they like
|
|
if (source.owners(line.userId)) fuTrue
|
|
else f(id, source)
|
|
}
|
|
}
|
|
|
|
private def tourLink(tourId: Tournament.ID, source: FullSource) =
|
|
tournamentRepo byId tourId flatMap {
|
|
_ ?? { tour =>
|
|
fuccess(tour.isScheduled) >>| {
|
|
source.teamId ?? { sourceTeamId =>
|
|
fuccess(tour.conditions.teamMember.exists(_.teamId == sourceTeamId)) >>|
|
|
tournamentRepo.isForTeam(tour.id, sourceTeamId)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private def simulLink(simulId: Tournament.ID, source: FullSource) =
|
|
simulApi teamOf simulId map {
|
|
_ exists source.teamId.has
|
|
}
|
|
|
|
private def swissLink(swissId: String, source: FullSource) =
|
|
swissApi teamOf Swiss.Id(swissId) map {
|
|
_ exists source.teamId.has
|
|
}
|
|
|
|
private def studyLink(studyId: String, source: FullSource) = fuFalse
|
|
|
|
private val multipleLinks = s"$domain.+$domain".r.unanchored
|
|
private val tournamentLinkR = s"$domain/tournament/(\\w+)".r.unanchored
|
|
private val simulLinkR = s"$domain/simul/(\\w+)".r.unanchored
|
|
private val swissLinkR = s"$domain/swiss/(\\w+)".r.unanchored
|
|
private val studyLinkR = s"$domain/study/(\\w+)".r.unanchored
|
|
}
|
|
|
|
private object LinkCheck {
|
|
|
|
sealed trait FullSource {
|
|
def owners: Set[User.ID]
|
|
def teamId: Option[Team.ID]
|
|
}
|
|
|
|
object FullSource {
|
|
case class TournamentSource(value: Tournament) extends FullSource {
|
|
def owners = Set(value.createdBy)
|
|
def teamId = value.conditions.teamMember.map(_.teamId)
|
|
}
|
|
case class SimulSource(value: Simul) extends FullSource {
|
|
def owners = Set(value.hostId)
|
|
def teamId = value.team
|
|
}
|
|
case class SwissSource(value: Swiss) extends FullSource {
|
|
def owners = Set(value.createdBy)
|
|
def teamId = value.teamId.some
|
|
}
|
|
case class TeamSource(value: Team) extends FullSource {
|
|
def owners = value.leaders
|
|
def teamId = value.id.some
|
|
}
|
|
case class StudySource(value: Study) extends FullSource {
|
|
def owners = value.members.idSet
|
|
def teamId = none
|
|
}
|
|
}
|
|
}
|