# \[ANN\] Telegram.jl - SDK, logger and bots

**URL:** <https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840>\
**Category:** Package Announcements\
**Created:** [June 22, 2020, 6:32am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840 "2020-06-22T06:32:23Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [June 22, 2020, 6:32am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/1 "2020-06-22T06:32:23Z")

</div>

Hello everyone! I am really happy to announce [Telegram.jl](https://github.com/Arkoniak/Telegram.jl), a package that contains native Julia [Telegram Messanger](https://telegram.org/) SDK, logging and bot facilities.

This package was built with the main idea of using Telegram as an instant message backend for various notification and reporting systems. So, the simplest way to use this package is by doing something like this

```julia
using Telegram, Telegram.API
tg = TelegramClient("YOUR TOKEN", chat_id = "YOUR CHAT_ID")

# Some lengthy calculations...
# ...

# After calculations complete
sendMessage(text = "Calculation completed, result is $result")

```

and you shouldn’t worry and check regularly when your script finishes its work, you will see notification on your phone!

Let me briefly describe the main features of the package.

1. One time setup for instant messaging.  
As you can see from the intro, if all you need is to send notification messages to single chat, you can set everything once at the beginning of the script

```julia
using Telegram, Telegram.API
tg = TelegramClient("YOUR TOKEN", chat_id = "YOUR CHAT_ID")

```

and all following `Telegram.jl` function calls will use these settings through all code, so the message sending looks like (of course, you can make everything explicit if needed).

```julia
sendMessage(text = "Hello world")

```

1. Sending pictures, documents, and so on.  
You can easily send `IO` objects, they will be converted to a proper format

```julia
# Send image stored as a file
sendPhoto(photo = open("picture.jpg", "r"))

# Send in-memory generated object
iob = IOBuffer()
print(iob, "Hello world!")
sendDocument(document = "hello.txt" => iob)

```

which may come handy if you generated some visual reports as a result of calculations.

1. Full cover of all Telegram bot functions.  
Well, this is just a small touch, but thanks to the combination of [Gumbo.jl](https://github.com/JuliaWeb/Gumbo.jl), [Cascadia.jl](https://github.com/Algocircle/Cascadia.jl) and [Underscores.jl](https://github.com/c42f/Underscores.jl) all Telegram bot API functions were extracted from relevant web page and transformed in Julia functions. There is a fallback method `apiquery` which accepts method as a `String`, so you can call `apiquery("getMe")`, but I find `getMe()` more convenient.  
So, if you look at [API Reference](https://arkoniak.github.io/Telegram.jl/dev/reference/#API-Reference) you would see more than 70 API methods with individual docstrings.

2. Logging system  
Another usage of Telegram API is the logging system. Thanks to the awesome [LoggingExtras.jl](https://github.com/oxinabox/LoggingExtras.jl) package, you only need to add couple of configuration lines and get telegram as an additional channel for critical messages.

```julia
using Telegram
using Logging, LoggingExtras

tg = TelegramClient(ENV["TG_TOKEN"], chat_id = ENV["TG_CHAT_ID"])
tg_logger = TelegramLogger(tg; async = false)
demux_logger = TeeLogger(
    MinLevelLogger(tg_logger, Logging.Error),
    ConsoleLogger()
)
global_logger(demux_logger)

@warn "It is bad" # goes to console
@info "normal stuff" # goes to console
@error "THE WORSE THING" # goes to console AND telegram
@debug "it is chill" # goes to console

```

So if you have already a working application with established logging, you do not need to change anything in the main code to get telegram instant messaging.

1. In addition, there is also a `run_bot` function, which makes it really easy to write Telegram bots. Here is an example of Echo bot, which just returns your message back

```julia
using Telegram, Telegram.API

TelegramClient(ENV["TG_TOKEN"])

run_bot() do msg
    sendMessage(text = msg.message.text, chat_id = msg.message.chat.id)
end

```

I’ve used this package to build a more advanced bot, which draws [turtle graphics](http://juliagraphics.github.io/Luxor.jl/stable/turtle/) with the help of [Luxor.jl](https://github.com/JuliaGraphics/Luxor.jl) package. As an input, it accepts a sequence of angles and then turtle draws an expanding spiral by turning on a defined angle each step. Code can be found in [bot documentation](https://arkoniak.github.io/Telegram.jl/dev/usage/#Turtle-graphics-bot) and it uses one of the features, all drawings are generated in memory and immediately sent to the Telegram without storing in the filesystem.

You can find this bot here: [Telegram: Contact @julia\_turtle\_experiment\_bot](https://t.me/julia_turtle_experiment_bot) and it’s still running without any issues after it was launched a few days ago.

P.S.: Development of this package was sponsored by a secret organization which prefer to remain anonymous, but you can find it’s logo by entering following coordinates in turtle bot: `30 30 179.02`

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 22, 2020, 6:50am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/2 "2020-06-22T06:50:55Z")

</div>

> [@Skoffer](#):
>
> shouldn’t worry and check regularly when your script finishes its work, you will see notification on your phone!

amazing! thanks for writing this.

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [June 22, 2020, 7:29am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/3 "2020-06-22T07:29:46Z")

</div>

This is brilliant!

Telegram has good github integration too (alerts when issues posted etc), so we’ll soon be able to let the bots do all our work for us, and they can talk to each other in geometrical.constructions… 🙂

---

<div class="post-metadata">

**Author:** ![anon67531922](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@anon67531922](https://discourse.julialang.org/u/anon67531922)\
**Post date:** [June 22, 2020, 7:32am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/4 "2020-06-22T07:32:57Z")

</div>

Very cool 👏👏👏

---

<div class="post-metadata">

**Author:** ![roble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roble/32/12303_2.png) [@roble](https://discourse.julialang.org/u/roble)\
**Post date:** [June 22, 2020, 8:51am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/5 "2020-06-22T08:51:55Z")

</div>

Wow, this is super easy to use. I am very happy to use such a nicely done package

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 22, 2020, 12:42pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/6 "2020-06-22T12:42:27Z")

</div>

Uhh really cool, that would have come really handy a couple weeks ago when I was looking for apartments and wrote an email bot. This would have been much easier and nicer!

---

<div class="post-metadata">

**Author:** ![rashid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rashid/32/9398_2.png) [@rashid](https://discourse.julialang.org/u/rashid)\
**Post date:** [July 4, 2020, 2:27pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/7 "2020-07-04T14:27:17Z")

</div>

Wow. I’ve been using similar packages in python and had been searching for something like this in Julia. Great work.

The API is mentioned everywhere in the package and the documentation as “Telegram API”, but from what I understand this package implements the “Telegram Bot API”. The [Telegram Bot API](https://core.telegram.org/bots/api) is an API specifically for bots, which is simpler but less customisable and acts as an intermediary between bots and the [Telegram API](https://core.telegram.org/api#telegram-api). The two APIs are described [here](https://core.telegram.org/api). It might be worth mentioning to avoid confusion. An example for both of these implemented in python would be, [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) for Telegram Bot API and [Telethon](https://github.com/LonamiWebs/Telethon) for Telegram API.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [July 4, 2020, 7:44pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/8 "2020-07-04T19:44:46Z")

</div>

Thank you, you are right. I’ve made necessary changes to documentation.

---

<div class="post-metadata">

**Author:** ![aurelio-amerio](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aurelio-amerio/32/10489_2.png) [@aurelio-amerio](https://discourse.julialang.org/u/aurelio-amerio)\
**Post date:** [August 25, 2020, 6:21pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/9 "2020-08-25T18:21:19Z")

</div>

Thank you very much for this awesome package, you have changed my life as an user who runs long computations ^^

---

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [April 29, 2021, 8:14pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/10 "2021-04-29T20:14:31Z")

</div>

Hello @Skoffer . For some reason, the following simple echo code stopped working:

```julia
using Telegram, Telegram.API

token = "xxx"

tg = TelegramClient(token)

foo(msg) = sendMessage(text = msg.message.text, chat_id = msg.message.chat.id)

run_bot(foo, tg)

```

It results in

```julia
Error: KeyError(:message)
└ @ Telegram ~/.julia/packages/Telegram/gsaco/src/bot.jl:34
┌ Error: UndefVarError(:ignore_errors)
└ @ Telegram ~/.julia/packages/Telegram/gsaco/src/bot.jl:43

```

Do you know what can be wrong?

Thank you.

---

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [April 29, 2021, 8:35pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/11 "2021-04-29T20:35:29Z")

</div>

Surprisingly, to make it work I have to run it the first time with an empty function:

```julia
function foo(msg)
    return nothing
end

```

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [April 30, 2021, 9:35am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/12 "2021-04-30T09:35:13Z")

</div>

`Telegram.jl` is a low-level library, so it does not make any preprocessing of input data. It means, that `msg` is a raw object which was received from Telegram and it is the developer’s responsibility to process it correctly. Tutorial is overly simplified, to keep essential things clear, but in a real world, more layers of data validation should be added of course.

In your particular case, there is no `:message` field in `msg` for some reason. There are multiple scenarios, why it has happened, maybe someone send emoji instead of text or may be there was some other special message, it’s hard to tell. You can avoid it in multiple ways, for example you can use `try/catch` block, like this

```julia
function foo(msg)
  try
    sendMessage(text = msg.message.text, chat_id = msg.message.chat.id)
  catch e
    @error e
  end
end

```

Or you can try to parse it

```julia
function msgdata(msg)
  message = get(msg, :message, nothing)
  message === nothing && return nothing, nothing
  text = get(message, :text, nothing)
  chat = get(message, :chat, nothing)
  chat === nothing && return text, nothing
  chat_id = get(chat, :id, nothing)
  return text, chat_id
end

function foo(msg)
   text, chat_id = msgdata(msg)
   if text !== nothing && chat_id !== nothing
     sendMessage(text = text, chat_id = chat_id)
   end
end

```

Regarding, your empty `foo` example, it just consumed “wrong” message and clear the message queue for proper messages.

---

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [April 30, 2021, 9:40am UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/13 "2021-04-30T09:40:04Z")

</div>

Thank you very much for the detailed explanation.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 9, 2021, 3:09pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/14 "2021-12-09T15:09:19Z")

</div>

Nice package!

I have one question. How can you send a plot **without creating a file on disk first**?

I tried this:

```julia
using GLMakie, Telegram

tg = Telegram.TelegramClient("token", chat_id = "id") # token , id hidden here for privacy

x = 0:0.01:π
plt = lines(x, sin.(x))

io = IOBuffer()
show(io, MIME"image/png"(), plt)

Telegram.API.sendPhoto(tg, photo=io)

```

But this gives me an HTTP Bad request error. The following picture is truncated to hide the token.  
Any suggestions?

![image](https://global.discourse-cdn.com/julialang/original/3X/0/9/09dd55648a4b177fe99c3726aedce3731855c633.png)

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 9, 2021, 3:18pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/15 "2021-12-09T15:18:17Z")

</div>

I found a way to send the plot as an attachment:

```julia
using GLMakie, Telegram

tg = Telegram.TelegramClient("token", chat_id = "id") # token , id hidden here for privacy

x = 0:0.01:π
plt = lines(x, sin.(x))
let io = IOBuffer()
	show(io, MIME"image/png"(), plt);
	Telegram.API.sendDocument(tg, document = ("plot.png" => io))
end

```

Though it would be nicer if I can send it as a photo, which is displayed within telegram.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [December 9, 2021, 4:31pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/16 "2021-12-09T16:31:56Z")

</div>

You can see all available methods here: [Telegram Bot API](https://core.telegram.org/bots/api#available-methods) They are in one-to-one correspondence with `Telegram.API` methods.

In particular, to send image as photo, you can use [Telegram Bot API](https://core.telegram.org/bots/api#sendphoto)

```julia
using GLMakie, Telegram

tg = Telegram.TelegramClient("token", chat_id = "id") # token , id hidden here for privacy

x = 0:0.01:π
plt = lines(x, sin.(x))
let io = IOBuffer()
	show(io, MIME"image/png"(), plt);
	Telegram.API.sendPhoto(tg, photo = ("plot.png" => io))
end

```

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [December 9, 2021, 5:28pm UTC](https://discourse.julialang.org/t/ann-telegram-jl-sdk-logger-and-bots/41840/17 "2021-12-09T17:28:52Z")

</div>

Thanks!
