mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-04-24 17:27:17 +00:00
use typed actors (#12)
* initial typed actor impl * fix sending response on ask
This commit is contained in:
parent
2e16a8c1fa
commit
8d516cdb15
@ -1,19 +1,33 @@
|
||||
val AkkaVersion = "2.6.10"
|
||||
val AkkaHttpVersion = "10.2.1"
|
||||
val SlickVersion = "3.3.3"
|
||||
|
||||
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
|
||||
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"
|
||||
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.10"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % "10.1.10"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.23"
|
||||
libraryDependencies += "com.github.swagger-akka-http" %% "swagger-akka-http" % "2.0.4"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http" % AkkaHttpVersion
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % AkkaVersion
|
||||
libraryDependencies += "com.github.swagger-akka-http" %% "swagger-akka-http" % "2.3.0"
|
||||
libraryDependencies += "javax.ws.rs" % "javax.ws.rs-api" % "2.1.1"
|
||||
|
||||
libraryDependencies += "io.spray" %% "spray-json" % "1.3.5"
|
||||
libraryDependencies += "com.lihaoyi" %% "scalatags" % "0.7.0"
|
||||
libraryDependencies += "io.spray" %% "spray-json" % "1.3.6"
|
||||
libraryDependencies += "com.lihaoyi" %% "scalatags" % "0.9.2"
|
||||
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.3.2"
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.3.2"
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick" % SlickVersion
|
||||
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % SlickVersion
|
||||
libraryDependencies += "org.flywaydb" % "flyway-core" % "6.0.6"
|
||||
libraryDependencies += "org.xerial" % "sqlite-jdbc" % "3.28.0"
|
||||
libraryDependencies += "org.postgresql" % "postgresql" % "9.3-1104-jdbc4"
|
||||
libraryDependencies += "org.xerial" % "sqlite-jdbc" % "3.32.3.2"
|
||||
libraryDependencies += "org.postgresql" % "postgresql" % "42.2.18"
|
||||
|
||||
libraryDependencies += "org.mindrot" % "jbcrypt" % "0.3m"
|
||||
|
||||
|
||||
// testing
|
||||
libraryDependencies += "org.scalactic" %% "scalactic" % "3.1.4" % "test"
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.4" % "test"
|
||||
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-actor-testkit-typed" % AkkaVersion % "test"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-stream-testkit" % AkkaVersion % "test"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http-testkit" % AkkaHttpVersion % "test"
|
||||
|
@ -54,12 +54,6 @@ me.arcanis.ffxivbis {
|
||||
port = 8000
|
||||
# hostname to use in docs, if not set host:port will be used
|
||||
#hostname = "127.0.0.1:8000"
|
||||
|
||||
# rate limits
|
||||
limits {
|
||||
intetval = 1m
|
||||
max-count = 60
|
||||
}
|
||||
}
|
||||
|
||||
default-dispatcher {
|
||||
|
@ -8,46 +8,53 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import akka.actor.typed.{Behavior, PostStop, Signal}
|
||||
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.stream.Materializer
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.http.RootEndpoint
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
import me.arcanis.ffxivbis.service.impl.DatabaseImpl
|
||||
import me.arcanis.ffxivbis.service.PartyService
|
||||
import me.arcanis.ffxivbis.service.{Database, PartyService}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.concurrent.{Await, ExecutionContext}
|
||||
import scala.util.{Failure, Success}
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
class Application extends Actor with StrictLogging {
|
||||
implicit private val executionContext: ExecutionContext = context.system.dispatcher
|
||||
implicit private val materializer: ActorMaterializer = ActorMaterializer()
|
||||
class Application(context: ActorContext[Nothing])
|
||||
extends AbstractBehavior[Nothing](context) with StrictLogging {
|
||||
|
||||
private val config = context.system.settings.config
|
||||
private val host = config.getString("me.arcanis.ffxivbis.web.host")
|
||||
private val port = config.getInt("me.arcanis.ffxivbis.web.port")
|
||||
logger.info("root supervisor started")
|
||||
startApplication()
|
||||
|
||||
override def receive: Receive = Actor.emptyBehavior
|
||||
override def onMessage(msg: Nothing): Behavior[Nothing] = Behaviors.unhandled
|
||||
|
||||
Migration(config).onComplete {
|
||||
case Success(_) =>
|
||||
val bisProvider = context.system.actorOf(BisProvider.props, "bis-provider")
|
||||
val storage = context.system.actorOf(DatabaseImpl.props, "storage")
|
||||
val party = context.system.actorOf(PartyService.props(storage), "party")
|
||||
override def onSignal: PartialFunction[Signal, Behavior[Nothing]] = {
|
||||
case PostStop =>
|
||||
logger.info("root supervisor stopped")
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
private def startApplication(): Unit = {
|
||||
val config = context.system.settings.config
|
||||
val host = config.getString("me.arcanis.ffxivbis.web.host")
|
||||
val port = config.getInt("me.arcanis.ffxivbis.web.port")
|
||||
|
||||
implicit val executionContext: ExecutionContext = context.system.executionContext
|
||||
implicit val materializer: Materializer = Materializer(context)
|
||||
|
||||
Migration(config)
|
||||
|
||||
val bisProvider = context.spawn(BisProvider(), "bis-provider")
|
||||
val storage = context.spawn(Database(), "storage")
|
||||
val party = context.spawn(PartyService(storage), "party")
|
||||
val http = new RootEndpoint(context.system, party, bisProvider)
|
||||
|
||||
logger.info(s"start server at $host:$port")
|
||||
val bind = Http()(context.system).bindAndHandle(http.route, host, port)
|
||||
Await.result(context.system.whenTerminated, Duration.Inf)
|
||||
bind.foreach(_.unbind())
|
||||
|
||||
case Failure(exception) => throw exception
|
||||
Http()(context.system).newServerAt(host, port).bindFlow(http.route)
|
||||
}
|
||||
}
|
||||
|
||||
object Application {
|
||||
def props: Props = Props(new Application)
|
||||
|
||||
def apply(): Behavior[Nothing] =
|
||||
Behaviors.setup[Nothing](context => new Application(context))
|
||||
}
|
||||
|
@ -8,13 +8,13 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.actor.typed.ActorSystem
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
object ffxivbis {
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
val config = ConfigFactory.load()
|
||||
val actorSystem = ActorSystem("ffxivbis", config)
|
||||
actorSystem.actorOf(Application.props, "ffxivbis")
|
||||
ActorSystem[Nothing](Application(), "ffxivbis", config)
|
||||
}
|
||||
}
|
||||
|
@ -8,22 +8,22 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.headers._
|
||||
import akka.http.scaladsl.server.AuthenticationFailedRejection._
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.pattern.ask
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.models.{Permission, User}
|
||||
import me.arcanis.ffxivbis.service.impl.DatabaseUserHandler
|
||||
import me.arcanis.ffxivbis.messages.{GetUser, Message}
|
||||
import me.arcanis.ffxivbis.models.Permission
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
// idea comes from https://synkre.com/bcrypt-for-akka-http-password-encryption/
|
||||
trait Authorization {
|
||||
|
||||
def storage: ActorRef
|
||||
def storage: ActorRef[Message]
|
||||
|
||||
def authenticateBasicBCrypt[T](realm: String,
|
||||
authenticate: (String, String) => Future[Option[T]]): Directive1[T] = {
|
||||
@ -40,21 +40,21 @@ trait Authorization {
|
||||
}
|
||||
|
||||
def authenticator(scope: Permission.Value, partyId: String)(username: String, password: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[String]] =
|
||||
(storage ? DatabaseUserHandler.GetUser(partyId, username)).mapTo[Option[User]].map {
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Option[String]] =
|
||||
storage.ask(GetUser(partyId, username, _)).map {
|
||||
case Some(user) if user.verify(password) && user.verityScope(scope) => Some(username)
|
||||
case _ => None
|
||||
}
|
||||
|
||||
def authAdmin(partyId: String)(username: String, password: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[String]] =
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Option[String]] =
|
||||
authenticator(Permission.admin, partyId)(username, password)
|
||||
|
||||
def authGet(partyId: String)(username: String, password: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[String]] =
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Option[String]] =
|
||||
authenticator(Permission.get, partyId)(username, password)
|
||||
|
||||
def authPost(partyId: String)(username: String, password: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[String]] =
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Option[String]] =
|
||||
authenticator(Permission.post, partyId)(username, password)
|
||||
}
|
||||
|
@ -8,37 +8,37 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.pattern.ask
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.api.v1.json.ApiAction
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceToBis, GetBiS, Message, RemovePieceFromBiS, RemovePiecesFromBiS}
|
||||
import me.arcanis.ffxivbis.models.{Piece, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.impl.DatabaseBiSHandler
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait BiSHelper extends BisProviderHelper {
|
||||
|
||||
def storage: ActorRef
|
||||
def storage: ActorRef[Message]
|
||||
|
||||
def addPieceBiS(playerId: PlayerId, piece: Piece)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseBiSHandler.AddPieceToBis(playerId, piece.withJob(playerId.job))).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(AddPieceToBis(playerId, piece.withJob(playerId.job), _))
|
||||
|
||||
def bis(partyId: String, playerId: Option[PlayerId])
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] =
|
||||
(storage ? DatabaseBiSHandler.GetBiS(partyId, playerId)).mapTo[Seq[Player]]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Seq[Player]] =
|
||||
storage.ask(GetBiS(partyId, playerId, _))
|
||||
|
||||
def doModifyBiS(action: ApiAction.Value, playerId: PlayerId, piece: Piece)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
action match {
|
||||
case ApiAction.add => addPieceBiS(playerId, piece)
|
||||
case ApiAction.remove => removePieceBiS(playerId, piece)
|
||||
}
|
||||
|
||||
def putBiS(playerId: PlayerId, link: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Unit] = {
|
||||
(storage ? DatabaseBiSHandler.RemovePiecesFromBiS(playerId)).flatMap { _ =>
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] = {
|
||||
storage.ask(RemovePiecesFromBiS(playerId, _)).flatMap { _ =>
|
||||
downloadBiS(link, playerId.job).flatMap { bis =>
|
||||
Future.traverse(bis.pieces)(addPieceBiS(playerId, _))
|
||||
}.map(_ => ())
|
||||
@ -46,7 +46,7 @@ trait BiSHelper extends BisProviderHelper {
|
||||
}
|
||||
|
||||
def removePieceBiS(playerId: PlayerId, piece: Piece)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseBiSHandler.RemovePieceFromBiS(playerId, piece)).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(RemovePieceFromBiS(playerId, piece, _))
|
||||
|
||||
}
|
||||
|
@ -8,19 +8,19 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.pattern.ask
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, DownloadBiS}
|
||||
import me.arcanis.ffxivbis.models.{BiS, Job}
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait BisProviderHelper {
|
||||
|
||||
def ariyala: ActorRef
|
||||
def provider: ActorRef[BiSProviderMessage]
|
||||
|
||||
def downloadBiS(link: String, job: Job.Job)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[BiS] =
|
||||
(ariyala ? BisProvider.GetBiS(link, job)).mapTo[BiS]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[BiS] =
|
||||
provider.ask(DownloadBiS(link, job, _))
|
||||
}
|
||||
|
@ -8,26 +8,26 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.pattern.ask
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.api.v1.json.ApiAction
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceTo, GetLoot, Message, RemovePieceFrom, SuggestLoot}
|
||||
import me.arcanis.ffxivbis.models.{Piece, Player, PlayerId, PlayerIdWithCounters}
|
||||
import me.arcanis.ffxivbis.service.LootSelector.LootSelectorResult
|
||||
import me.arcanis.ffxivbis.service.impl.DatabaseLootHandler
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait LootHelper {
|
||||
|
||||
def storage: ActorRef
|
||||
def storage: ActorRef[Message]
|
||||
|
||||
def addPieceLoot(playerId: PlayerId, piece: Piece, isFreeLoot: Boolean)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseLootHandler.AddPieceTo(playerId, piece, isFreeLoot)).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(
|
||||
AddPieceTo(playerId, piece, isFreeLoot, _))
|
||||
|
||||
def doModifyLoot(action: ApiAction.Value, playerId: PlayerId, piece: Piece, maybeFree: Option[Boolean])
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
(action, maybeFree) match {
|
||||
case (ApiAction.add, Some(isFreeLoot)) => addPieceLoot(playerId, piece, isFreeLoot)
|
||||
case (ApiAction.remove, _) => removePieceLoot(playerId, piece)
|
||||
@ -35,14 +35,14 @@ trait LootHelper {
|
||||
}
|
||||
|
||||
def loot(partyId: String, playerId: Option[PlayerId])
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] =
|
||||
(storage ? DatabaseLootHandler.GetLoot(partyId, playerId)).mapTo[Seq[Player]]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Seq[Player]] =
|
||||
storage.ask(GetLoot(partyId, playerId, _))
|
||||
|
||||
def removePieceLoot(playerId: PlayerId, piece: Piece)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseLootHandler.RemovePieceFrom(playerId, piece)).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(RemovePieceFrom(playerId, piece, _))
|
||||
|
||||
def suggestPiece(partyId: String, piece: Piece)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[PlayerIdWithCounters]] =
|
||||
(storage ? DatabaseLootHandler.SuggestLoot(partyId, piece)).mapTo[LootSelectorResult].map(_.result)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Seq[PlayerIdWithCounters]] =
|
||||
storage.ask(SuggestLoot(partyId, piece, _)).map(_.result)
|
||||
}
|
||||
|
@ -8,56 +8,56 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.pattern.ask
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.api.v1.json.ApiAction
|
||||
import me.arcanis.ffxivbis.models.{Party, PartyDescription, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.impl.{DatabaseBiSHandler, DatabasePartyHandler}
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceToBis, AddPlayer, GetParty, GetPartyDescription, GetPlayer, Message, RemovePlayer, UpdateParty}
|
||||
import me.arcanis.ffxivbis.models.{PartyDescription, Player, PlayerId}
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait PlayerHelper extends BisProviderHelper {
|
||||
|
||||
def storage: ActorRef
|
||||
def storage: ActorRef[Message]
|
||||
|
||||
def addPlayer(player: Player)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabasePartyHandler.AddPlayer(player)).mapTo[Int].map { res =>
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(ref => AddPlayer(player, ref)).map { res =>
|
||||
player.link match {
|
||||
case Some(link) =>
|
||||
downloadBiS(link, player.job).map { bis =>
|
||||
bis.pieces.map(storage ? DatabaseBiSHandler.AddPieceToBis(player.playerId, _))
|
||||
bis.pieces.map(piece => storage.ask(AddPieceToBis(player.playerId, piece, _)))
|
||||
}.map(_ => res)
|
||||
case None => Future.successful(res)
|
||||
}
|
||||
}.flatten
|
||||
|
||||
def doModifyPlayer(action: ApiAction.Value, player: Player)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
action match {
|
||||
case ApiAction.add => addPlayer(player)
|
||||
case ApiAction.remove => removePlayer(player.playerId)
|
||||
}
|
||||
|
||||
def getPartyDescription(partyId: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[PartyDescription] =
|
||||
(storage ? DatabasePartyHandler.GetPartyDescription(partyId)).mapTo[PartyDescription]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[PartyDescription] =
|
||||
storage.ask(GetPartyDescription(partyId, _))
|
||||
|
||||
def getPlayers(partyId: String, maybePlayerId: Option[PlayerId])
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] =
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Seq[Player]] =
|
||||
maybePlayerId match {
|
||||
case Some(playerId) =>
|
||||
(storage ? DatabasePartyHandler.GetPlayer(playerId)).mapTo[Option[Player]].map(_.toSeq)
|
||||
storage.ask(GetPlayer(playerId, _)).map(_.toSeq)
|
||||
case None =>
|
||||
(storage ? DatabasePartyHandler.GetParty(partyId)).mapTo[Party].map(_.players.values.toSeq)
|
||||
storage.ask(GetParty(partyId, _)).map(_.players.values.toSeq)
|
||||
}
|
||||
|
||||
def removePlayer(playerId: PlayerId)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabasePartyHandler.RemovePlayer(playerId)).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(RemovePlayer(playerId, _))
|
||||
|
||||
def updateDescription(partyDescription: PartyDescription)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabasePartyHandler.UpdateParty(partyDescription)).mapTo[Int]
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(UpdateParty(partyDescription, _))
|
||||
}
|
||||
|
@ -10,25 +10,29 @@ package me.arcanis.ffxivbis.http
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
import akka.actor.{ActorRef, ActorSystem}
|
||||
import akka.actor.typed.{ActorRef, ActorSystem, Scheduler}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.util.Timeout
|
||||
import com.typesafe.scalalogging.{Logger, StrictLogging}
|
||||
import me.arcanis.ffxivbis.http.api.v1.RootApiV1Endpoint
|
||||
import me.arcanis.ffxivbis.http.view.RootView
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
|
||||
class RootEndpoint(system: ActorSystem, storage: ActorRef, ariyala: ActorRef)
|
||||
class RootEndpoint(system: ActorSystem[Nothing],
|
||||
storage: ActorRef[Message],
|
||||
provider: ActorRef[BiSProviderMessage])
|
||||
extends StrictLogging {
|
||||
import me.arcanis.ffxivbis.utils.Implicits._
|
||||
|
||||
private val config = system.settings.config
|
||||
|
||||
implicit val scheduler: Scheduler = system.scheduler
|
||||
implicit val timeout: Timeout =
|
||||
config.getDuration("me.arcanis.ffxivbis.settings.request-timeout")
|
||||
|
||||
private val rootApiV1Endpoint: RootApiV1Endpoint = new RootApiV1Endpoint(storage, ariyala, config)
|
||||
private val rootView: RootView = new RootView(storage, ariyala)
|
||||
private val rootApiV1Endpoint: RootApiV1Endpoint = new RootApiV1Endpoint(storage, provider, config)
|
||||
private val rootView: RootView = new RootView(storage, provider)
|
||||
private val swagger: Swagger = new Swagger(config)
|
||||
private val httpLogger = Logger("http")
|
||||
|
||||
|
@ -16,6 +16,7 @@ import io.swagger.v3.oas.models.security.SecurityScheme
|
||||
import scala.io.Source
|
||||
|
||||
class Swagger(config: Config) extends SwaggerHttpService {
|
||||
|
||||
override val apiClasses: Set[Class[_]] = Set(
|
||||
classOf[api.v1.BiSEndpoint], classOf[api.v1.LootEndpoint],
|
||||
classOf[api.v1.PartyEndpoint], classOf[api.v1.PlayerEndpoint],
|
||||
|
@ -8,35 +8,34 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.pattern.ask
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.messages.{AddUser, DeleteUser, GetNewPartyId, GetUser, GetUsers, Message}
|
||||
import me.arcanis.ffxivbis.models.User
|
||||
import me.arcanis.ffxivbis.service.PartyService
|
||||
import me.arcanis.ffxivbis.service.impl.DatabaseUserHandler
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait UserHelper {
|
||||
|
||||
def storage: ActorRef
|
||||
def storage: ActorRef[Message]
|
||||
|
||||
def addUser(user: User, isHashedPassword: Boolean)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseUserHandler.AddUser(user, isHashedPassword)).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(AddUser(user, isHashedPassword, _))
|
||||
|
||||
def newPartyId(implicit executionContext: ExecutionContext, timeout: Timeout): Future[String] =
|
||||
(storage ? PartyService.GetNewPartyId).mapTo[String]
|
||||
def newPartyId(implicit timeout: Timeout, scheduler: Scheduler): Future[String] =
|
||||
storage.ask(GetNewPartyId)
|
||||
|
||||
def user(partyId: String, username: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[User]] =
|
||||
(storage ? DatabaseUserHandler.GetUser(partyId, username)).mapTo[Option[User]]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Option[User]] =
|
||||
storage.ask(GetUser(partyId, username, _))
|
||||
|
||||
def users(partyId: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[User]] =
|
||||
(storage ? DatabaseUserHandler.GetUsers(partyId)).mapTo[Seq[User]]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Seq[User]] =
|
||||
storage.ask(GetUsers(partyId, _))
|
||||
|
||||
def removeUser(partyId: String, username: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseUserHandler.DeleteUser(partyId, username)).mapTo[Int]
|
||||
(implicit timeout: Timeout, scheduler: Scheduler): Future[Unit] =
|
||||
storage.ask(DeleteUser(partyId, username, _))
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
@ -22,12 +22,15 @@ import io.swagger.v3.oas.annotations.{Operation, Parameter}
|
||||
import javax.ws.rs._
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.http.{Authorization, BiSHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
import me.arcanis.ffxivbis.models.PlayerId
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
@Path("api/v1")
|
||||
class BiSEndpoint(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class BiSEndpoint(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends BiSHelper with Authorization with JsonSupport {
|
||||
|
||||
def route: Route = createBiS ~ getBiS ~ modifyBiS
|
||||
|
@ -31,7 +31,7 @@ trait HttpHandler extends StrictLogging { this: JsonSupport =>
|
||||
.mapRejectionResponse {
|
||||
case response @ HttpResponse(_, _, entity: HttpEntity.Strict, _) =>
|
||||
val message = ErrorResponse(entity.data.utf8String).toJson
|
||||
response.copy(entity = HttpEntity(ContentTypes.`application/json`, message.compactPrint))
|
||||
response.withEntity(HttpEntity(ContentTypes.`application/json`, message.compactPrint))
|
||||
case other => other
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
@ -22,12 +22,14 @@ import io.swagger.v3.oas.annotations.{Operation, Parameter}
|
||||
import javax.ws.rs._
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.http.{Authorization, LootHelper}
|
||||
import me.arcanis.ffxivbis.messages.Message
|
||||
import me.arcanis.ffxivbis.models.PlayerId
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
@Path("api/v1")
|
||||
class LootEndpoint(override val storage: ActorRef)(implicit timeout: Timeout)
|
||||
class LootEndpoint(override val storage: ActorRef[Message])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends LootHelper with Authorization with JsonSupport with HttpHandler {
|
||||
|
||||
def route: Route = getLoot ~ modifyLoot
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
@ -22,11 +22,14 @@ import io.swagger.v3.oas.annotations.{Operation, Parameter}
|
||||
import javax.ws.rs._
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.http.{Authorization, PlayerHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
@Path("api/v1")
|
||||
class PartyEndpoint(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class PartyEndpoint(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends PlayerHelper with Authorization with JsonSupport with HttpHandler {
|
||||
|
||||
def route: Route = getPartyDescription ~ modifyPartyDescription
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
@ -22,12 +22,15 @@ import io.swagger.v3.oas.annotations.{Operation, Parameter}
|
||||
import javax.ws.rs._
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.http.{Authorization, PlayerHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
import me.arcanis.ffxivbis.models.PlayerId
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
@Path("api/v1")
|
||||
class PlayerEndpoint(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class PlayerEndpoint(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends PlayerHelper with Authorization with JsonSupport with HttpHandler {
|
||||
|
||||
def route: Route = getParty ~ modifyParty
|
||||
|
@ -8,21 +8,23 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.util.Timeout
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.http.api.v1.json.JsonSupport
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
|
||||
class RootApiV1Endpoint(storage: ActorRef, ariyala: ActorRef, config: Config)
|
||||
(implicit timeout: Timeout)
|
||||
class RootApiV1Endpoint(storage: ActorRef[Message],
|
||||
provider: ActorRef[BiSProviderMessage],
|
||||
config: Config)(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends JsonSupport with HttpHandler {
|
||||
|
||||
private val biSEndpoint = new BiSEndpoint(storage, ariyala)
|
||||
private val biSEndpoint = new BiSEndpoint(storage, provider)
|
||||
private val lootEndpoint = new LootEndpoint(storage)
|
||||
private val partyEndpoint = new PartyEndpoint(storage, ariyala)
|
||||
private val playerEndpoint = new PlayerEndpoint(storage, ariyala)
|
||||
private val partyEndpoint = new PartyEndpoint(storage, provider)
|
||||
private val playerEndpoint = new PlayerEndpoint(storage, provider)
|
||||
private val typesEndpoint = new TypesEndpoint(config)
|
||||
private val userEndpoint = new UserEndpoint(storage)
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
@ -22,12 +22,14 @@ import io.swagger.v3.oas.annotations.{Operation, Parameter}
|
||||
import javax.ws.rs._
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.http.{Authorization, UserHelper}
|
||||
import me.arcanis.ffxivbis.messages.Message
|
||||
import me.arcanis.ffxivbis.models.Permission
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
@Path("api/v1")
|
||||
class UserEndpoint(override val storage: ActorRef)(implicit timeout: Timeout)
|
||||
class UserEndpoint(override val storage: ActorRef[Message])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends UserHelper with Authorization with JsonSupport {
|
||||
|
||||
def route: Route = createParty ~ createUser ~ deleteUser ~ getUsers
|
||||
|
@ -9,10 +9,12 @@ case class LootResponse(
|
||||
@Schema(description = "looted piece", required = true) piece: PieceResponse,
|
||||
@Schema(description = "loot timestamp", required = true) timestamp: Instant,
|
||||
@Schema(description = "is loot free for all", required = true) isFreeLoot: Boolean) {
|
||||
|
||||
def toLoot: Loot = Loot(-1, piece.toPiece, timestamp, isFreeLoot)
|
||||
}
|
||||
|
||||
object LootResponse {
|
||||
|
||||
def fromLoot(loot: Loot): LootResponse =
|
||||
LootResponse(PieceResponse.fromPiece(loot.piece), loot.timestamp, loot.isFreeLoot)
|
||||
}
|
@ -14,10 +14,12 @@ import me.arcanis.ffxivbis.models.PartyDescription
|
||||
case class PartyDescriptionResponse(
|
||||
@Schema(description = "party id", required = true) partyId: String,
|
||||
@Schema(description = "party name") partyAlias: Option[String]) {
|
||||
|
||||
def toDescription: PartyDescription = PartyDescription(partyId, partyAlias)
|
||||
}
|
||||
|
||||
object PartyDescriptionResponse {
|
||||
|
||||
def fromDescription(description: PartyDescription): PartyDescriptionResponse =
|
||||
PartyDescriptionResponse(description.partyId, description.partyAlias)
|
||||
}
|
||||
|
@ -15,10 +15,12 @@ case class PieceResponse(
|
||||
@Schema(description = "piece type", required = true) pieceType: String,
|
||||
@Schema(description = "job name to which piece belong or AnyJob", required = true, example = "DNC") job: String,
|
||||
@Schema(description = "piece name", required = true, example = "body") piece: String) {
|
||||
|
||||
def toPiece: Piece = Piece(piece, PieceType.withName(pieceType), Job.withName(job))
|
||||
}
|
||||
|
||||
object PieceResponse {
|
||||
|
||||
def fromPiece(piece: Piece): PieceResponse =
|
||||
PieceResponse(piece.pieceType.toString, piece.job.toString, piece.piece)
|
||||
}
|
||||
|
@ -15,11 +15,13 @@ case class PlayerIdResponse(
|
||||
@Schema(description = "unique party ID. Required in responses", example = "abcdefgh") partyId: Option[String],
|
||||
@Schema(description = "job name", required = true, example = "DNC") job: String,
|
||||
@Schema(description = "player nick name", required = true, example = "Siuan Sanche") nick: String) {
|
||||
|
||||
def withPartyId(partyId: String): PlayerId =
|
||||
PlayerId(partyId, Job.withName(job), nick)
|
||||
}
|
||||
|
||||
object PlayerIdResponse {
|
||||
|
||||
def fromPlayerId(playerId: PlayerId): PlayerIdResponse =
|
||||
PlayerIdResponse(Some(playerId.partyId), playerId.job.toString, playerId.nick)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ case class PlayerIdWithCountersResponse(
|
||||
@Schema(description = "total count of looted pieces", required = true) lootCountTotal: Int)
|
||||
|
||||
object PlayerIdWithCountersResponse {
|
||||
|
||||
def fromPlayerId(playerIdWithCounters: PlayerIdWithCounters): PlayerIdWithCountersResponse =
|
||||
PlayerIdWithCountersResponse(
|
||||
playerIdWithCounters.partyId,
|
||||
|
@ -19,6 +19,7 @@ case class PlayerResponse(
|
||||
@Schema(description = "looted pieces") loot: Option[Seq[LootResponse]],
|
||||
@Schema(description = "link to best in slot", example = "https://ffxiv.ariyala.com/19V5R") link: Option[String],
|
||||
@Schema(description = "player loot priority", `type` = "number") priority: Option[Int]) {
|
||||
|
||||
def toPlayer: Player =
|
||||
Player(-1, partyId, Job.withName(job), nick,
|
||||
BiS(bis.getOrElse(Seq.empty).map(_.toPiece)),
|
||||
@ -27,6 +28,7 @@ case class PlayerResponse(
|
||||
}
|
||||
|
||||
object PlayerResponse {
|
||||
|
||||
def fromPlayer(player: Player): PlayerResponse =
|
||||
PlayerResponse(player.partyId, player.job.toString, player.nick,
|
||||
Some(player.bis.pieces.map(PieceResponse.fromPiece)),
|
||||
|
@ -16,11 +16,13 @@ case class UserResponse(
|
||||
@Schema(description = "username to login to party", required = true, example = "siuan") username: String,
|
||||
@Schema(description = "password to login to party", required = true, example = "pa55w0rd") password: String,
|
||||
@Schema(description = "user permission", defaultValue = "get", allowableValues = Array("get", "post", "admin")) permission: Option[Permission.Value] = None) {
|
||||
|
||||
def toUser: User =
|
||||
User(partyId, username, password, permission.getOrElse(Permission.get))
|
||||
}
|
||||
|
||||
object UserResponse {
|
||||
|
||||
def fromUser(user: User): UserResponse =
|
||||
UserResponse(user.partyId, user.username, "", Some(user.permission))
|
||||
}
|
||||
|
@ -8,16 +8,19 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{Authorization, PlayerHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
class BasePartyView(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class BasePartyView(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends PlayerHelper with Authorization {
|
||||
|
||||
def route: Route = getIndex
|
||||
|
@ -8,18 +8,21 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{Authorization, BiSHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
import me.arcanis.ffxivbis.models.{Piece, PieceType, Player, PlayerId}
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.util.Try
|
||||
|
||||
class BiSView(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class BiSView(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends BiSHelper with Authorization {
|
||||
|
||||
def route: Route = getBiS ~ modifyBiS
|
||||
@ -64,7 +67,7 @@ class BiSView(override val storage: ActorRef, override val ariyala: ActorRef)(im
|
||||
def getPiece(playerId: PlayerId, piece: String, pieceType: String) =
|
||||
Try(Piece(piece, PieceType.withName(pieceType), playerId.job)).toOption
|
||||
|
||||
def bisAction(playerId: PlayerId, piece: String, pieceType: String)(fn: Piece => Future[Int]) =
|
||||
def bisAction(playerId: PlayerId, piece: String, pieceType: String)(fn: Piece => Future[Unit]) =
|
||||
getPiece(playerId, piece, pieceType) match {
|
||||
case Some(item) => fn(item).map(_ => ())
|
||||
case _ => Future.failed(new Error(s"Could not construct piece from `$piece ($pieceType)`"))
|
||||
@ -73,9 +76,9 @@ class BiSView(override val storage: ActorRef, override val ariyala: ActorRef)(im
|
||||
PlayerId(partyId, player) match {
|
||||
case Some(playerId) => (maybePiece, maybePieceType, action, maybeLink) match {
|
||||
case (Some(piece), Some(pieceType), "add", _) =>
|
||||
bisAction(playerId, piece, pieceType) { item => addPieceBiS(playerId, item) }
|
||||
bisAction(playerId, piece, pieceType)(addPieceBiS(playerId, _))
|
||||
case (Some(piece), Some(pieceType), "remove", _) =>
|
||||
bisAction(playerId, piece, pieceType) { item => removePieceBiS(playerId, item) }
|
||||
bisAction(playerId, piece, pieceType)(removePieceBiS(playerId, _))
|
||||
case (_, _, "create", Some(link)) => putBiS(playerId, link).map(_ => ())
|
||||
case _ => Future.failed(new Error(s"Could not perform $action"))
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import scalatags.Text
|
||||
import scalatags.Text.all._
|
||||
|
||||
object ErrorView {
|
||||
|
||||
def template(error: Option[String]): Text.TypedTag[String] = error match {
|
||||
case Some(text) => p(id:="error", s"Error occurs: $text")
|
||||
case None => p("")
|
||||
|
@ -12,6 +12,7 @@ import scalatags.Text
|
||||
import scalatags.Text.all._
|
||||
|
||||
object ExportToCSVView {
|
||||
|
||||
def template: Text.TypedTag[String] =
|
||||
div(
|
||||
button(onclick:="exportTableToCsv('result.csv')")("Export to CSV"),
|
||||
|
@ -8,18 +8,21 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{PlayerHelper, UserHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
import me.arcanis.ffxivbis.models.{PartyDescription, Permission, User}
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.util.{Failure, Success}
|
||||
|
||||
class IndexView(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class IndexView(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends PlayerHelper with UserHelper {
|
||||
|
||||
def route: Route = createParty ~ getIndex
|
||||
|
@ -8,18 +8,20 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{Authorization, LootHelper}
|
||||
import me.arcanis.ffxivbis.messages.Message
|
||||
import me.arcanis.ffxivbis.models.{Job, Piece, PieceType, PlayerIdWithCounters}
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class LootSuggestView(override val storage: ActorRef)(implicit timeout: Timeout)
|
||||
class LootSuggestView(override val storage: ActorRef[Message])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends LootHelper with Authorization {
|
||||
|
||||
def route: Route = getIndex ~ suggestLoot
|
||||
|
@ -8,18 +8,20 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{Authorization, LootHelper}
|
||||
import me.arcanis.ffxivbis.messages.Message
|
||||
import me.arcanis.ffxivbis.models.{Piece, PieceType, Player, PlayerId}
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.util.Try
|
||||
|
||||
class LootView (override val storage: ActorRef)(implicit timeout: Timeout)
|
||||
class LootView(override val storage: ActorRef[Message])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends LootHelper with Authorization {
|
||||
|
||||
def route: Route = getLoot ~ modifyLoot
|
||||
|
@ -8,17 +8,20 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{Authorization, PlayerHelper}
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
import me.arcanis.ffxivbis.models._
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
class PlayerView(override val storage: ActorRef, override val ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
class PlayerView(override val storage: ActorRef[Message],
|
||||
override val provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends PlayerHelper with Authorization {
|
||||
|
||||
def route: Route = getParty ~ modifyParty
|
||||
|
@ -8,21 +8,24 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, Message}
|
||||
|
||||
class RootView(storage: ActorRef, ariyala: ActorRef)(implicit timeout: Timeout) {
|
||||
class RootView(storage: ActorRef[Message],
|
||||
provider: ActorRef[BiSProviderMessage])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler) {
|
||||
|
||||
private val basePartyView = new BasePartyView(storage, ariyala)
|
||||
private val indexView = new IndexView(storage, ariyala)
|
||||
private val basePartyView = new BasePartyView(storage, provider)
|
||||
private val indexView = new IndexView(storage, provider)
|
||||
|
||||
private val biSView = new BiSView(storage, ariyala)
|
||||
private val biSView = new BiSView(storage, provider)
|
||||
private val lootView = new LootView(storage)
|
||||
private val lootSuggestView = new LootSuggestView(storage)
|
||||
private val playerView = new PlayerView(storage, ariyala)
|
||||
private val playerView = new PlayerView(storage, provider)
|
||||
private val userView = new UserView(storage)
|
||||
|
||||
def route: Route =
|
||||
@ -31,6 +34,7 @@ class RootView(storage: ActorRef, ariyala: ActorRef)(implicit timeout: Timeout)
|
||||
}
|
||||
|
||||
object RootView {
|
||||
|
||||
def toHtml(template: String): HttpEntity.Strict =
|
||||
HttpEntity(ContentTypes.`text/html(UTF-8)`, template)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import scalatags.Text
|
||||
import scalatags.Text.all._
|
||||
|
||||
object SearchLineView {
|
||||
|
||||
def template: Text.TypedTag[String] =
|
||||
div(
|
||||
input(
|
||||
|
@ -8,18 +8,20 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.http.view
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.typed.{ActorRef, Scheduler}
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.util.Timeout
|
||||
import me.arcanis.ffxivbis.http.{Authorization, UserHelper}
|
||||
import me.arcanis.ffxivbis.messages.Message
|
||||
import me.arcanis.ffxivbis.models.{Permission, User}
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.util.Try
|
||||
|
||||
class UserView(override val storage: ActorRef)(implicit timeout: Timeout)
|
||||
class UserView(override val storage: ActorRef[Message])
|
||||
(implicit timeout: Timeout, scheduler: Scheduler)
|
||||
extends UserHelper with Authorization {
|
||||
|
||||
def route: Route = getUsers ~ modifyUsers
|
||||
|
@ -0,0 +1,8 @@
|
||||
package me.arcanis.ffxivbis.messages
|
||||
|
||||
import akka.actor.typed.ActorRef
|
||||
import me.arcanis.ffxivbis.models.{BiS, Job}
|
||||
|
||||
sealed trait BiSProviderMessage
|
||||
|
||||
case class DownloadBiS(link: String, job: Job.Job, replyTo: ActorRef[BiS]) extends BiSProviderMessage
|
@ -0,0 +1,10 @@
|
||||
package me.arcanis.ffxivbis.messages
|
||||
|
||||
import akka.actor.typed.ActorRef
|
||||
import me.arcanis.ffxivbis.models.Party
|
||||
|
||||
case class ForgetParty(partyId: String) extends Message
|
||||
|
||||
case class GetNewPartyId(replyTo: ActorRef[String]) extends Message
|
||||
|
||||
case class StoreParty(partyId: String, party: Party) extends Message
|
@ -0,0 +1,77 @@
|
||||
package me.arcanis.ffxivbis.messages
|
||||
|
||||
import akka.actor.typed.{ActorRef, Behavior}
|
||||
import me.arcanis.ffxivbis.models.{Party, PartyDescription, Piece, Player, PlayerId, User}
|
||||
import me.arcanis.ffxivbis.service.LootSelector
|
||||
|
||||
sealed trait DatabaseMessage extends Message {
|
||||
|
||||
def partyId: String
|
||||
}
|
||||
|
||||
object DatabaseMessage {
|
||||
|
||||
type Handler = PartialFunction[DatabaseMessage, Behavior[DatabaseMessage]]
|
||||
}
|
||||
|
||||
// bis handler
|
||||
case class AddPieceToBis(playerId: PlayerId, piece: Piece, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
case class GetBiS(partyId: String, playerId: Option[PlayerId], replyTo: ActorRef[Seq[Player]]) extends DatabaseMessage
|
||||
|
||||
case class RemovePieceFromBiS(playerId: PlayerId, piece: Piece, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
case class RemovePiecesFromBiS(playerId: PlayerId, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
// loot handler
|
||||
case class AddPieceTo(playerId: PlayerId, piece: Piece, isFreeLoot: Boolean, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
case class GetLoot(partyId: String, playerId: Option[PlayerId], replyTo: ActorRef[Seq[Player]]) extends DatabaseMessage
|
||||
|
||||
case class RemovePieceFrom(playerId: PlayerId, piece: Piece, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
case class SuggestLoot(partyId: String, piece: Piece, replyTo: ActorRef[LootSelector.LootSelectorResult]) extends DatabaseMessage
|
||||
|
||||
// party handler
|
||||
case class AddPlayer(player: Player, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = player.partyId
|
||||
}
|
||||
|
||||
case class GetParty(partyId: String, replyTo: ActorRef[Party]) extends DatabaseMessage
|
||||
|
||||
case class GetPartyDescription(partyId: String, replyTo: ActorRef[PartyDescription]) extends DatabaseMessage
|
||||
|
||||
case class GetPlayer(playerId: PlayerId, replyTo: ActorRef[Option[Player]]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
case class RemovePlayer(playerId: PlayerId, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
|
||||
case class UpdateParty(partyDescription: PartyDescription, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = partyDescription.partyId
|
||||
}
|
||||
|
||||
// user handler
|
||||
case class AddUser(user: User, isHashedPassword: Boolean, replyTo: ActorRef[Unit]) extends DatabaseMessage {
|
||||
override def partyId: String = user.partyId
|
||||
}
|
||||
|
||||
case class DeleteUser(partyId: String, username: String, replyTo: ActorRef[Unit]) extends DatabaseMessage
|
||||
|
||||
case class Exists(partyId: String, replyTo: ActorRef[Boolean]) extends DatabaseMessage
|
||||
|
||||
case class GetUser(partyId: String, username: String, replyTo: ActorRef[Option[User]]) extends DatabaseMessage
|
||||
|
||||
case class GetUsers(partyId: String, replyTo: ActorRef[Seq[User]]) extends DatabaseMessage
|
@ -0,0 +1,9 @@
|
||||
package me.arcanis.ffxivbis.messages
|
||||
|
||||
import akka.actor.typed.Behavior
|
||||
|
||||
trait Message
|
||||
|
||||
object Message {
|
||||
type Handler = PartialFunction[Message, Behavior[Message]]
|
||||
}
|
@ -26,14 +26,15 @@ object Job {
|
||||
object BodyTanks extends LeftSide
|
||||
object BodyRanges extends LeftSide
|
||||
|
||||
sealed trait Job {
|
||||
sealed trait Job extends Equals {
|
||||
|
||||
def leftSide: LeftSide
|
||||
def rightSide: RightSide
|
||||
|
||||
// conversion to string to avoid recursion
|
||||
override def canEqual(that: Any): Boolean = that.isInstanceOf[Job]
|
||||
|
||||
override def equals(obj: Any): Boolean = {
|
||||
def canEqual(obj: Any): Boolean = obj.isInstanceOf[Job]
|
||||
def equality(objRepr: String): Boolean = objRepr match {
|
||||
case _ if objRepr == AnyJob.toString => true
|
||||
case _ if this.toString == AnyJob.toString => true
|
||||
|
@ -8,21 +8,22 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.Actor
|
||||
import akka.actor.typed.Behavior
|
||||
import akka.actor.typed.scaladsl.Behaviors
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.messages.{DatabaseMessage}
|
||||
import me.arcanis.ffxivbis.models.{Party, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.impl.DatabaseImpl
|
||||
import me.arcanis.ffxivbis.storage.DatabaseProfile
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait Database extends Actor with StrictLogging {
|
||||
implicit def executionContext: ExecutionContext
|
||||
def profile: DatabaseProfile
|
||||
trait Database extends StrictLogging {
|
||||
|
||||
override def postStop(): Unit = {
|
||||
profile.db.close()
|
||||
super.postStop()
|
||||
}
|
||||
implicit def executionContext: ExecutionContext
|
||||
def config: Config
|
||||
def profile: DatabaseProfile
|
||||
|
||||
def filterParty(party: Party, maybePlayerId: Option[PlayerId]): Seq[Player] =
|
||||
maybePlayerId match {
|
||||
@ -36,11 +37,11 @@ trait Database extends Actor with StrictLogging {
|
||||
players <- profile.getParty(partyId)
|
||||
bis <- if (withBiS) profile.getPiecesBiS(partyId) else Future(Seq.empty)
|
||||
loot <- if (withLoot) profile.getPieces(partyId) else Future(Seq.empty)
|
||||
} yield Party(partyDescription, context.system.settings.config, players, bis, loot)
|
||||
} yield Party(partyDescription, config, players, bis, loot)
|
||||
}
|
||||
|
||||
object Database {
|
||||
trait DatabaseRequest {
|
||||
def partyId: String
|
||||
}
|
||||
|
||||
def apply(): Behavior[DatabaseMessage] =
|
||||
Behaviors.setup[DatabaseMessage](context => new DatabaseImpl(context))
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ class LootSelector(players: Seq[Player], piece: Piece, orderBy: Seq[String]) {
|
||||
}
|
||||
|
||||
object LootSelector {
|
||||
|
||||
def apply(players: Seq[Player], piece: Piece, orderBy: Seq[String]): LootSelectorResult =
|
||||
new LootSelector(players, piece, orderBy).suggest
|
||||
|
||||
|
@ -8,57 +8,65 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import akka.pattern.{ask, pipe}
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.actor.typed.{ActorRef, Behavior, DispatcherSelector, Scheduler}
|
||||
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
|
||||
import akka.util.Timeout
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.messages.{DatabaseMessage, Exists, ForgetParty, GetNewPartyId, GetParty, Message, StoreParty}
|
||||
import me.arcanis.ffxivbis.models.Party
|
||||
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
class PartyService(storage: ActorRef) extends Actor with StrictLogging {
|
||||
import PartyService._
|
||||
class PartyService(context: ActorContext[Message], storage: ActorRef[DatabaseMessage])
|
||||
extends AbstractBehavior[Message](context) with StrictLogging {
|
||||
import me.arcanis.ffxivbis.utils.Implicits._
|
||||
|
||||
private val cacheTimeout: FiniteDuration =
|
||||
context.system.settings.config.getDuration("me.arcanis.ffxivbis.settings.cache-timeout")
|
||||
implicit private val executionContext: ExecutionContext =
|
||||
context.system.dispatchers.lookup("me.arcanis.ffxivbis.default-dispatcher")
|
||||
implicit private val executionContext: ExecutionContext = {
|
||||
val selector = DispatcherSelector.fromConfig("me.arcanis.ffxivbis.default-dispatcher")
|
||||
context.system.dispatchers.lookup(selector)
|
||||
}
|
||||
implicit private val timeout: Timeout =
|
||||
context.system.settings.config.getDuration("me.arcanis.ffxivbis.settings.request-timeout")
|
||||
implicit private val scheduler: Scheduler = context.system.scheduler
|
||||
|
||||
override def receive: Receive = handle(Map.empty)
|
||||
override def onMessage(msg: Message): Behavior[Message] = handle(Map.empty)(msg)
|
||||
|
||||
private def handle(cache: Map[String, Party]): Receive = {
|
||||
private def handle(cache: Map[String, Party]): Message.Handler = {
|
||||
case ForgetParty(partyId) =>
|
||||
context become handle(cache - partyId)
|
||||
Behaviors.receiveMessage(handle(cache - partyId))
|
||||
|
||||
case GetNewPartyId =>
|
||||
val client = sender()
|
||||
getPartyId.pipeTo(client)
|
||||
case GetNewPartyId(client) =>
|
||||
getPartyId.foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case req @ impl.DatabasePartyHandler.GetParty(partyId) =>
|
||||
val client = sender()
|
||||
case StoreParty(partyId, party) =>
|
||||
Behaviors.receiveMessage(handle(cache.updated(partyId, party)))
|
||||
|
||||
case GetParty(partyId, client) =>
|
||||
val party = cache.get(partyId) match {
|
||||
case Some(party) => Future.successful(party)
|
||||
case None =>
|
||||
(storage ? req).mapTo[Party].map { party =>
|
||||
context become handle(cache + (partyId -> party))
|
||||
context.system.scheduler.scheduleOnce(cacheTimeout, self, ForgetParty(partyId))
|
||||
storage.ask(ref => GetParty(partyId, ref)).map { party =>
|
||||
context.self ! StoreParty(partyId, party)
|
||||
context.system.scheduler.scheduleOnce(cacheTimeout, () => context.self ! ForgetParty(partyId))
|
||||
party
|
||||
}
|
||||
}
|
||||
party.pipeTo(client)
|
||||
party.foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case req: Database.DatabaseRequest =>
|
||||
self ! ForgetParty(req.partyId)
|
||||
storage.forward(req)
|
||||
case req: DatabaseMessage =>
|
||||
storage ! req
|
||||
Behaviors.receiveMessage(handle(cache - req.partyId))
|
||||
}
|
||||
|
||||
private def getPartyId: Future[String] = {
|
||||
val partyId = Party.randomPartyId
|
||||
(storage ? impl.DatabaseUserHandler.Exists(partyId)).mapTo[Boolean].flatMap {
|
||||
storage.ask(ref => Exists(partyId, ref)).flatMap {
|
||||
case true => getPartyId
|
||||
case false => Future.successful(partyId)
|
||||
}
|
||||
@ -66,8 +74,7 @@ class PartyService(storage: ActorRef) extends Actor with StrictLogging {
|
||||
}
|
||||
|
||||
object PartyService {
|
||||
def props(storage: ActorRef): Props = Props(new PartyService(storage))
|
||||
|
||||
case class ForgetParty(partyId: String)
|
||||
case object GetNewPartyId
|
||||
def apply(storage: ActorRef[DatabaseMessage]): Behavior[Message] =
|
||||
Behaviors.setup[Message](context => new PartyService(context, storage))
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
import akka.actor.Actor
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
|
||||
class RateLimiter extends Actor {
|
||||
import RateLimiter._
|
||||
import me.arcanis.ffxivbis.utils.Implicits._
|
||||
|
||||
implicit private val executionContext: ExecutionContext = context.system.dispatcher
|
||||
|
||||
private val maxRequestCount: Int = context.system.settings.config.getInt("me.arcanis.ffxivbis.web.limits.max-count")
|
||||
private val requestInterval: FiniteDuration = context.system.settings.config.getDuration("me.arcanis.ffxivbis.web.limits.interval")
|
||||
|
||||
override def receive: Receive = handle(Map.empty)
|
||||
|
||||
private def handle(cache: Map[String, Usage]): Receive = {
|
||||
case username: String =>
|
||||
val client = sender()
|
||||
val usage = if (cache.contains(username)) {
|
||||
cache(username)
|
||||
} else {
|
||||
context.system.scheduler.scheduleOnce(requestInterval, self, Reset(username))
|
||||
Usage()
|
||||
}
|
||||
context become handle(cache + (username -> usage.increment))
|
||||
|
||||
val response = if (usage.count > maxRequestCount) Some(usage.left) else None
|
||||
client ! response
|
||||
|
||||
case Reset(username) =>
|
||||
context become handle(cache - username)
|
||||
}
|
||||
}
|
||||
|
||||
object RateLimiter {
|
||||
private case class Usage(count: Int = 0, since: Instant = Instant.now) {
|
||||
def increment: Usage = copy(count = count + 1)
|
||||
def left: Long = (Instant.now.toEpochMilli - since.toEpochMilli) / 1000
|
||||
}
|
||||
|
||||
case class Reset(username: String)
|
||||
}
|
@ -10,26 +10,33 @@ package me.arcanis.ffxivbis.service.bis
|
||||
|
||||
import java.nio.file.Paths
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import akka.actor.ClassicActorSystemProvider
|
||||
import akka.actor.typed.{Behavior, PostStop, Signal}
|
||||
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
|
||||
import akka.http.scaladsl.model._
|
||||
import akka.pattern.pipe
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.messages.{BiSProviderMessage, DownloadBiS}
|
||||
import me.arcanis.ffxivbis.models.{BiS, Job, Piece, PieceType}
|
||||
import spray.json._
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
class BisProvider extends Actor with XivApi with StrictLogging {
|
||||
class BisProvider(context: ActorContext[BiSProviderMessage])
|
||||
extends AbstractBehavior[BiSProviderMessage](context) with XivApi with StrictLogging {
|
||||
|
||||
override def receive: Receive = {
|
||||
case BisProvider.GetBiS(link, job) =>
|
||||
val client = sender()
|
||||
get(link, job).map(BiS(_)).pipeTo(client)
|
||||
override def system: ClassicActorSystemProvider = context.system
|
||||
|
||||
override def onMessage(msg: BiSProviderMessage): Behavior[BiSProviderMessage] =
|
||||
msg match {
|
||||
case DownloadBiS(link, job, client) =>
|
||||
get(link, job).map(BiS(_)).foreach(client ! _)
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
override def postStop(): Unit = {
|
||||
override def onSignal: PartialFunction[Signal, Behavior[BiSProviderMessage]] = {
|
||||
case PostStop =>
|
||||
shutdown()
|
||||
super.postStop()
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
private def get(link: String, job: Job.Job): Future[Seq[Piece]] = {
|
||||
@ -49,9 +56,8 @@ class BisProvider extends Actor with XivApi with StrictLogging {
|
||||
|
||||
object BisProvider {
|
||||
|
||||
def props: Props = Props(new BisProvider)
|
||||
|
||||
case class GetBiS(link: String, job: Job.Job)
|
||||
def apply(): Behavior[BiSProviderMessage] =
|
||||
Behaviors.setup[BiSProviderMessage](context => new BisProvider(context))
|
||||
|
||||
private def parseBisJsonToPieces(job: Job.Job,
|
||||
idParser: (Job.Job, JsObject) => Future[Map[String, Long]],
|
||||
|
@ -8,11 +8,11 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service.bis
|
||||
|
||||
import akka.actor.ActorContext
|
||||
import akka.actor.ClassicActorSystemProvider
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.http.scaladsl.model.headers.Location
|
||||
import akka.http.scaladsl.model.{HttpRequest, HttpResponse, Uri}
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.stream.Materializer
|
||||
import akka.stream.scaladsl.{Keep, Sink}
|
||||
import akka.util.ByteString
|
||||
import spray.json._
|
||||
@ -21,12 +21,12 @@ import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait RequestExecutor {
|
||||
|
||||
def context: ActorContext
|
||||
def system: ClassicActorSystemProvider
|
||||
|
||||
private val http = Http()(context.system)
|
||||
implicit val materializer: ActorMaterializer = ActorMaterializer()(context)
|
||||
private val http = Http()(system)
|
||||
implicit val materializer: Materializer = Materializer.createMaterializer(system)
|
||||
implicit val executionContext: ExecutionContext =
|
||||
context.system.dispatchers.lookup("me.arcanis.ffxivbis.default-dispatcher")
|
||||
system.classicSystem.dispatchers.lookup("me.arcanis.ffxivbis.default-dispatcher")
|
||||
|
||||
def sendRequest[T](uri: Uri, parser: JsObject => Future[T]): Future[T] =
|
||||
http.singleRequest(HttpRequest(uri = uri)).map {
|
||||
|
@ -17,7 +17,7 @@ import scala.util.Try
|
||||
|
||||
trait XivApi extends RequestExecutor {
|
||||
|
||||
private val config = context.system.settings.config
|
||||
private val config = system.classicSystem.settings.config
|
||||
private val xivapiUrl = config.getString("me.arcanis.ffxivbis.bis-provider.xivapi-url")
|
||||
private val xivapiKey = Try(config.getString("me.arcanis.ffxivbis.bis-provider.xivapi-key")).toOption
|
||||
|
||||
|
@ -8,43 +8,30 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service.impl
|
||||
|
||||
import akka.pattern.pipe
|
||||
import me.arcanis.ffxivbis.models.{Piece, PlayerId}
|
||||
import akka.actor.typed.scaladsl.Behaviors
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceToBis, DatabaseMessage, GetBiS, RemovePieceFromBiS, RemovePiecesFromBiS}
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
|
||||
trait DatabaseBiSHandler { this: Database =>
|
||||
import DatabaseBiSHandler._
|
||||
|
||||
def bisHandler: Receive = {
|
||||
case AddPieceToBis(playerId, piece) =>
|
||||
val client = sender()
|
||||
profile.insertPieceBiS(playerId, piece).pipeTo(client)
|
||||
def bisHandler: DatabaseMessage.Handler = {
|
||||
case AddPieceToBis(playerId, piece, client) =>
|
||||
profile.insertPieceBiS(playerId, piece).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case GetBiS(partyId, maybePlayerId) =>
|
||||
val client = sender()
|
||||
case GetBiS(partyId, maybePlayerId, client) =>
|
||||
getParty(partyId, withBiS = true, withLoot = false)
|
||||
.map(filterParty(_, maybePlayerId))
|
||||
.pipeTo(client)
|
||||
.foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case RemovePieceFromBiS(playerId, piece) =>
|
||||
val client = sender()
|
||||
profile.deletePieceBiS(playerId, piece).pipeTo(client)
|
||||
case RemovePieceFromBiS(playerId, piece, client) =>
|
||||
profile.deletePieceBiS(playerId, piece).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case RemovePiecesFromBiS(playerId) =>
|
||||
val client = sender()
|
||||
profile.deletePiecesBiS(playerId).pipeTo(client)
|
||||
case RemovePiecesFromBiS(playerId, client) =>
|
||||
profile.deletePiecesBiS(playerId).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
}
|
||||
}
|
||||
|
||||
object DatabaseBiSHandler {
|
||||
case class AddPieceToBis(playerId: PlayerId, piece: Piece) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class GetBiS(partyId: String, playerId: Option[PlayerId]) extends Database.DatabaseRequest
|
||||
case class RemovePieceFromBiS(playerId: PlayerId, piece: Piece) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class RemovePiecesFromBiS(playerId: PlayerId) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
}
|
||||
|
@ -8,24 +8,29 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service.impl
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.actor.typed.{Behavior, DispatcherSelector}
|
||||
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext}
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.messages.DatabaseMessage
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
import me.arcanis.ffxivbis.storage.DatabaseProfile
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
class DatabaseImpl extends Database
|
||||
class DatabaseImpl(context: ActorContext[DatabaseMessage])
|
||||
extends AbstractBehavior[DatabaseMessage](context) with Database
|
||||
with DatabaseBiSHandler with DatabaseLootHandler
|
||||
with DatabasePartyHandler with DatabaseUserHandler {
|
||||
|
||||
implicit val executionContext: ExecutionContext =
|
||||
context.system.dispatchers.lookup("me.arcanis.ffxivbis.default-dispatcher")
|
||||
val profile = new DatabaseProfile(executionContext, context.system.settings.config)
|
||||
override implicit val executionContext: ExecutionContext = {
|
||||
val selector = DispatcherSelector.fromConfig("me.arcanis.ffxivbis.default-dispatcher")
|
||||
context.system.dispatchers.lookup(selector)
|
||||
}
|
||||
override val config: Config = context.system.settings.config
|
||||
override val profile: DatabaseProfile = new DatabaseProfile(executionContext, config)
|
||||
|
||||
override def receive: Receive =
|
||||
override def onMessage(msg: DatabaseMessage): Behavior[DatabaseMessage] = handle(msg)
|
||||
|
||||
private def handle: DatabaseMessage.Handler =
|
||||
bisHandler orElse lootHandler orElse partyHandler orElse userHandler
|
||||
}
|
||||
|
||||
object DatabaseImpl {
|
||||
def props: Props = Props(new DatabaseImpl)
|
||||
}
|
||||
|
@ -10,42 +10,33 @@ package me.arcanis.ffxivbis.service.impl
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
import akka.pattern.pipe
|
||||
import me.arcanis.ffxivbis.models.{Loot, Piece, PlayerId}
|
||||
import akka.actor.typed.scaladsl.Behaviors
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceTo, DatabaseMessage, GetLoot, RemovePieceFrom, SuggestLoot}
|
||||
import me.arcanis.ffxivbis.models.Loot
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
|
||||
trait DatabaseLootHandler { this: Database =>
|
||||
import DatabaseLootHandler._
|
||||
|
||||
def lootHandler: Receive = {
|
||||
case AddPieceTo(playerId, piece, isFreeLoot) =>
|
||||
val client = sender()
|
||||
def lootHandler: DatabaseMessage.Handler = {
|
||||
case AddPieceTo(playerId, piece, isFreeLoot, client) =>
|
||||
val loot = Loot(-1, piece, Instant.now, isFreeLoot)
|
||||
profile.insertPiece(playerId, loot).pipeTo(client)
|
||||
profile.insertPiece(playerId, loot).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case GetLoot(partyId, maybePlayerId) =>
|
||||
val client = sender()
|
||||
case GetLoot(partyId, maybePlayerId, client) =>
|
||||
getParty(partyId, withBiS = false, withLoot = true)
|
||||
.map(filterParty(_, maybePlayerId))
|
||||
.pipeTo(client)
|
||||
.foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case RemovePieceFrom(playerId, piece) =>
|
||||
val client = sender()
|
||||
profile.deletePiece(playerId, piece).pipeTo(client)
|
||||
case RemovePieceFrom(playerId, piece, client) =>
|
||||
profile.deletePiece(playerId, piece).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case SuggestLoot(partyId, piece) =>
|
||||
val client = sender()
|
||||
getParty(partyId, withBiS = true, withLoot = true).map(_.suggestLoot(piece)).pipeTo(client)
|
||||
case SuggestLoot(partyId, piece, client) =>
|
||||
getParty(partyId, withBiS = true, withLoot = true)
|
||||
.map(_.suggestLoot(piece))
|
||||
.foreach(client ! _)
|
||||
Behaviors.same
|
||||
}
|
||||
}
|
||||
|
||||
object DatabaseLootHandler {
|
||||
case class AddPieceTo(playerId: PlayerId, piece: Piece, isFreeLoot: Boolean) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class GetLoot(partyId: String, playerId: Option[PlayerId]) extends Database.DatabaseRequest
|
||||
case class RemovePieceFrom(playerId: PlayerId, piece: Piece) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class SuggestLoot(partyId: String, piece: Piece) extends Database.DatabaseRequest
|
||||
}
|
||||
|
@ -8,30 +8,29 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service.impl
|
||||
|
||||
import akka.pattern.pipe
|
||||
import me.arcanis.ffxivbis.models.{BiS, PartyDescription, Player, PlayerId}
|
||||
import akka.actor.typed.scaladsl.Behaviors
|
||||
import me.arcanis.ffxivbis.messages.{AddPlayer, DatabaseMessage, GetParty, GetPartyDescription, GetPlayer, RemovePlayer, UpdateParty}
|
||||
import me.arcanis.ffxivbis.models.{BiS, Player}
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait DatabasePartyHandler { this: Database =>
|
||||
import DatabasePartyHandler._
|
||||
|
||||
def partyHandler: Receive = {
|
||||
case AddPlayer(player) =>
|
||||
val client = sender()
|
||||
profile.insertPlayer(player).pipeTo(client)
|
||||
def partyHandler: DatabaseMessage.Handler = {
|
||||
case AddPlayer(player, client) =>
|
||||
profile.insertPlayer(player).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case GetParty(partyId) =>
|
||||
val client = sender()
|
||||
getParty(partyId, withBiS = true, withLoot = true).pipeTo(client)
|
||||
case GetParty(partyId, client) =>
|
||||
getParty(partyId, withBiS = true, withLoot = true).foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case GetPartyDescription(partyId) =>
|
||||
val client = sender()
|
||||
profile.getPartyDescription(partyId).pipeTo(client)
|
||||
case GetPartyDescription(partyId, client) =>
|
||||
profile.getPartyDescription(partyId).foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case GetPlayer(playerId) =>
|
||||
val client = sender()
|
||||
case GetPlayer(playerId, client) =>
|
||||
val player = profile.getPlayerFull(playerId).flatMap { maybePlayerData =>
|
||||
Future.traverse(maybePlayerData.toSeq) { playerData =>
|
||||
for {
|
||||
@ -42,31 +41,15 @@ trait DatabasePartyHandler { this: Database =>
|
||||
playerData.link, playerData.priority)
|
||||
}
|
||||
}.map(_.headOption)
|
||||
player.pipeTo(client)
|
||||
player.foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case RemovePlayer(playerId) =>
|
||||
val client = sender()
|
||||
profile.deletePlayer(playerId).pipeTo(client)
|
||||
case RemovePlayer(playerId, client) =>
|
||||
profile.deletePlayer(playerId).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case UpdateParty(description) =>
|
||||
val client = sender()
|
||||
profile.insertPartyDescription(description).pipeTo(client)
|
||||
}
|
||||
}
|
||||
|
||||
object DatabasePartyHandler {
|
||||
case class AddPlayer(player: Player) extends Database.DatabaseRequest {
|
||||
override def partyId: String = player.partyId
|
||||
}
|
||||
case class GetParty(partyId: String) extends Database.DatabaseRequest
|
||||
case class GetPartyDescription(partyId: String) extends Database.DatabaseRequest
|
||||
case class GetPlayer(playerId: PlayerId) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class RemovePlayer(playerId: PlayerId) extends Database.DatabaseRequest {
|
||||
override def partyId: String = playerId.partyId
|
||||
}
|
||||
case class UpdateParty(partyDescription: PartyDescription) extends Database.DatabaseRequest {
|
||||
override def partyId: String = partyDescription.partyId
|
||||
case UpdateParty(description, client) =>
|
||||
profile.insertPartyDescription(description).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
}
|
||||
}
|
||||
|
@ -8,43 +8,32 @@
|
||||
*/
|
||||
package me.arcanis.ffxivbis.service.impl
|
||||
|
||||
import akka.pattern.pipe
|
||||
import me.arcanis.ffxivbis.models.User
|
||||
import akka.actor.typed.scaladsl.Behaviors
|
||||
import me.arcanis.ffxivbis.messages.{AddUser, DatabaseMessage, DeleteUser, Exists, GetUser, GetUsers}
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
|
||||
trait DatabaseUserHandler { this: Database =>
|
||||
import DatabaseUserHandler._
|
||||
|
||||
def userHandler: Receive = {
|
||||
case AddUser(user, isHashedPassword) =>
|
||||
val client = sender()
|
||||
def userHandler: DatabaseMessage.Handler = {
|
||||
case AddUser(user, isHashedPassword, client) =>
|
||||
val toInsert = if (isHashedPassword) user else user.withHashedPassword
|
||||
profile.insertUser(toInsert).pipeTo(client)
|
||||
profile.insertUser(toInsert).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case DeleteUser(partyId, username) =>
|
||||
val client = sender()
|
||||
profile.deleteUser(partyId, username).pipeTo(client)
|
||||
case DeleteUser(partyId, username, client) =>
|
||||
profile.deleteUser(partyId, username).foreach(_ => client ! ())
|
||||
Behaviors.same
|
||||
|
||||
case Exists(partyId) =>
|
||||
val client = sender()
|
||||
profile.exists(partyId).pipeTo(client)
|
||||
case Exists(partyId, client) =>
|
||||
profile.exists(partyId).foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case GetUser(partyId, username) =>
|
||||
val client = sender()
|
||||
profile.getUser(partyId, username).pipeTo(client)
|
||||
case GetUser(partyId, username, client) =>
|
||||
profile.getUser(partyId, username).foreach(client ! _)
|
||||
Behaviors.same
|
||||
|
||||
case GetUsers(partyId) =>
|
||||
val client = sender()
|
||||
profile.getUsers(partyId).pipeTo(client)
|
||||
case GetUsers(partyId, client) =>
|
||||
profile.getUsers(partyId).foreach(client ! _)
|
||||
Behaviors.same
|
||||
}
|
||||
}
|
||||
|
||||
object DatabaseUserHandler {
|
||||
case class AddUser(user: User, isHashedPassword: Boolean) extends Database.DatabaseRequest {
|
||||
override def partyId: String = user.partyId
|
||||
}
|
||||
case class DeleteUser(partyId: String, username: String) extends Database.DatabaseRequest
|
||||
case class Exists(partyId: String) extends Database.DatabaseRequest
|
||||
case class GetUser(partyId: String, username: String) extends Database.DatabaseRequest
|
||||
case class GetUsers(partyId: String) extends Database.DatabaseRequest
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ class DatabaseProfile(context: ExecutionContext, config: Config)
|
||||
}
|
||||
|
||||
object DatabaseProfile {
|
||||
|
||||
def now: Long = Instant.now.toEpochMilli
|
||||
def getSection(config: Config): Config = {
|
||||
val section = config.getString("me.arcanis.ffxivbis.database.mode")
|
||||
|
@ -15,6 +15,7 @@ import org.flywaydb.core.api.configuration.ClassicConfiguration
|
||||
import scala.concurrent.Future
|
||||
|
||||
class Migration(config: Config) {
|
||||
|
||||
def performMigration(): Future[Int] = {
|
||||
val section = DatabaseProfile.getSection(config)
|
||||
|
||||
@ -37,5 +38,6 @@ class Migration(config: Config) {
|
||||
}
|
||||
|
||||
object Migration {
|
||||
|
||||
def apply(config: Config): Future[Int] = new Migration(config).performMigration()
|
||||
}
|
||||
|
@ -1,52 +1,55 @@
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.testkit.typed.scaladsl.ActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.http.scaladsl.model.{StatusCodes, Uri}
|
||||
import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials}
|
||||
import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.TestKit
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.models.{BiS, Body, Job, PieceType}
|
||||
import me.arcanis.ffxivbis.messages.{AddPlayer, AddUser}
|
||||
import me.arcanis.ffxivbis.models.{BiS, Job}
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
import me.arcanis.ffxivbis.service.{PartyService, impl}
|
||||
import me.arcanis.ffxivbis.service.{Database, PartyService}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class BiSEndpointTest extends WordSpec
|
||||
with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
class BiSEndpointTest extends AnyWordSpecLike with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
|
||||
private val auth: Authorization =
|
||||
private val testKit = ActorTestKit(Settings.withRandomDatabase)
|
||||
override val testConfig: Config = testKit.system.settings.config
|
||||
|
||||
private val auth =
|
||||
Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword))
|
||||
private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}/bis")
|
||||
private val endpoint = Uri(s"/party/${Fixtures.partyId}/bis")
|
||||
private val playerId = PlayerIdResponse.fromPlayerId(Fixtures.playerEmpty.playerId)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout)
|
||||
private val askTimeout = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(askTimeout)
|
||||
|
||||
private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val provider: ActorRef = system.actorOf(BisProvider.props)
|
||||
private val party: ActorRef = system.actorOf(PartyService.props(storage))
|
||||
private val route: Route = new BiSEndpoint(party, provider)(timeout).route
|
||||
|
||||
override def testConfig: Config = Settings.withRandomDatabase
|
||||
private val storage = testKit.spawn(Database())
|
||||
private val provider = testKit.spawn(BisProvider())
|
||||
private val party = testKit.spawn(PartyService(storage))
|
||||
private val route = new BiSEndpoint(party, provider)(askTimeout, testKit.scheduler).route
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout)
|
||||
Await.result((storage ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
Await.result(Migration(testConfig), askTimeout)
|
||||
Await.result(storage.ask(AddUser(Fixtures.userAdmin, isHashedPassword = true, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
Await.result(storage.ask(AddPlayer(Fixtures.playerEmpty, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testConfig)
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
testKit.shutdownTestKit()
|
||||
}
|
||||
|
||||
private def compareBiSResponse(actual: PlayerResponse, expected: PlayerResponse): Unit = {
|
||||
|
@ -2,49 +2,52 @@ package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.testkit.typed.scaladsl.ActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.http.scaladsl.model.{StatusCodes, Uri}
|
||||
import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials}
|
||||
import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.TestKit
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.service.{PartyService, impl}
|
||||
import me.arcanis.ffxivbis.messages.{AddPlayer, AddUser}
|
||||
import me.arcanis.ffxivbis.service.{Database, PartyService}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class LootEndpointTest extends WordSpec
|
||||
with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
class LootEndpointTest extends AnyWordSpecLike with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
|
||||
private val auth: Authorization =
|
||||
private val testKit = ActorTestKit(Settings.withRandomDatabase)
|
||||
override val testConfig: Config = testKit.system.settings.config
|
||||
|
||||
private val auth =
|
||||
Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword))
|
||||
private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}/loot")
|
||||
private val endpoint = Uri(s"/party/${Fixtures.partyId}/loot")
|
||||
private val playerId = PlayerIdResponse.fromPlayerId(Fixtures.playerEmpty.playerId)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout)
|
||||
private val askTimeout = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(askTimeout)
|
||||
|
||||
private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val party: ActorRef = system.actorOf(PartyService.props(storage))
|
||||
private val route: Route = new LootEndpoint(party)(timeout).route
|
||||
|
||||
override def testConfig: Config = Settings.withRandomDatabase
|
||||
private val storage = testKit.spawn(Database())
|
||||
private val party = testKit.spawn(PartyService(storage))
|
||||
private val route = new LootEndpoint(party)(askTimeout, testKit.scheduler).route
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout)
|
||||
Await.result((storage ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
Await.result(Migration(testConfig), askTimeout)
|
||||
Await.result(storage.ask(AddUser(Fixtures.userAdmin, isHashedPassword = true, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
Await.result(storage.ask(AddPlayer(Fixtures.playerEmpty, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testConfig)
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
testKit.shutdownTestKit()
|
||||
}
|
||||
|
||||
"api v1 loot endpoint" must {
|
||||
|
@ -1,48 +1,52 @@
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.testkit.typed.scaladsl.ActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.http.scaladsl.model.{StatusCodes, Uri}
|
||||
import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials}
|
||||
import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.testkit.TestKit
|
||||
import akka.pattern.ask
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.messages.AddUser
|
||||
import me.arcanis.ffxivbis.models.PartyDescription
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
import me.arcanis.ffxivbis.service.impl
|
||||
import me.arcanis.ffxivbis.service.{Database, PartyService}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class PartyEndpointTest extends WordSpec
|
||||
with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
class PartyEndpointTest extends AnyWordSpecLike with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
|
||||
private val auth: Authorization =
|
||||
private val testKit = ActorTestKit(Settings.withRandomDatabase)
|
||||
override val testConfig: Config = testKit.system.settings.config
|
||||
|
||||
private val auth =
|
||||
Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword))
|
||||
private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}/description")
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout)
|
||||
private val endpoint = Uri(s"/party/${Fixtures.partyId}/description")
|
||||
private val askTimeout = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(askTimeout)
|
||||
|
||||
private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val provider: ActorRef = system.actorOf(BisProvider.props)
|
||||
private val route: Route = new PartyEndpoint(storage, provider)(timeout).route
|
||||
|
||||
override def testConfig: Config = Settings.withRandomDatabase
|
||||
private val storage = testKit.spawn(Database())
|
||||
private val provider = testKit.spawn(BisProvider())
|
||||
private val party = testKit.spawn(PartyService(storage))
|
||||
private val route = new PartyEndpoint(party, provider)(askTimeout, testKit.scheduler).route
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout)
|
||||
Await.result(Migration(testConfig), askTimeout)
|
||||
Await.result(storage.ask(AddUser(Fixtures.userAdmin, isHashedPassword = true, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testConfig)
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
testKit.shutdownTestKit()
|
||||
}
|
||||
|
||||
"api v1 party endpoint" must {
|
||||
|
@ -1,56 +1,57 @@
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.testkit.typed.scaladsl.ActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import akka.http.scaladsl.model.{StatusCodes, Uri}
|
||||
import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials}
|
||||
import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.TestKit
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.messages.{AddPlayer, AddUser}
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
import me.arcanis.ffxivbis.service.{PartyService, impl}
|
||||
import me.arcanis.ffxivbis.service.{Database, PartyService}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class PlayerEndpointTest extends WordSpec
|
||||
with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
class PlayerEndpointTest extends AnyWordSpecLike with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
|
||||
private val auth: Authorization =
|
||||
private val testKit = ActorTestKit(Settings.withRandomDatabase)
|
||||
override val testConfig: Config = testKit.system.settings.config
|
||||
|
||||
private val auth =
|
||||
Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword))
|
||||
private val endpoint: Uri = Uri(s"/party/${Fixtures.partyId}")
|
||||
private val playerId = PlayerIdResponse.fromPlayerId(Fixtures.playerEmpty.playerId)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout)
|
||||
private val endpoint = Uri(s"/party/${Fixtures.partyId}")
|
||||
private val askTimeout = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(askTimeout)
|
||||
|
||||
private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val provider: ActorRef = system.actorOf(BisProvider.props)
|
||||
private val party: ActorRef = system.actorOf(PartyService.props(storage))
|
||||
private val route: Route = new PlayerEndpoint(party, provider)(timeout).route
|
||||
|
||||
override def testConfig: Config = Settings.withRandomDatabase
|
||||
private val storage = testKit.spawn(Database())
|
||||
private val provider = testKit.spawn(BisProvider())
|
||||
private val party = testKit.spawn(PartyService(storage))
|
||||
private val route = new PlayerEndpoint(party, provider)(askTimeout, testKit.scheduler).route
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((storage ? impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true))(timeout).mapTo[Int], timeout)
|
||||
Await.result((storage ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
Await.result(Migration(testConfig), askTimeout)
|
||||
Await.result(storage.ask(AddUser(Fixtures.userAdmin, isHashedPassword = true, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
Await.result(storage.ask(AddPlayer(Fixtures.playerEmpty, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testConfig)
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
testKit.shutdownTestKit()
|
||||
}
|
||||
|
||||
"api v1 player endpoint" must {
|
||||
|
||||
"get users" in {
|
||||
val uri = endpoint.withQuery(Uri.Query(Map("nick" -> playerId.nick, "job" -> playerId.job)))
|
||||
val response = Seq(PlayerResponse.fromPlayer(Fixtures.playerEmpty))
|
||||
|
||||
Get(endpoint).withHeaders(auth) ~> route ~> check {
|
||||
|
@ -2,21 +2,21 @@ package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.testkit.ScalatestRouteTest
|
||||
import akka.http.scaladsl.server._
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.Settings
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.models.{Job, Party, Permission, Piece, PieceType}
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.language.postfixOps
|
||||
|
||||
class TypesEndpointTest extends WordSpec
|
||||
class TypesEndpointTest extends AnyWordSpecLike
|
||||
with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
|
||||
private val route: Route = new TypesEndpoint(testConfig).route
|
||||
override val testConfig: Config = Settings.withRandomDatabase
|
||||
|
||||
override def testConfig: Config = Settings.withRandomDatabase
|
||||
private val route = new TypesEndpoint(testConfig).route
|
||||
|
||||
"api v1 types endpoint" must {
|
||||
|
||||
|
@ -1,45 +1,47 @@
|
||||
package me.arcanis.ffxivbis.http.api.v1
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.testkit.typed.scaladsl.ActorTestKit
|
||||
import akka.http.scaladsl.model.{StatusCodes, Uri}
|
||||
import akka.http.scaladsl.model.headers.{Authorization, BasicHttpCredentials}
|
||||
import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
|
||||
import akka.http.scaladsl.server._
|
||||
import akka.testkit.TestKit
|
||||
import com.typesafe.config.Config
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.http.api.v1.json._
|
||||
import me.arcanis.ffxivbis.service.{PartyService, impl}
|
||||
import me.arcanis.ffxivbis.service.{Database, PartyService}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class UserEndpointTest extends WordSpec
|
||||
with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
class UserEndpointTest extends AnyWordSpecLike with Matchers with ScalatestRouteTest with JsonSupport {
|
||||
|
||||
private val auth: Authorization =
|
||||
private val testKit = ActorTestKit(Settings.withRandomDatabase)
|
||||
override val testConfig: Config = testKit.system.settings.config
|
||||
|
||||
private val auth =
|
||||
Authorization(BasicHttpCredentials(Fixtures.userAdmin.username, Fixtures.userPassword))
|
||||
private def endpoint: Uri = Uri(s"/party/$partyId/users")
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(timeout)
|
||||
private def endpoint = Uri(s"/party/$partyId/users")
|
||||
private val askTimeout = 60 seconds
|
||||
implicit private val routeTimeout: RouteTestTimeout = RouteTestTimeout(askTimeout)
|
||||
|
||||
private var partyId: String = Fixtures.partyId
|
||||
private val storage: ActorRef = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val party: ActorRef = system.actorOf(PartyService.props(storage))
|
||||
private val route: Route = new UserEndpoint(party)(timeout).route
|
||||
|
||||
override def testConfig: Config = Settings.withRandomDatabase
|
||||
private var partyId = Fixtures.partyId
|
||||
private val storage = testKit.spawn(Database())
|
||||
private val party = testKit.spawn(PartyService(storage))
|
||||
private val route = new UserEndpoint(party)(askTimeout, testKit.scheduler).route
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result(Migration(testConfig), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testConfig)
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
testKit.shutdownTestKit()
|
||||
}
|
||||
|
||||
"api v1 users endpoint" must {
|
||||
|
@ -2,9 +2,10 @@ package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class BiSTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class BiSTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"bis model" must {
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class JobTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class JobTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"job model" must {
|
||||
|
||||
@ -22,7 +23,7 @@ class JobTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
"equal AnyJob to others" in {
|
||||
Job.available.foreach { job =>
|
||||
Job.AnyJob shouldBe job
|
||||
Job.AnyJob shouldEqual job
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,10 @@ package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class PartyTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class PartyTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
private val partyDescription = PartyDescription.empty(Fixtures.partyId)
|
||||
private val party =
|
||||
|
@ -1,9 +1,10 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class PieceTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class PieceTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"piece model" must {
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class PieceTypeTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class PieceTypeTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"piece type model" must {
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class PlayerIdTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class PlayerIdTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"player id model" must {
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class PlayerTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class PlayerTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"player model" must {
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package me.arcanis.ffxivbis.models
|
||||
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
class UserTest extends WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class UserTest extends AnyWordSpecLike with Matchers {
|
||||
|
||||
"user model" must {
|
||||
|
||||
|
@ -1,79 +1,85 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceToBis, AddPlayer, GetBiS, RemovePieceFromBiS}
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.models._
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabaseBiSHandlerTest
|
||||
extends TestKit(ActorSystem("database-bis-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class DatabaseBiSHandlerTest extends ScalaTestWithActorTestKit(Settings.withRandomDatabase)
|
||||
with AnyWordSpecLike {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
private val database = testKit.spawn(Database())
|
||||
private val askTimeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((database ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
Await.result(Migration(testKit.system.settings.config), askTimeout)
|
||||
Await.result(database.ask(AddPlayer(Fixtures.playerEmpty, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testKit.system.settings.config)
|
||||
}
|
||||
|
||||
"database bis handler" must {
|
||||
|
||||
"add pieces to bis" in {
|
||||
database ! impl.DatabaseBiSHandler.AddPieceToBis(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
val probe = testKit.createTestProbe[Unit]()
|
||||
database ! AddPieceToBis(Fixtures.playerEmpty.playerId, Fixtures.lootBody, probe.ref)
|
||||
probe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabaseBiSHandler.AddPieceToBis(Fixtures.playerEmpty.playerId, Fixtures.lootHands)
|
||||
expectMsg(timeout, 1)
|
||||
database ! AddPieceToBis(Fixtures.playerEmpty.playerId, Fixtures.lootHands, probe.ref)
|
||||
probe.expectMessage(askTimeout, ())
|
||||
}
|
||||
|
||||
"get party bis set" in {
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootBody, Fixtures.lootHands)) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetBiS(Fixtures.playerEmpty.partyId, None, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyBiSCompare(party, Seq(Fixtures.lootBody, Fixtures.lootHands)) shouldEqual true
|
||||
}
|
||||
|
||||
"get bis set" in {
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, Some(Fixtures.playerEmpty.playerId))
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootBody, Fixtures.lootHands)) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetBiS(Fixtures.playerEmpty.partyId, Some(Fixtures.playerEmpty.playerId), probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyBiSCompare(party, Seq(Fixtures.lootBody, Fixtures.lootHands)) shouldEqual true
|
||||
}
|
||||
|
||||
"remove piece from bis set" in {
|
||||
database ! impl.DatabaseBiSHandler.RemovePieceFromBiS(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! RemovePieceFromBiS(Fixtures.playerEmpty.playerId, Fixtures.lootBody, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootHands)) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetBiS(Fixtures.playerEmpty.partyId, None, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyBiSCompare(party, Seq(Fixtures.lootHands)) shouldEqual true
|
||||
}
|
||||
|
||||
"update piece in bis set" in {
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
val newPiece = Hands(pieceType = PieceType.Savage, Job.DNC)
|
||||
|
||||
database ! impl.DatabaseBiSHandler.AddPieceToBis(Fixtures.playerEmpty.playerId, newPiece)
|
||||
expectMsg(timeout, 1)
|
||||
database ! AddPieceToBis(Fixtures.playerEmpty.playerId, newPiece, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabaseBiSHandler.GetBiS(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyBiSCompare(party, Seq(Fixtures.lootHands, newPiece)) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetBiS(Fixtures.playerEmpty.partyId, None, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyBiSCompare(party, Seq(Fixtures.lootHands, newPiece)) shouldEqual true
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,83 +1,89 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import me.arcanis.ffxivbis.messages.{AddPieceTo, AddPlayer, GetLoot, RemovePieceFrom}
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.models._
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabaseLootHandlerTest
|
||||
extends TestKit(ActorSystem("database-loot-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class DatabaseLootHandlerTest extends ScalaTestWithActorTestKit(Settings.withRandomDatabase)
|
||||
with AnyWordSpecLike {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
private val database = testKit.spawn(Database())
|
||||
private val askTimeout = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result((database ? impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty))(timeout).mapTo[Int], timeout)
|
||||
Await.result(Migration(testKit.system.settings.config), askTimeout)
|
||||
Await.result(database.ask(AddPlayer(Fixtures.playerEmpty, _))(askTimeout, testKit.scheduler), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testKit.system.settings.config)
|
||||
}
|
||||
|
||||
"database loot handler actor" must {
|
||||
|
||||
"add loot" in {
|
||||
val probe = testKit.createTestProbe[Unit]()
|
||||
Fixtures.loot.foreach { piece =>
|
||||
database ! impl.DatabaseLootHandler.AddPieceTo(Fixtures.playerEmpty.playerId, piece, isFreeLoot = false)
|
||||
expectMsg(timeout, 1)
|
||||
database ! AddPieceTo(Fixtures.playerEmpty.playerId, piece, isFreeLoot = false, probe.ref)
|
||||
probe.expectMessage(askTimeout, ())
|
||||
}
|
||||
}
|
||||
|
||||
"get party loot" in {
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, Fixtures.loot) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetLoot(Fixtures.playerEmpty.partyId, None, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyLootCompare(party, Fixtures.loot) shouldEqual true
|
||||
}
|
||||
|
||||
"get loot" in {
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, Some(Fixtures.playerEmpty.playerId))
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, Fixtures.loot) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetLoot(Fixtures.playerEmpty.partyId, Some(Fixtures.playerEmpty.playerId), probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyLootCompare(party, Fixtures.loot) shouldEqual true
|
||||
}
|
||||
|
||||
"remove loot" in {
|
||||
database ! impl.DatabaseLootHandler.RemovePieceFrom(Fixtures.playerEmpty.playerId, Fixtures.lootBody)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! RemovePieceFrom(Fixtures.playerEmpty.playerId, Fixtures.lootBody, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
val newLoot = Fixtures.loot.filterNot(_ == Fixtures.lootBody)
|
||||
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, newLoot) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetLoot(Fixtures.playerEmpty.partyId, None, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyLootCompare(party, newLoot) shouldEqual true
|
||||
}
|
||||
|
||||
"add same loot" in {
|
||||
database ! impl.DatabaseLootHandler.AddPieceTo(Fixtures.playerEmpty.playerId, Fixtures.lootBody, isFreeLoot = false)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! AddPieceTo(Fixtures.playerEmpty.playerId, Fixtures.lootBody, isFreeLoot = false, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
Fixtures.loot.foreach { piece =>
|
||||
database ! impl.DatabaseLootHandler.AddPieceTo(Fixtures.playerEmpty.playerId, piece, isFreeLoot = false)
|
||||
expectMsg(timeout, 1)
|
||||
database ! AddPieceTo(Fixtures.playerEmpty.playerId, piece, isFreeLoot = false, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
}
|
||||
|
||||
database ! impl.DatabaseLootHandler.GetLoot(Fixtures.playerEmpty.partyId, None)
|
||||
expectMsgPF(timeout) {
|
||||
case party: Seq[_] if partyLootCompare(party, Fixtures.loot ++ Fixtures.loot) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[Player]]()
|
||||
database ! GetLoot(Fixtures.playerEmpty.partyId, None, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Seq[Player]](askTimeout)
|
||||
partyLootCompare(party, Fixtures.loot ++ Fixtures.loot) shouldEqual true
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,73 +1,80 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
||||
import me.arcanis.ffxivbis.messages.{AddPlayer, GetParty, GetPlayer, RemovePlayer}
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.models._
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabasePartyHandlerTest
|
||||
extends TestKit(ActorSystem("database-party-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class DatabasePartyHandlerTest extends ScalaTestWithActorTestKit(Settings.withRandomDatabase)
|
||||
with AnyWordSpecLike {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
private val database = testKit.spawn(Database())
|
||||
private val askTimeout = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result(Migration(testKit.system.settings.config), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testKit.system.settings.config)
|
||||
}
|
||||
|
||||
"database party handler actor" must {
|
||||
|
||||
"add player" in {
|
||||
database ! impl.DatabasePartyHandler.AddPlayer(Fixtures.playerEmpty)
|
||||
expectMsg(timeout, 1)
|
||||
val probe = testKit.createTestProbe[Unit]()
|
||||
database ! AddPlayer(Fixtures.playerEmpty, probe.ref)
|
||||
probe.expectMessage(askTimeout, ())
|
||||
}
|
||||
|
||||
"get party" in {
|
||||
database ! impl.DatabasePartyHandler.GetParty(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case p: Party if Compare.seqEquals(p.getPlayers, Seq(Fixtures.playerEmpty)) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Party]()
|
||||
database ! GetParty(Fixtures.partyId, probe.ref)
|
||||
|
||||
val party = probe.expectMessageType[Party](askTimeout)
|
||||
Compare.seqEquals(party.getPlayers, Seq(Fixtures.playerEmpty)) shouldEqual true
|
||||
}
|
||||
|
||||
"get player" in {
|
||||
database ! impl.DatabasePartyHandler.GetPlayer(Fixtures.playerEmpty.playerId)
|
||||
expectMsg(timeout, Some(Fixtures.playerEmpty))
|
||||
val probe = testKit.createTestProbe[Option[Player]]()
|
||||
database ! GetPlayer(Fixtures.playerEmpty.playerId, probe.ref)
|
||||
probe.expectMessage(askTimeout, Some(Fixtures.playerEmpty))
|
||||
}
|
||||
|
||||
"update player" in {
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
val newPlayer = Fixtures.playerEmpty.copy(priority = 2)
|
||||
|
||||
database ! impl.DatabasePartyHandler.AddPlayer(newPlayer)
|
||||
expectMsg(timeout, 1)
|
||||
database ! AddPlayer(newPlayer, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabasePartyHandler.GetPlayer(newPlayer.playerId)
|
||||
expectMsg(timeout, Some(newPlayer))
|
||||
val probe = testKit.createTestProbe[Option[Player]]()
|
||||
database ! GetPlayer(newPlayer.playerId, probe.ref)
|
||||
probe.expectMessage(askTimeout, Some(newPlayer))
|
||||
|
||||
database ! impl.DatabasePartyHandler.GetParty(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case p: Party if Compare.seqEquals(p.getPlayers, Seq(newPlayer)) => ()
|
||||
}
|
||||
val partyProbe = testKit.createTestProbe[Party]()
|
||||
database ! GetParty(Fixtures.partyId, partyProbe.ref)
|
||||
|
||||
val party = partyProbe.expectMessageType[Party](askTimeout)
|
||||
Compare.seqEquals(party.getPlayers, Seq(newPlayer)) shouldEqual true
|
||||
}
|
||||
|
||||
"remove player" in {
|
||||
database ! impl.DatabasePartyHandler.RemovePlayer(Fixtures.playerEmpty.playerId)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! RemovePlayer(Fixtures.playerEmpty.playerId, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabasePartyHandler.GetPlayer(Fixtures.playerEmpty.playerId)
|
||||
expectMsg(timeout, None)
|
||||
val probe = testKit.createTestProbe[Option[Player]]()
|
||||
database ! GetPlayer(Fixtures.playerEmpty.playerId, probe.ref)
|
||||
probe.expectMessage(askTimeout, None)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,76 +1,85 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
||||
import me.arcanis.ffxivbis.messages.{AddUser, DeleteUser, GetUser, GetUsers}
|
||||
import me.arcanis.ffxivbis.models.User
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.storage.Migration
|
||||
import me.arcanis.ffxivbis.utils.Compare
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class DatabaseUserHandlerTest
|
||||
extends TestKit(ActorSystem("database-user-handler", Settings.withRandomDatabase))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class DatabaseUserHandlerTest extends ScalaTestWithActorTestKit(Settings.withRandomDatabase)
|
||||
with AnyWordSpecLike {
|
||||
|
||||
private val database = system.actorOf(impl.DatabaseImpl.props)
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
private val database = testKit.spawn(Database())
|
||||
private val askTimeout = 60 seconds
|
||||
|
||||
override def beforeAll: Unit = {
|
||||
Await.result(Migration(system.settings.config), timeout)
|
||||
Await.result(Migration(testKit.system.settings.config), askTimeout)
|
||||
}
|
||||
|
||||
override def afterAll: Unit = {
|
||||
TestKit.shutdownActorSystem(system)
|
||||
Settings.clearDatabase(system.settings.config)
|
||||
super.afterAll()
|
||||
Settings.clearDatabase(testKit.system.settings.config)
|
||||
}
|
||||
|
||||
"database user handler actor" must {
|
||||
|
||||
"add user" in {
|
||||
database ! impl.DatabaseUserHandler.AddUser(Fixtures.userAdmin, isHashedPassword = true)
|
||||
expectMsg(timeout, 1)
|
||||
val probe = testKit.createTestProbe[Unit]()
|
||||
database ! AddUser(Fixtures.userAdmin, isHashedPassword = true, probe.ref)
|
||||
probe.expectMessage(askTimeout, ())
|
||||
}
|
||||
|
||||
"get user" in {
|
||||
database ! impl.DatabaseUserHandler.GetUser(Fixtures.partyId, Fixtures.userAdmin.username)
|
||||
expectMsg(timeout, Some(Fixtures.userAdmin))
|
||||
val probe = testKit.createTestProbe[Option[User]]()
|
||||
database ! GetUser(Fixtures.partyId, Fixtures.userAdmin.username, probe.ref)
|
||||
probe.expectMessage(askTimeout, Some(Fixtures.userAdmin))
|
||||
}
|
||||
|
||||
"get users" in {
|
||||
database ! impl.DatabaseUserHandler.AddUser(Fixtures.userGet, isHashedPassword = true)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! AddUser(Fixtures.userGet, isHashedPassword = true, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUsers(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case u: Seq[_] if Compare.seqEquals(u, Fixtures.users) => ()
|
||||
}
|
||||
val probe = testKit.createTestProbe[Seq[User]]()
|
||||
database ! GetUsers(Fixtures.partyId, probe.ref)
|
||||
|
||||
val users = probe.expectMessageType[Seq[User]]
|
||||
Compare.seqEquals(users, Fixtures.users) shouldEqual true
|
||||
}
|
||||
|
||||
"update user" in {
|
||||
val newUser= Fixtures.userGet.copy(password = Fixtures.userPassword2).withHashedPassword
|
||||
val newUserSet = Seq(newUser, Fixtures.userAdmin)
|
||||
|
||||
database ! impl.DatabaseUserHandler.AddUser(newUser, isHashedPassword = true)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! AddUser(newUser, isHashedPassword = true, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUser(Fixtures.partyId, newUser.username)
|
||||
expectMsg(timeout, Some(newUser))
|
||||
val probe = testKit.createTestProbe[Option[User]]()
|
||||
database ! GetUser(Fixtures.partyId, newUser.username, probe.ref)
|
||||
probe.expectMessage(askTimeout, Some(newUser))
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUsers(Fixtures.partyId)
|
||||
expectMsgPF(timeout) {
|
||||
case u: Seq[_] if Compare.seqEquals(u, newUserSet) => ()
|
||||
}
|
||||
val partyProbe = testKit.createTestProbe[Seq[User]]()
|
||||
database ! GetUsers(Fixtures.partyId, partyProbe.ref)
|
||||
|
||||
val users = partyProbe.expectMessageType[Seq[User]]
|
||||
Compare.seqEquals(users, newUserSet) shouldEqual true
|
||||
}
|
||||
|
||||
"remove user" in {
|
||||
database ! impl.DatabaseUserHandler.DeleteUser(Fixtures.partyId, Fixtures.userGet.username)
|
||||
expectMsg(timeout, 1)
|
||||
val updateProbe = testKit.createTestProbe[Unit]()
|
||||
database ! DeleteUser(Fixtures.partyId, Fixtures.userGet.username, updateProbe.ref)
|
||||
updateProbe.expectMessage(askTimeout, ())
|
||||
|
||||
database ! impl.DatabaseUserHandler.GetUser(Fixtures.partyId, Fixtures.userGet.username)
|
||||
expectMsg(timeout, None)
|
||||
val probe = testKit.createTestProbe[Option[User]]()
|
||||
database ! GetUser(Fixtures.partyId, Fixtures.userGet.username, probe.ref)
|
||||
probe.expectMessage(askTimeout, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
package me.arcanis.ffxivbis.service
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.pattern.ask
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import akka.actor.testkit.typed.scaladsl.ActorTestKit
|
||||
import akka.actor.typed.scaladsl.AskPattern.Askable
|
||||
import me.arcanis.ffxivbis.messages.DownloadBiS
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.models._
|
||||
import me.arcanis.ffxivbis.service.bis.BisProvider
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class LootSelectorTest extends TestKit(ActorSystem("lootselector"))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class LootSelectorTest extends AnyWordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
|
||||
import me.arcanis.ffxivbis.utils.Converters._
|
||||
|
||||
@ -23,16 +24,19 @@ class LootSelectorTest extends TestKit(ActorSystem("lootselector"))
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def beforeAll(): Unit = {
|
||||
val provider = system.actorOf(BisProvider.props)
|
||||
val testKit = ActorTestKit(Settings.withRandomDatabase)
|
||||
val provider = testKit.spawn(BisProvider())
|
||||
|
||||
val dncSet = Await.result((provider ? BisProvider.GetBiS(Fixtures.link, Job.DNC) )(timeout).mapTo[BiS], timeout)
|
||||
val dncSet = Await.result(provider.ask(DownloadBiS(Fixtures.link, Job.DNC, _) )(timeout, testKit.scheduler), timeout)
|
||||
dnc = dnc.withBiS(Some(dncSet))
|
||||
|
||||
val drgSet = Await.result((provider ? BisProvider.GetBiS(Fixtures.link2, Job.DRG) )(timeout).mapTo[BiS], timeout)
|
||||
val drgSet = Await.result(provider.ask(DownloadBiS(Fixtures.link2, Job.DRG, _) )(timeout, testKit.scheduler), timeout)
|
||||
drg = drg.withBiS(Some(drgSet))
|
||||
|
||||
default = default.withPlayer(dnc).withPlayer(drg)
|
||||
system.stop(provider)
|
||||
|
||||
testKit.stop(provider)
|
||||
testKit.shutdownTestKit()
|
||||
}
|
||||
|
||||
"loot selector" must {
|
||||
|
@ -1,33 +1,32 @@
|
||||
package me.arcanis.ffxivbis.service.bis
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.testkit.{ImplicitSender, TestKit}
|
||||
import me.arcanis.ffxivbis.Fixtures
|
||||
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
|
||||
import me.arcanis.ffxivbis.messages.DownloadBiS
|
||||
import me.arcanis.ffxivbis.{Fixtures, Settings}
|
||||
import me.arcanis.ffxivbis.models._
|
||||
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike}
|
||||
import org.scalatest.wordspec.AnyWordSpecLike
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.language.postfixOps
|
||||
|
||||
class BisProviderTest extends TestKit(ActorSystem("bis-provider"))
|
||||
with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
|
||||
class BisProviderTest extends ScalaTestWithActorTestKit(Settings.withRandomDatabase)
|
||||
with AnyWordSpecLike {
|
||||
|
||||
private val timeout: FiniteDuration = 60 seconds
|
||||
|
||||
override def afterAll: Unit = TestKit.shutdownActorSystem(system)
|
||||
private val provider = testKit.spawn(BisProvider())
|
||||
private val askTimeout = 60 seconds
|
||||
|
||||
"ariyala actor" must {
|
||||
|
||||
"get best in slot set (ariyala)" in {
|
||||
val provider = system.actorOf(BisProvider.props)
|
||||
provider ! BisProvider.GetBiS(Fixtures.link, Job.DNC)
|
||||
expectMsg(timeout, Fixtures.bis)
|
||||
val probe = testKit.createTestProbe[BiS]()
|
||||
provider ! DownloadBiS(Fixtures.link, Job.DNC, probe.ref)
|
||||
probe.expectMessage(askTimeout, Fixtures.bis)
|
||||
}
|
||||
|
||||
"get best in slot set (etro)" in {
|
||||
val provider = system.actorOf(BisProvider.props)
|
||||
provider ! BisProvider.GetBiS(Fixtures.link3, Job.DNC)
|
||||
expectMsg(timeout, Fixtures.bis)
|
||||
val probe = testKit.createTestProbe[BiS]()
|
||||
provider ! DownloadBiS(Fixtures.link3, Job.DNC, probe.ref)
|
||||
probe.expectMessage(askTimeout, Fixtures.bis)
|
||||
}
|
||||
|
||||
}
|
||||
|
6
test.sbt
6
test.sbt
@ -1,6 +0,0 @@
|
||||
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.8" % "test"
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
|
||||
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.5.26" % "test"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-stream-testkit" % "2.5.26" % "test"
|
||||
libraryDependencies += "com.typesafe.akka" %% "akka-http-testkit" % "10.1.10" % "test"
|
Loading…
Reference in New Issue
Block a user