đŸ‘©â€đŸ« Tutoriels#

Dans cette page, nous essayons d’expliquer comment rĂ©aliser un certain nombre d’actions avec notre librairie Python. IdĂ©alement, il vaut mieux la suivre Ă©tape par Ă©tape afin de suivre le cheminement, mais si vous vous sentez Ă  l’aise, vous pouvez essayer d’accĂ©der directement Ă  la section qui vous intĂ©resse.

Les bases#

OlvidClient#

Pour interagir avec le daemon, il vous faudra systĂ©matiquement crĂ©er une instance de la classe OlvidClient. Il peut s’agir de la classe d’origine ou d’une classe enfant.

Cette classe va automatiquement rĂ©cupĂ©rer une clĂ© client en utilisant l’environnement ou un fichier .env. (cf. Configuration)

Grùce à ce client, on pourra notamment exécuter des commandes et mettre en place des listeners de notifications.

Voici Ă  quoi ressemble un fichier main.py de base contenant la crĂ©ation d’un client Olvid et l’exĂ©cution d’une commande (afficher l’identitĂ© courante). Cette structure est Ă  utiliser dans chacun des exemples de code de cette page, il suffit de remplacer le contenu de la fonction main par le code de votre choix.

import asyncio
from olvid import OlvidClient, datatypes

async def main():
    client = OlvidClient()
    
    # code to replace
    print(await client.identity_get())

asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())

Commande#

Toutes les mĂ©thodes gRPC de commandes exposĂ©es par le daemon sont facilement accessibles grĂące Ă  des mĂ©thodes de la classe OlvidClient. Par exemple, pour envoyer un message (mĂ©thode MessageSend en gRPC), on utilisera la mĂ©thode message_send de notre instance d’OlvidClient.

Dans le cas oĂč nous connaissons l’identifiant de la discussion dans laquelle poster, cela donnerait :

from olvid import OlvidClient

client = OlvidClient()
client.message_send(discussion_id=1, body="Use Olvid !")

Notification#

La classe OlvidClient implĂ©mente Ă©galement des mĂ©thodes qui permettent de facilement Ă©couter les notifications Ă©mises par le daemon. Ces mĂ©thodes commencent toutes par le prĂ©fixe on_ et doivent ĂȘtre redĂ©finies dans une classe fille d’OlvidClient.

Par exemple, pour afficher dans le terminal quand un message est reçu et lorsqu’une rĂ©action est ajoutĂ©e, on peut faire :

import asyncio
from olvid import OlvidClient, datatypes

class Bot(OlvidClient):
    async def on_message_received(self, message: datatypes.Message):
        print(f"Message received: {message.body}")

    async def on_message_reaction_added(self, message: datatypes.Message, reaction: datatypes.MessageReaction):
        print(f"Reaction added: {reaction.reaction}")

async def main():
    bot = Bot()
    await bot.run_forever()

asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())

Conseils et astuces#

AutoInvitationBot#

Pour rendre plus facile la mise en relation avec un bot, il est possible de mettre en place un autre bot, déjà écrit, qui acceptera toutes les invitations reçues.

Il suffit de crĂ©er un bot AutoInvitationBot du module olvid.tools. Il va automatiquement s’enregistrer pour recevoir les notifications de nouvelles invitations et les accepter.

Note

Un AutoInvitationBot ne peut accepter que les présentations et les invitations de groupe. Il ne peut pas accepter automatiquement les invitations directes avec échange de SAS code.

Voici un programme qui lance une instance de l’AutoInvitationBot en tñche de fond. Il est tout à fait possible de lancer plusieurs bots en parallùle.

import asyncio
from olvid import OlvidClient, datatypes, tools

class Bot(OlvidClient):
    async def on_message_received(self, message: datatypes.Message):
        print(f"Message received: {message.body}")

async def main():
    bot = Bot()
    tools.AutoInvitationBot()
    await bot.run_forever()

asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())

Divers#

Envoyer un message éphémÚre#

Les points d’entrĂ©e API messageSend et messageSendWithAttachments permettent de spĂ©cifier l’éphĂ©mĂ©ralitĂ© du message Ă  envoyer. On utilisera pour cela l’objet olvid.datatypes.MessageEphemerality.

