Giter VIP home page Giter VIP logo

telegram's People

Contributors

aaabramov avatar alari avatar alexgruperm avatar bilki avatar carloo1 avatar cobr123 avatar danilbykov avatar devcexx avatar drewnoff avatar evis avatar ex0ns avatar hugemane avatar ivan-klass avatar jj avatar kirhgoff avatar larroy avatar laughedelic avatar lolgab avatar mukel avatar onilton avatar perevedko avatar ravinderpayal avatar reimai avatar rema7 avatar scala-steward avatar tobscore avatar xdracam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

telegram's Issues

Bot starts but doesn't receive updates

Hi.

I'm developing a bot to send messages to a channel.

Locally, while I develop the bot and run it, it works fine and receives all commands.
But in a production environment, were a firewall blocks all requests by default, it doesn't work. My bot isn't receiving messages or commands.

I already allowed "api.telegram.org:443" in the firewall. This liberation works. I can send requests to it via telnet. But wasn't enough.

There another port or address that I need allow?

Gifs in v.3.0.16

Hi,
There's a way to send gifs in the older version 3.16, apart from senting the Gif URL?
Cheers

Use async http client

Right now you are using synchronous http api which wrapped into Future. Let use truly async clients like spray-client, dispatch or so to provide real async communication

InlineQueryResultArticle doesn't send type?

Hello,
I'm having a problem with answering inline queries.
Library version is 4.0.0-RC1.
System information:

 ~/testproject $ uname -a
 FreeBSD scaladev 11.1-RELEASE-p10 FreeBSD 11.1-RELEASE-p10 #0: Tue May  8 05:21:56 UTC 2018     [email protected]:/usr/obj/usr/src/sys/GENERIC  amd64
 ~/testproject $ scala -version
 Scala code runner version 2.12.6 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.
 ~/testproject $ java -version
 openjdk version "1.8.0_172"
 OpenJDK Runtime Environment (build 1.8.0_172-b11)
 OpenJDK 64-Bit Server VM (build 25.172-b11, mixed mode)

sbt version is 1.0.

This is the whole code (things are named like that because I'm just starting to try out things):

 import com.bot4s.telegram.api.declarative.InlineQueries
 import com.softwaremill.sttp.okhttp.OkHttpFutureBackend
 import com.bot4s.telegram.clients.SttpClient
 import com.bot4s.telegram.methods._
 import com.bot4s.telegram.models._
 import slogging.{LogLevel, LoggerConfig, PrintLoggerFactory}

 class EchoBot(val token: String) extends TelegramBot with Polling with InlineQueries {
   LoggerConfig.factory = PrintLoggerFactory()
   LoggerConfig.level = LogLevel.TRACE

   onInlineQuery { implicit q =>
     val results = Seq(
       InlineQueryResultArticle("1", "Klingt lustig",
         inputMessageContent = InputTextMessageContent("Klingt lustig")))
     answerInlineQuery(results, Some(60))                                                                                                                                                   
   }                                                                                                                                                                              

   implicit val backend = OkHttpFutureBackend()                                                                                                                                             
   override val client: RequestHandler = new SttpClient(token)                                                                                                                              
 }

 object Hello extends App {
   new EchoBot("<bot token>").run()
 }

When the bot receives an inline query, the output looks like this:

 [trace, com.bot4s.telegram.clients.SttpClient] REQUEST c529aba4-79d6-4cca-87eb-cb8c9d9f8a77 AnswerInlineQuery(1302304079610336554,List(InlineQueryResultArticle(1,Klingt lustig,InputTextMessageContent(Klingt lustig,None,None),None,None,None,None,None,None,None,article)),Some(60),None,None,None,None)
 [error, com.bot4s.telegram.clients.SttpClient] RESPONSE c529aba4-79d6-4cca-87eb-cb8c9d9f8a77 java.util.NoSuchElementException: Status code 400: {"ok":false,"error_code":400,"description":"Bad Request: can't find field \"type\""}

I don't actually know if this is a problem with the library, but I think it might be. If it's a user error, then I'm sorry and would like to know how to do it properly.
Thanks!

Remove service message

Can I remove the service message using the this
for eg

xyz joined the group
pqr left the group 

I want to remove the telegram message whenever user join or leave the group

Can I configure HTTPS for Telegram webhooks?

I can't see any place where we configure HTTPS in telegrambot4s..

As a result we can see that telegrambot4s is served in HTTP:

[WARN] [11/06/2017 12:03:39.680] [default-akka.actor.default-dispatcher-5] [akka.actor.ActorSystemImpl(default)] Illegal request, responding with status '400 Bad Request': Unsupported HTTP method: HTTP method too long (started with '����ᅡ���ᄒ��→¢£��'). Increase `akka.http.server.parsing.max-method-length` to support HTTP methods with more characters.

Custom command prefix

I need to start command without prefix "/". Add possibility to api change CommandPrefix.

404 links in Games section of README

The command receiver check should be done comparing the bot username, not its first name.

Currently, when a message is received and the receiver is extracted from the received text, it is compared against the first name of the bot instead of comparing it with its username, as the Telegram client suggests while typing a command like here.

This is because, in info.mukel.telegrambot4s.api.declarative.Commands, the field botName holds the first name of the bot instead of its username.

/hello or hello

In every example you show use like this

bot.on("/command") {...}

I got confused, cause in this way it doesn't work.
But it works like this:

bot.on("command") {...}

GetUpdates fails multiple times with an UnsupportedContentTypeException

I run a bot on a server and I noticed that there are some reoccuring exceptions with the Polling. The Exception reads as follows:

ERROR - GetUpdates failed
akka.http.scaladsl.unmarshalling.Unmarshaller$UnsupportedContentTypeException: Unsupported Content-Type, supported: application/json
        at akka.http.scaladsl.unmarshalling.Unmarshaller$UnsupportedContentTypeException$.apply(Unmarshaller.scala:158)
        at akka.http.scaladsl.unmarshalling.Unmarshaller$EnhancedFromEntityUnmarshaller$.$anonfun$forContentTypes$3(Unmarshaller.scala:114)
        at akka.http.scaladsl.unmarshalling.Unmarshaller$$anon$1.apply(Unmarshaller.scala:58)
        at akka.http.scaladsl.unmarshalling.Unmarshaller.$anonfun$transform$3(Unmarshaller.scala:23)
        at akka.http.scaladsl.unmarshalling.Unmarshaller$$anon$1.apply(Unmarshaller.scala:58)
        at akka.http.scaladsl.unmarshalling.Unmarshal.to(Unmarshal.scala:25)
        at info.mukel.telegrambot4s.clients.AkkaClient.toApiResponse(AkkaClient.scala:38)
        at info.mukel.telegrambot4s.clients.AkkaClient.$anonfun$apply$2(AkkaClient.scala:50)
        at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:304)
        at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:37)
        at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
        at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:140)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

