Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Apr 23 14:07
    scala-steward closed #273
  • Apr 23 14:07
    scala-steward commented #273
  • Apr 23 14:07
    scala-steward opened #279
  • Apr 23 11:38
    Shestaevd closed #278
  • Apr 22 21:01
    Shestaevd edited #278
  • Apr 21 17:27
    Shestaevd edited #278
  • Apr 21 17:25
    Shestaevd opened #278
  • Apr 20 18:10
    scala-steward closed #274
  • Apr 20 18:10
    scala-steward commented #274
  • Apr 20 18:10
    scala-steward opened #277
  • Apr 20 02:09
    scala-steward closed #272
  • Apr 20 02:09
    scala-steward commented #272
  • Apr 20 02:09
    scala-steward opened #276
  • Apr 07 06:09
    scala-steward closed #271
  • Apr 07 06:09
    scala-steward commented #271
  • Apr 07 06:09
    scala-steward opened #275
  • Apr 01 08:09
    scala-steward closed #267
  • Apr 01 08:09
    scala-steward commented #267
  • Apr 01 08:09
    scala-steward opened #274
  • Mar 30 20:16
    scala-steward closed #261
Yura Slinkin
@augustjune
Hi @nickdndev! Currently, there's no time limit for the duration of a started scenario, so in a situation where doesn't follow up, it will be hanging in memory in case user wants to get back to the thread.
Although, scenarios are optimized to be very lightweight (you can easily have 10000+ of them), there's an issue that addresses this feature: augustjune/canoe#158
I think I'm able to find some time to work on this
Esenbaev Nursultan
@eanea
@augustjune, hi) when are you gonna release to update the last API?
Yura Slinkin
@augustjune
Hi @eanea I can do that later today. does that work for you?
Esenbaev Nursultan
@eanea
@augustjune, yes, would be great)
Lior Liviev
@liorl00
Hey, I have an inline button and I want it to trigger another scenario, how do I do that?
Lior Liviev
@liorl00
@augustjune
Yura Slinkin
@augustjune
Hi @liorl00
In order to achieve that you have to share the state between the callback handler and scenario that you want to be triggered.
Lior Liviev
@liorl00
can you give me an example?
Yura Slinkin
@augustjune
Here's an example
  def run(args: List[String]): IO[ExitCode] =
    Stream
      .resource(TelegramClient.global[IO](token))
      .flatMap { implicit client =>
        Stream.eval(Store.make[IO]).flatMap { store =>
          Bot
            .fromStream(Bot.polling[IO].updates.through(answerCallbacks(store)))
            .follow(createButton, trigger(store)(reaction))
        }
      }
      .compile
      .drain
      .as(ExitCode.Success)

  def createButton[F[_]: TelegramClient]: Scenario[F, Unit] =
    for {
      msg <- Scenario.expect(command("callback"))
      _ <- Scenario.eval(
        msg.chat.send(content = "pretty message", keyboard = setupMarkupWithSungleCallbackButton("button", "xx"))
      )
    } yield ()

  def trigger[F[_]: TelegramClient](lastCallback: Store[F])(main: Scenario[F, Unit]): Scenario[F, Unit] =
    Scenario.eval(lastCallback.check("xx")).ifM(main, Scenario.done)

  def reaction[F[_]: TelegramClient]: Scenario[F, Unit] = ???

  def answerCallbacks[F[_]: Monad: TelegramClient](lastCallback: Store[F]): Pipe[F, Update, Update] =
    _.evalTap {
      case CallbackButtonSelected(_, query) =>
        query.data match {
          case Some(cbd) => lastCallback.save(cbd) *> query.finish
          case _         => lastCallback.clean
        }
      case _ => lastCallback.clean
    }

  def setupMarkupWithSungleCallbackButton(text: String, data: String): Keyboard.Inline = {
    val inlineBtn = InlineKeyboardButton.callbackData(text = text, cbd = data)
    val inlineKeyboardMarkUp = InlineKeyboardMarkup.singleButton(inlineBtn)
    Keyboard.Inline(inlineKeyboardMarkUp)
  }


