Skip to content

Repository files navigation

Deal-Voyager

Ton Forfait, Ton Choix

Deal-Voyager est un comparateur de forfaits mobiles français, 100 % indépendant. Il scrape automatiquement les prix des opérateurs (MNO/MVNO), puis les classe au centime près pour vous aider à trouver l'offre la plus honnête : sans partenariat financier, sans publicité et sans bullshit.

TypeScript Vue.js Nuxt TailwindCSS Node.js Express Crawlee Playwright PostgreSQL Docker


Fonctionnalités principales

  • Scraping automatisé et contrôlé : Crawlee + Playwright/Cheerio pour 18 opérateurs, avec retries, sessions, limites de concurrence, détection des blocages et validation avant sauvegarde. Cron horaire, déclenchement manuel, détection 4G/5G et Data Europe/DOM.
  • Classement transparent sur 1 an : tri basé sur le coût annuel total, avec prix mensuel x 12, carte SIM, frais d'activation et frais de résiliation. Score euro/Go calculé.
  • Design néobrutaliste et dark mode : interface avec bordures épaisses, contrastes forts, ombres nettes et dark mode dynamique. Inclut une page 404 sur-mesure.
  • Filtrage avancé : slider interactif de 0 à 500 Go, saisie directe au Go près et filtre exclusif par réseau (Orange, SFR, Bouygues, Free).
  • Bot Discord dédié : alertes de nouveaux forfaits formatées en temps réel pour vos serveurs.
  • Liens directs sans affiliation : accès en un clic aux pages opérateurs, zéro tracking.
  • Control Room : panneau d'administration hybride, accessible uniquement via /admin et protégé par Basic Auth, avec suivi du scraping en temps réel, gestion des frais par opérateur, label "Fairplay" et bouton de purge de la base.
  • Déploiement Docker sécurisé : stack complète (frontend, backend, BDD) avec credentials configurables via .env, proxy interne Nitro et zéro port exposé inutilement.

Opérateurs couverts

Opérateur Type Réseau Détection 4G/5G
Sosh MNO low-cost Orange Oui
RED by SFR MNO low-cost SFR Oui
B&You MNO low-cost Bouygues Telecom Oui
Free Mobile MNO Free Oui
YouPrice MVNO Orange / SFR / Bouygues Telecom Oui (multi-réseau)
Coriolis MVNO SFR Oui
La Poste Mobile MVNO Bouygues Telecom Oui
NRJ Mobile MVNO Bouygues Telecom Oui
Auchan Telecom MVNO Bouygues Telecom Oui
Cdiscount Mobile MVNO Bouygues Telecom Oui
Syma Mobile MVNO SFR Oui
Lebara MVNO SFR Oui
Lycamobile MVNO Bouygues Telecom Oui
Prixtel MVNO SFR Oui
TeleCoop MVNO Orange Oui
Akeo Telecom MVNO Orange / Bouygues Telecom Oui
Nordnet MVNO Orange Oui
France Téléphone (Bleutel) MVNO Orange / Bouygues Telecom Oui

