Page:
Développement-Plugins
No results
2
Développement-Plugins
Claude edited this page 2026-05-16 12:33:42 +02:00
Table of Contents
- Développement de Plugins
- Structure d'un plugin
- Manifest — plugin.json
- Point d'entrée — main.py
- API disponible — ctx
- Requêtes HTTP
- Stockage clé/valeur (Redis, isolé par plugin)
- Storage provider (hébergement de fichiers)
- Hooks disponibles
- Permissions disponibles
- Imports Python autorisés dans le sandbox
- Exemple complet — Plugin Imgur
- Installation
- Désactiver le stockage local (admin)
Développement de Plugins
NoxIRC supporte un système de plugins backend permettant d'étendre les fonctionnalités via des scripts Python exécutés dans un sandbox sécurisé.
Structure d'un plugin
Un plugin est un fichier ZIP contenant au minimum :
mon-plugin.zip
├── plugin.json # Manifest obligatoire
└── main.py # Point d'entrée (configurable)
Manifest — plugin.json
{
"id": "mon-plugin",
"name": "Mon Plugin",
"version": "1.0.0",
"author": "Auteur",
"description": "Description courte du plugin",
"type": ["backend"],
"hooks": ["on_message_received"],
"permissions": [],
"entry_point": "main.py",
"min_noxirc_version": "1.0.0"
}
Champs du manifest
| Champ | Type | Description |
|---|---|---|
id |
string | Identifiant unique (slug, ex: imgur-uploader) |
name |
string | Nom affiché dans l'interface |
version |
string | Version semver |
hooks |
array | Hooks que le plugin utilise |
permissions |
array | Permissions requises |
entry_point |
string | Fichier Python principal (défaut: main.py) |
Point d'entrée — main.py
Le plugin doit exposer une fonction register(ctx, hooks) :
def register(ctx, hooks):
hooks.subscribe("on_message_received", on_message)
def on_message(payload):
target = payload.get("target")
message = payload.get("message")
nick = payload.get("by")
# Traitement...
API disponible — ctx
Requêtes HTTP
Permission requise :
network.outbound:<domaine>
# GET
response = ctx.http_get("https://api.example.com/data")
# {"status": 200, "body": "..."}
# POST
response = ctx.http_post("https://api.example.com/endpoint", {"key": "value"})
Stockage clé/valeur (Redis, isolé par plugin)
# Lire
api_key = ctx.store_get("api_key")
# Écrire
ctx.store_set("last_run", "2026-01-01")
Storage provider (hébergement de fichiers)
Permission requise :
storage.register
def register(ctx, hooks):
def upload(file_bytes, filename, content_type, user_id):
# file_bytes : bytes — contenu brut du fichier
# filename : str — nom original
# content_type : str — type MIME
# Retourne : {"url": str, "provider_path": str}
import json
response = ctx.http_post("https://api.monhost.com/upload", {
"filename": filename,
})
body = json.loads(response["body"])
return {"url": body["link"], "provider_path": body["id"]}
def delete(provider_path):
ctx.http_post("https://api.monhost.com/delete", {"id": provider_path})
return True
ctx.storage.register(
name="monhost",
label="Mon hébergeur",
upload_fn=upload,
delete_fn=delete, # optionnel
)
Hooks disponibles
| Hook | Payload | Description |
|---|---|---|
on_message_received |
{target, by, message, is_private, is_highlight, network_id, user_id} |
Message IRC reçu |
on_highlight |
{target, by, message, is_private, network_id, user_id} |
Mention de l'utilisateur |
on_file_upload |
{file_id, filename, content_type, size, user_id} |
Fichier uploadé |
on_connect |
{network_id} |
Connexion à un réseau IRC |
on_disconnect |
{network_id} |
Déconnexion |
Permissions disponibles
| Permission | Accès accordé |
|---|---|
network.outbound:<domaine> |
Requêtes HTTP vers le domaine spécifié |
storage.register |
Enregistrement d'un provider de stockage |
irc.send |
Émission d'événements IRC |
"permissions": ["network.outbound:api.imgur.com", "storage.register"]
Imports Python autorisés dans le sandbox
json, re, math, datetime
Exemple complet — Plugin Imgur
plugin.json :
{
"id": "imgur-uploader",
"name": "Imgur Uploader",
"version": "1.0.0",
"author": "Vous",
"description": "Upload les fichiers sur Imgur",
"type": ["backend"],
"hooks": [],
"permissions": ["network.outbound:api.imgur.com", "storage.register"],
"entry_point": "main.py"
}
main.py :
import json
def register(ctx, hooks):
def upload(file_bytes, filename, content_type, user_id):
client_id = ctx.store_get("imgur_client_id") or "VOTRE_CLIENT_ID"
response = ctx.http_post("https://api.imgur.com/3/image", {
"image": list(file_bytes),
"type": "file",
})
body = json.loads(response["body"])
if not body.get("success"):
raise Exception("Imgur upload failed: " + str(body))
return {
"url": body["data"]["link"],
"provider_path": body["data"]["id"],
}
def delete(provider_path):
ctx.http_post("https://api.imgur.com/3/image/" + provider_path + "/delete", {})
return True
ctx.storage.register("imgur", "Imgur", upload_fn=upload, delete_fn=delete)
Installation
Via le panel d'administration : Administration → Plugins → Installer
Via l'API :
curl -X POST /api/plugins/install \
-H "Authorization: Bearer <token>" \
-d '{"plugin_id": "imgur-uploader", "version": "1.0.0", "source_url": "https://..."}'
Désactiver le stockage local (admin)
Pour forcer l'utilisation d'un provider plugin :
curl -X PUT /api/admin/settings \
-H "Authorization: Bearer <token>" \
-d '{"key": "local_storage_enabled", "value": "false"}'