Voici un exemple en python. Il est possible de spĂ©cifier les paramĂštres read_once, visibility_duration et existence_duration de maniĂšre indĂ©pendante. Les durĂ©es d’existence et de visibilitĂ© sont en secondes.

import asyncio

from olvid import datatypes, OlvidClient

async def main():
    client = OlvidClient()
    async for discussion in client.discussion_list():
        await client.message_send(
            discussion_id=discussion.id,
            body="Self-destruct message",
            ephemerality=datatypes.MessageEphemerality(
                visibility_duration=10,
                existence_duration=60,
                read_once=True
            )
        )

asyncio.run(main())

Utilisation avancée#

Listener#

Pour une implĂ©mentation plus fine de l’écoute des notifications, il est possible d’utiliser la notion de Listener. Un listener est une souscription d’une fonction callback Ă  un type de notification. Cette fonction sera appelĂ©e Ă  chaque fois qu’une notification de ce type est reçue.

Chaque type de notification a sa propre classe dans le module olvid.listeners.

Dans cet exemple, la mĂ©thode reply_to_message sera appelĂ©e Ă  chaque fois qu’un message arrive.

import asyncio
from olvid import OlvidClient, datatypes, listeners

async def reply_to_message(message: datatypes.Message):
    await message.reply(f"Reply to: {message.body}")

async def main():
    client = OlvidClient()
    listener = listeners.MessageReceivedListener(handler=reply_to_message)
    client.add_listener(listener)
    await client.run_forever()

asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())

Listener: expiration#

Par dĂ©faut, un listener Ă©coute les notifications pour toujours, mais il est possible d’utiliser l’argument count pour n’écouter qu’un certain nombre de notifications. Dans ce cas, lorsque que count notifications ont Ă©tĂ© traitĂ©es, l’listener est arrĂȘtĂ©.

Dans cet exemple, on rĂ©pond au prochain message reçu puis le programme s’arrĂȘte.

import asyncio
from olvid import OlvidClient, datatypes, listeners

async def reply_to_message(message: datatypes.Message):
    await message.reply(f"Reply to: {message.body}")

async def main():
    client = OlvidClient()
    # added count parameter set to 1
    listener = listeners.MessageReceivedListener(handler=reply_to_message, count=1)
    client.add_listener(listener)
    
    # wait_for_listeners_end: returns when all listeners are finished
    await client.wait_for_listeners_end()
    
    print("Program end")

asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())

Listener : filtrage#

Les listeners permettent également de filtrer les notifications à traiter. Pour cela, on peut ajouter une ou plusieurs fonctions de filtrage à notre listener.

Par exemple, on peut vouloir traiter uniquement les messages envoyés par un contact donné.

import asyncio
from olvid import OlvidClient, datatypes, listeners

CONTACT_ID: int = 1

async def reply_to_message(message: datatypes.Message):
    await message.reply(f"Reply to: {message.body}")

def check_sender_id(message: datatypes.Message):
    return message.sender_id == CONTACT_ID
    
async def main():
    client = OlvidClient()
    # only notifications matching check_sender_id will be handled 
    listener = listeners.MessageReceivedListener(handler=reply_to_message, checkers=[check_sender_id])
    client.add_listener(listener)
    
    await client.wait_for_listeners_end()
    
asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())

Listener avancé#

Il est tout à fait possible de combiner le filtrage et l’expiration.

Ici, on l’utilise pour effectuer une action et quitter le programme quand le message que l’on vient d’envoyer arrive sur le tĂ©lĂ©phone de son destinataire.

import asyncio
from olvid import OlvidClient, datatypes, listeners

DISCUSSION_ID: int = 1

def get_message_id_checker(message_id: datatypes.MessageId):
  def checker(message: datatypes.Message):
      return message.sender_id == message_id
  return checker

async def main():
    client = OlvidClient()
    
    # send a message
    message = await client.message_send(discussion_id=DISCUSSION_ID, body="Hello there !")
    
    # add a listener to do something when message had been delivered, then program will exit 
    listener = listeners.MessageDeliveredListener(
        handler=lambda m: print("Message delivered"),
        checkers=[get_message_id_checker(message.id)],
        count=1
    )
    client.add_listener(listener)
    
    await client.wait_for_listeners_end()
    
    print("Program end")

asyncio.set_event_loop(asyncio.new_event_loop())
asyncio.get_event_loop().run_until_complete(main())