Telegram Bot Interface

The shc.interfaces.telegram provides an SHC Interface which allows interacting with SHC connectable objects via the Telegram messenger in form of a chat bot. Each instance of the TelegramBot interface represents one Telegram bot. It can be used to send messages (send_message()) to specific Telegram users (e.g. from SHC logic handlers) or create named connector objects, allowing authorized users to read and update the values of connected SHC objects.

Bot Setup

For creating a Bot interface, first register a Telegram bot, using the “BotFather”, as described in Telegram’s documentation. In the process, you will receive an API token for the Telegram Bot API, something like 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw.

In your SHC project, create a Telegram Bot instance and a Telegram authentication/authorization provider. Currently, SHC only includes the SimpleTelegramAuth authentication provider, which uses a fixed dict of usernames with Telegram user/chat ids to authenticate users. (You can subclass the TelegramAuthProvider class to integrate a custom authentication source.)

from shc.interface.telegram import SimpleTelegramAuth, TelegramBot

telegram_auth = SimpleTelegramAuth({
    'alice': 12345678,     # replace with custom username and your Telegram user id
})
telegram_bot = TelegramBot("110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw", telegram_auth)  # insert your API token

If you don’t know your Telegram user id yet, leave the SimpleTelegramAuth’s user dict empty. When starting a chat with the bot (see next paragraph), it will tell you your user id.

Afterwards, each user must start a chat with the bot manually. Otherwise, Telegram will prevent the bot from sending messages to the user. Simply open a chat with the bot and send a text message /start. If you’re not authorized yet, the bot will tell you so and also tell you your Telegram user id, which can be added to the Telegram authentication provider of your SHC project.

Connector interaction

To create connectable Connector objects, use one of the following methods:

Each of them takes a name for the connector, along with sets of users for authorization and (partially) Users are able to search for and select connectors by their name to read and write the value of a connected object:

Screenshot of the Telegram App on Android while chatting with an SHC bot. It shows the /start command with the bot's response and the search for connectors matching the search term "Foo". The bot responded with "Please chose" and a custom keyboard, allowing to select "/s Foo" and "/s Foobar". Screenshot of the Telegram App on Android while chatting with an SHC bot. It shows the same chat history as the previous image, but now the "Foobar" connector has been selected. Thus, it's current value is shown ("Foobar is currently off.") and its possible to change it ("Switch?") with a custom keyboard with the buttons "on", "off" and "/cancel". Screenshot of the Telegram App on Android while chatting with an SHC bot. It shows the same chat history as the previous image, but now the "Foobar" connector has been set to True by responding with "on". The Bot responded with an "OK" emoji.

When sending some word to the bot, it will present all matching (and authorized) connector objects to select from. After selecting a connected (from the list or manually with the /s command), the current value (if any) is shown and its possible to send a new value; supported by a list of predefined options (depending on the connector type and configuration). With the /cancel command (and inline “Cancel” buttons), it’s possible to de-select the selected connector to do a new search.

Module docs

class shc.interfaces.telegram.TelegramBot(api_token: str, auth_provider: TelegramAuthProvider[UserT, RoleT], telegram_server: TelegramAPIServer = TelegramAPIServer(base='https://api.telegram.org/bot{token}/{method}', file='https://api.telegram.org/file/bot{token}/{path}'))

The Telegram Bot interface.

An instance of this class represents a single Telegram chat bot.