The really bad part about this is not the uncaught exception, but that the error occurs multiple times afterwards. I checked the logs and apparently the error appeared 382 times in about 12 seconds, in my example between 2:32:25 and 2:32:37. To show the frequency, I'll add an excerpt of the logs:

2017-12-09 02:32:25,980 ERROR h.i.t.IWINewsBot [Polling.scala:39] GetUpdates failed
2017-12-09 02:32:26,006 ERROR h.i.t.IWINewsBot [Polling.scala:39] GetUpdates failed
2017-12-09 02:32:26,035 ERROR h.i.t.IWINewsBot [Polling.scala:39] GetUpdates failed
2017-12-09 02:32:26,060 ERROR h.i.t.IWINewsBot [Polling.scala:39] GetUpdates failed
2017-12-09 02:32:26,090 ERROR h.i.t.IWINewsBot [Polling.scala:39] GetUpdates failed
2017-12-09 02:32:26,113 ERROR h.i.t.IWINewsBot [Polling.scala:39] GetUpdates failed

How to stop the running bot?

I start sbt and then run my bot. How do I stop it? And another small question. I was using ~run with tilda at the beginning of the command, it means something like watch mode I think and it this working (when I change source code sbt detects it and was recomplining automatically) but now doesn't.

Dependency isn't available in the repo

