🤖 Lunr Chatbot Library
Bibliothèque Python pour créer des bots pour l'application LunR avec chiffrement de bout en bout (E2E).
📋 Table des matières
🚀 Installation
pip install lunr_chatbot
Dépendances
- Python >= 3.9
- aiohttp >= 3.9.0
- websockets >= 12.0
- cryptography >= 41.0.0
⚡ Démarrage rapide
1. Créer un bot depuis l'application LunR
Pour créer un bot, rendez-vous dans l'application LunR :
- Allez dans votre page Profil
- Cliquez sur "Gérer mes bots"
- Créez un nouveau bot en remplissant les informations :
- Nom du bot
- Description
- Capacités (optionnel)
- Une fois créé, vous obtiendrez :
bot_token: Token JWT pour authentifier le bot (copiez-le depuis l'appli)api_key: Clé API unique (gardez-la secrète!)
⚠️ Important : Conservez précieusement ces tokens, ils ne seront plus affichés après la création.
2. Créer un bot simple
from lunr_chatbot import LunRBotClient
# Configurer le bot avec le token copié depuis l'application
bot = LunRBotClient(
api_url="http://localhost:8000",
bot_token="YOUR_BOT_TOKEN_HERE" # Token copié depuis LunR
)
# Handler pour les messages
@bot.on_message
async def handle_message(message):
if message.content == "/hello":
await bot.send_message(
message.group_id,
"Hello! 👋 Je suis un bot LunR!"
)
# Lancer le bot
bot.run("GROUP_ID_HERE")
3. Ajouter le bot à un groupe
Depuis l'application LunR ou via l'API (en tant qu'admin du groupe):
curl -X POST http://localhost:8000/api/groups/{GROUP_ID}/add-bot/ \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"bot_id": BOT_PROFILE_ID}'
🎯 Création d'un bot
Fonctionnalités principales
1. Recevoir des messages
@bot.on_message
async def handle_message(message):
print(f"Message de {message.sender.display_name}: {message.content}")
# Le contenu est automatiquement déchiffré
if message.content.startswith("/"):
# Traiter les commandes
await handle_command(message)
2. Envoyer des messages
# Message simple
await bot.send_message(group_id, "Bonjour le monde!")
# Avec indicateur "en train d'écrire"
await bot.send_typing(True)
await asyncio.sleep(1)
await bot.send_typing(False)
await bot.send_message(group_id, "Message après réflexion...")
3. Réactions
@bot.on_reaction
async def handle_reaction(reaction_data):
emoji = reaction_data['reaction']
message_id = reaction_data['message_id']
user = reaction_data['user']
print(f"{user['username']} a réagi avec {emoji}")
# Ajouter une réaction
await bot.add_reaction(message_id, "👍")
4. Indicateurs de frappe
@bot.on_typing
async def handle_typing(typing_data):
if typing_data['type'] == 'user_typing':
user = typing_data['user']
print(f"{user['username']} est en train d'écrire...")
Structure d'un bot complet
import logging
from lunr_chatbot import LunRBotClient
# Configuration du logging
logging.basicConfig(level=logging.INFO)
# Configuration
API_URL = "http://localhost:8000"
BOT_TOKEN = "your_token"
GROUP_ID = "group_uuid"
# Créer le bot
bot = LunRBotClient(api_url=API_URL, bot_token=BOT_TOKEN)
@bot.on_message
async def handle_message(message):
"""Handler principal pour les messages"""
# Ignorer les messages de bots (éviter les boucles)
if message.sender.is_bot:
return
content = message.content.lower().strip()
if content == "/help":
await bot.send_message(message.group_id, "Aide du bot...")
elif content.startswith("/"):
await bot.send_message(
message.group_id,
f"Commande inconnue: {content}"
)
if __name__ == "__main__":
bot.run(GROUP_ID)
📚 Exemples
Echo Bot
Bot simple qui répète les messages:
python examples/echo_bot.py
Weather Bot
Bot qui donne la météo (données fictives):
python examples/weather_bot.py
AI Assistant Bot
Bot assistant avec calculs et base de connaissances:
python examples/ai_assistant_bot.py
📖 Référence API
LunRBotClient
Méthodes
__init__(api_url, bot_token, auto_decrypt=True)
Initialise le client bot.
Paramètres:
api_url(str): URL de l'API (ex: "http://localhost:8000")bot_token(str): Token JWT du botauto_decrypt(bool): Déchiffrer automatiquement les messages entrants
async initialize()
Initialise le bot (authentification, clés de chiffrement).
async join_group(group_id)
Rejoint un groupe et établit la connexion WebSocket.
Paramètres:
group_id(str): UUID du groupe
async send_message(group_id, content, message_type='text')
Envoie un message chiffré dans un groupe.
Paramètres:
group_id(str): UUID du groupecontent(str): Contenu du message (sera chiffré automatiquement)message_type(str): Type de message ('text', 'image', 'file', 'voice')
async send_typing(is_typing=True)
Envoie un indicateur "en train d'écrire".
async add_reaction(message_id, reaction)
Ajoute une réaction emoji à un message.
Paramètres:
message_id(str): UUID du messagereaction(str): Emoji (ex: '👍', '❤️')
run(group_id)
Lance le bot de manière synchrone (bloquante).
async run_async(group_id)
Lance le bot de manière asynchrone.
Décorateurs
@bot.on_message
Enregistre un handler pour les messages entrants.
@bot.on_message
async def handle(message):
# message.content - Contenu déchiffré
# message.sender - Objet User
# message.group_id - ID du groupe
pass
@bot.on_reaction
Enregistre un handler pour les réactions.
@bot.on_reaction
async def handle(reaction_data):
# reaction_data['reaction'] - Emoji
# reaction_data['message_id'] - ID du message
# reaction_data['user'] - Utilisateur
pass
@bot.on_typing
Enregistre un handler pour les indicateurs de frappe.
Modèles de données
Message
@dataclass
class Message:
id: str # UUID du message
content: str # Contenu déchiffré
content_encrypted: str # Contenu chiffré (brut)
sender: User # Expéditeur
group_id: str # ID du groupe
message_type: str # 'text', 'image', 'file', 'voice', 'poll'
created_at: datetime # Date de création
is_edited: bool # Message modifié?
reply_to: Optional[Message] # Message auquel on répond
reactions: Dict[str, List[User]] # Réactions
User
@dataclass
class User:
id: int
username: str
email: str
first_name: Optional[str]
last_name: Optional[str]
avatar: Optional[str]
is_online: bool
is_bot: bool
@property
def display_name(self) -> str:
# Retourne le nom d'affichage
Group
@dataclass
class Group:
id: str
name: Optional[str]
group_type: str # 'private' ou 'group'
members: List[User]
description: Optional[str]
avatar: Optional[str]
@property
def is_private(self) -> bool:
# True si discussion privée
🔒 Sécurité
Chiffrement E2E
Tous les messages sont automatiquement chiffrés de bout en bout:
- Génération de clés RSA: Le bot génère une paire de clés RSA 2048 bits
- Échange de clés: La clé publique est partagée avec le serveur
- Clés de groupe: Chaque groupe a une clé AES-256-GCM unique
- Chiffrement des messages: Les messages sont chiffrés avec AES-256-GCM
- Déchiffrement automatique: La bibliothèque déchiffre automatiquement les messages entrants
Bonnes pratiques
✅ À faire:
- Garder le
bot_tokenetapi_keysecrets - Utiliser HTTPS en production (
wss://pour WebSocket) - Limiter les permissions des bots
- Valider toutes les entrées utilisateur
- Implémenter un rate limiting personnalisé si nécessaire
❌ À ne pas faire:
- Commiter les tokens dans Git
- Partager les clés API publiquement
- Ignorer les erreurs de chiffrement
- Faire confiance aveuglément aux entrées utilisateur
Variables d'environnement
Utilisez des variables d'environnement pour les secrets:
import os
API_URL = os.getenv("ONDES_API_URL", "http://localhost:8000")
BOT_TOKEN = os.getenv("ONDES_BOT_TOKEN")
GROUP_ID = os.getenv("ONDES_GROUP_ID")
if not BOT_TOKEN:
raise ValueError("ONDES_BOT_TOKEN est requis")
🐛 Débogage
Activer les logs détaillés
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
Problèmes courants
Erreur d'authentification
AuthenticationError: Token invalide ou expiré
Solution: Vérifiez que le token est correct et qu'il n'a pas expiré.
Erreur de chiffrement
EncryptionError: Clé de groupe non disponible
Solution: Assurez-vous que le bot est membre du groupe et a reçu la clé de chiffrement.
WebSocket déconnecté
WebSocketError: WebSocket non connecté
Solution: Appelez await bot.join_group(group_id) avant d'envoyer des messages.
🤝 Contribution
Les contributions sont les bienvenues!
- Forkez le projet
- Créez une branche feature (
git checkout -b feature/amazing-feature) - Committez vos changements (
git commit -m 'Add amazing feature') - Pushez vers la branche (
git push origin feature/amazing-feature) - Ouvrez une Pull Request
📄 Licence
MIT License - Voir le fichier LICENSE pour plus de détails.
📞 Support
- 📧 Email: support@ondeschat.com
- 🐛 Issues: https://github.com/MartinBellot/ondes_chat/issues
- 📚 Documentation: https://docs.ondeschat.com
🎉 Remerciements
Merci à tous les contributeurs qui ont participé à ce projet!
Fait avec ❤️ par l'équipe de Ondes
Metadata
Release files for lunr-chatbot 1.0.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| lunr_chatbot-1.0.5.tar.gz | 17.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lunr_chatbot-1.0.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 33.3 kB
Release files / lunr_chatbot-1.0.5.tar.gz
| Download URL | lunr_chatbot-1.0.5.tar.gz |
|---|---|
| Size | 17.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
016670988af635921e3eb794d3aa891ba8b32cd9a892945cef95889c3235460d
|
|
BLAKE2b-256 checksum How to use checksums |
3db57ff00d6e151ca81e3c8b510457fa45bea2e3153d4ff3463226b40874c11f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / lunr_chatbot-1.0.5-py3-none-any.whl
| Download URL | lunr_chatbot-1.0.5-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
af2a06cfa213aac38300b20f2be5a658094bda6e6c41767b7054320fb2d922c1
|
|
BLAKE2b-256 checksum How to use checksums |
5e3380ec88a29a597d45c002d5c69a9d4b775b80fc5ec8a0a66e2df2f3a6d98c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Security for lunr-chatbot 1.0.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.