Architecture

                    ┌─────────────────────────┐
                    │     Navigateur (port    │
                    │     configurable)       │
                    └────────────┬────────────┘
                                 │
                    ┌────────────▼────────────┐                  ┌───────────────┐
                    │   Frontend Nuxt (SSR)   │                  │  API Discord  │
                    │   Proxy /api/v1/** ─────┼──► Backend ──────► (Bot alerts & │
                    │   Auth HTTP Basic       │    Express:3001  │  Webhooks)    │
                    └─────────────────────────┘        │         └───────────────┘
                                                       ▼
                                                 ┌────────────────┐
                                                 │ PostgreSQL:5432│
                                                 └────────────────┘

Seul le port du frontend est exposé. Le backend et PostgreSQL communiquent exclusivement via le réseau Docker interne. Le Backend effectue lui-même ses requêtes sortantes vers l'API de Discord.

Couche Technologie Rôle
Frontend Nuxt 4 (Vue 3) + Tailwind CSS Interface utilisateur, SSR, proxy API via Nitro routeRules
Backend Node.js + Express 5 + discord.js API REST, orchestration du scraping, alertes via Discord Bot, rate limiting
Scrapers Crawlee + Playwright + Cheerio HTTP prioritaire quand possible, navigateur pour les parcours interactifs, validation centralisée
BDD PostgreSQL 15 + Prisma ORM Stockage des forfaits (MobilePlan), paramétrage (OperatorSettings) et serveurs Discord cibles (DiscordSubscription)
Infra Docker Compose Conteneurisation, réseau interne, healthchecks

Demarrage Rapide

Prerequis

  • Docker (Engine + Compose)
  • 4 Go de RAM minimum (instances Chromium headless pendant le scraping)

1. Configuration

git clone https://github.com/votre-username/Deal-Voyager.git
cd Deal-Voyager
cp .env.example .env

Editez le fichier .env avec vos propres credentials :

# Admin credentials (OBLIGATOIRE)
DEAL_VOYAGER_ADMIN_USERNAME=votre_identifiant
DEAL_VOYAGER_ADMIN_PASSWORD=votre_mot_de_passe

# Base de données PostgreSQL (OBLIGATOIRE)
DEAL_VOYAGER_POSTGRES_USER=dealvoyager
DEAL_VOYAGER_POSTGRES_PASSWORD=votre_mdp_postgres
DEAL_VOYAGER_POSTGRES_DB=deal_voyager

# Configuration Discord Bot (Requis pour /deal-setup et les alertes automatiques)
DISCORD_CLIENT_ID=votre_client_id_discord
DISCORD_BOT_TOKEN=votre_token_bot_discord

# Port public (optionnel, défaut: 3000)
DEAL_VOYAGER_APP_PORT=3000
DEAL_VOYAGER_CORS_ORIGIN=http://localhost:3000

Important : Le déploiement refuse de démarrer si les variables obligatoires ne sont pas définies.

2. Lancement

docker compose up -d --build

Le conteneur backend execute automatiquement prisma db push au demarrage pour creer/mettre a jour le schema.

Utilisation du proxy de collecte

Le compose démarre un proxy Squid interne nommé proxy. Par défaut, Crawlee et Playwright font transiter les requêtes des scrapers par ce service grâce à :

SCRAPER_PROXY_URLS=http://proxy:3128

Le proxy n'expose aucun port sur la machine hôte : seul le réseau Docker de Deal Voyager peut l'utiliser. Il centralise la sortie HTTP(S) des collecteurs, mais ne masque pas l'adresse IP publique de votre connexion Internet.

Pour utiliser un ou plusieurs proxies externes, indiquez leurs URL séparées par des virgules. Les identifiants peuvent être inclus dans chaque URL :

SCRAPER_PROXY_URLS=http://utilisateur:mot_de_passe@proxy.example:3128,https://proxy2.example:8443

Pour désactiver complètement le routage par proxy, laissez la valeur vide dans votre .env, puis recréez le backend :

SCRAPER_PROXY_URLS=
docker compose up -d --force-recreate backend

Les journaux sont consultables avec docker compose logs -f proxy backend.

3. Acces

Service URL
Comparateur http://localhost:3000
Control Room http://localhost:3000/admin

L'API n'est pas exposee directement - toutes les requetes /api/v1/* passent par le proxy Nuxt.

4. Premier Scraping

  1. Rendez-vous sur la Control Room (authentification HTTP Basic).
  2. Cliquez sur Lancer l'extraction maintenant.
  3. Patientez 1 a 2 minutes - la page suit la progression automatiquement.
  4. Les offres apparaissent sur l'accueil une fois le scraping termine.

5. Configuration du Bot Discord (Optionnel)

Pour permettre à votre communauté de recevoir des alertes automatiques lors de changements de prix :

  1. Créez une application sur le Discord Developer Portal.
  2. Ajoutez un Bot à l'application et récupérez son Token.
  3. Renseignez les variables correspondantes dans votre .env :
    DISCORD_CLIENT_ID=votre_client_id
    DISCORD_BOT_TOKEN=votre_token_app
  4. Redémarrez vos conteneurs (docker compose up -d --build). Le bouton "Inviter le Bot" de l'accueil utilisera désormais votre Client ID.
  5. Une fois le bot invité sur un serveur Discord, un administrateur doit taper la commande /deal-setup dans le salon souhaité pour activer l'envoi des notifications automatiques (Format Embed Néo-Brutaliste).

Securité & Privacy

Mesure Détail
Pas de credentials par défaut Aucun fallback admin/secret. Variables d'environnement obligatoires.
Comparaison timing-safe Mots de passe comparés via XOR constant-time (backend + frontend).
Sécurité par l'obscurité Le bouton /admin n'est pas affiché publiquement dans l'interface.
Rate limiting 10 tentatives max par IP sur 15 min (backend).
API interne Le backend n'est pas exposé : les appels web passent par le proxy inverse Nitro du frontend.
Proxy de collecte Squid accepte uniquement le trafic du réseau Docker et n'expose aucun port public.
PostgreSQL isolé Port 5432 non exposé, accessible uniquement via le réseau Docker.
CORS restreint Whitelist configurable au lieu de origin: *.
Auth header transmis Le header HTTP Basic du navigateur est stocké côté serveur (useState) et réutilisé pour les appels API.

Endpoints API (/api/v1)

Tous accessibles via le proxy frontend. Les routes marquees d'un cadenas necessitent l'authentification Basic.

Methode Endpoint Auth Description
GET /deals Toutes les offres triees par score.
GET /stats Etat du backend (nombre d'offres, dernier scraping, statut).
GET /operators Configuration par operateur (SIM, frais, fairplay).
POST /scrape Oui Declenche le scraping global.
PUT /operators/:name/simprice Oui Met a jour les frais (SIM, activation, resiliation).
PUT /operators/:name/fairplay Oui Bascule le label Fairplay.
DELETE /clear Oui Purge la base de donnees.

Structure du Projet

Deal-Voyager/
├── backend/
│   ├── src/
│   │   ├── controllers/        # Logique de reponse HTTP
│   │   ├── middlewares/        # Auth Basic + rate limiting
│   │   ├── services/
│   │   │   └── scrapers/       # Un fichier par operateur
│   │   │       ├── sosh.scraper.ts
│   │   │       ├── red.scraper.ts
│   │   │       ├── byou.scraper.ts
│   │   │       ├── free.scraper.ts
│   │   │       ├── youprice.scraper.ts
│   │   │       ├── coriolis.scraper.ts
│   │   │       ├── laposte.scraper.ts
│   │   │       ├── nrj.scraper.ts
│   │   │       ├── auchan.scraper.ts
│   │   │       ├── cdiscount.scraper.ts
│   │   │       ├── syma.scraper.ts
│   │   │       ├── lebara.scraper.ts
│   │   │       ├── lycamobile.scraper.ts
│   │   │       ├── prixtel.scraper.ts
│   │   │       ├── telecoop.scraper.ts
│   │   │       ├── akeo.scraper.ts
│   │   │       ├── nordnet.scraper.ts
│   │   │       ├── francetelephone.scraper.ts
│   │   │       └── types.ts
│   │   ├── routes/
│   │   └── lib/                # Prisma Client
│   ├── prisma/schema.prisma
│   ├── entrypoint.sh
│   └── Dockerfile
│
├── frontend/
│   ├── components/             # DealCard, DataSlider, OperatorBadge...
│   ├── layouts/
│   ├── middleware/             # Auth HTTP Basic (route middleware)
│   ├── pages/                 # Accueil + Admin
│   ├── assets/css/
│   └── Dockerfile
│
├── compose.yml
├── .env.example                # Template de configuration
├── CHANGELOG.md
└── README.md

Deploiement sur un Serveur

Pour exposer Deal-Voyager sur un domaine avec HTTPS, ajoutez un reverse proxy (Caddy recommande) devant le frontend :

# Exemple Caddyfile
deal-voyager.mondomaine.fr {
    reverse_proxy frontend:3000
}

Pensez a :

  • Rediriger les ports 80/443 sur votre routeur
  • Pointer le DNS vers l'IP publique de votre serveur
  • Mettre a jour DEAL_VOYAGER_APP_PORT si necessaire

Licence

GNU General Public License v3.0 - Voir LICENSE.

Releases

Packages

Contributors

Languages