[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: com.bot4s#telegram-core_2.12;4.0.0-RC1: not found
[warn] :: com.bot4s#telegram-akka_2.12;4.0.0-RC1: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::

GameShortName doesn't handle at receiveCallbackQuery

here is the code

object PokerTelegramBot extends TelegramBot with Polling with Messages {
  lazy val token = "SOME_TOKEN"

  override def receiveMessage(msg: Message) = {
    msg.text.foreach {
      case "/start" ⇒
        println("start handled")
        val inlineBtns = InlineKeyboardMarkup(Seq(Seq(InlineKeyboardButton(
          text = "Play now!",
          callbackData = Some("{ game_short_name: \"cpptest\" }")))))
        reply("To play game press button", replyMarkup = Some(inlineBtns))(msg)

      case any ⇒ println(s"unhandled message <$any>")
    }
  }

  override def receiveCallbackQuery(callbackQuery: CallbackQuery) = {
    println(s"gameShortName: ${callbackQuery.gameShortName}")
    println(s"data: ${callbackQuery.data}")
  }
}

after button click we see callbackQuery.gameShortName = None and callbackQuery.data = Some({ game_short_name: "cpptest" })

Wrong version in README

There seems to be an error in your README, I guess the version for the SBT example should be 2.0.1 and not 2.1.0.

Best regards
Fabian

Incorrect order of messages when polling is used

There is an incorrect order of messages (sent by api.request(SendMessage)), when the polling method is used. How to keep sent messages in order? Is there any way to fix that without using webhooks?

Download Audio File

Sorry about this but I didn't find the way to extract an Audio file from server, I'm using this code:

val fileRequest:GetFile = new GetFile(msg.audio.get.fileId) // whats the next step

Regards

WebHook mode, high CPU consumption

Hello @mukel.
This issue is continue #76
I have configured bot as HTTPS destination, it works fine and needs a small CPU resource (in my configuration 1-2%.)
Now I need to use Cassandra session (CqlSession) inside bot. My idea is using bot to send it commands like /info /lastbar /lasttick. Bot receive commands and in method(s) onCommand execute Cassandra query(ies) and return results to telegram chat.

  1. First solution:
    In the main application create CqlSession, open connection and send CqlSession instance inside bot as parameter, like this
  val bot = new telegBotWH(log, config, sessSrc)
  val eol = bot.run
...
where
class telegBotWH(log :org.slf4j.Logger,
                 config :Config,
                 sessSrc :CassSessionSrc)
    extends AkkaTelegramBot
    with Webhook
    with CommonFuncs
    with Commands[Future]
{
...
  onCommand('ticksall) { implicit msg =>
    onCommandLog(msg)
    val ticksCounts: Seq[TicksCnt] = sessSrc.getTicksDistrib
    reply(ticksCounts.sortBy(t => t.tickCount)(Ordering[Long].reverse).mkString(EOL))
    Future.successful()
  }
...

it works as expected, stable and fast.
But application use high cpu, jumps 20-50% (in my VDS). Also in silent mode, when I do not communicate with bot.
It's inappropriate for me.
I use jmc, jconsole for research and found that a lot of cpu spend on thread s0-timer-0 (s0 cassandra). But there are no queries to DB at all, no explicit timers or scheduled tasks.
I can understand why a silent session uses high CPU.

My second idea is moving Cassandra session from parameter of telegBotWH and convert it into children Actor.
Code:

inside telegBotWH, after 
port
def httpsContext
client

I create child Actor
val cassSessActor = system.actorOf(CassSessActor.props(config), "CassSessActor")

From logs I see that when child Actor created it successful open session to db.
Next onCommand and send message to Actor to execute db query.

  onCommand('tickers) { implicit msg =>
    log.info("onCommand[tickers]")
    cassSessActor ! "get_tickers"
    Future.successful()
  }

Also from log I see that child Actor real read DB and has data. But,
I have 2 ways to send result back to bot

  1. Using
    in child Actor
override def receive: Receive = {
    case "get_tickers" => {
      val listTickers :Seq[Ticker] = sessSrc.getTickersDict.toList
      log.info("inside CassSessActor read tickers, size="+listTickers.size+" send it back to bot.")
      context.parent ! listTickers
}

in bot

  def receive: Receive = {
    case seqTickers : Seq[Ticker] => {
      log.info("Receive tickers dict from cassSessActor")
      log.info("Output inside telegBotWH")
      seqTickers.foreach(t => log.info("["+t.tickerId+"] - "+t.tickerCode))
    }

In this case Bot don't receive message from child actor, there is no error.
If I change context.parent ! listTickers to sender ! listTickers
There is error:

10:18:07.220 [default-akka.actor.default-dispatcher-4] INFO  mtspredbot.Main$ - onCommand[check]
[INFO] [07/03/2019 10:18:07.245] [default-akka.actor.default-dispatcher-16] [akka://default/user/CassSessActor] Receive check message from bot.
[INFO] [07/03/2019 10:18:07.247] [default-akka.actor.default-dispatcher-6] [akka://default/deadLetters] Message [java.lang.String] 
from Actor[akka://default/user/CassSessActor#1672889139] 
to   Actor[akka://default/deadLetters] was not delivered. 
[2] dead letters encountered. 
If this is not an expected behavior, then [Actor[akka://default/deadLetters]] may have terminated unexpectedly, 
This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

json4s incorrect enum parsing due to erasure

Telegram keeps adding new entity types without proper notice.
To keep bots from breaking randomly I added a safe fallback for unknown/new entity types.
I backported this fix to v3, but hit json4s/json4s#142

json4s relies on reflection but Scala enums are indistinguishable at runtime; json4s tries all defined enum parsers until one succeeds; this is dangerous since it can break type safety.

My attempt to fix this was mostly correct, but didn't consider that the order in which the enum deserializers are added actually matters; WTF. At least is deterministic...

I just pushed a fix to avoid future breakages due to new entity types; but bot masters should port bots to v4 which is based on circe and gracefully accepts unknown/new entity types.

Released v3.0.16 with the fix.
/cc @Rovak

Upcoming refactor

I'm planning a major refactor, these are some of the planned changes/features, please leave your feature in the comments.

  • Remove Akka from dependencies, add it as an optional backend. ~~ Ship Akka as default backend (convenience wins) ~~, ship ScalajHttp as default, allow other backends (RossHttp).
  • Update to Telegram Bot API 3.5 (WIP)
  • Provide other backend alternatives (Scalaj-http)
  • Improve error handling.
  • Provide composable request handlers (retry, full log, chain requests...)
  • Add proper examples for Heroku, Google App Engine...
  • Support for Scala.js,
  • Support for several backends e.g. AkkaHttp, Sttp, Scalaj aand custom ones.
  • Transparent JSON marshalling, no need for implicits nor reflection.

Bot API 2.0

Thank you for great library, I'm beginner in Scala, but everything looks very easy to use for me.

Recently Telegram announced Bot API 2.0. Do you have any plans to implement new features like inline keyboards, location and phone number sharing?

GetUpdates failed: org.json4s.package$MappingException: No usable value for result

The full stack trace is quite long…

GetUpdates failed
org.json4s.package$MappingException: No usable value for result
No usable value for message
No usable value for entities
No usable value for type
No usable value for $outer
Can't find field scala$Enumeration$$vmap from class scala.Enumeration
	at org.json4s.reflect.package$.fail(package.scala:95)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:526)
	at org.json4s.Extraction$ClassInstanceBuilder.$anonfun$instantiate$4(Extraction.scala:546)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
	at scala.collection.TraversableLike.map(TraversableLike.scala:234)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
	at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546)
	at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597)
	at org.json4s.Extraction$.$anonfun$extract$9(Extraction.scala:400)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:392)
	at org.json4s.Extraction$.extract(Extraction.scala:39)
	at org.json4s.ExtractableJsonAstNode.extract(ExtractableJsonAstNode.scala:21)
	at info.mukel.telegrambot4s.marshalling.JsonMarshallers.fromJson(JsonMarshallers.scala:46)
	at info.mukel.telegrambot4s.marshalling.JsonMarshallers.fromJson$(JsonMarshallers.scala:46)
	at info.mukel.telegrambot4s.marshalling.JsonMarshallers$.fromJson(JsonMarshallers.scala:49)
	at info.mukel.telegrambot4s.marshalling.AkkaHttpMarshalling$.$anonfun$camelCaseJsonUnmarshaller$1(AkkaHttpMarshalling.scala:16)
	at akka.http.scaladsl.util.FastFuture$.$anonfun$map$1(FastFuture.scala:23)
	at akka.http.scaladsl.util.FastFuture$.strictTransform$1(FastFuture.scala:41)
	at akka.http.scaladsl.util.FastFuture$.$anonfun$transformWith$3(FastFuture.scala:51)
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
	at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: org.json4s.package$MappingException: No usable value for message
No usable value for entities
No usable value for type
No usable value for $outer
Can't find field scala$Enumeration$$vmap from class scala.Enumeration
	at org.json4s.reflect.package$.fail(package.scala:95)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:526)
	at org.json4s.Extraction$ClassInstanceBuilder.$anonfun$instantiate$4(Extraction.scala:546)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
	at scala.collection.TraversableLike.map(TraversableLike.scala:234)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
	at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546)
	at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597)
	at org.json4s.Extraction$.$anonfun$extract$9(Extraction.scala:400)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:392)
	at org.json4s.Extraction$CollectionBuilder.$anonfun$mkCollection$1(Extraction.scala:410)
	at scala.collection.immutable.List.map(List.scala:283)
	at org.json4s.Extraction$CollectionBuilder.mkCollection(Extraction.scala:410)
	at org.json4s.Extraction$CollectionBuilder.result(Extraction.scala:443)
	at org.json4s.Extraction$.$anonfun$extract$8(Extraction.scala:382)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:382)
	at org.json4s.Extraction$.$anonfun$extract$6(Extraction.scala:366)
	at scala.Option.flatMap(Option.scala:171)
	at org.json4s.Extraction$.$anonfun$extract$5(Extraction.scala:366)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:366)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:514)
	... 28 more
