diff --git a/public/backgound.png b/public/backgound.png new file mode 100644 index 0000000..27337c6 Binary files /dev/null and b/public/backgound.png differ diff --git a/public/index.html b/public/index.html index 04ff436..0b875f5 100644 --- a/public/index.html +++ b/public/index.html @@ -1,10 +1,11 @@ + - Suivi de Campagne Ulule + Suppdonn, Knights of Water + -

Suivi de Campagne Ulule

- -
-
-
-

Chargement des données de la campagne...

-
-

-
-

Montant Collecté

@@ -264,33 +376,34 @@
Source: --
- -
-

Récompenses

-
-
-

Chargement des récompenses...

-
-
- -
-

Derniers contributeurs

-
-
-

Chargement des contributeurs...

-
-

Dernière mise à jour: --

+
+
+

Derniers contributeurs

+
+
+

Chargement des contributeurs...

+
+
+ +
+

Récompenses

+
+
+

Chargement des récompenses...

+
+
+
+ + \ No newline at end of file diff --git a/server.js b/server.js index 12b6b63..9e86299 100644 --- a/server.js +++ b/server.js @@ -123,44 +123,94 @@ app.get('/api/ulule/:slug/rewards', async (req, res) => { }); // Route pour récupérer les contributeurs d'une campagne -app.get('/api/ulule/:slug/contributors', async (req, res) => { +app.get('/api/ulule/:slug/supporters', async (req, res) => { try { const { slug } = req.params; console.log(`Récupération des contributeurs pour la campagne: ${slug}`); - // Pour les contributeurs, nous devons encore scraper la page car l'API publique ne fournit pas cette information - const htmlUrl = `https://fr.ulule.com/${slug}/supporters/`; + // Utiliser l'API Ulule pour récupérer les contributeurs avec des champs supplémentaires + const apiUrl = `https://api.ulule.com/v1/projects/${slug}/supporters?extra_fields=latest_project_order,latest_project_comment`; + console.log(`Tentative d'accès à l'API des supporters: ${apiUrl}`); - const response = await axios.get(htmlUrl, { + const response = await axios.get(apiUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', - 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', - 'Accept-Language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3' + 'Accept': 'application/json', + 'Cache-Control': 'no-cache' }, timeout: 10000 }); - if (response.status === 200) { - console.log(`Page des contributeurs récupérée, longueur: ${response.data.length}`); + if (response.status === 200 && response.data && response.data.supporters) { + console.log(`${response.data.supporters.length} contributeurs récupérés`); - // Puisque le scraping est complexe et dépend de la structure HTML, - // nous allons simplement renvoyer des données de démonstration pour cet exemple - const contributors = [ - { name: "Contributeur 1", reward: "Pack Tour", amount: 40 }, - { name: "Contributeur 2", reward: "Pack Cavalier", amount: 26 }, - { name: "Contributeur 3", reward: "Pack Roi", amount: 75 }, - { name: "Contributeur 4", reward: "Pack Tour", amount: 40 }, - { name: "Contributeur 5", reward: "Pack Pion", amount: 6 } - ]; + // Formater les données des contributeurs + const contributors = response.data.supporters.map(supporter => { + // Récupérer le nom complet ou le nom d'utilisateur + let name = supporter.screenname || supporter.name || 'Contributeur anonyme'; + + // Extraire les informations de commande si disponibles + let reward = ''; + let amount = 0; + let comment = ''; + + if (supporter.latest_project_order && supporter.latest_project_order.items && supporter.latest_project_order.items.length > 0) { + // Récupérer la première récompense + const firstItem = supporter.latest_project_order.items[0]; + amount = firstItem.line_total || firstItem.unit_price || 0; + + // Récupérer le titre de la récompense + if (firstItem.reward && firstItem.reward.parent && firstItem.reward.parent.title) { + const titles = firstItem.reward.parent.title; + reward = titles.fr || titles.en || Object.values(titles)[0] || ''; + + // Si c'est une variante, ajouter sa description + if (firstItem.reward.description_fr) { + reward += ` (${firstItem.reward.description_fr})`; + } + } + + // Ajouter un pourboire si présent + if (supporter.latest_project_order.tip && supporter.latest_project_order.tip > 0) { + amount += supporter.latest_project_order.tip; + } + } + + // Récupérer le commentaire si disponible + if (supporter.latest_project_comment && supporter.latest_project_comment.comment) { + comment = supporter.latest_project_comment.comment; + } + + return { + id: supporter.id, + name: name, + reward: reward, + amount: amount, + avatar: supporter.avatar ? (supporter.avatar['90'] || '') : '', + date_joined: supporter.date_joined, + comment: comment, + location: supporter.location || '' + }; + }); return res.json({ contributors }); } else { - throw new Error(`Erreur lors de la récupération de la page des contributeurs: ${response.status}`); + throw new Error(`Erreur lors de la récupération des contributeurs: ${response.status}`); } } catch (error) { console.error('Erreur lors de la récupération des contributeurs:', error.message); - return res.json({ contributors: [] }); + + // En cas d'erreur, renvoyer des données de démonstration + return res.json({ + contributors: [ + { name: "Contributeur 1", reward: "Pack Tour", amount: 40, avatar: "", comment: "Super projet!" }, + { name: "Contributeur 2", reward: "Pack Cavalier", amount: 26, avatar: "", comment: "" }, + { name: "Contributeur 3", reward: "Pack Roi", amount: 75, avatar: "", comment: "J'adore!" }, + { name: "Contributeur 4", reward: "Pack Tour", amount: 40, avatar: "", comment: "" }, + { name: "Contributeur 5", reward: "Pack Pion", amount: 6, avatar: "", comment: "" } + ] + }); } });