Skip to content

Commit

Permalink
Make it compile with Scala 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Katrix committed May 28, 2024
1 parent a22242a commit 413ffde
Show file tree
Hide file tree
Showing 18 changed files with 111 additions and 58 deletions.
4 changes: 2 additions & 2 deletions ackcord/src/main/scala/ackcord/BotSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ object BotSettings {
val f2 = f(context)

if (f2.isDefinedAt(event)) f2(event)
else F.pure(context)
else this.F.pure(context)
}
})

Expand All @@ -101,7 +101,7 @@ object BotSettings {
install(new GatewayProcessHandler.Base[F]("AnonymousEventListener") with DispatchEventProcess[F] {
override def onDispatchEvent(event: GatewayDispatchEvent, context: Context): F[Unit] =
if (f.isDefinedAt(event)) f(event)
else F.unit
else this.F.unit
})

def assembledProcessor: GatewayProcess[F] = {
Expand Down
39 changes: 27 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,32 @@ lazy val circeVersion = "0.14.2"
lazy val generateData = taskKey[Unit]("Generate AckCord data classes")

lazy val commonSettings = Seq(
scalaVersion := "2.13.8",
crossScalaVersions := Seq(scalaVersion.value),
scalacOptions ++= Seq(
"-deprecation",
"-feature",
"-unchecked",
"-Xlint",
"-Ywarn-dead-code"
),
libraryDependencies += compilerPlugin("org.typelevel" %% "kind-projector" % "0.13.2" cross CrossVersion.full),
scalaVersion := "2.13.14",
crossScalaVersions := Seq(scalaVersion.value, "3.3.2"),
scalacOptions ++= {
if (scalaVersion.value.startsWith("2"))
Seq(
"-deprecation",
"-feature",
"-unchecked",
"-Xlint",
"-Wdead-code"
)
else
Seq(
"-deprecation",
"-feature",
"-unchecked",
"-Wunused:all",
//"-Xlint",
"-Ykind-projector"
)
},
libraryDependencies ++= {
if (scalaVersion.value.startsWith("2"))
Seq(compilerPlugin("org.typelevel" %% "kind-projector" % "0.13.3" cross CrossVersion.full))
else Nil
},
generateData := {
val sourceDir = (Compile / sourceDirectory).value.getParentFile.getParentFile.getParentFile / "src" / "main"
val scalaDir = sourceDir / "scala"
Expand Down Expand Up @@ -57,8 +73,7 @@ lazy val data = crossProject(JSPlatform, JVMPlatform)
.settings(
commonSettings,
publishSettings,
name := "data",
libraryDependencies += "com.chuusai" %%% "shapeless" % "2.3.8",
name := "data",
libraryDependencies ++= Seq(
"io.circe" %%% "circe-core" % circeVersion,
"io.circe" %%% "circe-parser" % circeVersion
Expand Down
2 changes: 1 addition & 1 deletion data/src/main/scala/ackcord/data/IntOrString.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object IntOrString {
case class AsInt(i: Int) extends IntOrString

implicit val codec: Codec[IntOrString] = Codec.from(
Decoder[Int].map(AsInt).or(Decoder[String].map(AsString)),
Decoder[Int].map(AsInt.apply).or(Decoder[String].map(AsString.apply)),
{
case AsString(s) => Json.fromString(s)
case AsInt(i) => Json.fromInt(i)
Expand Down
4 changes: 2 additions & 2 deletions data/src/main/scala/ackcord/data/base/discordObject.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class DiscordObject(val json: Json, startCache: Map[String, Any]) {
def objWithUndef[A <: DiscordObject, V](companion: DiscordObjectCompanion[A], name: String, obj: UndefOr[V])(
implicit encoder: Encoder[V]
): A = obj match {
case UndefOrSome(value) => objWith(companion, name, value)
case UndefOrUndefined(_, _) => objWithout(companion, name)
case UndefOrSome(value) => objWith[A, V](companion, name, value)
case UndefOrUndefined(_, _) => objWithout[A](companion, name)
}

def objWithUndef[A <: DiscordObject, V](companion: DiscordObjectCompanion[A], name: String, obj: JsonOption[V])(
Expand Down
6 changes: 3 additions & 3 deletions data/src/main/scala/ackcord/data/snowflakeDefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ object Snowflake {

def apply[A](content: String): Snowflake[A] = apply[A](JLong.parseUnsignedLong(content))

def apply[A](other: Snowflake[_]): Snowflake[A] =
other.asInstanceOf[Snowflake[A]]
def apply[A, B](other: Snowflake[A]): Snowflake[B] =
other.asInstanceOf[Snowflake[B]]

/**
* Creates a snowflake tag for the earliest moment in time. Use this for
Expand Down Expand Up @@ -138,5 +138,5 @@ object Snowflake {
trait SnowflakeCompanion[Type] {
def apply(content: String): Snowflake[Type] = JLong.parseUnsignedLong(content).asInstanceOf[Snowflake[Type]]
def apply(long: Long): Snowflake[Type] = long.asInstanceOf[Snowflake[Type]]
def apply(other: Snowflake[_]): Snowflake[Type] = other.asInstanceOf[Snowflake[Type]]
def apply[A](other: Snowflake[A]): Snowflake[Type] = other.asInstanceOf[Snowflake[Type]]
}
4 changes: 3 additions & 1 deletion gateway/src/main/scala/ackcord/gateway/gatewayProcess.scala
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,7 @@ trait GatewayProcessHandler[F[_]] extends GatewayProcessComponent[F] {
override def valueFromReturn[A](ret: Unit): Option[A] = None
}
object GatewayProcessHandler {
abstract class Base[F[_]](val name: String)(implicit val F: Monad[F]) extends GatewayProcessHandler[F]
abstract class Base[F[_]](name0: String)(implicit val F: Monad[F]) extends GatewayProcessHandler[F] {
val name: String = name0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ trait ApplicationCommandController[F[_]] extends InteractionHandlerOps[F] with I
nameLocalizations,
description,
descriptionLocalizations,
minValue.map(IntOrDouble.OfInt),
maxValue.map(IntOrDouble.OfInt),
minValue.map(IntOrDouble.OfInt.apply),
maxValue.map(IntOrDouble.OfInt.apply),
None,
None,
(name, nameLocalizations, i) =>
Expand Down Expand Up @@ -334,8 +334,8 @@ trait ApplicationCommandController[F[_]] extends InteractionHandlerOps[F] with I
nameLocalizations,
description,
descriptionLocalizations,
minValue.map(IntOrDouble.OfDouble),
maxValue.map(IntOrDouble.OfDouble),
minValue.map(IntOrDouble.OfDouble.apply),
maxValue.map(IntOrDouble.OfDouble.apply),
None,
None,
(name, nameLocalizations, num) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ sealed trait SlashCommandOrGroup[F[_]] extends CreatedApplicationCommand[F] {
override def commandType: ApplicationCommandType = ApplicationCommandType.ChatInput
}

case class SlashCommand[F[_], A] private (
case class SlashCommand[F[_], A] private[interactions] (
name: String,
nameLocalizations: JsonOption[Map[String, String]],
descriptionSome: String,
Expand Down Expand Up @@ -234,7 +234,7 @@ case class SlashCommand[F[_], A] private (
}

}
case class SlashCommandGroup[F[_]] private (
case class SlashCommandGroup[F[_]] private[interactions] (
name: String,
nameLocalizations: JsonOption[Map[String, String]],
descriptionSome: String,
Expand Down Expand Up @@ -293,7 +293,7 @@ case class SlashCommandGroup[F[_]] private (
}
}

case class UserCommand[F[_]] private (
case class UserCommand[F[_]] private[interactions] (
name: String,
nameLocalizations: JsonOption[Map[String, String]],
defaultMemberPermissions: Option[Permissions],
Expand Down Expand Up @@ -335,7 +335,7 @@ case class UserCommand[F[_]] private (
)
}

case class MessageCommand[F[_]] private (
case class MessageCommand[F[_]] private[interactions] (
name: String,
nameLocalizations: JsonOption[Map[String, String]],
defaultMemberPermissions: Option[Permissions],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ object IntOrDouble {
implicit val codec: Codec[IntOrDouble] = Codec.from(
(c: HCursor) =>
c.as[Int]
.map(OfInt)
.orElse(c.as[Double].map(OfDouble)),
.map(OfInt.apply)
.orElse(c.as[Double].map(OfDouble.apply)),
{
case OfInt(i) => Json.fromInt(i)
case OfDouble(d) => Json.fromDoubleOrString(d)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ object StringOrIntOrDouble {
implicit val codec: Codec[StringOrIntOrDouble] = Codec.from(
(c: HCursor) =>
c.as[String]
.map(OfString)
.orElse(c.as[Int].map(OfInt))
.orElse(c.as[Double].map(OfDouble)),
.map(OfString.apply)
.orElse(c.as[Int].map(OfInt.apply))
.orElse(c.as[Double].map(OfDouble.apply)),
{
case OfString(s) => Json.fromString(s)
case OfInt(i) => Json.fromInt(i)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ object StringOrIntOrDoubleOrBoolean {
implicit val codec: Codec[StringOrIntOrDoubleOrBoolean] = Codec.from(
(c: HCursor) =>
c.as[String]
.map(OfString)
.orElse(c.as[Int].map(OfInt))
.orElse(c.as[Double].map(OfDouble))
.orElse(c.as[Boolean].map(OfBoolean)),
.map(OfString.apply)
.orElse(c.as[Int].map(OfInt.apply))
.orElse(c.as[Double].map(OfDouble.apply))
.orElse(c.as[Boolean].map(OfBoolean.apply)),
{
case OfString(s) => Json.fromString(s)
case OfInt(i) => Json.fromInt(i)
Expand Down
10 changes: 6 additions & 4 deletions interactions/src/main/scala/ackcord/interactions/params.scala
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ sealed trait ParamList[A] {
def ~[B, G[_]](param: Param[_, B, G]): ParamList[A ~ G[B]] = ParamList.ParamListBranch(this, param)

/** Map all the parameters in this parameter list. */
def map[B](f: Param[_, _, Any] => B): List[B] = foldRight(Nil: List[B])(f(_) :: _)
def map[B](f: Param[_, _, ParamList.AnyK] => B): List[B] = foldRight(Nil: List[B])(f(_) :: _)

protected def constructParam[Orig, A1, F[_]](
param: Param[Orig, A1, F],
Expand Down Expand Up @@ -393,18 +393,20 @@ sealed trait ParamList[A] {
): Seq[ApplicationCommandOptionChoice]

/** Fold this parameter list. */
def foldRight[B](start: B)(f: (Param[_, _, Any], B) => B): B = {
def foldRight[B](start: B)(f: (Param[_, _, ParamList.AnyK], B) => B): B = {
@tailrec
def inner(list: ParamList[_], b: B): B = list match {
case startParam: ParamList.ParamListStart[_, _, Any @unchecked] => f(startParam.leaf, b)
case branchParam: ParamList.ParamListBranch[_, _, Any @unchecked] =>
case startParam: ParamList.ParamListStart[_, _, ParamList.AnyK] => f(startParam.leaf, b)
case branchParam: ParamList.ParamListBranch[_, _, ParamList.AnyK] =>
inner(branchParam.left, f(branchParam.right, b))
}

inner(this, start)
}
}
object ParamList {
type AnyK[_] = Any

implicit def paramToParamList[A, F[_]](param: Param[_, A, F]): ParamList[F[A]] = ParamListStart(param)

case class ParamListStart[Orig, A, F[_]](leaf: Param[Orig, A, F]) extends ParamList[F[A]] {
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
logLevel := Level.Warn
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.9.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0")
addSbtPlugin("com.47deg" % "sbt-microsites" % "1.4.3")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ object RequestHandling {
.ratelimitRequest(request.route, request, request.identifier)
.flatMap[RequestAnswer[Response]] {
case Right(req) =>
runRequestWithoutRatelimits(req, backend, settings).flatTap(settings.ratelimiter.reportRatelimits)
runRequestWithoutRatelimits[Response, R, R1, F](req, backend, settings).flatTap(settings.ratelimiter.reportRatelimits)
case Left(dropped) => backend.responseMonad.unit(dropped)
}
}
Expand Down
6 changes: 3 additions & 3 deletions requests/src/main/scala/ackcord/requests/base/Requests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Requests[F[_], +R](
def runRequestWithoutRatelimits[Response, R1 >: R with Effect[F]](
request: AckCordRequest[Response, R1]
)(implicit @unused iKnowWhatImDoing: Requests.IWantToMakeRequestsWithoutRatelimits): F[RequestAnswer[Response]] =
addExtraProcessing(request, RequestHandling.runRequestWithoutRatelimits(request, backend, settings))
addExtraProcessing(request, RequestHandling.runRequestWithoutRatelimits[Response, R, R1, F](request, backend, settings))

/**
* Run a normal request, returning the [[RequestAnswer]]. If it fails, it
Expand All @@ -46,7 +46,7 @@ class Requests[F[_], +R](
def runRequestToAnswer[Response, R1 >: R with Effect[F]](
request: AckCordRequest[Response, R1]
): F[RequestAnswer[Response]] =
addExtraProcessing(request, RequestHandling.runRequest(request, backend, settings))
addExtraProcessing(request, RequestHandling.runRequest[Response, R, R1, F](request, backend, settings))

/**
* Run a normal request, returning the response type. If it fails, it will
Expand All @@ -66,7 +66,7 @@ class Requests[F[_], +R](
): F[RequestAnswer[Response]] =
addExtraProcessing(
request,
RequestHandling.runRequestWithRetry(RequestHandling.runRequest(request, backend, settings), settings)(
RequestHandling.runRequestWithRetry(RequestHandling.runRequest[Response, R, R1, F](request, backend, settings), settings)(
backend.responseMonad
)
)
Expand Down
30 changes: 30 additions & 0 deletions requests/src/main/scala/ackcord/requests/base/orelse.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ackcord.requests.base

/**
* Like `Option.orElse` on the type level and like `Either` on the value level.
*
* Instead of left and right constructors `OrElse` has primary and secondary implicits that lazily
* try to resolve first a value of type `A` or otherwise a value of type `B`.
*/
sealed trait OrElse[+A, +B] {
def fold[C](prim: A => C, sec: B => C): C
def unify[C >: A](implicit ev: B <:< C): C = fold(identity, ev)
}

final class Primary[+A](value: A) extends OrElse[A, Nothing] {
def fold[C](prim: A => C, sec: Nothing => C): C = prim(value)
}

final class Secondary[+B](value: => B) extends OrElse[Nothing, B] {
def fold[C](prim: Nothing => C, sec: B => C): C = sec(value)
}

object OrElse extends OrElse0 {
implicit def primary[A, B](implicit a: A): A OrElse B =
new Primary(a)
}

private[base] abstract class OrElse0 {
implicit def secondary[A, B](implicit b: => B): A OrElse B =
new Secondary(b)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ import cats.{Monad, Order}
import sttp.monad.{MonadError => SttpMonadError}

//noinspection MutatorLikeMethodIsParameterless
class CatsEffectDiscordRatelimiter[F[_]: Async: SttpMonadError](logRateLimitEvents: Boolean = false)(
protected val globalRatelimitQueue: CatsPQueue[F],
class CatsEffectDiscordRatelimiter[F[_]: Async: SttpMonadError] private (logRateLimitEvents: Boolean = false)(
catsGlobalRatelimitQueue: CatsPQueue[F],
routeRateLimitQueues: RouteMap[F, CatsPQueue[F]],
protected val globalTokenBucket: CatsTokenBucket[F],
catsGlobalTokenBucket: CatsTokenBucket[F],
routeTokenBuckets: RouteMap[F, CatsTokenBucket[F]],
routeLimitsNoParams: MapRef[F, String, Option[Int]],
uriToBucket: MapRef[F, String, Option[Bucket]],
supervisor: Supervisor[F]
) extends BaseDiscordRatelimiter[F](logRateLimitEvents) {

override protected def globalRatelimitQueue: PQueue[F] = catsGlobalRatelimitQueue

override protected def globalTokenBucket: TokenBucket[F] = catsGlobalTokenBucket

override protected def routeRatelimitQueue(route: RequestRoute): F[PQueue[F]] =
routeRateLimitQueues.getOrMake(route, CatsPQueue[F]).widen

Expand Down Expand Up @@ -84,13 +88,13 @@ class CatsEffectDiscordRatelimiter[F[_]: Async: SttpMonadError](logRateLimitEven
_ <- routeTokenBuckets.updateBucket(route, bucket)
} yield ()

override protected def globalRatelimitRetry: F[Long] = globalTokenBucket.retryAt
override protected def globalRatelimitRetry: F[Long] = catsGlobalTokenBucket.retryAt

override protected def routeRatelimitReset(route: RequestRoute): F[Long] =
routeTokenBuckets.get(route).flatMap(_.flatTraverse(_.resetAt)).map(_.getOrElse(-1))

override protected def onGlobalRatelimit(retryAt: Long): F[Unit] =
globalTokenBucket.setResetRetryAt(-1, retryAt)
catsGlobalTokenBucket.setResetRetryAt(-1, retryAt)

private def releaseWaitingRequests(bucket: CatsTokenBucket[F], queue: CatsPQueue[F]): F[Unit] =
acquireTokenLockstep(bucket).use { case (hasTokens, acquire) =>
Expand All @@ -113,7 +117,7 @@ class CatsEffectDiscordRatelimiter[F[_]: Async: SttpMonadError](logRateLimitEven
} yield ()

protected def start: F[Unit] = {
def checkOnGlobalQueue: F[Unit] = releaseWaitingRequests(globalTokenBucket, globalRatelimitQueue)
def checkOnGlobalQueue: F[Unit] = releaseWaitingRequests(catsGlobalTokenBucket, catsGlobalRatelimitQueue)

def checkOnRouteQueues: F[Unit] =
for {
Expand Down Expand Up @@ -229,7 +233,7 @@ object CatsEffectDiscordRatelimiter {
implicit def order[F[_]]: Order[QueueElement[F]] = Order.reverse(Order.by(_.time))
}

class CatsPQueue[F[_]: Concurrent](underlying: cats.effect.std.PQueue[F, QueueElement[F]])
private class CatsPQueue[F[_]: Concurrent](underlying: cats.effect.std.PQueue[F, QueueElement[F]])
extends BaseDiscordRatelimiter.PQueue[F] {
override def size: F[Int] = underlying.size

Expand Down
Loading

0 comments on commit 413ffde

Please sign in to comment.