Telegram¶
A connector for Telegram.
⚠️ Breaking Changes introduced in opsdroid 0.20.0¶
We have moved this connector from calling the API to get updates, to subscribe to webhook events. This means that if you are running this connector in older versions, the connector will receiving updates from Telegram.
Migration requirements¶
expose opsdroid to the web through a secure connection (https) - you can use ngrok to forward your traffic through a secure url.
Include the following in your opsdroid configuration
web:
base-url: <secure url/ngrok url>
If you need any help migrating, please asks on our matrix channel.
Requirements¶
A Telegram account - to create a bot
A Bot API Token
A secure URL where opsdroid is running (could be forwarded by ngrok)
Note: To register a new bot, open Telegram, write @BotFather and type /newbot
.
Provide a name and username (ending in bot) and BotFather will give you your API Token.
Configuration¶
web:
base-url: <https://your-opsdroid-url-or-ngrok-url>
connectors:
telegram:
# required
token: "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ-ZYXWVUT" # Telegram bot token
# optional
bot-name: opsdroid # Name to be used by the bot in some replies, defaults to opsdroid
reply-unauthorized: True # Should the bot reply to unauthorized users?
whitelisted-users: # List of users who can speak to the bot, if not set anyone can speak
- user1
- user2
Note: You MUST specify the base-url
in the web
config, otherwise opsdroid won’t be able to receive webhook notifications.
Usage¶
You can add this connector to:
Direct Messages
Groups
Channels
If you want opsdroid to work on your group or channel, you should add it by opening your channel/group details and select the Add Members button, then search for your bot username and add it. It’s a good idea to add the bot as admin, because in some cases where you have privacy active, opsdroid won’t be able to read user’s names.
Direct Messages¶
To interact with your bot directly, start a new message, click search and type your bot name. For example, if you named your bot: MyAwesome_Bot
you can just search for that name and wait for the result to show up, then click on the name of your bot and a new chat window will start. You can now talk with your bot and give him commands.
[6:13:11 PM] Fabio:
hello
Unread messages
[6:13:12 PM] opsdroid:
Hi FabioRosado
If you are using a list of users that can interact with the bot by using the configuration parameter whitelisted-users
, you might want to set the parameter reply-unauthorized
to True
to make opsdroid reply to an unauthorized user, that the user can’t interact with the bot.
Groups¶
Opsdroid will listen to every message sent to a group, so it’s a good idea to set a list of users that can interact with the bot if you are using opsdroid skills that some users shouldn’t be able to trigger.
To set up a list of users that can interact with the bot, you can set the option configuration parameter whitelisted-users
- you should try to use the user id
obtained from Telegram response. Also, if you set up the configuration parameter reply-unauthorized
you might want to set it to false
so the bot doesn’t send a message every time someone says something to the group.
Channels¶
By default Telegram doesn’t show the name of the user that sends messages to a channel, if you want to change this behaviour, you can open your channel, click the channel name to open the settings, chose edit and toggle the option Sign Messages
.
Note: If you have a discussion group, opsdroid will reply to any command sent to a channel in that group.
Whitelisting users¶
This is an optional config option that you can include on your config.yaml
to prevent unauthorized users to interact with your bot.
Currently, you can specify a user nickname
or a userID
. Using the userID
method is preferable as it will increase the security of the connector since users can’t change this ID.
Here is how you can whitelist a user:
telegram:
token: <your bot token>
whitelisted-users:
- user1
- 124324234 # this is a userID
Finding your userID
is not straight forward. This value is sent by Telegram when a user sends a private message to someone (the bot in this case) or when someone calls the getUpdate
from the API.
To find a userID
by a private message, set the logging
level to debug
and start a new private message to the bot. You will see the API response on your console - it will look similar to this:
{
"update_id": 539026743,
"message": {
"message_id": 109,
"from": {
"id": 4532189818,
"is_bot": false,
"first_name": "user",
"language_code": "en"
},
"chat": {}
}
}
Use the id
value from the message["from"]
field and add it to your whitelisted-users
config option.
Parsing images/videos/files¶
Unfortunately, we are unable to parse any of these formats, the reason for that is because Telegram doesn’t send us any real useful information that we can feed to opsdroid. When you send an image to a channel, Telegram sends us a file id, format and sizes, but no URL or anything that we could use to download the image.
Events Available¶
The Telegram Connector contains a few events that you can access on your skills. These events were created to allow you to use these messages types on your custom made skills.
- class opsdroid.connector.telegram.events.Poll(poll, question, options, total_votes, *args, **kwargs)¶
Event class that triggers when a poll is sent.
- class opsdroid.connector.telegram.events.Contact(contact, phone_number, first_name, *args, **kwargs)¶
Event class that triggers when a contact is sent.
- class opsdroid.connector.telegram.events.Location(location, latitude, longitude, *args, **kwargs)¶
Event class that triggers when a location message is sent.
- class opsdroid.events.JoinGroup(user_id=None, user=None, target=None, connector=None, raw_event=None, raw_parses=None, event_id=None, linked_event=None)¶
Event to represent joining a group (not a room).
The group could be a slack team or a matrix community.
- class opsdroid.events.LeaveGroup(user_id=None, user=None, target=None, connector=None, raw_event=None, raw_parses=None, event_id=None, linked_event=None)¶
Even to represent leaving a group(not a room).
The group could be a slack team, matrix community or a telegram group.
- class opsdroid.events.PinMessage(user_id=None, user=None, target=None, connector=None, raw_event=None, raw_parses=None, event_id=None, linked_event=None)¶
Event to represent pinning a message or other event.
- class opsdroid.events.Reply(text, *args, **kwargs)¶
Event class representing a message sent in reply to another Message.
The
linked_event
property should hold either anopsdroid.events.Event
class or an id for an event to which this message is replying.
- class opsdroid.events.EditedMessage(*args, **kwargs)¶
A
opsdroid.events.Message
which has been edited.The
linked_event
property should hold either anopsdroid.events.Event
class or an id for an event to which the edit applies. The linked_event for Slack is the ts (timestamp) of the message to be edited
Reference¶
- class opsdroid.connector.telegram.ConnectorTelegram(*args, **kwargs)¶
A connector for the chat service Telegram.
- build_url(method)¶
Build the url to connect to the API.
- Parameters
method (string) – API call end point.
- Returns
String that represents the full API url.
- async connect()¶
Create route and subscribe to Telegram webhooks.
The first thing we do on connect is to set up the route to receive events from Telegram, we also pass some arguments to the webhook to get events from messages, edited messages, channel posts and update id which is basically the event id.
One thing that is worth mentioning here, is that Telegram doesn’t implement a request authenticity policy, instead they suggest that we use our token on the webhook route, but using the token on the url doesn’t seem like a good idea, we are instead generating a strong pseudo-random string using the
secrets
library and add that string to our webhook route.
- async disconnect()¶
Delete active webhook.
If we terminate opsdroid, we should delete the active webhook, otherwise Telegram will keep pinging out webhook for a few minutes before giving up.
- static get_user(response, bot_name)¶
Get user from response.
The API response is different depending on how the bot is set up and where the message is coming from.
Since Telegram sends different payloads, depending of where the message is being sent from, this method tries to handle all the cases.
If the message came from a channel, we use either the
author_signature
or the bot name for the user and use themessage_id
for theuser_id
, this is because channel posts don’t contain users.Similarly, if a message was posted on a channel, Telegram will forward it to a group - if it was created from the channel. So we handle the case where there is a
forward_signature
in the payload otherwise we use the bot name.- Parameters
response (dict) – Response returned by aiohttp.ClientSession.
bot_name (str) – Name of the bot used in opsdroid configuration.
- Returns
Extracted username and user id
- Return type
string, string
- async handle_messages(message, user, user_id, update_id)¶
Handle text messages received from Telegram.
Here we create our opsdroid events depending of the type of message that we get from Telegram.
Unfortunately, telegram doesn’t give much information when the message is an image, video, sticker or documents. It only give us back the file id, sizes, formats and that’s it. Since we can’t really use any of this information to make opsdroid parse the message, we decided to just log a message in debug mode with the payload and return None.
- Parameters
message (dict) – The payload received from Telegram
user (string) – The name of the user that sent the message
user_id (int) – The unique user id from the user that send the message
update_id (int) – The unique id for the event sent by Telegram
- Returns
Will only return none if it’s an event we can’t parse.
- Return type
opsdroid.event or None
- handle_user_permission(response, user, user_id)¶
Handle user permissions.
This will check if the user that tried to talk with the bot is allowed to do so. It will also work with userid to improve security.
- async listen()¶
Listen method of the connector.
Since we are using webhooks, we don’t need to implement the listen method.
- async send_file(file_event)¶
Send File to Telegram.
Gets the chat id from the channel and then sends the bytes of the file as multipart/form-data.
- async send_image(file_event)¶
Send Image to Telegram.
Gets the chat id from the channel and then sends the bytes of the image as multipart/form-data.
- async send_message(message)¶
Respond with a message.
- Parameters
message (object) – An instance of Message.
- async telegram_webhook_handler(request)¶
Handle event from Telegram webhooks.
This method will try to handle three different kinds of events:
Edited messages
Messages
Channel posts
Since the payload is pretty much the same both for channel posts and messages we are using the same method to handle both of these events.
We also check the permissions of the user that talked with the bot, if the user has permissions then the event is parsed, if not we either send a message saying that the user can’t talk with the bot or just keep silent.
- Parameters
request (aiohttp.web.Request) – Request made to the post route created for webhook subscription.
- Returns
Send a
received
message and a status 200 back to Telegram.- Return type