Caused by: org.json4s.package$MappingException: No usable value for entities
No usable value for type
No usable value for $outer
Can't find field scala$Enumeration$$vmap from class scala.Enumeration
	at org.json4s.reflect.package$.fail(package.scala:95)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:526)
	at org.json4s.Extraction$ClassInstanceBuilder.$anonfun$instantiate$4(Extraction.scala:546)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
	at scala.collection.TraversableLike.map(TraversableLike.scala:234)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
	at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546)
	at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597)
	at org.json4s.Extraction$.$anonfun$extract$9(Extraction.scala:400)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:392)
	at org.json4s.Extraction$.$anonfun$extract$6(Extraction.scala:366)
	at scala.Option.flatMap(Option.scala:171)
	at org.json4s.Extraction$.$anonfun$extract$5(Extraction.scala:366)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:366)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:514)
	... 54 more
Caused by: org.json4s.package$MappingException: No usable value for type
No usable value for $outer
Can't find field scala$Enumeration$$vmap from class scala.Enumeration
	at org.json4s.reflect.package$.fail(package.scala:95)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:526)
	at org.json4s.Extraction$ClassInstanceBuilder.$anonfun$instantiate$4(Extraction.scala:546)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
	at scala.collection.TraversableLike.map(TraversableLike.scala:234)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
	at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546)
	at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597)
	at org.json4s.Extraction$.$anonfun$extract$9(Extraction.scala:400)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:392)
	at org.json4s.Extraction$CollectionBuilder.$anonfun$mkCollection$1(Extraction.scala:410)
	at scala.collection.immutable.List.map(List.scala:283)
	at org.json4s.Extraction$CollectionBuilder.mkCollection(Extraction.scala:410)
	at org.json4s.Extraction$CollectionBuilder.result(Extraction.scala:443)
	at org.json4s.Extraction$.$anonfun$extract$8(Extraction.scala:382)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:382)
	at org.json4s.Extraction$.$anonfun$extract$6(Extraction.scala:366)
	at scala.Option.flatMap(Option.scala:171)
	at org.json4s.Extraction$.$anonfun$extract$5(Extraction.scala:366)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:366)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:514)
	... 73 more
