Receiving Messages¶
In this section we'll learn how a bot can handle incoming messages and attachments
Message events and the notifications loop¶
In order to receive the messages sent in the chats where the bot is a member, we need to register for some events provided by the SDK.
Additionally, we must instruct the Connection
object that we want to
start receiving notifications frome the backend, through the
start_notifications()
method
from teamwire_api import Connection, Events
def message_handler(event_type, message):
# the chat we received message from
chat = message.chat
# print the thread id of the chat
print(f'New message received in chat id: {chat.tid}')
# print the name of the user who sent the message
print(f'> From: {message.from_user.full_name()}')
if message.msg:
# print the body of the message
print(f'> Body: {message.msg}')
if message.attachments:
# print the number of attachments received
print(f'> Attachments: {len(message.attachments)}')
with Connection() as connection:
# register handler for NEW_MESSAGE events
connection.set_handler([Events.NEW_MESSAGE], message_handler)
# start the notifications listening loop
connection.start_notifications()
In the above snippet, we first register a handler for NEW_MESSAGE
events, so
when a new message is received, the same is invoked with the
message as a Message
object as an argument, which contains all the required information.
In particular, it contains a reference to the parent Chat
object, as well
as the sender User
object, the message body and attachments.
The event handler can be either a normal function or an asyncio coroutine.
Please note that when we invoke connection.start_notifications()
the SDK starts an infinite
loop, waiting for incoming notifications from the backend, so the bot will
not exit until CTRL-C is pressed.
For additional details on the structures involved in this brief example, please
check out the Message
and Chat
classes.
Handling attachments¶
As we have seen in the previous section, a received message can contain either
a text body, attachments, or both. In order to access the attachments eventually
included with the message we can use the attachments
list provided by the
Message
object.
Teamwire supports a wide range of attachments, e.g. location, calendar event, and attachments containing binary assets, like images, audio, video, etc.
In this example we'll explore how we can save a received image to disk.
from teamwire_api import Connection, Events, AttachmentType
from datetime import datetime
async def message_handler(event_type, message):
if not message.attachments:
print('received message without attachments')
return
# iterate over the attachments list
for att in message.attachments:
# if the current attachment is not an image, ignore it
if att.type != AttachmentType.GALLERY:
print(f'received attachment: {att}')
continue
# store the image attachment to disk as png file
filename = f'{datetime.now()}_{message.from_user.full_name()}.png'
print(f'received image attachment, storing to {filename}')
await att.store(filename)
with Connection() as connection:
connection.set_handler([Events.NEW_MESSAGE], message_handler)
connection.start_notifications()
In particular, each attachment has a type
property, which we can use to discriminate between them.
Attachments containing assets (i.e. subclasses of the
AssetAttachment
class)
like those containing images, videos, etc. provide a load
and
a store
coroutines to respectively extract the
content of the attachment, returning it as binary data, and to directly store
the data to a file.
Please note, that since we are now using coroutines, the message_handler
function should be a coroutine itself.