<commit_before>package lila.relay

import akka.actor._
import org.joda.time.DateTime
import ornicar.scalalib.Zero
import play.api.libs.json._
import reactivemongo.bson._
import io.lemonlabs.uri.Url

import lila.db.dsl._
import lila.study.{ StudyApi, Study, StudyMaker, Settings }
import lila.user.User
import lila.security.Granter

final class RelayApi(
    repo: RelayRepo,
    studyApi: StudyApi,
    withStudy: RelayWithStudy,
    system: ActorSystem
) {

  import BSONHandlers._
  import lila.study.BSONHandlers.LikesBSONHandler

  def byId(id: Relay.Id) = repo.coll.byId[Relay](id.value)

  def byIdAndContributor(id: Relay.Id, me: User) = byIdWithStudy(id) map {
    _ collect {
      case Relay.WithStudy(relay, study) if study.canContribute(me.id) || Granter(_.Beta)(me) => relay
    }
  }

  def byIdWithStudy(id: Relay.Id): Fu[Option[Relay.WithStudy]] = WithRelay(id) { relay =>
    studyApi.byId(relay.studyId) map2 { (study: Study) =>
      Relay.WithStudy(relay, study)
    }
  }

  def fresh(me: Option[User]): Fu[Relay.Fresh] =
    repo.scheduled.flatMap(withStudy andLiked me) zip
      repo.ongoing.flatMap(withStudy andLiked me) map {
        case c ~ s => Relay.Fresh(c, s)
      }

  private[relay] def toSync = repo.coll.find($doc(
    "sync.until" $exists true,
    "sync.nextAt" $lt DateTime.now
  )).list[Relay]()

  def setLikes(id: Relay.Id, likes: lila.study.Study.Likes): Funit =
    repo.coll.updateField($id(id), "likes", likes).void

  def create(data: RelayForm.Data, user: User): Fu[Relay] = {
    val relay = data make user
    repo.coll.insert(relay) >>
      studyApi.importGame(StudyMaker.ImportGame(
        id = relay.studyId.some,
        name = Study.Name(relay.name).some,
        settings = Settings.init.copy(
          chat = Settings.UserSelection.Everyone,
          sticky = false
        ).some,
        from = Study.From.Relay(none).some
      ), user) inject relay
  }

  def requestPlay(id: Relay.Id, v: Boolean): Funit = WithRelay(id) { relay =>
    update(relay) { r =>
      if (v) r.withSync(_.play) else r.withSync(_.pause)
    } void
  }

  def update(from: Relay)(f: Relay => Relay): Fu[Relay] = {
    val relay = f(from)
    if (relay == from) fuccess(relay)
    else repo.coll.update($id(relay.id), relay.withSync(_.clearLog)).void >> {
      (relay.sync.playing != from.sync.playing) ?? publishRelay(relay)
    } >>- {
      relay.sync.log.events.lastOption.ifTrue(relay.sync.log != from.sync.log).foreach { event =>
        sendToContributors(relay.id, "relayLog", JsonView.syncLogEventWrites writes event)
      }
    } inject relay
  }

  def getOngoing(id: Relay.Id): Fu[Option[Relay]] =
    repo.coll.find($doc("_id" -> id, "finished" -> false)).uno[Relay]

  private[relay] def autoStart: Funit =
    repo.coll.find($doc(
      "startsAt" $lt DateTime.now.plusMinutes(30) // start 30 minutes early to fetch boards<commit_msg>only clear relay sync log when upstream URL has changed<commit_after>package lila.relay

import akka.actor._
import org.joda.time.DateTime
import ornicar.scalalib.Zero
import play.api.libs.json._
import reactivemongo.bson._
import io.lemonlabs.uri.Url

import lila.db.dsl._
import lila.study.{ StudyApi, Study, StudyMaker, Settings }
import lila.user.User
import lila.security.Granter

final class RelayApi(
    repo: RelayRepo,
    studyApi: StudyApi,
    withStudy: RelayWithStudy,
    system: ActorSystem
) {

  import BSONHandlers._
  import lila.study.BSONHandlers.LikesBSONHandler

  def byId(id: Relay.Id) = repo.coll.byId[Relay](id.value)

  def byIdAndContributor(id: Relay.Id, me: User) = byIdWithStudy(id) map {
    _ collect {
      case Relay.WithStudy(relay, study) if study.canContribute(me.id) || Granter(_.Beta)(me) => relay
    }
  }

  def byIdWithStudy(id: Relay.Id): Fu[Option[Relay.WithStudy]] = WithRelay(id) { relay =>
    studyApi.byId(relay.studyId) map2 { (study: Study) =>
      Relay.WithStudy(relay, study)
    }
  }

  def fresh(me: Option[User]): Fu[Relay.Fresh] =
    repo.scheduled.flatMap(withStudy andLiked me) zip
      repo.ongoing.flatMap(withStudy andLiked me) map {
        case c ~ s => Relay.Fresh(c, s)
      }

  private[relay] def toSync = repo.coll.find($doc(
    "sync.until" $exists true,
    "sync.nextAt" $lt DateTime.now
  )).list[Relay]()

  def setLikes(id: Relay.Id, likes: lila.study.Study.Likes): Funit =
    repo.coll.updateField($id(id), "likes", likes).void

  def create(data: RelayForm.Data, user: User): Fu[Relay] = {
    val relay = data make user
    repo.coll.insert(relay) >>
      studyApi.importGame(StudyMaker.ImportGame(
        id = relay.studyId.some,
        name = Study.Name(relay.name).some,
        settings = Settings.init.copy(
          chat = Settings.UserSelection.Everyone,
          sticky = false
        ).some,
        from = Study.From.Relay(none).some
      ), user) inject relay
  }

  def requestPlay(id: Relay.Id, v: Boolean): Funit = WithRelay(id) { relay =>
    update(relay) { r =>
      if (v) r.withSync(_.play) else r.withSync(_.pause)
    } void
  }

  def update(from: Relay)(f: Relay => Relay): Fu[Relay] = {
    val relay = f(from) |> { r =>
      if (r.sync.upstream.url != from.sync.upstream.url) r.withSync(_.clearLog) else r
    }
    if (relay == from) fuccess(relay)
    else repo.coll.update($id(relay.id), relay).void >> {
      (relay.sync.playing != from.sync.playing) ?? publishRelay(relay)
    } >>- {
      relay.sync.log.events.lastOption.ifTrue(relay.sync.log != from.sync.log).foreach { event =>
        sendToContributors(relay.id, "relayLog", JsonView.syncLogEventWrites writes event)
      }
    } inject relay
  }

  def getOngoing(id: Relay.Id): Fu[Option[Relay]] =
    repo.coll.find($doc("_id" -> id, "finished" -> false)).uno[Relay]

  private[relay] def autoStart: Funit =
    repo.coll.find($doc(
      "startsAt" $lt DateTime.now.plusMinutes(30) // start 30 minutes early to fetch boards
{'fraction_non_alphanumeric': 0.14247038917089677, 'fraction_numerical': 0.001692047377326565, 'mean_word_length': 3.222142857142857, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3296014', 'n_tokens_mistral': 2217, 'n_tokens_neox': 2129, 'n_words': 427}