🖼️ Tampons, signatures & filigranes — Image SDK

L'objet global Image permet d'apposer un tampon, une signature ou un filigrane directement sur une image existante (contrat scanné, facture, photo). BotStrike télécharge les images depuis leur URL HTTPS, gère automatiquement le format (PNG/JPG/WEBP/GIF), redimensionne, applique l'opacité et exporte le résultat.

⏳ Bientôt disponible. La création d'images, les signatures et les tampons ne sont pas encore ouverts — ils arrivent prochainement. Voir la page de tarification.
📌 Règle d'or — Tout passe par URL HTTPS. Vous fournissez les URLs publiques de l'image de fond et du tampon/signature. BotStrike télécharge tout, conserve la transparence, et vous renvoie le chemin du fichier final. Aucun fichier local à gérer côté utilisateur.

1 — Le principe

Le bot prend deux URLs :

  1. L'image de base — le contrat, la facture, le document à tamponner
  2. Le tampon ou la signature — un PNG transparent

BotStrike superpose le tampon sur l'image de base à la position (x, y) que vous indiquez. Le résultat est une nouvelle image tamponnée qui peut être renvoyée à l'utilisateur.

2 — API Image

Python — style namespace

MéthodeDescription
Image.open(url)Télécharge et ouvre une image depuis URL HTTPS. Renvoie un objet image.
Image.blank(width, height, color)Crée un fond vide (par défaut blanc)
Image.paste(base, overlay, x, y, width, height, opacity)Colle overlay SUR base. opacity 0..1 pour filigrane.
Image.text(base, text, x, y, size, color)Écrit du texte sur l'image
Image.save(img, 'nom.png')Sauvegarde et retourne le chemin

JavaScript — style chaînable

MéthodeDescription
await Image.open(url)Renvoie un wrapper chaînable
await Image.blank(w, h, color)Fond vide chaînable
await base.paste(overlay, {x, y, width, height, opacity})Superpose overlay
await base.text(text, {x, y, size})Écrit du texte
await base.save('nom.png')Sauvegarde et renvoie le chemin
⚠️ JavaScript : toutes les méthodes Image sont asynchrones — utilisez systématiquement await.

3 — Exemple : tamponner un document

L'utilisateur fournit (via /setdoc, /settampon) les URLs de son document à tamponner et de son tampon. Le bot superpose le tampon dessus et renvoie le résultat.

Python
JavaScript
# URLs configurées une fois et stockées dans Props
doc_url    = Props.get('doc_url')     # ex: https://i.imgur.com/contract.jpg
tampon_url = Props.get('tampon_url')  # ex: https://i.imgur.com/stamp.png

# 1) Charger les deux images depuis leurs URLs HTTPS
base   = Image.open(doc_url)
tampon = Image.open(tampon_url)

# 2) Apposer le tampon SUR le document (en bas Ă  droite, 200px de large)
Image.paste(base, tampon, x=base.width - 250, y=base.height - 250, width=200)

# 3) Ajouter une mention manuscrite à côté
Image.text(base, 'Signe le 22/04/2026',
           x=base.width - 250, y=base.height - 50, size=18, color='#000')

# 4) Sauvegarder et envoyer
path = Image.save(base, 'document_tamponne.png')
bot.sendPhoto(path, '✅ Document tamponné')
const docUrl    = await Props.get('doc_url');
const tamponUrl = await Props.get('tampon_url');

// 1) Charger les deux images depuis URLs HTTPS
const base   = await Image.open(docUrl);
const tampon = await Image.open(tamponUrl);

// 2) Apposer le tampon SUR le document
await base.paste(tampon, {
    x: base.width - 250,
    y: base.height - 250,
    width: 200,
});

// 3) Texte à côté
await base.text('Signe le 22/04/2026', {
    x: base.width - 250,
    y: base.height - 50,
    size: 32,
});

// 4) Sauvegarder et envoyer
const path = await base.save('document_tamponne.png');
await bot.sendPhoto(path, '✅ Document tamponné');

4 — Apposer signature + tampon sur un contrat

Cas typique : un contrat doit être signé par l'utilisateur. Le bot ajoute la signature à gauche et le cachet de l'entreprise à droite.

Python
JavaScript
contrat_url   = args.strip()  # URL du contrat envoyée par l'utilisateur
signature_url = Props.get('signature_url')
tampon_url    = Props.get('tampon_url')

# Charger le contrat (image scannée du document)
base = Image.open(contrat_url)

# Charger les overlays
sig = Image.open(signature_url)
tmp = Image.open(tampon_url)

# Coller la signature en bas Ă  gauche, le tampon en bas Ă  droite
Image.paste(base, sig, x=80,                  y=base.height - 220, width=180)
Image.paste(base, tmp, x=base.width - 280,    y=base.height - 250, width=200)

# Date sous la signature
Image.text(base, 'Le 22/04/2026', x=100, y=base.height - 50, size=20)

path = Image.save(base, 'contrat_signe.png')
bot.sendDocument(path, '✅ Contrat signé et tamponné')
const contratUrl   = (args || '').trim();
const signatureUrl = await Props.get('signature_url');
const tamponUrl    = await Props.get('tampon_url');

const base = await Image.open(contratUrl);
const sig  = await Image.open(signatureUrl);
const tmp  = await Image.open(tamponUrl);

await base.paste(sig, {x: 80,                  y: base.height - 220, width: 180});
await base.paste(tmp, {x: base.width - 280,    y: base.height - 250, width: 200});
await base.text('Le 22/04/2026', {x: 100, y: base.height - 50, size: 32});

const path = await base.save('contrat_signe.png');
await bot.sendDocument(path, '✅ Contrat signé et tamponné');

5 — Filigrane semi-transparent (watermark)

Pour protéger une image (preuve, brouillon), on superpose un logo ou un texte avec une opacité faible (0.2 - 0.4).

Python
JavaScript
photo_url = args.strip()
logo_url  = Props.get('logo_url')

base = Image.open(photo_url)
logo = Image.open(logo_url)

# Filigrane logo au centre, à 25% d'opacité
Image.paste(base, logo,
    x=(base.width - 400) // 2,
    y=(base.height - 400) // 2,
    width=400,
    opacity=0.25)

# Texte "BROUILLON" en rouge par-dessus
Image.text(base, 'BROUILLON', x=300, y=base.height - 200, size=80, color='#FF0000')

path = Image.save(base, 'protege.png')
bot.sendPhoto(path)
const photoUrl = (args || '').trim();
const logoUrl  = await Props.get('logo_url');

const base = await Image.open(photoUrl);
const logo = await Image.open(logoUrl);

await base.paste(logo, {
    x: Math.floor((base.width - 400) / 2),
    y: Math.floor((base.height - 400) / 2),
    width: 400,
    opacity: 0.25,
});

await base.text('BROUILLON', {x: 300, y: base.height - 200, size: 64});

const path = await base.save('protege.png');
await bot.sendPhoto(path);

6 — Créer un certificat depuis un fond vide

Vous voulez générer un certificat de complétion personnalisé sans modèle de base ? Partez d'un fond blanc créé via Image.blank().

Python
JavaScript
logo_url   = Props.get('logo_url')
tampon_url = Props.get('tampon_url')

# Fond blanc 1200x800
base = Image.blank(1200, 800, color='#FFFFFF')

# Logo en haut, centre
logo = Image.open(logo_url)
Image.paste(base, logo, x=500, y=40, width=200)

# Textes
Image.text(base, 'CERTIFICAT DE FORMATION', x=270, y=260, size=42, color='#1a1a2e')
Image.text(base, 'Decerne a',                x=520, y=360, size=22, color='#555')
Image.text(base, message['from']['first_name'], x=440, y=420, size=36, color='#000')
Image.text(base, 'Pour avoir complete la formation BotStrike Pro',
           x=300, y=520, size=18, color='#333')
