📦 Properties (Stockage persistant)
Le système de mémoire permanente de votre bot — sauvegarder des données pour le bot entier ou pour chaque utilisateur individuellement
Introduction
Quand un utilisateur envoie une commande à votre bot, le code s'exécute puis tout disparaît. Les variables, les données — rien ne survit d'une commande à l'autre. C'est là qu'interviennent les Properties.
Les Properties sont le système de stockage permanent de BotStrike. Elles vous permettent de sauvegarder n'importe quelle donnée (nombre, texte, JSON…) et de la retrouver plus tard, même après un redéploiement du bot.
setProp pour écrire et getProp pour lire.
Types de données acceptés : nombres (entiers, décimaux), texte, booléens (vrai/faux), JSON (objets et tableaux), dates. Le type est détecté automatiquement.
Les deux types de Properties
BotStrike sépare les données en deux espaces distincts, chacun avec son utilité :
🤖 Bot Properties — Données globales
Stockées au niveau du bot entier. Tous les utilisateurs partagent les mêmes données.
Cas d'usage :
- Configuration du bot (langue par défaut, message de bienvenue, liens…)
- Compteurs globaux (nombre total d'utilisateurs, nombre de commandes…)
- Données partagées (liste de produits, FAQ, règles du groupe…)
- État global du bot (mode maintenance, version…)
Python : bot.setProp() / bot.getProp()
JavaScript : Bot.setProp() / Bot.getProp()
👤 User Properties — Données par utilisateur
Stockées individuellement pour chaque utilisateur. L'utilisateur A ne voit pas les données de B.
Cas d'usage :
- Solde / monnaie virtuelle (coins, crédits, points…)
- Niveau, XP, progression dans un jeu
- Préférences personnelles (langue, notifications, thème…)
- Panier d'achat, commandes en cours
- Historique personnel, favoris
- État d'un formulaire en cours (étape actuelle…)
Python : bot.setUserProp() / bot.getUserProp()
JavaScript : User.setProp() / User.getProp()
Bot.setProp("coins", 100), tous les utilisateurs verront le même solde. Utilisez User.setProp("coins", 100) pour que chaque personne ait son propre solde.
Bot.setProp — Écrire une donnée globale
Sauvegarde une valeur accessible par toutes les commandes et tous les utilisateurs du bot.
Stocker un nombre
bot.setProp("total_users", 150)
bot.setProp("bot_version", 2.5)
Stocker du texte
bot.setProp("welcome_msg", "Bienvenue dans notre bot ! 🎉")
bot.setProp("rules", "1. Soyez respectueux\n2. Pas de spam\n3. Amusez-vous !")
Stocker un booléen
# Mettre le bot en maintenance
bot.setProp("maintenance", True)
Stocker du JSON (objet complexe)
bot.setProp("config", {
"langue": "fr",
"actif": True,
"admins": [123456789, 987654321],
"limites": {"messages_par_jour": 100}
})
Stocker une liste
bot.setProp("produits", [
{"nom": "T-shirt", "prix": 25},
{"nom": "Casquette", "prix": 15},
{"nom": "Mug", "prix": 10}
])
Stocker un nombre
Bot.setProp("total_users", 150);
Bot.setProp("bot_version", 2.5);
Stocker du texte
Bot.setProp("welcome_msg", "Bienvenue dans notre bot ! 🎉");
Bot.setProp("rules", "1. Soyez respectueux\n2. Pas de spam\n3. Amusez-vous !");
Stocker un booléen
// Mettre le bot en maintenance
Bot.setProp("maintenance", true);
Stocker du JSON (objet complexe)
Bot.setProp("config", {
langue: "fr",
actif: true,
admins: [123456789, 987654321],
limites: { messages_par_jour: 100 }
});
Stocker une liste
Bot.setProp("produits", [
{ nom: "T-shirt", prix: 25 },
{ nom: "Casquette", prix: 15 },
{ nom: "Mug", prix: 10 }
]);
Bot.getProp — Lire une donnée globale
Récupère une valeur précédemment sauvegardée. Retourne None (Python) ou null (JS) si la property n'existe pas.
Lire une valeur simple
total = bot.getProp("total_users")
bot.sendMessage("Utilisateurs : " + str(total))
Lire du JSON
# Le JSON est automatiquement parsé — vous recevez un dict Python
config = bot.getProp("config")
bot.sendMessage("Langue : " + config["langue"])
bot.sendMessage("Admins : " + str(len(config["admins"])))
Vérifier si une property existe
msg = bot.getProp("welcome_msg")
if msg:
bot.sendMessage(msg)
else:
bot.sendMessage("Aucun message de bienvenue configuré.")
Vérifier le mode maintenance
# Au début d'une commande quelconque if bot.getProp("maintenance"): bot.sendMessage("🔧 Le bot est en maintenance. Revenez plus tard !") else: # Exécuter la commande normalement bot.sendMessage("Tout fonctionne ✅")
Lire une valeur simple
var total = Bot.getProp("total_users");
Bot.sendMessage("Utilisateurs : " + total);
Lire du JSON
// Le JSON est automatiquement parsé — vous recevez un objet JS
var config = Bot.getProp("config");
Bot.sendMessage("Langue : " + config.langue);
Bot.sendMessage("Admins : " + config.admins.length);
Vérifier si une property existe
var msg = Bot.getProp("welcome_msg");
if (msg) {
Bot.sendMessage(msg);
} else {
Bot.sendMessage("Aucun message de bienvenue configuré.");
}
Vérifier le mode maintenance
// Au début d'une commande quelconque
if (Bot.getProp("maintenance")) {
Bot.sendMessage("🔧 Le bot est en maintenance. Revenez plus tard !");
} else {
Bot.sendMessage("Tout fonctionne ✅");
}
getProp retourne None / null. Faire config["langue"] sur None causera une erreur.
Bot.deleteProp — Supprimer une donnée globale
Efface définitivement une property du stockage du bot.
# Supprimer une property bot.deleteProp("old_config") # Désactiver le mode maintenance bot.deleteProp("maintenance") bot.sendMessage("✅ Maintenance terminée !")
// Supprimer une property Bot.deleteProp("old_config"); // Désactiver le mode maintenance Bot.deleteProp("maintenance"); Bot.sendMessage("✅ Maintenance terminée !");
💰 Bot.currency() — compteur numérique pratique
Helper pour gérer une valeur numérique persistante (solde, score, points) sans réécrire get → +N → set à chaque fois.
const wallet = Bot.currency(`solde_${user.id}`); // 0 par défaut
wallet.add(100); // +100
wallet.sub(20);
wallet.set(1000);
wallet.reset();
const v = wallet.value;
Bot.sendMessage(`Solde : ${wallet} coins`);
wallet = Bot.currency(f"solde_{user['id']}")
wallet.add(100)
wallet.sub(20)
wallet.set(1000); wallet.reset()
v = wallet.value
Bot.sendMessage(f"Solde : {wallet} coins")
Méthodes disponibles : .add(n), .sub(n), .mul(n), .div(n), .set(n), .reset(), .value.
🔢 Identifiant et compteur de modifications
Chaque propriété affichée dans l'onglet Propriétés de l'app porte un identifiant numérique stable #N et un compteur du nombre de modifications. Ces métadonnées sont stockées automatiquement dans props_meta.json à côté de props.json et sont mises à jour à chaque appel setProp() ou édition depuis l'application.
- id — numéro unique attribué à la création (jamais ré-attribué)
- modified — nombre de fois où la propriété a été écrite
- modifiers — liste séparée par virgule des derniers identifiants/usernames qui l'ont modifiée (max 20)
User.setProp — Écrire une donnée utilisateur
Sauvegarde une valeur uniquement pour l'utilisateur qui exécute la commande. Chaque personne a son propre espace de stockage isolé.
Stocker un solde
bot.setUserProp("coins", 100)
bot.sendMessage("Vous avez reçu 100 🪙 de bienvenue !")
Stocker des préférences
bot.setUserProp("langue", "fr")
bot.setUserProp("notifications", True)
bot.setUserProp("theme", "dark")
Stocker un panier d'achat
bot.setUserProp("panier", [
{"produit": "T-shirt", "quantite": 2, "prix": 25},
{"produit": "Mug", "quantite": 1, "prix": 10}
])
bot.sendMessage("Panier mis à jour ✅")
Suivre la progression d'un formulaire
# Enregistrer l'étape actuelle d'un formulaire multi-étapes
bot.setUserProp("form_step", "email")
bot.setUserProp("form_data", {
"nom": u["prenom"],
"email": "",
"telephone": ""
})
bot.sendMessage("Entrez votre adresse email :")
bot.waitForResponse(lambda reply: handle_email(reply))
Stocker un solde
User.setProp("coins", 100);
Bot.sendMessage("Vous avez reçu 100 🪙 de bienvenue !");
Stocker des préférences
User.setProp("langue", "fr");
User.setProp("notifications", true);
User.setProp("theme", "dark");
Stocker un panier d'achat
User.setProp("panier", [
{ produit: "T-shirt", quantite: 2, prix: 25 },
{ produit: "Mug", quantite: 1, prix: 10 }
]);
Bot.sendMessage("Panier mis à jour ✅");
Suivre la progression d'un formulaire
// Enregistrer l'étape actuelle d'un formulaire multi-étapes
User.setProp("form_step", "email");
User.setProp("form_data", {
nom: user.first_name,
email: "",
telephone: ""
});
Bot.sendMessage("Entrez votre adresse email :");
Bot.waitForResponse(function(ctx) { /* traiter l'email */ });
User.getProp — Lire une donnée utilisateur
Récupère la donnée de l'utilisateur courant. Chaque utilisateur lit ses propres données sans voir celles des autres.
Lire le solde
coins = bot.getUserProp("coins")
if coins is not None:
bot.sendMessage("💰 Votre solde : " + str(coins) + " 🪙")
else:
bot.sendMessage("Vous n'avez pas encore de compte. Tapez /start !")
Afficher le profil complet
coins = bot.getUserProp("coins") or 0
niveau = bot.getUserProp("niveau") or 1
xp = bot.getUserProp("xp") or 0
langue = bot.getUserProp("langue") or "fr"
profil = "👤 Votre profil\n\n"
profil += "📛 Nom : " + u["prenom"] + "\n"
profil += "🪙 Coins : " + str(coins) + "\n"
profil += "⭐ Niveau : " + str(niveau) + "\n"
profil += "✨ XP : " + str(xp) + "\n"
profil += "🌍 Langue : " + langue
bot.sendMessage(profil)
Reprendre un formulaire en cours
step = bot.getUserProp("form_step")
if step:
bot.sendMessage("Vous avez un formulaire en cours (étape : " + step + ")")
bot.sendMessage("Tapez /cancel pour annuler ou continuez :")
else:
bot.sendMessage("Aucun formulaire en cours.")
Lire le solde
var coins = User.getProp("coins");
if (coins !== null) {
Bot.sendMessage("💰 Votre solde : " + coins + " 🪙");
} else {
Bot.sendMessage("Vous n'avez pas encore de compte. Tapez /start !");
}
Afficher le profil complet
var coins = User.getProp("coins") || 0;
var niveau = User.getProp("niveau") || 1;
var xp = User.getProp("xp") || 0;
var langue = User.getProp("langue") || "fr";
var profil = "👤 Votre profil\n\n";
profil += "📛 Nom : " + user.first_name + "\n";
profil += "🪙 Coins : " + coins + "\n";
profil += "⭐ Niveau : " + niveau + "\n";
profil += "✨ XP : " + xp + "\n";
profil += "🌍 Langue : " + langue;
Bot.sendMessage(profil);
Reprendre un formulaire en cours
var step = User.getProp("form_step");
if (step) {
Bot.sendMessage("Vous avez un formulaire en cours (étape : " + step + ")");
Bot.sendMessage("Tapez /cancel pour annuler ou continuez :");
} else {
Bot.sendMessage("Aucun formulaire en cours.");
}
User.deleteProp — Supprimer une donnée utilisateur
Efface une donnée de l'espace personnel de l'utilisateur courant.
# Vider le panier bot.deleteUserProp("panier") bot.sendMessage("🛒 Panier vidé !") # Annuler un formulaire bot.deleteUserProp("form_step") bot.deleteUserProp("form_data") bot.sendMessage("Formulaire annulé.") # Réinitialiser le compte d'un utilisateur bot.deleteUserProp("coins") bot.deleteUserProp("niveau") bot.deleteUserProp("xp") bot.sendMessage("Compte réinitialisé.")
// Vider le panier User.deleteProp("panier"); Bot.sendMessage("🛒 Panier vidé !"); // Annuler un formulaire User.deleteProp("form_step"); User.deleteProp("form_data"); Bot.sendMessage("Formulaire annulé."); // Réinitialiser le compte d'un utilisateur User.deleteProp("coins"); User.deleteProp("niveau"); User.deleteProp("xp"); Bot.sendMessage("Compte réinitialisé.");
Accéder aux données d'un autre utilisateur
Parfois vous avez besoin de lire les données d'un utilisateur spécifique — par exemple pour un classement, un transfert de coins, ou un système d'administration.
Lire les données d'un autre user
# Lire les coins de l'utilisateur 987654321
other_coins = bot.getUserProp("coins", user_id=987654321)
if other_coins is not None:
bot.sendMessage("Cet utilisateur a " + str(other_coins) + " 🪙")
else:
bot.sendMessage("Cet utilisateur n'a pas de compte.")
Exemple : commande /check <user_id>
# L'admin tape : /check 987654321
if params:
target_id = int(params)
coins = bot.getUserProp("coins", user_id=target_id) or 0
niveau = bot.getUserProp("niveau", user_id=target_id) or 1
bot.sendMessage(
"📊 Profil #" + str(target_id) + "\n"
"🪙 Coins : " + str(coins) + "\n"
"⭐ Niveau : " + str(niveau)
)
else:
bot.sendMessage("Usage : /check <user_id>")
Lire les données d'un autre user
// Lire les coins de l'utilisateur 987654321
var otherCoins = Bot.getUserProp("coins", 987654321);
if (otherCoins !== null) {
Bot.sendMessage("Cet utilisateur a " + otherCoins + " 🪙");
} else {
Bot.sendMessage("Cet utilisateur n'a pas de compte.");
}
Exemple : commande /check <user_id>
// L'admin tape : /check 987654321
if (params) {
var targetId = parseInt(params);
var coins = Bot.getUserProp("coins", targetId) || 0;
var niveau = Bot.getUserProp("niveau", targetId) || 1;
Bot.sendMessage(
"📊 Profil #" + targetId + "\n" +
"🪙 Coins : " + coins + "\n" +
"⭐ Niveau : " + niveau
);
} else {
Bot.sendMessage("Usage : /check <user_id>");
}
u["id"] (Python) ou user.id (JS). Chaque utilisateur Telegram a un ID numérique unique.
Modifier la prop d'un autre utilisateur (+N)
Pour ajouter ou soustraire un nombre à la propriété d'un autre utilisateur, il faut lire sa valeur, la modifier, puis la réécrire avec son user_id.
Ajouter +3 points à un autre utilisateur
# L'admin tape : /add_pt 987654321
target_id = int(params) # ID de l'autre utilisateur
# 1. Lire sa valeur actuelle
pts = bot.getUserProp("points", user_id=target_id) or 0
# 2. Ajouter 3
pts = pts + 3
# 3. Réécrire pour cet utilisateur
bot.setUserProp("points", pts, user_id=target_id)
bot.sendMessage("✅ +3 points donnés ! Il en a maintenant : " + str(pts))
Commande admin /add_pt <user_id> <montant>
# Usage : /add_pt 987654321 50
if params:
parts = params.split()
if len(parts) == 2:
target_id = int(parts[0])
montant = int(parts[1])
solde = bot.getUserProp("coins", user_id=target_id) or 0
solde = solde + montant
bot.setUserProp("coins", solde, user_id=target_id)
bot.sendMessage("✅ +" + str(montant) + " 🪙 donné à #" + str(target_id) + " — nouveau solde : " + str(solde))
else:
bot.sendMessage("Usage : /add_pt <user_id> <montant>")
else:
bot.sendMessage("Usage : /add_pt <user_id> <montant>")
Ajouter +3 points à un autre utilisateur
// L'admin tape : /add_pt 987654321
var targetId = parseInt(params); // ID de l'autre utilisateur
// 1. Lire sa valeur actuelle
var pts = Bot.getUserProp("points", targetId) || 0;
// 2. Ajouter 3
pts = pts + 3;
// 3. Réécrire pour cet utilisateur
Bot.setUserProp("points", pts, targetId);
Bot.sendMessage("✅ +3 points donnés ! Il en a maintenant : " + pts);
Commande admin /add_pt <user_id> <montant>
// Usage : /add_pt 987654321 50
if (params) {
var parts = params.split(" ");
if (parts.length === 2) {
var targetId = parseInt(parts[0]);
var montant = parseInt(parts[1]);
var solde = Bot.getUserProp("coins", targetId) || 0;
solde = solde + montant;
Bot.setUserProp("coins", solde, targetId);
Bot.sendMessage("✅ +" + montant + " 🪙 donné à #" + targetId + " — nouveau solde : " + solde);
} else {
Bot.sendMessage("Usage : /add_pt <user_id> <montant>");
}
} else {
Bot.sendMessage("Usage : /add_pt <user_id> <montant>");
}
user.id === adminId avant de modifier les données d'un autre utilisateur.
Incrémenter, décrémenter, modifier
Les Properties n'ont pas de méthode « ajouter +1 » — il faut lire la valeur, la modifier, puis la réécrire.
Ajouter des coins
coins = bot.getUserProp("coins") or 0
coins = coins + 50
bot.setUserProp("coins", coins)
bot.sendMessage("+ 50 🪙 ! Total : " + str(coins))
Retirer des coins (avec vérification)
prix = 30
coins = bot.getUserProp("coins") or 0
if coins >= prix:
coins = coins - prix
bot.setUserProp("coins", coins)
bot.sendMessage("Achat effectué ! Reste : " + str(coins) + " 🪙")
else:
bot.sendMessage("❌ Solde insuffisant ! Vous avez " + str(coins) + " 🪙, il en faut " + str(prix))
Compteur global (ex : nombre de /start)
total = bot.getProp("total_starts") or 0
total = total + 1
bot.setProp("total_starts", total)
bot.sendMessage("Bienvenue ! Vous êtes le visiteur n°" + str(total) + " 🎉")
Ajouter un élément à une liste
# Ajouter un produit au panier
panier = bot.getUserProp("panier") or []
panier.append({"produit": "Casquette", "prix": 15})
bot.setUserProp("panier", panier)
bot.sendMessage("Casquette ajoutée au panier (" + str(len(panier)) + " articles)")
Modifier un champ dans un objet JSON
# Changer la langue de l'utilisateur
settings = bot.getUserProp("settings") or {}
settings["langue"] = "en"
bot.setUserProp("settings", settings)
bot.sendMessage("Language changed to English 🇬🇧")
Ajouter des coins
var coins = User.getProp("coins") || 0;
coins = coins + 50;
User.setProp("coins", coins);
Bot.sendMessage("+ 50 🪙 ! Total : " + coins);
Retirer des coins (avec vérification)
var prix = 30;
var coins = User.getProp("coins") || 0;
if (coins >= prix) {
coins = coins - prix;
User.setProp("coins", coins);
Bot.sendMessage("Achat effectué ! Reste : " + coins + " 🪙");
} else {
Bot.sendMessage("❌ Solde insuffisant ! Vous avez " + coins + " 🪙, il en faut " + prix);
}
Compteur global (ex : nombre de /start)
var total = Bot.getProp("total_starts") || 0;
total = total + 1;
Bot.setProp("total_starts", total);
Bot.sendMessage("Bienvenue ! Vous êtes le visiteur n°" + total + " 🎉");
Ajouter un élément à une liste
// Ajouter un produit au panier
var panier = User.getProp("panier") || [];
panier.push({ produit: "Casquette", prix: 15 });
User.setProp("panier", panier);
Bot.sendMessage("Casquette ajoutée au panier (" + panier.length + " articles)");
Modifier un champ dans un objet JSON
// Changer la langue de l'utilisateur
var settings = User.getProp("settings") || {};
settings.langue = "en";
User.setProp("settings", settings);
Bot.sendMessage("Language changed to English 🇬🇧");
val = getProp → val += X → setProp(val)
Conversions utiles (string → nombre, nombre → texte…)
Les données saisies par l'utilisateur (message, params) sont toujours des chaînes de texte (string). Si vous voulez les utiliser comme nombres, il faut les convertir.
String → entier (int)
# L'utilisateur envoie "42" — c'est un texte, pas un nombre
texte = message # "42" (string)
nombre = int(texte) # 42 (entier)
nombre = int(params) # pratique pour les paramètres de commande
String → décimal (float)
prix = float("3.99") # 3.99
montant = float(params) # si l'utilisateur tape "1.5"
Nombre → string (pour concatener)
coins = 150
bot.sendMessage("Vous avez " + str(coins) + " 🪙")
# Sans str() → TypeError: can only concatenate str (not "int") to str
Vérifier que c'est bien un nombre avant de convertir
if params and params.isdigit():
montant = int(params)
coins = bot.getUserProp("coins") or 0
coins = coins + montant
bot.setUserProp("coins", coins)
bot.sendMessage("+" + str(montant) + " ajouté ! Total : " + str(coins))
else:
bot.sendMessage("❌ Entrez un nombre valide.")
Tableau de conversions Python
| Depuis | Vers | Code |
|---|---|---|
| string | entier | int("42") → 42 |
| string | décimal | float("3.5") → 3.5 |
| entier / décimal | string | str(42) → "42" |
| string | booléen | bool("oui") → True (toute chaîne non-vide) |
| décimal | entier (arrondi) | int(3.9) → 3 (tronqué) |
| entier | arrondi supérieur | import math; math.ceil(3.2) → 4 |
String → entier (parseInt)
// L'utilisateur envoie "42" — c'est un texte, pas un nombre
var texte = message; // "42" (string)
var nombre = parseInt(texte); // 42 (entier)
var nombre = parseInt(params); // pratique pour les paramètres
String → décimal (parseFloat)
var prix = parseFloat("3.99"); // 3.99
var montant = parseFloat(params); // si l'utilisateur tape "1.5"
Nombre → string (pour concatener)
var coins = 150;
Bot.sendMessage("Vous avez " + coins + " 🪙"); // OK, JS concatène auto
Bot.sendMessage("Vous avez " + String(coins) + " 🪙"); // explicite
Vérifier que c'est bien un nombre avant de convertir
if (params) {
var montant = parseInt(params);
if (!isNaN(montant)) {
var coins = User.getProp("coins") || 0;
coins = coins + montant;
User.setProp("coins", coins);
Bot.sendMessage("+" + montant + " ajouté ! Total : " + coins);
} else {
Bot.sendMessage("❌ Entrez un nombre valide.");
}
}
Tableau de conversions JavaScript
| Depuis | Vers | Code |
|---|---|---|
| string | entier | parseInt("42") → 42 |
| string | décimal | parseFloat("3.5") → 3.5 |
| nombre | string | String(42) ou (42).toString() → "42" |
| string | booléen | Boolean("oui") → true (toute chaîne non-vide) |
| décimal | entier (tronqué) | Math.floor(3.9) → 3 |
| décimal | arrondi supérieur | Math.ceil(3.2) → 4 |
| any | vérifier si nombre | !isNaN(parseInt(val)) |
params et message sont toujours des strings. Dès que vous voulez faire des maths dessus, convertissez d'abord avec int() / parseInt().
Lister toutes les properties
Parcourez toutes les properties Bot stockées, avec possibilité de filtrer par préfixe.
# Lister toutes les props du bot props = bot.listProps() for p in props: bot.sendMessage(p["name"] + " = " + str(p["value"])) # Lister seulement celles commençant par "config_" config_props = bot.listProps(prefix="config_") # Même nom qu'en JavaScript : Bot.getProps ou Props.getProps scores = Props.getProps({"prefix": "score_"})
// Lister toutes les props du bot var props = Bot.getProps(); for (var i = 0; i < props.length; i++) { Bot.sendMessage(props[i].name + " = " + props[i].value); } // Lister seulement celles commençant par "config_" var configProps = Bot.getProps({ prefix: "config_" }); // Même chose depuis Props var scores = Props.getProps({ prefix: "score_" });
Exemple complet : Système de coins
Voici un système monétaire complet avec bonus quotidien et transfert entre joueurs.
Commande /daily — Bonus quotidien
# Vérifier le dernier bonus last_daily = bot.getUserProp("last_daily") or 0 now = int(time.time()) # 86400 secondes = 24 heures if now - last_daily < 86400: restant = 86400 - (now - last_daily) heures = restant // 3600 minutes = (restant % 3600) // 60 bot.sendMessage("⏰ Prochain bonus dans " + str(heures) + "h " + str(minutes) + "min") else: bonus = 50 coins = bot.getUserProp("coins") or 0 coins = coins + bonus bot.setUserProp("coins", coins) bot.setUserProp("last_daily", now) bot.sendMessage("🎁 Bonus quotidien : +" + str(bonus) + " 🪙\nSolde : " + str(coins))
Commande /send — Transfert de coins
# Usage : /send 987654321 50 if not params or " " not in params: bot.sendMessage("Usage : /send <user_id> <montant>") else: parts = params.split(" ") target_id = int(parts[0]) montant = int(parts[1]) mes_coins = bot.getUserProp("coins") or 0 if montant <= 0: bot.sendMessage("❌ Montant invalide.") elif mes_coins < montant: bot.sendMessage("❌ Solde insuffisant (" + str(mes_coins) + " 🪙)") else: # Retirer de l'expéditeur mes_coins = mes_coins - montant bot.setUserProp("coins", mes_coins) # Ajouter au destinataire ses_coins = bot.getUserProp("coins", user_id=target_id) or 0 # Note : setProp pour un autre user n'existe pas # On stocke un "pending" que le destinataire récupérera bot.sendMessage("✅ " + str(montant) + " 🪙 envoyés ! Reste : " + str(mes_coins))
Commande /daily — Bonus quotidien
// Vérifier le dernier bonus var lastDaily = User.getProp("last_daily") || 0; var now = Math.floor(Date.now() / 1000); // 86400 secondes = 24 heures if (now - lastDaily < 86400) { var restant = 86400 - (now - lastDaily); var heures = Math.floor(restant / 3600); var minutes = Math.floor((restant % 3600) / 60); Bot.sendMessage("⏰ Prochain bonus dans " + heures + "h " + minutes + "min"); } else { var bonus = 50; var coins = User.getProp("coins") || 0; coins = coins + bonus; User.setProp("coins", coins); User.setProp("last_daily", now); Bot.sendMessage("🎁 Bonus quotidien : +" + bonus + " 🪙\nSolde : " + coins); }
Commande /send — Transfert de coins
// Usage : /send 987654321 50
if (!params || !params.includes(" ")) {
Bot.sendMessage("Usage : /send <user_id> <montant>");
} else {
var parts = params.split(" ");
var targetId = parseInt(parts[0]);
var montant = parseInt(parts[1]);
var mesCoins = User.getProp("coins") || 0;
if (montant <= 0) {
Bot.sendMessage("❌ Montant invalide.");
} else if (mesCoins < montant) {
Bot.sendMessage("❌ Solde insuffisant (" + mesCoins + " 🪙)");
} else {
mesCoins = mesCoins - montant;
User.setProp("coins", mesCoins);
Bot.sendMessage("✅ " + montant + " 🪙 envoyés ! Reste : " + mesCoins);
}
}
Exemple complet : Système de niveaux / XP
Un système de progression avec XP, niveaux, et paliers.
Donner de l'XP à chaque message (commande *)
# Cette commande s'exécute sur CHAQUE message (wildcard *) xp = bot.getUserProp("xp") or 0 niveau = bot.getUserProp("niveau") or 1 # Gagner 10 XP par message xp = xp + 10 # Calculer le seuil pour le prochain niveau seuil = niveau * 100 # Niveau 1 = 100 XP, Niveau 2 = 200 XP, etc. # Level up ? if xp >= seuil: niveau = niveau + 1 xp = xp - seuil bot.setUserProp("niveau", niveau) bot.sendMessage( "🎊 LEVEL UP !\n\n" "⭐ Niveau " + str(niveau) + " atteint !\n" "Prochain palier : " + str(niveau * 100) + " XP" ) bot.setUserProp("xp", xp)
Commande /rank — Voir son rang
xp = bot.getUserProp("xp") or 0
niveau = bot.getUserProp("niveau") or 1
seuil = niveau * 100
# Barre de progression visuelle
progression = int((xp / seuil) * 10)
barre = "█" * progression + "░" * (10 - progression)
bot.sendMessage(
"📊 Votre progression\n\n"
"⭐ Niveau : " + str(niveau) + "\n"
"✨ XP : " + str(xp) + " / " + str(seuil) + "\n"
"[" + barre + "] " + str(int(xp / seuil * 100)) + "%"
)
Donner de l'XP à chaque message (commande *)
// S'exécute sur CHAQUE message (wildcard *) var xp = User.getProp("xp") || 0; var niveau = User.getProp("niveau") || 1; // Gagner 10 XP par message xp = xp + 10; var seuil = niveau * 100; if (xp >= seuil) { niveau = niveau + 1; xp = xp - seuil; User.setProp("niveau", niveau); Bot.sendMessage( "🎊 LEVEL UP !\n\n" + "⭐ Niveau " + niveau + " atteint !\n" + "Prochain palier : " + (niveau * 100) + " XP" ); } User.setProp("xp", xp);
Commande /rank — Voir son rang
var xp = User.getProp("xp") || 0;
var niveau = User.getProp("niveau") || 1;
var seuil = niveau * 100;
// Barre de progression visuelle
var progression = Math.floor((xp / seuil) * 10);
var barre = "█".repeat(progression) + "░".repeat(10 - progression);
Bot.sendMessage(
"📊 Votre progression\n\n" +
"⭐ Niveau : " + niveau + "\n" +
"✨ XP : " + xp + " / " + seuil + "\n" +
"[" + barre + "] " + Math.floor(xp / seuil * 100) + "%"
);
Exemple complet : Système de parrainage
Récompensez les utilisateurs qui invitent leurs amis avec un lien de parrainage.
Commande /start — Détecter le parrainage
# Si l'utilisateur arrive via un lien : /start 123456789 # params contient l'ID du parrain deja_inscrit = bot.getUserProp("inscrit") if not deja_inscrit: bot.setUserProp("inscrit", True) bot.setUserProp("coins", 50) # Bonus de bienvenue # Si parrainé par quelqu'un if params: parrain_id = int(params) # Enregistrer qui l'a parrainé bot.setUserProp("parrain", parrain_id) # Compter les filleuls du parrain (prop globale) key = "referrals_" + str(parrain_id) count = bot.getProp(key) or 0 bot.setProp(key, count + 1) bot.sendMessage("🎉 Bienvenue ! Vous avez été parrainé.\n+50 🪙 de bienvenue !") else: bot.sendMessage("🎉 Bienvenue !\n+50 🪙 de bienvenue !") else: bot.sendMessage("Re-bonjour " + u["prenom"] + " ! 👋")
Commande /invite — Obtenir son lien
my_id = u["id"]
# Récupérer le username du bot via l'objet bot
lien = "https://t.me/VOTRE_BOT?start=" + str(my_id)
count = bot.getProp("referrals_" + str(my_id)) or 0
bot.sendMessage(
"🔗 Votre lien de parrainage :\n\n"
+ lien + "\n\n"
"👥 Filleuls : " + str(count) + "\n"
"🪙 Bonus par filleul : +25 coins"
)
Commande /start — Détecter le parrainage
// Si l'utilisateur arrive via un lien : /start 123456789
var dejaInscrit = User.getProp("inscrit");
if (!dejaInscrit) {
User.setProp("inscrit", true);
User.setProp("coins", 50);
if (params) {
var parrainId = parseInt(params);
User.setProp("parrain", parrainId);
var key = "referrals_" + parrainId;
var count = Bot.getProp(key) || 0;
Bot.setProp(key, count + 1);
Bot.sendMessage("🎉 Bienvenue ! Vous avez été parrainé.\n+50 🪙 de bienvenue !");
} else {
Bot.sendMessage("🎉 Bienvenue !\n+50 🪙 de bienvenue !");
}
} else {
Bot.sendMessage("Re-bonjour " + user.first_name + " ! 👋");
}
Commande /invite — Obtenir son lien
var myId = user.id;
var lien = "https://t.me/VOTRE_BOT?start=" + myId;
var count = Bot.getProp("referrals_" + myId) || 0;
Bot.sendMessage(
"🔗 Votre lien de parrainage :\n\n" +
lien + "\n\n" +
"👥 Filleuls : " + count + "\n" +
"🪙 Bonus par filleul : +25 coins"
);
Bonnes pratiques
✅ Ce qu'il faut faire
- Noms explicites — Utilisez
user_coinsplutôt quecoudata1 - Toujours vérifier — Testez si
getPropretourneNone/nullavant d'utiliser la valeur - Utiliser
or 0— Pour les compteurs :coins = getProp("coins") or 0 - Séparer Bot et User — Données globales dans Bot, données personnelles dans User
- Préfixes cohérents —
config_pour la config,stat_pour les stats,form_pour les formulaires
❌ Ce qu'il ne faut PAS faire
- Pas de
Bot.setProp("coins", 100)pour un solde — c'est partagé entre tous les users ! - Pas de données sensibles — Ne stockez jamais de mots de passe ou tokens dans les properties
- Pas de « lire et oublier » — Si vous modifiez une valeur, n'oubliez pas de la réécrire avec
setProp - Pas de noms dynamiques incontrôlés — Évitez
setProp(message, value)où le nom vient du texte de l'utilisateur
Récapitulatif complet
| Action | Python | JavaScript |
|---|---|---|
| Écrire | bot.setProp("clé", valeur) | Bot.setProp("clé", valeur) |
| Lire | bot.getProp("clé") | Bot.getProp("clé") |
| Supprimer | bot.deleteProp("clé") | Bot.deleteProp("clé") |
| Lister tout | Bot.getProps() ou bot.listProps() | Bot.getProps() |
| Lister filtré | Bot.getProps({"prefix": "x"}) | Bot.getProps({prefix: "x"}) |
| Action | Python | JavaScript |
|---|---|---|
| Écrire | bot.setUserProp("clé", val) | User.setProp("clé", val) |
| Lire (soi) | bot.getUserProp("clé") | User.getProp("clé") |
| Lire (autre) | bot.getUserProp("clé", user_id=ID) | Bot.getUserProp("clé", ID) |
| Supprimer | bot.deleteUserProp("clé") | User.deleteProp("clé") |
Quand utiliser Bot vs User ?
| Donnée | Bot ou User ? | Pourquoi |
|---|---|---|
| Solde / coins | User | Chaque personne a son propre solde |
| Niveau / XP | User | Progression individuelle |
| Préférences | User | Chacun ses réglages |
| Panier d'achat | User | Commandes personnelles |
| Message de bienvenue | Bot | Le même pour tout le monde |
| Compteur total | Bot | Statistique globale |
| Liste de produits | Bot | Catalogue partagé |
| Mode maintenance | Bot | État global du bot |
| Liste de filleuls | Bot | Compteur par parrain (stocké globalement) |
📦 Stockage éphémère, helpers & limites
En plus de Props et User, deux outils sont disponibles pour des cas spécifiques :
1️⃣ Bot.set / Bot.get_data — Stockage éphémère (RAM)
Données perdues au redémarrage du bot. Très rapide, parfait pour le contexte d'une conversation.
Bot.set("step_" + str(chat_id), "awaiting_email")
step = Bot.get_data("step_" + str(chat_id), "start") # 2e arg = défaut
Bot.delete("step_" + str(chat_id))
# Vérifier l'utilisation
stats = Bot.storage() # {used: 0.05, remaining: 499.95} (en Ko, plafond 500 Ko)
Bot.set("step_" + chat_id, "awaiting_email");
let step = Bot.get_data("step_" + chat_id, "start");
Bot.delete("step_" + chat_id);
let stats = Bot.storage(); // {used: 0.05, remaining: 499.95} (en Ko, plafond 500 Ko)
2️⃣ Bot.currency — Compteur numérique avec helpers
Wrapper pratique autour de Props pour les compteurs (solde, points, niveaux). Crée automatiquement la clé et expose des méthodes métier.
wallet = Bot.currency(f"solde_{user['id']}")
wallet.add(100) # +100
wallet.sub(20) # -20
wallet.set(1000) # définir = 1000
wallet.reset() # = 0
Bot.sendMessage(f"💰 Solde : {wallet.value} coins")
let wallet = Bot.currency(`solde_${user.id}`);
wallet.add(100);
wallet.sub(20);
wallet.set(1000);
wallet.reset();
Bot.sendMessage(`💰 Solde : ${wallet.value} coins`);
3️⃣ Portée du stockage persistant
Chaque fichier a une capacité généreuse, largement suffisante pour un catalogue, des réglages et l'historique d'un client. Elle n'est pas sans fin pour autant : n'empilez pas dans les propriétés du bot ce qui grandit sans cesse (toutes les commandes de tous les clients, un journal). Rangez plutôt ce qui appartient à quelqu'un dans SES propriétés, et purgez ce qui est terminé. Si une écriture dépasse la capacité, elle est refusée avec un message explicite indiquant la taille atteinte.
| Élément | Portée | Stockage |
|---|---|---|
Bot.set / Bot.get_data | Le bot entier | Éphémère — perdue au restart |
Props.set / Props.get | Le bot entier | Persistant (props.json) |
User.setProp / User.getProp | Un fichier par utilisateur | Persistant (user_props/{uid}.json) |
# Vérifier l'usage Props info = Props.storage() # {used: 142.0, remaining: 358.0} (en Ko) Bot.sendMessage(f"Storage : {info['used']:.1f} Ko utilisés")
- Pour les données par user →
User.setProp()(pas Props avec clé par user, qui sature vite) - Pour les logs / historique → plutôt un Webhook vers une vraie base externe
- Pour les sessions temporaires →
Bot.set()(pas de pollution disque)
👑 Le propriétaire et ses clients
Deux erreurs reviennent dans presque tous les bots qui prennent des commandes ou des réservations. Elles ne lèvent aucune erreur : elles marchent à l'essai, et cassent avec de vrais clients.
- Une mémoire commune pour une donnée d'un client.
Props/Bot.setPropsont partagés par tout le bot. Si deux clients remplissent un panier ou une réservation en même temps, leurs réponses se mélangent. Ce qu'UN client est en train de faire va dansUser.setProp. - Prévenir le propriétaire avec
user.id.user.idest la personne qui écrit, c'est-à-dire le client. À l'essai, c'est vous qui écrivez, donc ça « marche » ; en vrai, vous ne recevez rien. UtilisezBot.ownerId.
Bot.ownerId et Bot.isOwner()
Bot.ownerId est l'identifiant Telegram du propriétaire du bot (celui du compte BotStrike, ou du compte Telegram qui a créé le bot dans le chat IA). Bot.isOwner() dit si c'est lui qui écrit. Ne faites jamais « le premier qui tape /admin devient administrateur » : un client plus rapide récupérerait les données de tous les autres.
Une commande réservée au propriétaire
if not Bot.isOwner():
Bot.sendMessage("Commande réservée au propriétaire.")
else:
commandes = Props.get("commandes", [])
Bot.sendMessage(f"{len(commandes)} commande(s) reçue(s).")
Prévenir le propriétaire
if Bot.ownerId:
Bot.sendMessage("🔔 Nouvelle réservation", {"chat_id": Bot.ownerId})
Un dialogue à plusieurs questions, par client
# /reserver User.setProp("resa", {}) Bot.sendMessage("Ton nom ? (ou « annuler »)") Bot.waitForResponse({"runCommand": "/resa_nom"}) # /resa_nom — `message` contient la réponse rep = (message or "").strip() if rep.lower() == "annuler": User.deleteProp("resa") Bot.sendMessage("Annulé 👍") elif len(rep) < 2: Bot.sendMessage("Écris ton nom 🙂") Bot.waitForResponse({"runCommand": "/resa_nom"}) # on redemande else: resa = User.getProp("resa", {}); resa["nom"] = rep; User.setProp("resa", resa) Bot.sendMessage("Pour combien de personnes ?") Bot.waitForResponse({"runCommand": "/resa_nb"})
Une commande réservée au propriétaire
if (!Bot.isOwner()) {
Bot.sendMessage("Commande réservée au propriétaire.");
return;
}
var commandes = Props.get("commandes", []);
Bot.sendMessage(commandes.length + " commande(s) reçue(s).");
Prévenir le propriétaire
if (Bot.ownerId) {
await Bot.sendMessage("🔔 Nouvelle réservation", { chat_id: Bot.ownerId });
}
Un dialogue à plusieurs questions, par client
// /reserver User.setProp("resa", {}); Bot.sendMessage("Ton nom ? (ou « annuler »)"); Bot.waitForResponse({ runCommand: "/resa_nom" }); // /resa_nom — `message` contient la réponse var rep = (message || "").trim(); if (rep.toLowerCase() === "annuler") { User.deleteProp("resa"); Bot.sendMessage("Annulé 👍"); return; } if (rep.length < 2) { Bot.sendMessage("Écris ton nom 🙂"); Bot.waitForResponse({ runCommand: "/resa_nom" }); // on redemande return; } var resa = User.getProp("resa", {}); resa.nom = rep; User.setProp("resa", resa); Bot.sendMessage("Pour combien de personnes ?"); Bot.waitForResponse({ runCommand: "/resa_nb" });
Vérifiez chaque réponse avant de la garder : un nombre de personnes est un nombre entre 1 et 50, un e-mail contient un @, un téléphone a au moins 8 chiffres. Sinon, dites ce que vous attendez et redemandez. Pour un choix fermé (jour, créneau, taille), proposez des boutons plutôt qu'une saisie libre. Et si un texte tapé par l'utilisateur casse la mise en forme Markdown (un _ dans un nom), BotStrike renvoie automatiquement le message en texte brut plutôt que de le perdre.
Le nom donné à runCommand doit être exactement celui de la commande, barre oblique comprise : "/resa_nom" et "resa_nom" sont deux commandes différentes.