Parameters:
  • api_token – The API token for connecting to the Telegram Bot API. It can be retrieved from Telegram’s “BotFather” after registering the bot.

  • auth_provider

    An authentication provider to authenticate users by their Telegram user id, check authorization and find the chat id of a given user to send them a message.

    When creating connector objects, user role objects that are compatible with the the auth_provider must be used for authorization. For the SimpleTelegramAuth user roles are simple str objects representing the authorized users’ names, but other TelegramAuthProvider implemantations may use more sophisticated user/group role objects.

  • telegram_server – The Telegram Bot API server to connect to. Usually, Telegram’s official servers should be used (the default value). However, you may also run a local HTTP API, communicating with Telegram’s network (see https://core.telegram.org/bots/api#using-a-local-bot-api-server). We also use this option for testing purposes.

generic_connector(type_: Type[T], name: str, to_message: Callable[[T], str], parse_value: Callable[[str], T], read_roles: Set[RoleT], set_roles: Optional[Set[RoleT]] = None, send_users: Set[UserT] = {}, options: Optional[List[str]] = None) TelegramConnector[T, RoleT]

Create a new connector object with any type, using the given formatting and parsing callback functions

Parameters:
  • type – The value type of this connector. Will be used as the .type attribute, used for SHC’s static type checking

  • name – The connector’s name, which users will use for searching and selecting the connector to read and write its value.

  • to_message – A formatting function, used for converting a value into a string, when read by the user or sent to the user by subscription

  • parse_value – A function for parsing values sent by the user for publishing in SHC

  • read_roles – A set of user roles which are allowed to read the current value from the connector. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • set_roles – A set of user roles which are allowed to send value updates via Telegram to the connector, i.e. to change the value of connected objects. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • send_users – A set of users which shall receive a Telegram message for every value update published to the connector within SHC. The role objects must be valid user objects of the auth_provider of this bot interface.

  • options – A list of values the user can select from for sending a new value. They are used to create a custom keyboard, which is shows to the user when selecting this connector. The options must be strings, which are supported to be parsed by the parse_value function. If this parameter is omitted, no custom keyboard is shown, i.e. the user is expected to use the normal text keyboard.

str_connector(name: str, read_roles: Set[RoleT], set_roles: Optional[Set[RoleT]] = None, send_users: Set[UserT] = {}) TelegramConnector[str, RoleT]

Create a new connector object with string type values

Parameters:
  • name – The connector’s name, which users will use for searching and selecting the connector to read and write its value.

  • read_roles – A set of user roles which are allowed to read the current value from the connector. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • set_roles – A set of user roles which are allowed to send value updates via Telegram to the connector, i.e. to change the value of connected objects. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • send_users – A set of users which shall receive a Telegram message for every value update published to the connector within SHC. The role objects must be valid user objects of the auth_provider of this bot interface.

on_off_connector(name: str, read_roles: Set[RoleT], set_roles: Optional[Set[RoleT]] = None, send_users: Set[UserT] = {}) TelegramConnector[bool, RoleT]

Create a new connector object with bool values, represented to the user as ‘on’ and ‘off’

Parameters:
  • name – The connector’s name, which users will use for searching and selecting the connector to read and write its value.

  • read_roles – A set of user roles which are allowed to read the current value from the connector. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • set_roles – A set of user roles which are allowed to send value updates via Telegram to the connector, i.e. to change the value of connected objects. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • send_users – A set of users which shall receive a Telegram message for every value update published to the connector within SHC. The role objects must be valid user objects of the auth_provider of this bot interface.

trigger_connector(name: str, read_roles: Set[RoleT], set_roles: Optional[Set[RoleT]] = None, send_users: Set[UserT] = {}) TelegramConnector[None, RoleT]

Create a new connector object None-type values

This connector type is primarily meant to trigger handler functions. When a user with set authorization selects such a connector, they will be asked “Trigger?” and presented with a custom keyboard with a “do” and a “/cancel” button. Sending “do” will make the connector publish a None value (which is valid for triggering handlers via .trigger()).

The connector can also be used to send info messages to users: When .write() is called, it will send a message “{name} has been triggered” to all users in the send_users set. However, the connector does not support reading values.

Parameters:
  • name – The connector’s name, which users will use for searching and selecting the connector to read and write its value.

  • read_roles – A set of user roles which are allowed to read the current value from the connector. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • set_roles – A set of user roles which are allowed to send value updates via Telegram to the connector, i.e. to change the value of connected objects. The role objects must be valid authorization roles of the auth_provider of this bot interface.

  • send_users – A set of users which shall receive a Telegram message for every value update published to the connector within SHC. The role objects must be valid user objects of the auth_provider of this bot interface.

class shc.interfaces.telegram.TelegramAuthProvider

Abstract base class for authentication & authorization providers for the SHC TelegramBot interface

A TelegramAuthProvider allows to authenticate Telegram users by their chat id and check their authorization for specific functions of the TelegramBot interface based on a custom ‘Role’ type. The AuthProvider’s Role type is used to define the set of authorized roles for each individual function of the TelegramBot interface. The set of roles is treated as a black box by the bot and only passed to the AuthProvider to check authorization.

When a user interacts with the bot, the bot authenticates them by their chat id using get_telegram_user(). If the method returns None, the user is rejected. Otherwise, the authenticated user is returned, represented as an (arbitrary) unique user id string. For each interaction with a Bot functionality, the AuthProvider’s has_user_role() method is used to check if the specific user (user id string) is allowed to use the functionality based on the given set of role objects.

Provided implementations by SHC:

class shc.interfaces.telegram.SimpleTelegramAuth(users: Dict[str, int])

A simple implementation of a TelegramAuthProvider.

It uses a fixed dict for mapping user id strings and telegram chat ids and uses the user id strings themselves as role definitions. Thus, it does not have a concept of user groups; you always need to specify the set of all authorized user ids for each TelegramBot connector. (Of course, you can put the set in a variable to reuse it.)

Parameters:

users – Dict of users in the form {user_id: telegram_chat_id}