Image.text(base, 'Le 22/04/2026', x=500, y=620, size=16, color='#666')

# Tampon de l'organisation en bas Ă  droite
tampon = Image.open(tampon_url)
Image.paste(base, tampon, x=900, y=600, width=200, opacity=0.85)

path = Image.save(base, 'certificat.png')
bot.sendPhoto(path, '🏆 Voici votre certificat !')
const logoUrl   = await Props.get('logo_url');
const tamponUrl = await Props.get('tampon_url');

const base = await Image.blank(1200, 800, '#FFFFFF');

const logo = await Image.open(logoUrl);
await base.paste(logo, {x: 500, y: 40, width: 200});

await base.text('CERTIFICAT DE FORMATION', {x: 270, y: 260, size: 64});
await base.text('Decerne a',                {x: 520, y: 360, size: 32});
await base.text(message.from.first_name,    {x: 440, y: 420, size: 64});
await base.text('Pour avoir complete la formation BotStrike Pro',
                {x: 300, y: 520, size: 32});
await base.text('Le 22/04/2026', {x: 500, y: 620, size: 32});

const tampon = await Image.open(tamponUrl);
await base.paste(tampon, {x: 900, y: 600, width: 200, opacity: 0.85});

const path = await base.save('certificat.png');
await bot.sendPhoto(path, '🏆 Voici votre certificat !');

7 — Configuration : commandes /settampon et /setsignature

L'admin enregistre une seule fois l'URL HTTPS de son tampon et de sa signature. Le bot vérifie le format et stocke dans Props.

# Commande : /settampon https://i.imgur.com/stamp.png
url = (args or '').strip()

if not url.startswith('https://'):
    bot.sendMessage('❌ URL invalide. Fournissez un lien HTTPS.')
    return
if not any(url.lower().endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.webp']):
    bot.sendMessage('⚠️ Format non géré. Utilisez PNG (recommandé pour la transparence).')
    return

Props.set('tampon_url', url)
bot.sendMessage('✅ Tampon enregistré !\n\nTestez avec /tamponner en envoyant le lien d\'un document.')

8 — Où héberger les images ?

⚠️ L'URL doit pointer DIRECTEMENT vers le fichier image (terminer par .png, .jpg, …). Pas vers une page de galerie. Test : ouvrez l'URL en navigation privée — vous devez voir l'image seule, sans interface autour.

9 — Préparer un PNG transparent pour signature/tampon

Pour qu'un tampon ou une signature s'intègre parfaitement (sans rectangle blanc autour), il faut un PNG avec fond transparent. Trois options :

  1. remove.bg — Glissez votre photo de signature/tampon → fond auto-supprimé → téléchargez le PNG.
  2. photopea.com — Photoshop gratuit dans le navigateur. Outil "baguette magique" pour effacer le blanc.
  3. Pour une signature manuscrite : signez sur papier blanc, photographiez, puis passez le résultat dans remove.bg.

Une fois le PNG transparent obtenu, hébergez-le et fournissez l'URL au bot.

10 — Bonnes pratiques

11 — Erreurs fréquentes

ErreurCauseSolution
Fond blanc autour du tamponPNG sans canal alphaRefaire le PNG sur remove.bg
Tampon trop grand/petitParamètre width inadaptéAjuster en pixels (200 = signature classique pour image 1200px)
cannot identify image fileURL pointe vers HTML, pas imageTester l'URL en navigation privée — image seule attendue
Erreur de téléchargementURL HTTP au lieu de HTTPSToujours utiliser https://
Tampon invisibleCoordonnées hors imageVérifier que x < base.width et y < base.height
Image vide en JSOubli de awaitToujours await base.save(...)