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

api.Api.scala Maven / Gradle / Ivy

The newest version!
package masterleagueapi
package api

import io.circe.Decoder
import fs2._
import fs2.util.Catchable
import spinoco.fs2.http
import http._
import masterleagueapi.codec._
import masterleagueapi.codec.Decoders._
import fs2.interop.cats._
import scodec.Attempt
import spinoco.protocol.http._
import DefaultResources._
import scodec.Err
import cats.implicits._
import scala.concurrent.duration.FiniteDuration
import masterleagueapi.net._
import net.Bridge._

object Api {

  def streamAPI[A](uri: Uri, delay: FiniteDuration)(implicit decoder: Decoder[A]): Stream[Task, Either[Err, APIResult[A]]] = Stream.force(http.client[Task]().map { client =>
    {
      val initialrequest = Attempt.successful(HttpRequest.get[Task](uri)).toEither
      def results2requests(eapiresult: Either[Err, APIResult[A]]): Stream[Task, Either[Err, HttpRequest[Task]]] = eapiresult.traverse(getRequests)
      def reqs2as(ereq: Either[Err, HttpRequest[Task]]): Stream[Task, Either[Err, APIResult[A]]] = ereq match {
        case Right(request) => getEntries(client)(implicitly[Catchable[Task]], decoder)(request).map(_.toEither)
        case Left(err) => Stream(Left(err))
      }

      Crawler.crawl(initialrequest, reqs2as, results2requests, time.sleep[Task](delay))
    }
  })

  def streamAPIResults[A](uri: Uri, delay: FiniteDuration)(implicit decoder: Decoder[A]): Stream[Task, Either[Err, A]] = streamAPI(uri, delay)(decoder).flatMap {
    case Right(ar) => Stream.emits(ar.results.map(Right(_)))
    case Left(err) => Stream(Left(err))
  }

  def apiToMap[A <: APIEntry](uri: Uri, delay: FiniteDuration)(implicit decoder: Decoder[A]): Task[Either[Err, Map[Long, A]]] = {
    val results = streamAPIResults(uri, delay)(decoder)
    results.runFold(Attempt.successful(Map.empty[Long, A])) {
      case (res, next) => for {
        have <- res
        res <- Attempt.fromEither(next)
      } yield have.updated(res.id, res)
    }.map(_.toEither)
  }

  def apiToList[A](uri: Uri, delay: FiniteDuration)(implicit decoder: Decoder[A]): Task[Either[Err, List[A]]] = {
    val results = streamAPIResults(uri, delay)(decoder)

    results.runFold(Attempt.successful(List.empty[A])) {
      case (res, next) => for {
        have <- res
        res <- Attempt.fromEither(next)
      } yield res :: have
    }.map(_.toEither)
  }

  def runSingleArray[A <: APIEntry](uri: Uri)(implicit decoder: Decoder[A]): Task[Either[Err, Map[Long, A]]] = {
    val tresponsestream = for {
      client <- http.client[Task]()
    } yield client.request(HttpRequest.get[Task](uri))
    implicit val bodydecoder = CirceSupport.circeDecoder[List[A]](decodePlainArray)

    val liststream = for {
      response <- Stream.force(tresponsestream)
      body <- Stream.eval(response.bodyAs[List[A]])
    } yield body

    liststream.runFold(Attempt.successful(Map.empty[Long, A])) {
      case (res, next) => for {
        have <- res
        batch <- next
      } yield (have ++ batch.map(r => (r.id, r)).toMap)
    }.map(_.toEither)

  }

  def matches(wait: FiniteDuration) = apiToMap[MatchEntry](Endpoints.matches, wait)
  def heroes(wait: FiniteDuration) = apiToMap[HeroEntry](Endpoints.heroes, wait)
  def players(wait: FiniteDuration) = apiToMap[PlayerEntry](Endpoints.players, wait)
  def tournaments(wait: FiniteDuration) = apiToMap[TournamentEntry](Endpoints.tournaments, wait)
  def calendar(wait: FiniteDuration): Task[Either[Err, List[CalendarEntry]]] = apiToList[CalendarEntry](Endpoints.calendar, wait)
  def teams(wait: FiniteDuration) = apiToMap[TeamEntry](Endpoints.teams, wait)

  val regions = runSingleArray[RegionEntry](Endpoints.regions)
  val patches = runSingleArray[PatchEntry](Endpoints.patches)
  val maps = runSingleArray[MapEntry](Endpoints.maps)

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy