mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-23 15:08:13 +02:00
fix: Corriger l'affichage des emojis dans les stories Facebook
Problème: Les emojis s'affichaient comme des carrés bizarres dans les stories publiées sur Facebook (alors que la prévisualisation fonctionnait). Cause: Le téléchargement des images emoji depuis le CDN Twemoji par défaut échouait lors de la génération de l'image de story côté serveur. Solution: 1. Utilisation d'un CDN plus fiable (jsDelivr) au lieu du CDN Twemoji par défaut 2. Ajout d'une logique de retry (3 tentatives avec exponential backoff) 3. Ajout d'un timeout de 10 secondes pour éviter les blocages 4. Meilleure gestion des erreurs avec logs détaillés 5. Cache des emojis téléchargés pour améliorer les performances Les emojis devraient maintenant s'afficher correctement dans les stories Facebook publiées depuis l'application.
This commit is contained in:
1 file changed
+59
-18
@@ -19,7 +19,10 @@ export class EmojiRenderer {
|
|||||||
*/
|
*/
|
||||||
private parseTextWithEmojis(text: string): EmojiSegment[] {
|
private parseTextWithEmojis(text: string): EmojiSegment[] {
|
||||||
const emojis = parse(text);
|
const emojis = parse(text);
|
||||||
console.log(`📝 Parse texte: "${text}" => ${emojis.length} emoji(s) trouvé(s)`);
|
|
||||||
|
if (emojis.length > 0) {
|
||||||
|
console.log(`📝 Texte avec ${emojis.length} emoji(s) détecté(s)`);
|
||||||
|
}
|
||||||
|
|
||||||
if (emojis.length === 0) {
|
if (emojis.length === 0) {
|
||||||
return [{ type: 'text', content: text }];
|
return [{ type: 'text', content: text }];
|
||||||
@@ -29,8 +32,6 @@ export class EmojiRenderer {
|
|||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
|
|
||||||
for (const emoji of emojis) {
|
for (const emoji of emojis) {
|
||||||
console.log(` - Emoji détecté: "${emoji.text}" => URL: ${emoji.url}`);
|
|
||||||
|
|
||||||
// Add text before emoji
|
// Add text before emoji
|
||||||
if (emoji.indices[0] > lastIndex) {
|
if (emoji.indices[0] > lastIndex) {
|
||||||
const textContent = text.substring(lastIndex, emoji.indices[0]);
|
const textContent = text.substring(lastIndex, emoji.indices[0]);
|
||||||
@@ -61,25 +62,67 @@ export class EmojiRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download and cache emoji image
|
* Convert default Twemoji URL to jsDelivr CDN (more reliable)
|
||||||
|
* Example: https://twemoji.maxcdn.com/v/latest/72x72/1f600.png
|
||||||
|
* Becomes: https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/72x72/1f600.png
|
||||||
|
*/
|
||||||
|
private convertToReliableCDN(url: string): string {
|
||||||
|
// Extract the emoji filename (e.g., "1f600.png")
|
||||||
|
const match = url.match(/\/([a-f0-9\-]+\.png)$/i);
|
||||||
|
if (!match) return url;
|
||||||
|
|
||||||
|
const filename = match[1];
|
||||||
|
// Use jsDelivr CDN which is more reliable
|
||||||
|
return `https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/72x72/${filename}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download and cache emoji image with retry logic
|
||||||
*/
|
*/
|
||||||
private async getEmojiImage(url: string): Promise<Buffer> {
|
private async getEmojiImage(url: string): Promise<Buffer> {
|
||||||
if (this.emojiCache.has(url)) {
|
// Use reliable CDN URL
|
||||||
return this.emojiCache.get(url)!;
|
const reliableUrl = this.convertToReliableCDN(url);
|
||||||
|
|
||||||
|
if (this.emojiCache.has(reliableUrl)) {
|
||||||
|
return this.emojiCache.get(reliableUrl)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 Téléchargement emoji depuis:', url);
|
console.log('🔍 Téléchargement emoji depuis:', reliableUrl);
|
||||||
const response = await fetch(url);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
// Retry logic: try up to 3 times
|
||||||
console.error(`❌ Erreur téléchargement emoji: ${response.status} ${response.statusText}`);
|
let lastError: Error | null = null;
|
||||||
throw new Error(`Failed to fetch emoji: ${response.status}`);
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
||||||
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), 10000); // 10 second timeout
|
||||||
|
|
||||||
|
const response = await fetch(reliableUrl, {
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Emoji téléchargé avec succès');
|
||||||
|
const buffer = Buffer.from(await response.arrayBuffer());
|
||||||
|
this.emojiCache.set(reliableUrl, buffer);
|
||||||
|
return buffer;
|
||||||
|
} catch (error) {
|
||||||
|
lastError = error as Error;
|
||||||
|
console.warn(`⚠️ Tentative ${attempt}/3 échouée:`, error instanceof Error ? error.message : error);
|
||||||
|
|
||||||
|
if (attempt < 3) {
|
||||||
|
// Wait before retry (exponential backoff: 500ms, 1000ms)
|
||||||
|
await new Promise(resolve => setTimeout(resolve, attempt * 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Emoji téléchargé avec succès');
|
console.error(`❌ Échec téléchargement emoji après 3 tentatives:`, lastError);
|
||||||
const buffer = Buffer.from(await response.arrayBuffer());
|
throw lastError || new Error('Failed to fetch emoji');
|
||||||
this.emojiCache.set(url, buffer);
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,10 +173,8 @@ export class EmojiRenderer {
|
|||||||
|
|
||||||
ctx.drawImage(emojiImage, currentX, emojiY, emojiSize, emojiSize);
|
ctx.drawImage(emojiImage, currentX, emojiY, emojiSize, emojiSize);
|
||||||
currentX += emojiSize;
|
currentX += emojiSize;
|
||||||
console.log(`✅ Emoji "${segment.content}" dessiné avec succès`);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`❌ Erreur lors du chargement/rendu de l'emoji "${segment.content}":`, error);
|
console.error(`❌ Impossible de charger l'emoji "${segment.content}":`, error instanceof Error ? error.message : error);
|
||||||
console.error(' URL:', segment.url);
|
|
||||||
// Fallback: draw text representation
|
// Fallback: draw text representation
|
||||||
ctx.fillText(segment.content, currentX, y);
|
ctx.fillText(segment.content, currentX, y);
|
||||||
currentX += ctx.measureText(segment.content).width;
|
currentX += ctx.measureText(segment.content).width;
|
||||||
|
|||||||
Reference in new issue
Block a user