Caused by: org.json4s.package$MappingException: No usable value for $outer
Can't find field scala$Enumeration$$vmap from class scala.Enumeration
	at org.json4s.reflect.package$.fail(package.scala:95)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:526)
	at org.json4s.Extraction$ClassInstanceBuilder.$anonfun$instantiate$4(Extraction.scala:546)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
	at scala.collection.TraversableLike.map(TraversableLike.scala:234)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
	at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:546)
	at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:597)
	at org.json4s.Extraction$.$anonfun$extract$9(Extraction.scala:400)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:392)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:514)
	... 99 more
Caused by: org.json4s.package$MappingException: Can't find field scala$Enumeration$$vmap from class scala.Enumeration
	at org.json4s.reflect.package$.fail(package.scala:95)
	at org.json4s.reflect.ScalaSigReader$.read$1(ScalaSigReader.scala:43)
	at org.json4s.reflect.ScalaSigReader$.$anonfun$readField$3(ScalaSigReader.scala:47)
	at scala.Option.getOrElse(Option.scala:121)
	at org.json4s.reflect.ScalaSigReader$.read$1(ScalaSigReader.scala:47)
	at org.json4s.reflect.ScalaSigReader$.readField(ScalaSigReader.scala:49)
	at org.json4s.reflect.Reflector$ClassDescriptorBuilder.$anonfun$fields$3(Reflector.scala:69)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
	at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:52)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
	at scala.collection.TraversableLike.map(TraversableLike.scala:234)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
	at org.json4s.reflect.Reflector$ClassDescriptorBuilder.fields(Reflector.scala:68)
	at org.json4s.reflect.Reflector$ClassDescriptorBuilder.properties(Reflector.scala:85)
	at org.json4s.reflect.Reflector$ClassDescriptorBuilder.result(Reflector.scala:184)
	at org.json4s.reflect.Reflector$.createDescriptor(Reflector.scala:53)
	at org.json4s.reflect.Reflector$.$anonfun$describe$1(Reflector.scala:48)
	at org.json4s.reflect.package$Memo.apply(package.scala:36)
	at org.json4s.reflect.Reflector$.describe(Reflector.scala:48)
	at org.json4s.Extraction$.$anonfun$extract$9(Extraction.scala:393)
	at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
	at org.json4s.Extraction$.extract(Extraction.scala:392)
	at org.json4s.Extraction$ClassInstanceBuilder.buildCtorArg(Extraction.scala:514)
	... 113 more

I'm not sure that the problem is on your side. I think the actual JSON value would be helpful, I can send it to you privately if you wish.

Using bot as https destination without ngrok