trait Store[F[_]] {
  def save(id: String): F[Unit]

  def clean: F[Unit]

  def check(id: String): F[Boolean]
}

object Store {
  def make[F[_]: Concurrent]: F[Store[F]] =
    Ref[F].of(none[String]).map { ref =>
      new Store[F] {
        def save(id: String): F[Unit] = ref.set(id.some)

        def clean: F[Unit] = ref.set(none)

        def check(id: String): F[Boolean] = ref.get.map(_.contains(id))
      }
    }
}
Basically, you set the state in the callback handler and read the state as the first step in your scenario.
Lior Liviev
@liorl00
Thank you :)
Yura Slinkin
@augustjune
You can share the state with Ref and you can see I used a small wrapper around it (Store) to simplify access to the data
Lior Liviev
@liorl00
The only problem is that I need to rewrite it to zio)
Yura Slinkin
@augustjune
Well, the effect type is abstracted, so you can as well use zio.Task specifying it just on the top level in run
Lior Liviev
@liorl00
can you show me the imports as well?
Yura Slinkin
@augustjune
Here you go :wink:
import canoe.api._
import canoe.api.models.Keyboard
import canoe.models.{CallbackButtonSelected, InlineKeyboardButton, InlineKeyboardMarkup, Update}
import canoe.syntax._
import cats.Monad
import cats.effect.concurrent.Ref
import cats.effect.{Concurrent, ExitCode, IO, IOApp}
import cats.implicits._
import fs2.{Pipe, Stream}
Lior Liviev
@liorl00
Thx)
Lior Liviev
@liorl00
Oh and what is query.finish
Can't find this method
Yura Slinkin
@augustjune
It's a method that stops processing circle in telegram when you hit a callback button
Are you using laterst version 0.5.0?
Lior Liviev
@liorl00
yes
Yura Slinkin
@augustjune
in that case finish should be available if you have imported canoe.api._
Lior Liviev
@liorl00
@augustjune Is it okay to use chat.send in answerCallbacks without Scenario.eval?
Yura Slinkin
@augustjune
@liorl00 yeah, totally cool. Scenario.eval just allows you to lift F[A] into Scenario context
Lior Liviev
@liorl00
thx)
Lior Liviev
@liorl00
@augustjune do you know if there any other way to trigger Scenario in callback than sharing the state?
Lior Liviev
@liorl00
@augustjune ?
Yura Slinkin
@augustjune
@liorl00 I don't think there is any other way as of now
that's something that could be added to Scenario though
if you're interested, you can raise an issue in the project and I'll find some time to work on it soon
:wink:
Lior Liviev
@liorl00
@augustjune Hey is it possible now to use this api?
https://core.telegram.org/bots/api#loginurl
Yura Slinkin
@augustjune
@liorl00 Hi
Yes, you can use it in combination with InlineKeyboardButton. There's an optional argument that takes this object LoginUrl that you can should construct yourself and create a button with it
Lior Liviev
@liorl00
@augustjune Could you give me an example pls?)
Cause I don't see any method with loginUrl
Yura Slinkin
@augustjune
yeah, you're right
InlineKeyboardButton constructor methods don't expose this param, my bad
Lior Liviev
@liorl00
could you implement this pls, I really need this method :)
Yura Slinkin
@augustjune
definitely
I'll get back to you later today with this
Lior Liviev
@liorl00
Thank you, I'll be waiting)
Yura Slinkin
@augustjune
@liorl00 btw, PRs are welcome :wink:
this is an easy one, just another constructor method in InlineKeyboardButton companion object with some description
Lior Liviev
@liorl00
@augustjune Should be right: augustjune/canoe#230
Lior Liviev
@liorl00
@augustjune I hope you can merge it today, cause I need it badly)
Yura Slinkin
@augustjune
@liorl00 new version 0.5.1 with your change is available in maven central :tada:
Lior Liviev
@liorl00
@augustjune Hey wanted to say thank you for the last update, really helped. Could you also check my issue. Maybe you remember about being able to call scenarios in callbacks? augustjune/canoe#218