Scripts
Écrivez vos déclencheurs et vos actions en TypeScript pour donner vie à vos automatisations.
Les déclencheurs et les actions s’écrivent en TypeScript. Rawtoh exécute votre code dans un environnement sécurisé et isolé (sandbox) chaque fois qu’un événement correspondant arrive.
Toutes les API du runtime sont disponibles via import { ... } from "rawtoh". Vous pouvez aussi importer des scripts partagés pour réutiliser du code entre vos automatisations.
L’éditeur de scripts
Rawtoh intègre un éditeur de code avec autocomplétion TypeScript et coloration syntaxique. L’éditeur est divisé en trois panneaux :
- Explorateur — une arborescence de tous vos déclencheurs, actions et scripts partagés, organisés par chemin, avec vos automatisations à la racine
- Éditeur — l’éditeur de code Monaco dans lequel vous écrivez vos scripts
- Activité — les journaux d’exécution, les événements et les traces d’appels aux modules, en temps réel
Vous pouvez ouvrir plusieurs scripts dans des onglets et enregistrer avec Ctrl+S. L’éditeur propose l’autocomplétion des imports "rawtoh" et des chemins de scripts partagés. Un Ctrl+Click sur un chemin d’import vous amène au script partagé.
Lorsque l’IA est disponible pour votre organisation, appuyez sur Ctrl+I dans une action ou un déclencheur pour décrire une modification, puis examinez-la sous forme de diff avant de l’accepter.
Écrire le code d’un déclencheur
Le code d’un déclencheur est une fonction de filtrage. Il reçoit l’événement et doit utiliser export default avec une valeur évaluée à vrai (truthy) pour que l’action associée s’exécute. Le code d’un déclencheur dispose d’un délai maximal de 5 secondes.
Imports disponibles
| Import | Description |
|---|---|
event | L’objet événement (name, payload, emitter_group, emitter_name) |
trigger | L’objet déclencheur lui-même |
Seuls event et trigger sont disponibles dans les déclencheurs. log, sleep, module et storage ne sont pas disponibles — les appeler lève une erreur.
L’objet événement
import { event } from "rawtoh"
event.name // "chat.message"
event.payload // { username: "alice", message: "!hello", ... }
event.emitter_group // "twitch"
event.emitter_name // "main-bot"Exemples
// Always fire (pass-through trigger)
export default trueimport { event } from "rawtoh"
// Only fire for a specific command
export default event.payload.message === "!hello"import { event } from "rawtoh"
// Fire for subscribers only
export default event.payload.is_subscriber === trueimport { event } from "rawtoh"
// Un module ne peut pas faire `return` au niveau racine. Pour une condition
// en plusieurs étapes, mettez les vérifications dans une fonction et exportez son résultat.
function matches() {
const p = event.payload
if (!p.is_mod && !p.is_broadcaster) return false
if (!p.message.startsWith("!poll ")) return false
return p.message.includes("|")
}
export default matches()Écrire le code d’une action
Le code d’une action contient la logique métier — ce qui se passe réellement lorsque le déclencheur s’active. Les actions s’exécutent de manière asynchrone, avec un délai maximal de 30 secondes. Le await de premier niveau est pris en charge.
Imports disponibles
| Import | Description |
|---|---|
event | L’événement à l’origine de cette exécution |
trigger | Le déclencheur qui a correspondu |
module(group, name?) | Renvoie un proxy exposant .request() et .notify() |
storage | Stockage clé-valeur avec .get(key), .set(key, value) et la mise à jour atomique .update(key, fn) |
log(...args) | Écrit dans les journaux, visibles dans le panneau Activité |
sleep(ms) | Met l’exécution en pause pendant la durée indiquée |
exit() | Arrête l’action ici et marque le processus comme réussi. Un return au niveau racine est interdit dans un module ; c’est le retour anticipé. Impossible à intercepter, et les blocs finally ne s’exécutent pas |
Appeler les méthodes d’un module
Utilisez la fonction module() pour appeler les méthodes des modules connectés :
import { module } from "rawtoh"
// Send a Twitch chat message
await module("twitch").request("chat.say", {
message: "Hello from Rawtoh!"
})
// Change OBS scene (fire-and-forget)
await module("obs").notify("scene.set_current", {
sceneName: "BRB"
})
// Target a specific instance
await module("twitch", "alerts-bot").request("chat.say", {
message: "New follower!"
})Exemple complet
import { event, log, module, storage } from "rawtoh"
// Welcome new subscribers with a custom message
const user = event.payload.display_name
const plan = event.payload.plan_name
// Bump the sub count in storage (atomic, safe under concurrent subs)
const count = await storage.update("sub_count", (n) => (n ?? 0) + 1)
// Send a chat message
await module("twitch").request("chat.say", {
message: `Welcome @${user}! You're subscriber #${count} (${plan})`
})
log(`New sub: ${user} (${plan}), total: ${count}`)Scripts partagés
Les scripts partagés vous permettent de réutiliser du code dans plusieurs déclencheurs et actions. Ils apparaissent dans l’Explorateur aux côtés de vos actions et déclencheurs.
Utilisez la syntaxe standard export et import. Les scripts partagés peuvent être importés par chemin absolu (depuis la racine de l’arborescence) ou par chemin relatif :
Définir un script partagé
// /utils/format (shared script)
export function greet(name) {
return `Hello, ${name}!`
}
export function upper(str) {
return str.toUpperCase()
}Importer des scripts partagés
import { event, log, module } from "rawtoh"
import { greet } from "/utils/format"
// Use shared function in your action
await module("twitch").request("chat.say", {
message: greet(event.payload.username)
})// Relative imports also work (from the current script's directory)
import { upper } from "./format"
import { double } from "../math/double"Les scripts partagés peuvent eux aussi importer depuis "rawtoh" et depuis d’autres scripts partagés. En revanche, les scripts partagés importés par des déclencheurs ne doivent pas utiliser les API réservées aux actions (log, sleep, module, storage) — les appeler lève une erreur à l’exécution.
Organiser vos scripts
Les actions et les scripts partagés suivent une hiérarchie par chemins, comme un système de fichiers. Regroupez les automatisations liées dans des dossiers :
/twitch
/chat
/greet <- action: welcome new users
/commands <- action: handle !commands
/subs
/alert <- action: sub notification
/obs
/scenes
/auto-switch <- action: switch scenes automatically
/utils
/format <- shared: reusable formatting functions
/config <- shared: common configuration
/alerts
/donation <- action: donation alertVous pouvez activer ou désactiver des dossiers entiers d’un seul coup — pratique pour couper un groupe d’automatisations sans les supprimer.
Conseils
- Utilisez le panneau Activité pour déboguer — il affiche en temps réel chaque événement, chaque journal d’exécution et chaque appel à un module.
- Utilisez
log()sans modération — les journaux apparaissent dans le détail de l’exécution et vous aident à comprendre ce qui se passe. - Utilisez les temporisations sur les déclencheurs pour éviter le spam. Choisissez la limitation (throttle : se déclenche d’abord, puis attend) ou l’anti-rebond (debounce : attend, puis se déclenche).
- Commencez simplement — un déclencheur
export default trueassocié à une actionlog(event.payload)est un excellent moyen d’explorer les données qu’envoie un module. - Utilisez les scripts partagés pour éviter de dupliquer du code entre vos actions — extrayez la logique commune dans
/utils/ou un dossier équivalent. - N’utilisez pas
returndans les actions — la valeur de retour est ignorée. Utilisezthrowpour signaler une erreur. - Utilisez
storage.update()pour les compteurs — ungetsuivi d’unsetpeut perdre des incréments lorsque deux actions s’exécutent en même temps.