Hello @mukel
I try to use your library like this:
class telegBotWH(log :org.slf4j.Logger, config :Config) extends AkkaTelegramBot with Webhook with Commands[Future] { ...
and next want explisitely load certificate with:
val cfile :java.io.File= new File("C:\\tcert\\mtspredbot.pem") val inpCertFilePath :java.nio.file.Path = cfile.toPath override val certificate :Option[InputFile] = Option(InputFile(inpCertFilePath))
I use next WebHook address https://xxx.xxx.xxx.xxx
where xxx.xxx.xxx.xxx is my VDS

When I run bot there is next output
[trace, com.bot4s.telegram.clients.AkkaHttpClient] REQUEST 5ebe2b43-f7da-4fe9-80f3-a04448d3df8e SetWebhook(https://xxx.xxx.xxx.xxx,Some(Path(C:\tcert\mtspredbot.pem)),None,None) Press [ENTER] to shutdown the bot, it may take a few seconds... [trace, com.bot4s.telegram.clients.AkkaHttpClient] RESPONSE 5ebe2b43-f7da-4fe9-80f3-a04448d3df8e true [WARN] [06/28/2019 15:58:30.996] [default-akka.actor.default-dispatcher-16] [akka.actor.ActorSystemImpl(default)] Illegal request, responding with status '400 Bad Request': Unsupported HTTP method: The HTTP method started with 0x16 rather than any known HTTP method. Perhaps this was an HTTPS request sent to an HTTP endpoint?
My question. Is it possible to use bot wuth this configuration as destination for telegram with https.

I know about ngrok and it works fine but wants to use it directly, because it's vds.

4.4.0-RC1: UnsupportedAkkaVersion

For dependencies:

"com.bot4s"           %% "telegram-core" % "4.4.0-RC1"
"com.bot4s"           %% "telegram-akka" % "4.4.0-RC1"

I am getting runtime error:

Exception in thread "main" akka.UnsupportedAkkaVersion: Current version of Akka is [2.5.22], but akka-http requires version [2.5.23]

image

Private bot

Hi,
I would like to implement a secure bot feature, meaning that the bot could only respond to specific channels (groups or users), I thought the best would be to add the filter inside the handleUpdate methods of the Commands class, allowing us not to call the action if the msg.chat.id does not match any of the authorized one.

Here are my questions:

  • Do you see a better place to add this feature ?
  • Where would you put the authorized groups ? in a config file ? (maybe add config to the project, but it seems overkill)

Error code in TelegramApiException

Would be nice to have a telegram error code available in exception. I.e. in case of 429 ([Error]: Too many requests: retry later) API user might want to resend the message with some delay instead of failing.

Unable to connect: "Failed to clear webhook"|"Connection reset by peer"

Hello, my bot is failing to start with error

Failed to clear webhook
akka.stream.StreamTcpException: The connection closed with error: Connection reset by peer

My guess is my connection to Telegram servers gets blocked.

Among your resent issues I saw your answer about proxy support. Is it still possible to access your refactored version (3.1.0-RC1)?

Bot to retrieve voice message

Please point me to the right direction on implementing this.

I have the snippet so far:

onMessage{ implicit msg =>
request(GetFile(msg.voice.map(_.fileId).getOrElse(""))
.onComplete{
case Success(file) => ??? //what to do next to get the actual file (when i try file.filePath it gives me something like this --> voice/file_1)
}
}

Thanks,

Line breaks in photo/document caption are broken

I've updated library from 3.0.4 to 3.0.13 and faced the problem with line breaks in document title. They are sent as plain text.

SendDocument(chatId, InputFile("file.png", byteArray),
  caption = Some("first line\nsecond line"))

Resulting message in 3.0.4:

first line
second line

In 3.0.13:

first line\nsecond line

I'm getting a "not found"

$ sbt
[info] Set current project to bobot (in build file:/home/jmerelo/Asignaturas/cloud-computing/BoBot/)
> run
[info] Updating {file:/home/jmerelo/Asignaturas/cloud-computing/BoBot/}bobot...
[info] Resolving com.github.mukel#telegrambot4s_2.10;v1.2.2 ...
[warn]  module not found: com.github.mukel#telegrambot4s_2.10;v1.2.2
[warn] ==== local: tried
[warn]   /home/jmerelo/.ivy2/local/com.github.mukel/telegrambot4s_2.10/v1.2.2/ivys/ivy.xml
[warn] ==== public: tried
[warn]   https://repo1.maven.org/maven2/com/github/mukel/telegrambot4s_2.10/v1.2.2/telegrambot4s_2.10-v1.2.2.pom
[warn] ==== jitpack: tried
[warn]   https://jitpack.io/com/github/mukel/telegrambot4s_2.10/v1.2.2/telegrambot4s_2.10-v1.2.2.pom
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  ::          UNRESOLVED DEPENDENCIES         ::
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  :: com.github.mukel#telegrambot4s_2.10;v1.2.2: not found
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn] 
[warn]  Note: Unresolved dependencies path:
[warn]      com.github.mukel:telegrambot4s_2.10:v1.2.2 (/home/jmerelo/Asignaturas/cloud-computing/BoBot/build.sbt#L3-4)
[warn]        +- default:bobot_2.10:0.1-SNAPSHOT
[trace] Stack trace suppressed: run last *:update for the full output.
[error] (*:update) sbt.ResolveException: unresolved dependency: com.github.mukel#telegrambot4s_2.10;v1.2.2: not found

info.mukel.telegrambot4s.api.TelegramApiException: Not Found

Hi!
I'm making a request with SendMessage, but info.mukel.telegrambot4s.api.TelegramApiException: Not Found
I looked into the code of info.mukel.telegrambot4s.methods.ApiRequest[R] and found this:
def methodName: String = getClass.getSimpleName.reverse.dropWhile(_ == '$').reverse
but this code return SendMessage, expected sendMessage (in Telegram API).

Actor bindings architecture

The actor bindings open new ways of building bots; FSM actors will greatly simplify the creation of stateful workflows leveraging over a widely known and used model (FSM Actors).

Actor bindings can be added by mixing ActorDispatcher.

Here's an example of a very simple per-chat dispatcher:
Per-chat actor dispatcher

The purpose of this issue is to agree on a general design for a more powerful abstraction.
Possibly including:

  • FSM
  • Expiring actors
  • State management and persistency

Verbose loge messages to console by default

Printing to console all http messages by default leads to verbose output: https://github.com/mukel/telegrambot4s/blob/e1d6c9938d43d1daef5e1f16460f37da5c7a6372/src/main/scala/info/mukel/telegrambot4s/api/TelegramApiAkka.scala#L59.

In many case i would like to ignore this messages, but i can't. Please, use logging instead of printing to console. For example, using https://github.com/typesafehub/scala-logging. It will help users to control library output.

Commands hijacking for bots with access to messages

Bot name after the @ is not checked. If a bot has been granted full access to messages in a chat, it will inspect all commands and execute their callbacks while ignoring which bot the command was actually adressed to.

for example, typing /start@youtube while my bot is present with access to messages will execute the /start command on my bot.

Check webhook before setting new one

Problem:
We are using webhooks and have scaling environment (e.g. k8s) and we scale our bot app from 1 to 3+ instances. They are launched in parallel and each one tries to set the same webhook via setWebhook.
And as expected Telegram responds with 429 Too Many Requests.

Solution:
Before setting the webhook execute getWebhookInfo method and compare it with com.bot4s.telegram.methods.SetWebhook parameters.

Concerns:

  • if certificate was changes than there is no way to find this out
  • there still might be races between instances but I believe Telegram handles this method as atomic

Or at least we can provide some sort of parameter which configures this behavior.

I am fine with submitting PR after we agree on solution.

Commands order and their execution

Hello @mukel
It is great pleasure to read your code and use this project. I have some idea that I found useful and also I have implementation and I can contribute if you let me.
So when we give commands with on(some:String){function} they don't preserve order and if we have "registered"command twice in code it will be executed twice. What if we will make commands ordered, execute them once so that we will play around with commands that match from specific to more general one?
Cheers,
/Jakhongir

In Poling.scala function def run() -> wrap handleUpdate in Future

May be it's a good idea to wrap handleUpdate in a Future object

Because getUpdates return Future[Array] and increment of a updateOffset value happens after update will be handled.

It lead to if getUpdates return more then 1 item and/or handle will take more then 1 second, getUpdate will call again with same updateOffset value.

override def run(): Unit = {
    // setWebhook(None)
    var updatesOffset = 0
    while (running) {
      for (updates <- getUpdates(offset = updatesOffset)) {
        for (u <- updates ) {
          Future(handleUpdate(u))
        updatesOffset = updatesOffset max (u.updateId + 1)
        }
      }
      Thread.sleep(pollingCycle)
    }
  }

Cant run LmgtfyBot example bot

Hello, i've got error java.lang.NoClassDefFoundError: com/softwaremill/sttp/package$UriContext$ when i'm trying run example bot.
Dependencies
libraryDependencies += "com.bot4s" %% "telegram-core" % "4.0.0-RC1" libraryDependencies += "com.bot4s" %% "telegram-akka" % "4.0.0-RC1" libraryDependencies += "com.softwaremill.sttp" %% "core" % "1.3.8"

The error
[trace, com.bot4s.telegram.clients.SttpClient] REQUEST c67d3f8a-996b-4808-aa04-5ff784e2c700 DeleteWebhook Exception in thread "main" java.lang.NoClassDefFoundError: com/softwaremill/sttp/package$UriContext$ at com.bot4s.telegram.clients.SttpClient.sendRequest(SttpClient.scala:41) at com.bot4s.telegram.api.RequestHandler.apply(RequestHandler.scala:37) at com.bot4s.telegram.api.RequestHandler.apply$(RequestHandler.scala:24) at com.bot4s.telegram.clients.SttpClient.apply(SttpClient.scala:22) at com.bot4s.telegram.api.Polling.run(Polling.scala:95) at com.bot4s.telegram.api.Polling.run$(Polling.scala:90) at HelloWorld.com$bot4s$telegram$api$declarative$Commands$$super$run(HelloWorld.scala:12) at com.bot4s.telegram.api.declarative.Commands.run(Commands.scala:99) at com.bot4s.telegram.api.declarative.Commands.run$(Commands.scala:97) at HelloWorld.run(HelloWorld.scala:12) at Main$.delayedEndpoint$Main$1(Main.scala:5) at Main$delayedInit$body.apply(Main.scala:4) at scala.Function0.apply$mcV$sp(Function0.scala:34) at scala.Function0.apply$mcV$sp$(Function0.scala:34) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App.$anonfun$main$1$adapted(App.scala:76) at scala.collection.immutable.List.foreach(List.scala:389) at scala.App.main(App.scala:76) at scala.App.main$(App.scala:74) at Main$.main(Main.scala:4) at Main.main(Main.scala) Caused by: java.lang.ClassNotFoundException: com.softwaremill.sttp.package$UriContext$ at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 21 more

Bot will stuck in infinite loop when receive "group upgraded to supergroup" message

Steps to reproduce:

  1. Create group
  2. Add bot (without group privacy) to it
  3. Upgrade to supergroup

Expected behavior:

Bot will correctly handle all these events

Actual behavior:

Bot cannot parse one of the update messages and fails with:

[info] No usable value for id
[info] Did not find value which can be converted into long
[info]  at org.json4s.reflect.package$.fail(package.scala:95)
[info]  at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:526)
[info]  at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546)
[info]  at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546)
[info]  at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
[info]  at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
[info]  at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
[info]  at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
[info]  at scala.collection.TraversableLike$class.map(TraversableLike.scala:234)
[info]  at scala.collection.AbstractTraversable.map(Traversable.scala:104)
[info] Caused by: org.json4s.package$MappingException: No usable value for id
[info] Did not find value which can be converted into long
[info]  at org.json4s.reflect.package$.fail(package.scala:95)
[info]  at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:526)
[info]  at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546)
[info]  at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$15.apply(Extraction.scala:546)
[info]  at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
[info]  at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234)
[info]  at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
[info]  at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
[info]  at scala.collection.TraversableLike$class.map(TraversableLike.scala:234)
[info]  at scala.collection.AbstractTraversable.map(Traversable.scala:104)
[info] Caused by: org.json4s.package$MappingException: Did not find value which can be converted into long
[info]  at org.json4s.reflect.package$.fail(package.scala:95)
[info]  at org.json4s.Extraction$$anonfun$org$json4s$Extraction$$convert$2.apply(Extraction.scala:704)
[info]  at org.json4s.Extraction$$anonfun$org$json4s$Extraction$$convert$2.apply(Extraction.scala:704)
[info]  at scala.Option.getOrElse(Option.scala:121)
[info]  at org.json4s.Extraction$.org$json4s$Extraction$$convert(Extraction.scala:704)
[info]  at org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:394)
[info]  at org.json4s.Extraction$$anonfun$extract$6.apply(Extraction.scala:392)
[info]  at org.json4s.Extraction$.customOrElse(Extraction.scala:606)
[info]  at org.json4s.Extraction$.extract(Extraction.scala:392)
[info]  at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:514)

