From c691416ec011ae3083ede6b94515f7171c1a4be8 Mon Sep 17 00:00:00 2001 From: Mike Limansky Date: Sat, 6 Dec 2025 19:32:01 +0300 Subject: [PATCH 1/3] Migrate from akka to pekko --- .github/workflows/build.yml | 2 +- .../bot4s/telegram/models/AkkaInputFile.scala | 9 ---- build.sc | 48 +++++++++---------- .../com/bot4s/telegram/api/ActorBroker.scala | 2 +- .../com/bot4s/telegram/api/GameManager.scala | 8 ++-- .../bot4s/telegram/api/PekkoTelegramBot.scala | 8 ++-- .../com/bot4s/telegram/api/WebRoutes.scala | 8 ++-- .../src/com/bot4s/telegram/api/Webhook.scala | 10 ++-- .../telegram/clients/PekkoHttpClient.scala | 20 ++++---- .../clients/YetAnotherPekkoClient.scala | 20 ++++---- .../marshalling/PekkoHttpMarshalling.scala | 12 ++--- .../telegram/models/PekkoInputFile.scala | 11 +++++ .../PekkoHttpMarshallingSuite.scala | 22 ++++----- 13 files changed, 91 insertions(+), 89 deletions(-) delete mode 100644 akka/src/com/bot4s/telegram/models/AkkaInputFile.scala rename {akka => pekko}/src/com/bot4s/telegram/api/ActorBroker.scala (91%) rename {akka => pekko}/src/com/bot4s/telegram/api/GameManager.scala (93%) rename akka/src/com/bot4s/telegram/api/AkkaTelegramBot.scala => pekko/src/com/bot4s/telegram/api/PekkoTelegramBot.scala (50%) rename {akka => pekko}/src/com/bot4s/telegram/api/WebRoutes.scala (86%) rename {akka => pekko}/src/com/bot4s/telegram/api/Webhook.scala (85%) rename akka/src/com/bot4s/telegram/clients/AkkaHttpClient.scala => pekko/src/com/bot4s/telegram/clients/PekkoHttpClient.scala (69%) rename akka/src/com/bot4s/telegram/clients/YetAnotherAkkaClient.scala => pekko/src/com/bot4s/telegram/clients/YetAnotherPekkoClient.scala (65%) rename akka/src/com/bot4s/telegram/marshalling/AkkaHttpMarshalling.scala => pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala (86%) create mode 100644 pekko/src/com/bot4s/telegram/models/PekkoInputFile.scala rename akka/test/src/com/bot4s/telegram/marshalling/AkkaHttpMarshallingSuite.scala => pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala (60%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e81ebbd..39539a01 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: - name: Check code format uses: jrouly/scalafmt-native-action@v4 with: - arguments: "-c .scalafmt.conf --test core akka examples" + arguments: "-c .scalafmt.conf --test core pekko examples" - name: Compile run: ./mill '_._[_].compile' - name: Test diff --git a/akka/src/com/bot4s/telegram/models/AkkaInputFile.scala b/akka/src/com/bot4s/telegram/models/AkkaInputFile.scala deleted file mode 100644 index 3d0b1c39..00000000 --- a/akka/src/com/bot4s/telegram/models/AkkaInputFile.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.bot4s.telegram.models - -trait AkkaInputFile extends InputFile - -object AkkaInputFile { - final case class ByteString(filename: String, contents: akka.util.ByteString) extends AkkaInputFile - - def apply(filename: String, contents: akka.util.ByteString): AkkaInputFile = ByteString(filename, contents) -} diff --git a/build.sc b/build.sc index d8d1a7a4..c3154bc0 100644 --- a/build.sc +++ b/build.sc @@ -22,22 +22,22 @@ object library { val scalaLogging = "3.9.5" val logback = "1.5.18" val scalajHttp = "2.4.2" - val akkaVersion = "2.6.20" - val akkaActor = akkaVersion - val akkaStream = akkaVersion - val akkaHttp = "10.5.2" - val akkaTestkit = akkaVersion - val akkaHttpCors = "1.2.0" + val pekkoVersion = "1.3.0" + val pekkoActor = pekkoVersion + val pekkoStream = pekkoVersion + val pekkoHttp = "1.3.0" + val pekkoTestkit = pekkoVersion + val pekkoHttpCors = pekkoHttp val hammock = "0.11.3" val monix = "3.4.1" val sbtTesting = "1.0" } - val akkaHttp = mvn"com.typesafe.akka::akka-http::${Version.akkaHttp}" - val akkaHttpTestkit = mvn"com.typesafe.akka::akka-http-testkit::${Version.akkaHttp}" - val akkaTestkit = mvn"com.typesafe.akka::akka-testkit::${Version.akkaTestkit}" - val akkaActor = mvn"com.typesafe.akka::akka-actor::${Version.akkaActor}" - val akkaStream = mvn"com.typesafe.akka::akka-stream::${Version.akkaStream}" + val pekkoHttp = mvn"org.apache.pekko::pekko-http::${Version.pekkoHttp}" + val pekkoHttpTestkit = mvn"org.apache.pekko::pekko-http-testkit::${Version.pekkoHttp}" + val pekkoTestkit = mvn"org.apache.pekko::pekko-testkit::${Version.pekkoTestkit}" + val pekkoActor = mvn"org.apache.pekko::pekko-actor::${Version.pekkoActor}" + val pekkoStream = mvn"org.apache.pekko::pekko-stream::${Version.pekkoStream}" val asyncHttpClientBackendCats = mvn"com.softwaremill.sttp.client3::async-http-client-backend-cats-ce2::${Version.sttp}" val asyncHttpClientBackendCats3 = @@ -49,7 +49,7 @@ object library { val scalajHttp = mvn"org.scalaj::scalaj-http::${Version.scalajHttp}" val scalaLogging = mvn"com.typesafe.scala-logging::scala-logging::${Version.scalaLogging}" val scalaMockScalaTest = mvn"org.scalamock::scalamock::${Version.scalaMockScalaTest}" - val akkaHttpCors = mvn"ch.megard::akka-http-cors::${Version.akkaHttpCors}" + val pekkoHttpCors = mvn"org.apache.pekko::pekko-http-cors::${Version.pekkoHttpCors}" val scalaTest = mvn"org.scalatest::scalatest::${Version.scalaTest}" val sbtTesting = mvn"org.scala-sbt:test-interface:${Version.sbtTesting}" @@ -165,19 +165,19 @@ object core extends Module { } -object akka extends Module { +object pekko extends Module { - object jvm extends Cross[AkkaModule](ScalaVersions) - trait AkkaModule extends Bot4sTelegramCrossPlatform with Publishable { + object jvm extends Cross[pekkoModule](ScalaVersions) + trait pekkoModule extends Bot4sTelegramCrossPlatform with Publishable { override val platformSegment: String = "jvm" - override val location: String = "akka" - override def artifactName = "telegram-akka" + override val location: String = "pekko" + override def artifactName = "telegram-pekko" override def mvnDeps = Task { super.mvnDeps() ++ Seq( - library.akkaActor, - library.akkaHttp, - library.akkaStream + library.pekkoActor, + library.pekkoHttp, + library.pekkoStream ) } @@ -188,8 +188,8 @@ object akka extends Module { override def mvnDeps = Task { super.mvnDeps() ++ Seq( - library.akkaTestkit, - library.akkaHttpTestkit + library.pekkoTestkit, + library.pekkoHttpTestkit ) } } @@ -215,12 +215,12 @@ object examples extends Module { override def mvnDeps = Task { super.mvnDeps() ++ Seq( - library.akkaHttpCors, + library.pekkoHttpCors, library.sttpOkHttp ) ++ versionDependencies() } - override def moduleDeps = super.moduleDeps ++ Seq(core.jvm(), akka.jvm()) + override def moduleDeps = super.moduleDeps ++ Seq(core.jvm(), pekko.jvm()) } object catsjvm extends Cross[ExamplesCatsModule](ScalaVersions) diff --git a/akka/src/com/bot4s/telegram/api/ActorBroker.scala b/pekko/src/com/bot4s/telegram/api/ActorBroker.scala similarity index 91% rename from akka/src/com/bot4s/telegram/api/ActorBroker.scala rename to pekko/src/com/bot4s/telegram/api/ActorBroker.scala index f50e9daf..b3564d7a 100644 --- a/akka/src/com/bot4s/telegram/api/ActorBroker.scala +++ b/pekko/src/com/bot4s/telegram/api/ActorBroker.scala @@ -1,6 +1,6 @@ package com.bot4s.telegram.api -import akka.actor.ActorRef +import org.apache.pekko.actor.ActorRef import com.bot4s.telegram.models.{ Update, User } import scala.concurrent.Future diff --git a/akka/src/com/bot4s/telegram/api/GameManager.scala b/pekko/src/com/bot4s/telegram/api/GameManager.scala similarity index 93% rename from akka/src/com/bot4s/telegram/api/GameManager.scala rename to pekko/src/com/bot4s/telegram/api/GameManager.scala index 766eb184..dcd514d8 100644 --- a/akka/src/com/bot4s/telegram/api/GameManager.scala +++ b/pekko/src/com/bot4s/telegram/api/GameManager.scala @@ -4,9 +4,9 @@ import java.net.URLDecoder import java.nio.charset.StandardCharsets import java.util.Base64 -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.{ Directive1, Route } +import org.apache.pekko.http.scaladsl.model.StatusCodes +import org.apache.pekko.http.scaladsl.server.Directives._ +import org.apache.pekko.http.scaladsl.server.{ Directive1, Route } import com.bot4s.telegram.marshalling import com.bot4s.telegram.methods.{ GetGameHighScores, SetGameScore } import com.bot4s.telegram.models.{ CallbackQuery, ChatId, User } @@ -35,7 +35,7 @@ import io.circe.generic.extras.Configuration * or even better, submit a PR with your approach. */ trait GameManager extends WebRoutes { - this: BotBase[Future] with BotExecutionContext with AkkaImplicits => + this: BotBase[Future] with BotExecutionContext with PekkoImplicit => import com.bot4s.telegram.marshalling._ diff --git a/akka/src/com/bot4s/telegram/api/AkkaTelegramBot.scala b/pekko/src/com/bot4s/telegram/api/PekkoTelegramBot.scala similarity index 50% rename from akka/src/com/bot4s/telegram/api/AkkaTelegramBot.scala rename to pekko/src/com/bot4s/telegram/api/PekkoTelegramBot.scala index 9c73bce1..ee2c9687 100644 --- a/akka/src/com/bot4s/telegram/api/AkkaTelegramBot.scala +++ b/pekko/src/com/bot4s/telegram/api/PekkoTelegramBot.scala @@ -1,14 +1,14 @@ package com.bot4s.telegram.api -import akka.actor.ActorSystem +import org.apache.pekko.actor.ActorSystem import com.bot4s.telegram.future.TelegramBot -trait AkkaTelegramBot extends TelegramBot with AkkaDefaults +trait PekkoTelegramBot extends TelegramBot with PekkoDefaults -trait AkkaImplicits { +trait PekkoImplicit { implicit val system: ActorSystem } -trait AkkaDefaults extends AkkaImplicits { +trait PekkoDefaults extends PekkoImplicit { implicit val system: ActorSystem = ActorSystem() } diff --git a/akka/src/com/bot4s/telegram/api/WebRoutes.scala b/pekko/src/com/bot4s/telegram/api/WebRoutes.scala similarity index 86% rename from akka/src/com/bot4s/telegram/api/WebRoutes.scala rename to pekko/src/com/bot4s/telegram/api/WebRoutes.scala index 50f723aa..f58ef6e0 100644 --- a/akka/src/com/bot4s/telegram/api/WebRoutes.scala +++ b/pekko/src/com/bot4s/telegram/api/WebRoutes.scala @@ -1,15 +1,15 @@ package com.bot4s.telegram.api -import akka.http.scaladsl.{ Http, HttpsConnectionContext } -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.Route +import org.apache.pekko.http.scaladsl.{ Http, HttpsConnectionContext } +import org.apache.pekko.http.scaladsl.server.Directives._ +import org.apache.pekko.http.scaladsl.server.Route import com.bot4s.telegram.future.BotExecutionContext import com.typesafe.scalalogging.StrictLogging import scala.concurrent.{ Future, Promise } trait WebRoutes extends BotBase[Future] with StrictLogging { - this: BotExecutionContext with AkkaImplicits => + this: BotExecutionContext with PekkoImplicit => val port: Int val interfaceIp: String = "::0" diff --git a/akka/src/com/bot4s/telegram/api/Webhook.scala b/pekko/src/com/bot4s/telegram/api/Webhook.scala similarity index 85% rename from akka/src/com/bot4s/telegram/api/Webhook.scala rename to pekko/src/com/bot4s/telegram/api/Webhook.scala index 0ed8c8bb..8d581aec 100644 --- a/akka/src/com/bot4s/telegram/api/Webhook.scala +++ b/pekko/src/com/bot4s/telegram/api/Webhook.scala @@ -1,8 +1,8 @@ package com.bot4s.telegram.api -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.Route +import org.apache.pekko.http.scaladsl.model.StatusCodes +import org.apache.pekko.http.scaladsl.server.Directives._ +import org.apache.pekko.http.scaladsl.server.Route import com.bot4s.telegram.future.BotExecutionContext import com.bot4s.telegram.methods.SetWebhook import com.bot4s.telegram.models.{ InputFile, Update } @@ -17,10 +17,10 @@ import scala.util.control.NonFatal * Automatically registers the webhook on run(). */ trait Webhook extends WebRoutes with StrictLogging { - this: BotBase[Future] with BotExecutionContext with AkkaImplicits => + this: BotBase[Future] with BotExecutionContext with PekkoImplicit => import com.bot4s.telegram.marshalling._ - import com.bot4s.telegram.marshalling.AkkaHttpMarshalling._ + import com.bot4s.telegram.marshalling.PekkoHttpMarshalling._ /** * URL for the webhook. diff --git a/akka/src/com/bot4s/telegram/clients/AkkaHttpClient.scala b/pekko/src/com/bot4s/telegram/clients/PekkoHttpClient.scala similarity index 69% rename from akka/src/com/bot4s/telegram/clients/AkkaHttpClient.scala rename to pekko/src/com/bot4s/telegram/clients/PekkoHttpClient.scala index 6ab84e6d..ae2173fd 100644 --- a/akka/src/com/bot4s/telegram/clients/AkkaHttpClient.scala +++ b/pekko/src/com/bot4s/telegram/clients/PekkoHttpClient.scala @@ -1,14 +1,14 @@ package com.bot4s.telegram.clients -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.marshalling._ -import akka.http.scaladsl.model._ -import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.stream.Materializer +import org.apache.pekko.actor.ActorSystem +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.marshalling._ +import org.apache.pekko.http.scaladsl.model._ +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.stream.Materializer import cats.instances.future._ import com.bot4s.telegram.api.RequestHandler -import com.bot4s.telegram.marshalling.AkkaHttpMarshalling +import com.bot4s.telegram.marshalling.PekkoHttpMarshalling import com.bot4s.telegram.marshalling._ import com.bot4s.telegram.methods.{ Request, Response } import io.circe.{ Decoder, Encoder } @@ -17,19 +17,19 @@ import com.typesafe.scalalogging.StrictLogging import scala.concurrent.{ ExecutionContext, Future } /** - * Akka-backed Telegram Bot API client + * Pekko-backed Telegram Bot API client * Provide transparent camelCase <-> underscore_case conversions during serialization/deserialization * * @param token Bot token */ -class AkkaHttpClient(token: String, telegramHost: String = "api.telegram.org")(implicit +class PekkoHttpClient(token: String, telegramHost: String = "api.telegram.org")(implicit system: ActorSystem, materializer: Materializer, ec: ExecutionContext ) extends RequestHandler[Future] with StrictLogging { - import AkkaHttpMarshalling._ + import PekkoHttpMarshalling._ private val apiBaseUrl = s"https://$telegramHost/bot$token/" private val http = Http() diff --git a/akka/src/com/bot4s/telegram/clients/YetAnotherAkkaClient.scala b/pekko/src/com/bot4s/telegram/clients/YetAnotherPekkoClient.scala similarity index 65% rename from akka/src/com/bot4s/telegram/clients/YetAnotherAkkaClient.scala rename to pekko/src/com/bot4s/telegram/clients/YetAnotherPekkoClient.scala index 9e0f5b1e..d3401379 100644 --- a/akka/src/com/bot4s/telegram/clients/YetAnotherAkkaClient.scala +++ b/pekko/src/com/bot4s/telegram/clients/YetAnotherPekkoClient.scala @@ -1,13 +1,13 @@ package com.bot4s.telegram.clients -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model.Uri.Path -import akka.http.scaladsl.model._ -import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.stream.Materializer -import akka.stream.scaladsl.{ Sink, Source } +import org.apache.pekko.actor.ActorSystem +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.marshalling.Marshal +import org.apache.pekko.http.scaladsl.model.Uri.Path +import org.apache.pekko.http.scaladsl.model._ +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.stream.Materializer +import org.apache.pekko.stream.scaladsl.{ Sink, Source } import cats.instances.future._ import com.bot4s.telegram.api.RequestHandler import com.bot4s.telegram.methods.{ Request, Response } @@ -17,7 +17,7 @@ import com.bot4s.telegram.marshalling.responseDecoder import scala.concurrent.{ ExecutionContext, Future } -class YetAnotherAkkaClient(token: String, telegramHost: String = "api.telegram.org")(implicit +class YetAnotherPekkoClient(token: String, telegramHost: String = "api.telegram.org")(implicit system: ActorSystem, materializer: Materializer, ec: ExecutionContext @@ -26,7 +26,7 @@ class YetAnotherAkkaClient(token: String, telegramHost: String = "api.telegram.o private val flow = Http().outgoingConnectionHttps(telegramHost) - import com.bot4s.telegram.marshalling.AkkaHttpMarshalling._ + import com.bot4s.telegram.marshalling.PekkoHttpMarshalling._ override def sendRequest[T <: Request: Encoder]( request: T diff --git a/akka/src/com/bot4s/telegram/marshalling/AkkaHttpMarshalling.scala b/pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala similarity index 86% rename from akka/src/com/bot4s/telegram/marshalling/AkkaHttpMarshalling.scala rename to pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala index 214d807b..d04a0ba1 100644 --- a/akka/src/com/bot4s/telegram/marshalling/AkkaHttpMarshalling.scala +++ b/pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala @@ -1,14 +1,14 @@ package com.bot4s.telegram.marshalling -import akka.http.scaladsl.marshalling.{ Marshaller, Marshalling, ToEntityMarshaller } -import akka.http.scaladsl.model._ -import akka.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller } +import org.apache.pekko.http.scaladsl.marshalling.{ Marshaller, Marshalling, ToEntityMarshaller } +import org.apache.pekko.http.scaladsl.model._ +import org.apache.pekko.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller } import com.bot4s.telegram.marshalling import com.bot4s.telegram.methods.{ JsonRequest, MultipartRequest, Request } -import com.bot4s.telegram.models.{ AkkaInputFile, InputFile } +import com.bot4s.telegram.models.{ PekkoInputFile, InputFile } import io.circe.{ Decoder, Encoder } -object AkkaHttpMarshalling { +object PekkoHttpMarshalling { implicit def camelCaseJsonUnmarshaller[R](implicit decR: Decoder[R]): FromEntityUnmarshaller[R] = Unmarshaller.stringUnmarshaller @@ -40,7 +40,7 @@ object AkkaHttpMarshalling { case InputFile.Path(path) => Multipart.FormData.BodyPart.fromPath(key, MediaTypes.`application/octet-stream`, path) - case AkkaInputFile.ByteString(filename, bytes) => + case PekkoInputFile.ByteString(filename, bytes) => Multipart.FormData.BodyPart( key, HttpEntity(MediaTypes.`application/octet-stream`, bytes), diff --git a/pekko/src/com/bot4s/telegram/models/PekkoInputFile.scala b/pekko/src/com/bot4s/telegram/models/PekkoInputFile.scala new file mode 100644 index 00000000..1882a361 --- /dev/null +++ b/pekko/src/com/bot4s/telegram/models/PekkoInputFile.scala @@ -0,0 +1,11 @@ +package com.bot4s.telegram.models + +import org.apache.pekko.util.{ ByteString => PekkoByteString } + +trait PekkoInputFile extends InputFile + +object PekkoInputFile { + final case class ByteString(filename: String, contents: PekkoByteString) extends PekkoInputFile + + def apply(filename: String, contents: PekkoByteString): PekkoInputFile = ByteString(filename, contents) +} diff --git a/akka/test/src/com/bot4s/telegram/marshalling/AkkaHttpMarshallingSuite.scala b/pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala similarity index 60% rename from akka/test/src/com/bot4s/telegram/marshalling/AkkaHttpMarshallingSuite.scala rename to pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala index aff92583..bf9bf34f 100644 --- a/akka/test/src/com/bot4s/telegram/marshalling/AkkaHttpMarshallingSuite.scala +++ b/pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala @@ -1,25 +1,25 @@ package com.bot4s.telegram.marshalling -import akka.http.scaladsl.marshalling.Marshal -import akka.http.scaladsl.model.RequestEntity -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.testkit.{ RouteTestTimeout, ScalatestRouteTest } -import akka.util.ByteString +import org.apache.pekko.http.scaladsl.marshalling.Marshal +import org.apache.pekko.http.scaladsl.model.RequestEntity +import org.apache.pekko.http.scaladsl.server.Directives._ +import org.apache.pekko.http.scaladsl.testkit.{ RouteTestTimeout, ScalatestRouteTest } +import org.apache.pekko.util.ByteString import com.bot4s.telegram.api.TestUtils -import com.bot4s.telegram.marshalling.AkkaHttpMarshalling.underscore_case_marshaller +import com.bot4s.telegram.marshalling.PekkoHttpMarshalling.underscore_case_marshaller import com.bot4s.telegram.methods.SendDocument -import com.bot4s.telegram.models.{ AkkaInputFile, InputFile } +import com.bot4s.telegram.models.{ PekkoInputFile, InputFile } import org.scalatest.matchers.should.Matchers import org.scalatest.funsuite.AnyFunSuite import concurrent.duration._ -class AkkaHttpMarshallingSuite extends AnyFunSuite with ScalatestRouteTest with Matchers with TestUtils { +class PekkoHttpMarshallingSuite extends AnyFunSuite with ScalatestRouteTest with Matchers with TestUtils { implicit def defaultTimeout: RouteTestTimeout = RouteTestTimeout(5.seconds) - test("Correctly serialize top-level string members in Akka multipart requests") { + test("Correctly serialize top-level string members in Pekko multipart requests") { val captionWithLineBreak = "this is a line\nand then\t another line" val channelId = "this_is_a_channel" val fileId = "and_a_file_id" @@ -34,10 +34,10 @@ class AkkaHttpMarshallingSuite extends AnyFunSuite with ScalatestRouteTest with } } - test("Handles AkkaInputFile") { + test("Handles PekkoInputFile") { val channelId = "this_is_a_channel" val content = "file content" - val entity = SendDocument(channelId, AkkaInputFile("Pepe", ByteString(content))) + val entity = SendDocument(channelId, PekkoInputFile("Pepe", ByteString(content))) Post("/", Marshal(entity).to[RequestEntity]) ~> { formFields("document") { document => complete(document) From 738fcad8ba254d523c7c400909c05d2042da0448 Mon Sep 17 00:00:00 2001 From: Mike Limansky Date: Sun, 7 Dec 2025 12:36:26 +0300 Subject: [PATCH 2/3] Fix scalafmt --- .../com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala | 2 +- .../bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala b/pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala index d04a0ba1..4e4a191e 100644 --- a/pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala +++ b/pekko/src/com/bot4s/telegram/marshalling/PekkoHttpMarshalling.scala @@ -5,7 +5,7 @@ import org.apache.pekko.http.scaladsl.model._ import org.apache.pekko.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller } import com.bot4s.telegram.marshalling import com.bot4s.telegram.methods.{ JsonRequest, MultipartRequest, Request } -import com.bot4s.telegram.models.{ PekkoInputFile, InputFile } +import com.bot4s.telegram.models.{ InputFile, PekkoInputFile } import io.circe.{ Decoder, Encoder } object PekkoHttpMarshalling { diff --git a/pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala b/pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala index bf9bf34f..240f05f5 100644 --- a/pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala +++ b/pekko/test/src/com/bot4s/telegram/marshalling/PekkoHttpMarshallingSuite.scala @@ -9,7 +9,7 @@ import org.apache.pekko.util.ByteString import com.bot4s.telegram.api.TestUtils import com.bot4s.telegram.marshalling.PekkoHttpMarshalling.underscore_case_marshaller import com.bot4s.telegram.methods.SendDocument -import com.bot4s.telegram.models.{ PekkoInputFile, InputFile } +import com.bot4s.telegram.models.{ InputFile, PekkoInputFile } import org.scalatest.matchers.should.Matchers import org.scalatest.funsuite.AnyFunSuite From 66cc3e6f35d33d1951c66d4e827ec9256c1bd2d3 Mon Sep 17 00:00:00 2001 From: Mike Limansky Date: Sun, 7 Dec 2025 15:10:58 +0300 Subject: [PATCH 3/3] Fix examples compilation with pekko --- examples/src-jvm-2/AkkaExampleBot.scala | 6 ------ examples/src-jvm-2/GitHubHosted2048Bot.scala | 19 +++++++++---------- examples/src-jvm-2/LmgtfyBot.scala | 4 ++-- examples/src-jvm-2/PekkoExampleBot.scala | 6 ++++++ examples/src-jvm-2/PerChatRequestsBot.scala | 6 +++--- examples/src-jvm-2/PollingWithWebRoutes.scala | 4 ++-- examples/src-jvm-2/QrCodesBot.scala | 14 +++++++------- examples/src-jvm-2/SelfHosted2048Bot.scala | 14 +++++++------- examples/src-jvm-2/SpotifyBot.scala | 10 +++++----- examples/src-jvm-2/VoiceFileBot.scala | 10 +++++----- examples/src-jvm-2/WebhookBot.scala | 8 ++++---- examples/src-jvm-2/WebhookSSLBot.scala | 12 ++++++------ 12 files changed, 56 insertions(+), 57 deletions(-) delete mode 100644 examples/src-jvm-2/AkkaExampleBot.scala create mode 100644 examples/src-jvm-2/PekkoExampleBot.scala diff --git a/examples/src-jvm-2/AkkaExampleBot.scala b/examples/src-jvm-2/AkkaExampleBot.scala deleted file mode 100644 index 2b44875c..00000000 --- a/examples/src-jvm-2/AkkaExampleBot.scala +++ /dev/null @@ -1,6 +0,0 @@ -import com.bot4s.telegram.api.AkkaTelegramBot -import com.bot4s.telegram.clients.AkkaHttpClient - -abstract class AkkaExampleBot(val token: String) extends AkkaTelegramBot { - override val client = new AkkaHttpClient(token) -} diff --git a/examples/src-jvm-2/GitHubHosted2048Bot.scala b/examples/src-jvm-2/GitHubHosted2048Bot.scala index 71736470..fdc23981 100644 --- a/examples/src-jvm-2/GitHubHosted2048Bot.scala +++ b/examples/src-jvm-2/GitHubHosted2048Bot.scala @@ -1,15 +1,14 @@ -import akka.http.scaladsl.model.Uri -import akka.http.scaladsl.model.Uri.{ Path, Query } -import akka.http.scaladsl.model.headers.HttpOrigin -import akka.http.scaladsl.server.RouteConcatenation._ -import akka.http.scaladsl.server.Route - -import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher +import org.apache.pekko.http.scaladsl.model.Uri +import org.apache.pekko.http.scaladsl.model.Uri.{ Path, Query } +import org.apache.pekko.http.scaladsl.model.headers.HttpOrigin +import org.apache.pekko.http.scaladsl.server.RouteConcatenation._ +import org.apache.pekko.http.scaladsl.server.Route +import org.apache.pekko.http.cors.scaladsl.settings.CorsSettings +import org.apache.pekko.http.cors.scaladsl.model.HttpOriginMatcher +import org.apache.pekko.http.cors.scaladsl.CorsDirectives._ import cats.instances.future._ import cats.syntax.functor._ -import ch.megard.akka.http.cors.scaladsl.CorsDirectives.cors -import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings import com.bot4s.telegram.api.declarative.{ Callbacks, Commands } import com.bot4s.telegram.api.{ GameManager, Payload } import com.bot4s.telegram.future.Polling @@ -48,7 +47,7 @@ import scala.concurrent.Future * @param gameManagerHost Base URL of the game manager. */ class GitHubHosted2048Bot(token: String, gameManagerHost: String) - extends AkkaExampleBot(token) + extends PekkoExampleBot(token) with Polling with Commands[Future] with Callbacks[Future] diff --git a/examples/src-jvm-2/LmgtfyBot.scala b/examples/src-jvm-2/LmgtfyBot.scala index c5d24444..12d22db4 100644 --- a/examples/src-jvm-2/LmgtfyBot.scala +++ b/examples/src-jvm-2/LmgtfyBot.scala @@ -1,5 +1,5 @@ -import akka.http.scaladsl.model.Uri -import akka.http.scaladsl.model.Uri.Query +import org.apache.pekko.http.scaladsl.model.Uri +import org.apache.pekko.http.scaladsl.model.Uri.Query import cats.instances.future._ import cats.syntax.functor._ import com.bot4s.telegram.Implicits._ diff --git a/examples/src-jvm-2/PekkoExampleBot.scala b/examples/src-jvm-2/PekkoExampleBot.scala new file mode 100644 index 00000000..fea0e3e1 --- /dev/null +++ b/examples/src-jvm-2/PekkoExampleBot.scala @@ -0,0 +1,6 @@ +import com.bot4s.telegram.api.PekkoTelegramBot +import com.bot4s.telegram.clients.PekkoHttpClient + +abstract class PekkoExampleBot(val token: String) extends PekkoTelegramBot { + override val client = new PekkoHttpClient(token) +} diff --git a/examples/src-jvm-2/PerChatRequestsBot.scala b/examples/src-jvm-2/PerChatRequestsBot.scala index 293cc6a0..0eddff3a 100644 --- a/examples/src-jvm-2/PerChatRequestsBot.scala +++ b/examples/src-jvm-2/PerChatRequestsBot.scala @@ -1,15 +1,15 @@ -import akka.actor.{ Actor, ActorRef, Props, Terminated } +import org.apache.pekko.actor.{ Actor, ActorRef, Props, Terminated } import cats.syntax.functor._ import cats.instances.future._ import com.bot4s.telegram.api.declarative.Commands -import com.bot4s.telegram.api.{ ActorBroker, AkkaDefaults } +import com.bot4s.telegram.api.{ ActorBroker, PekkoDefaults } import com.bot4s.telegram.future.Polling import com.bot4s.telegram.methods.SendMessage import com.bot4s.telegram.models.{ Message, Update } import scala.concurrent.Future -trait PerChatRequests extends ActorBroker with AkkaDefaults { +trait PerChatRequests extends ActorBroker with PekkoDefaults { override val broker = Some(system.actorOf(Props(new Broker), "broker")) diff --git a/examples/src-jvm-2/PollingWithWebRoutes.scala b/examples/src-jvm-2/PollingWithWebRoutes.scala index 87692b6b..cb7f4563 100644 --- a/examples/src-jvm-2/PollingWithWebRoutes.scala +++ b/examples/src-jvm-2/PollingWithWebRoutes.scala @@ -13,7 +13,7 @@ import scala.concurrent.Future * and even serving entire websites. */ class PollingWithWebRoutes(token: String) - extends AkkaExampleBot(token) + extends PekkoExampleBot(token) with Polling with WebRoutes with Commands[Future] { @@ -24,7 +24,7 @@ class PollingWithWebRoutes(token: String) reply("Hello").void } - import akka.http.scaladsl.server.Directives._ + import org.apache.pekko.http.scaladsl.server.Directives._ override def routes = pathEndOrSingleSlash { complete("I'm running...") diff --git a/examples/src-jvm-2/QrCodesBot.scala b/examples/src-jvm-2/QrCodesBot.scala index 24f8656b..47865eef 100644 --- a/examples/src-jvm-2/QrCodesBot.scala +++ b/examples/src-jvm-2/QrCodesBot.scala @@ -1,14 +1,14 @@ import java.net.URLEncoder -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.{ HttpRequest, Uri } -import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.util.ByteString +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.model.{ HttpRequest, Uri } +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.util.ByteString import com.bot4s.telegram.api.declarative.Commands import com.bot4s.telegram.api._ import com.bot4s.telegram.future.Polling import com.bot4s.telegram.methods._ -import com.bot4s.telegram.models.AkkaInputFile +import com.bot4s.telegram.models.PekkoInputFile import scala.concurrent.Future @@ -16,7 +16,7 @@ import scala.concurrent.Future * Generates QR codes from text/url. */ class QrCodesBot(token: String) - extends AkkaExampleBot(token) + extends PekkoExampleBot(token) with Polling with Commands[Future] with ChatActions[Future] { @@ -31,7 +31,7 @@ class QrCodesBot(token: String) response <- Http().singleRequest(HttpRequest(uri = Uri(url))) if response.status.isSuccess() bytes <- Unmarshal(response).to[ByteString] - photo = AkkaInputFile("qrcode.png", bytes) + photo = PekkoInputFile("qrcode.png", bytes) _ <- uploadingPhoto // Hint the user _ <- request(SendPhoto(msg.source, photo)) } yield () diff --git a/examples/src-jvm-2/SelfHosted2048Bot.scala b/examples/src-jvm-2/SelfHosted2048Bot.scala index 364a6fef..14e0b0ad 100644 --- a/examples/src-jvm-2/SelfHosted2048Bot.scala +++ b/examples/src-jvm-2/SelfHosted2048Bot.scala @@ -1,12 +1,12 @@ -import akka.http.scaladsl.model.Uri -import akka.http.scaladsl.model.Uri.{ Path, Query } -import akka.http.scaladsl.server.Directives.{ getFromResourceDirectory, pathPrefix } -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.server.RouteConcatenation._ +import org.apache.pekko.http.scaladsl.model.Uri +import org.apache.pekko.http.scaladsl.model.Uri.{ Path, Query } +import org.apache.pekko.http.scaladsl.server.Directives.{ getFromResourceDirectory, pathPrefix } +import org.apache.pekko.http.scaladsl.server.Route +import org.apache.pekko.http.scaladsl.server.RouteConcatenation._ import cats.instances.future._ import cats.syntax.functor._ import com.bot4s.telegram.api.declarative.{ Callbacks, Commands } -import com.bot4s.telegram.api.{ AkkaDefaults, GameManager, Payload } +import com.bot4s.telegram.api.{ GameManager, Payload, PekkoDefaults } import com.bot4s.telegram.future.Polling import com.bot4s.telegram.methods.SendGame @@ -35,7 +35,7 @@ import scala.concurrent.Future class SelfHosted2048Bot(token: String, gameManagerHost: String) extends ExampleBot(token) with Polling - with AkkaDefaults + with PekkoDefaults with Callbacks[Future] with GameManager with Commands[Future] { diff --git a/examples/src-jvm-2/SpotifyBot.scala b/examples/src-jvm-2/SpotifyBot.scala index fcbb0e8a..5f5a7071 100644 --- a/examples/src-jvm-2/SpotifyBot.scala +++ b/examples/src-jvm-2/SpotifyBot.scala @@ -1,9 +1,9 @@ import java.net.URLEncoder -import akka.http.scaladsl.Http -import akka.http.scaladsl.model._ -import akka.http.scaladsl.model.headers.{ Authorization, BasicHttpCredentials } -import akka.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.model._ +import org.apache.pekko.http.scaladsl.model.headers.{ Authorization, BasicHttpCredentials } +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal import cats.instances.future._ import cats.syntax.functor._ import com.bot4s.telegram.future.Polling @@ -22,7 +22,7 @@ import scala.concurrent.Future * The provided clientId/secret are not guaranteed to work forever. * See [[https://developer.spotify.com/web-api/authorization-guide/]] */ -class SpotifyBot(token: String) extends AkkaExampleBot(token) with Polling { +class SpotifyBot(token: String) extends PekkoExampleBot(token) with Polling { val limit = 10 diff --git a/examples/src-jvm-2/VoiceFileBot.scala b/examples/src-jvm-2/VoiceFileBot.scala index 0d7dd91f..d12006eb 100644 --- a/examples/src-jvm-2/VoiceFileBot.scala +++ b/examples/src-jvm-2/VoiceFileBot.scala @@ -1,7 +1,7 @@ -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.{ HttpRequest, Uri } -import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.util.ByteString +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.model.{ HttpRequest, Uri } +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.util.ByteString import cats.instances.future._ import cats.syntax.functor._ import com.bot4s.telegram.api.declarative.Commands @@ -14,7 +14,7 @@ import scala.util.{ Failure, Success } /** * This bot receives voice recordings and outputs the file size. */ -class VoiceFileBot(token: String) extends AkkaExampleBot(token) with Polling with Commands[Future] { +class VoiceFileBot(token: String) extends PekkoExampleBot(token) with Polling with Commands[Future] { onMessage { implicit msg => using(_.voice) { voice => diff --git a/examples/src-jvm-2/WebhookBot.scala b/examples/src-jvm-2/WebhookBot.scala index aacc99ed..7d7a5250 100644 --- a/examples/src-jvm-2/WebhookBot.scala +++ b/examples/src-jvm-2/WebhookBot.scala @@ -1,8 +1,8 @@ import java.net.URLEncoder -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.{ HttpRequest, Uri } -import akka.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.model.{ HttpRequest, Uri } +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal import com.bot4s.telegram.api.Webhook import com.bot4s.telegram.methods._ import com.bot4s.telegram.models.Message @@ -13,7 +13,7 @@ import scala.concurrent.Future * Webhook-backed JS calculator. * To test Webhooks locally, use an SSH tunnel or ngrok. */ -class WebhookBot(token: String) extends AkkaExampleBot(token) with Webhook { +class WebhookBot(token: String) extends PekkoExampleBot(token) with Webhook { val port = 8080 val webhookUrl = "https://88c444ab.ngrok.io" diff --git a/examples/src-jvm-2/WebhookSSLBot.scala b/examples/src-jvm-2/WebhookSSLBot.scala index 8c887f16..edcc32cb 100644 --- a/examples/src-jvm-2/WebhookSSLBot.scala +++ b/examples/src-jvm-2/WebhookSSLBot.scala @@ -1,8 +1,8 @@ import java.net.URLEncoder -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.{ HttpRequest, Uri } -import akka.http.scaladsl.unmarshalling.Unmarshal +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.model.{ HttpRequest, Uri } +import org.apache.pekko.http.scaladsl.unmarshalling.Unmarshal import com.bot4s.telegram.api.Webhook import com.bot4s.telegram.methods._ import com.bot4s.telegram.models.Message @@ -10,12 +10,12 @@ import com.bot4s.telegram.models.Message import scala.concurrent.Future import com.bot4s.telegram.models.InputFile import java.io.File -import akka.http.scaladsl.HttpsConnectionContext +import org.apache.pekko.http.scaladsl.HttpsConnectionContext import java.security.KeyStore import javax.net.ssl.KeyManagerFactory import javax.net.ssl.TrustManagerFactory import javax.net.ssl.SSLContext -import akka.http.scaladsl.ConnectionContext +import org.apache.pekko.http.scaladsl.ConnectionContext import java.security.SecureRandom /** @@ -34,7 +34,7 @@ import java.security.SecureRandom * * Replace XXXX with your bot's key */ -class WebhookSSLBot(token: String) extends AkkaExampleBot(token) with Webhook { +class WebhookSSLBot(token: String) extends PekkoExampleBot(token) with Webhook { val port = 8080 val webhookUrl = "https://domain.extension:8443"