Telegram4s v3.0.9

bot4s.telegram 4.0.0-RC1 is out!

The project went through a major refactor, some changes/additions :

  • Repo moved to bot4s organization
  • Got a community-friendly domain: bot4s.com
  • Scala.js support via sttp, run your bots on the browser!
  • Library comes in two artifacts: core + akka
  • Several backends: akka-http, scalaj-http and sttp (incomplete implementations for hammock and RosHttp due to limitations)
  • Ported all JSON serialization from json4s to circe (transparent for users)
  • Support for API v4.0
  • Use mill instead of SBT
  • Support for proxies (using ScalajHttpClient).

To try the latest version add to your build.sbt:

resolvers += Resolver.sonatypeRepo("staging")

libraryDependencies ++= Seq(
  "com.bot4s" %% "telegram-core" % "4.0.0-RC1",
  "com.bot4s" %% "telegram-akka" % "4.0.0-RC1"
)

whenAsync and whenOrElseAsync

I have been searching for a way to implement filters in a non-blocking way. I have read a few parts of the source codes but could not implement that.
For Instance, code authenticates user against db

def isChatAuthenticated(msg: Message): Future[Boolean] = 
  db.users.find(msg.chat.id).map(_.isDefined)

when(onCommand("post") isChatAuthenticated) {....}

but currently, when is implement as

 def when[T](actionInstaller: Action[Action[T]], filter: Filter[T])(action: Action[T]): Unit = {
      val newAction = {
        t: T =>
          if (filter(t))
            action(t)
      }
      actionInstaller(newAction)
  }

where if is blocking

AnswerCallbackQuery URL_INVALID

here is the code

object PokerTelegramBot extends TelegramBot with Polling with Messages {
  lazy val token = "SOME_TOKEN"

  override def receiveMessage(msg: Message) = {
    msg.text.foreach {
      case "/start" ⇒
        println("start handled")
        val inlineBtns = InlineKeyboardMarkup(Seq(Seq(InlineKeyboardButton(
          text = "Play now!",
          callbackData = Some("{ game_short_name: \"cpptest\" }")))))
        reply("To play game press button", replyMarkup = Some(inlineBtns))(msg)

      case any ⇒ println(s"unhandled message <$any>")
    }
  }

  override def receiveCallbackQuery(callbackQuery: CallbackQuery) = {
    println(s"gameShortName: ${callbackQuery.gameShortName}")
    println(s"data: ${callbackQuery.data}")
    callbackQuery.data.foreach { data ⇒
      if (data.contains("game_short_name: \"cpptest\""))
        request(AnswerCallbackQuery(callbackQuery.id, url = Some("http://google.com")))
    }
  }
}

exception happens

info.mukel.telegrambot4s.api.TelegramApiException: Bad Request: URL_INVALID
        at info.mukel.telegrambot4s.clients.AkkaClient$$anonfun$apply$3.apply(AkkaClient.scala:56)
        at info.mukel.telegrambot4s.clients.AkkaClient$$anonfun$apply$3.apply(AkkaClient.scala:51)
        at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:253)
        at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251)
        at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:36)
        at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:121)
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

How to use Methods?

Hi
Examples cover only primitive commands like: onCommand, onCallbackQuery, etc
What about Methods, how to use them?
As example i want to GetUserProfilePhotos what should i do?

Code example from readme not compiling

Code example from readme not compiling, version "info.mukel" %% "telegrambot4s" % "2.9.5".

error: not found: value onCommand
code:

object WebhookBot extends TelegramBot with Webhook with Commands {
  import info.mukel.telegrambot4s.Implicits._

  def token = "TOKEN"
  override val port = 443
  override val webhookUrl = "https://ed88ff73.ngrok.io"

  val rng = new Random(System.currentTimeMillis())
  onCommand("/coin") { implicit msg => reply(if (rng.nextBoolean()) "Head!" else "Tail!") }
  onCommand("/real") { implicit msg => reply(rng.nextDouble().toString) }
  onCommand("/die") { implicit msg => reply((rng.nextInt(6) + 1).toString) }
  onCommand("/dice") { implicit msg => reply((rng.nextInt(6) + 1) + " " + (rng.nextInt(6) + 1)) }
  onCommand("/random") { implicit msg =>
    withArgs {
      case Seq(Extractor.Int(n)) if n > 0 =>
        reply(rng.nextInt(n).toString)
      case _ =>
        reply("Invalid argumentヽ(ಠ_ಠ)ノ")
    }
  }
  onCommand("/choose") { implicit msg =>
    withArgs { args =>
      reply(if (args.isEmpty) "Empty list." else args(rng.nextInt(args.size)))
    }
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.