{"id":50148619,"url":"https://github.com/airkyzzz/annfrenchtechsender","last_synced_at":"2026-05-24T07:02:24.718Z","repository":{"id":355475329,"uuid":"1072321528","full_name":"AirKyzzZ/AnnFrenchTechSender","owner":"AirKyzzZ","description":"Client lourd Python (CustomTkinter + Selenium) d'envoi automatisé de candidatures aux organisations French Tech Bordeaux. Architecture 3 couches, SQLite + JSON + TXT, tests pytest. Réalisation E6 du BTS SIO SLAM.","archived":false,"fork":false,"pushed_at":"2026-05-03T20:38:28.000Z","size":313,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-03T21:14:07.369Z","etag":null,"topics":["bcrypt","bts-sio","customtkinter","desktop-application","e6","pyinstaller","python","selenium","slam","sqlite"],"latest_commit_sha":null,"homepage":"https://github.com/AirKyzzZ/AnnFrenchTechSender#bts-sio-e6--documentation","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AirKyzzZ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-08T15:00:00.000Z","updated_at":"2026-05-03T20:38:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/AirKyzzZ/AnnFrenchTechSender","commit_stats":null,"previous_names":["airkyzzz/annfrenchtechsender"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/AirKyzzZ/AnnFrenchTechSender","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirKyzzZ%2FAnnFrenchTechSender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirKyzzZ%2FAnnFrenchTechSender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirKyzzZ%2FAnnFrenchTechSender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirKyzzZ%2FAnnFrenchTechSender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AirKyzzZ","download_url":"https://codeload.github.com/AirKyzzZ/AnnFrenchTechSender/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirKyzzZ%2FAnnFrenchTechSender/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33424573,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"online","status_checked_at":"2026-05-24T02:00:06.296Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bcrypt","bts-sio","customtkinter","desktop-application","e6","pyinstaller","python","selenium","slam","sqlite"],"created_at":"2026-05-24T07:02:20.943Z","updated_at":"2026-05-24T07:02:24.713Z","avatar_url":"https://github.com/AirKyzzZ.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FT Sender, French Tech Bordeaux\n\n\u003e Client lourd Python d'envoi automatisé de candidatures aux organisations\n\u003e de l'annuaire French Tech Bordeaux.\n\u003e\n\u003e **Réalisation professionnelle n° 2 du dossier de l'épreuve E6 du BTS SIO\n\u003e option SLAM, session 2026** (EPSI Bordeaux).\n\n[![Python](https://img.shields.io/badge/python-3.11-blue?style=flat-square)](https://www.python.org/)\n[![Tests](https://img.shields.io/badge/tests-pytest-green?style=flat-square)](https://docs.pytest.org/)\n[![License](https://img.shields.io/badge/license-Educational-orange?style=flat-square)](#licence-et-responsabilité)\n\n---\n\n## Sommaire\n\n- [Documentation BTS SIO E6](#documentation-bts-sio-e6)\n- [Aperçu du projet](#aperçu-du-projet)\n- [Fonctionnalités](#fonctionnalités)\n- [Pré-requis](#pré-requis)\n- [Installation](#installation)\n- [Utilisation](#utilisation)\n- [Architecture du projet](#architecture-du-projet)\n- [Choix techniques](#choix-techniques)\n- [Tests](#tests)\n- [Build (exécutable standalone)](#build-exécutable-standalone)\n- [Technologies](#technologies)\n- [Historique des versions](#historique-des-versions)\n- [Licence et responsabilité](#licence-et-responsabilité)\n- [Auteur](#auteur)\n\n---\n\n## Documentation BTS SIO E6\n\nDocumentation technique complète à l'attention de la commission d'interrogation E6.\nTout est versionné dans le dossier [`docs/`](docs/).\n\n| Document | Contenu |\n|---|---|\n| [`docs/README.md`](docs/README.md) | Index de la documentation et parcours suggéré pour le jury |\n| [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Stack, architecture en trois couches, threading, communication thread-safe, choix de stockage |\n| [`docs/COMPETENCES.md`](docs/COMPETENCES.md) | Mapping détaillé des trois compétences SLAM (Concevoir+dev / Maintenance / Gérer les données) avec preuves de code |\n| [`docs/SECURITE.md`](docs/SECURITE.md) | Hachage bcrypt, requêtes SQL paramétrées, isolation par utilisateur, anti-détection Selenium |\n| [`docs/TESTS.md`](docs/TESTS.md) | Stratégie de tests (unitaires, intégration, E2E avec mocks), commandes |\n| [`docs/uml/`](docs/uml/) | Diagrammes Mermaid : cas d'utilisation, séquences (auth, envoi), classes, déploiement, MCD |\n\n**Compétences SLAM couvertes (bloc 2 du référentiel BTS SIO 2026) :**\n\n- ✓ **Concevoir et développer une solution applicative**, POO, threading thread-safe (queues + events), CustomTkinter, Selenium, packaging PyInstaller, tests pytest\n- ✓ **Assurer la maintenance corrective ou évolutive**, Évolution CLI legacy → desktop UI, ajout authentification + SQLite + tests, anti-détection, rotation de session\n- ✓ **Gérer les données**, Hybride SQL + NoSQL : SQLite (relations + agrégations), JSON (config), TXT (blacklist), choix justifié dans la documentation\n\n## Aperçu du projet\n\nL'envoi manuel de candidatures à plusieurs centaines d'organisations est répétitif,\nchronophage et sujet aux doublons. FT Sender automatise ce processus tout en\nrestant **entièrement local** (aucune dépendance à un service cloud), avec\n**authentification multi-utilisateur** et **historique de déduplication** pour\néviter de recontacter une organisation déjà sollicitée avec succès.\n\n## Fonctionnalités\n\n- **Authentification locale** : inscription et connexion avec mot de passe haché (bcrypt, 12 rounds)\n- **Profil candidat** : sauvegarde et modification des informations personnelles (nom, email, téléphone, message de candidature)\n- **Envoi automatisé** : envoi en masse avec barre de progression, statistiques temps réel et logs détaillés\n- **Historique des envois** : suivi des candidatures envoyées, détection des doublons (ne renvoie pas aux entreprises déjà contactées avec succès)\n- **Liste noire** : gestion des organisations à ignorer\n- **Journaux** : visualisation des logs en temps réel avec filtres par niveau\n- **Paramètres** : configuration des délais, timeouts, mode headless et chemins de fichiers\n- **Anti-détection** : masquage de Selenium, user-agent réel, timing humain, rotation de session\n- **Contrôle** : démarrer, mettre en pause et arrêter l'envoi à tout moment\n\n## Pré-requis\n\n- Python 3.10 ou supérieur (testé sur 3.11)\n- Google Chrome installé sur le système\n- Fichier `urls_entreprises.csv` avec les URLs des organisations (généré par le scraper)\n\n## Installation\n\n```bash\n# Cloner le dépôt\ngit clone https://github.com/AirKyzzZ/AnnFrenchTechSender.git\ncd AnnFrenchTechSender\n\n# Créer un environnement virtuel\npython -m venv venv\nsource venv/bin/activate  # macOS / Linux\n# ou: venv\\Scripts\\activate  # Windows\n\n# Installer les dépendances\npip install -r requirements.txt\n```\n\n## Utilisation\n\n### Lancer l'application desktop\n\n```bash\npython app/main.py\n```\n\n### Première utilisation\n\n1. **Écran de connexion** : créez un compte (nom d'utilisateur + mot de passe) puis connectez-vous\n2. **Onglet Profil** : remplissez vos informations personnelles et votre message de candidature, puis cliquez sur « Enregistrer »\n3. **Onglet Paramètres** : ajustez les délais et options si nécessaire\n4. **Onglet Envoi** : cliquez sur « Démarrer l'envoi » (cochez « Mode test » pour un essai sans envoi réel)\n5. **Suivi** : observez la progression, les statistiques et les logs en temps réel\n\n### Scraper les URLs (si nécessaire)\n\nSi vous n'avez pas encore le fichier `urls_entreprises.csv` :\n\n```bash\npython scripts/scrapper.py\n```\n\n### Scripts CLI (legacy)\n\nLes scripts en ligne de commande originaux sont conservés dans `scripts/` :\n\n```bash\npython scripts/sender.py                       # envoi en mode terminal\npython scripts/sender.py --dry-run             # mode test sans envoi réel\npython scripts/sender.py --visible             # mode visible (fenêtre Chrome)\npython scripts/blacklist_manager.py list       # gestion de la liste noire\npython scripts/blacklist_manager.py add \u003curl\u003e\npython scripts/blacklist_manager.py remove \u003curl\u003e\n```\n\n## Architecture du projet\n\n```\nAnnFrenchTechSender/\n├── app/                           # Application desktop\n│   ├── main.py                    # Point d'entrée (init DB, thème, fenêtre)\n│   ├── core/                      # Logique métier\n│   │   ├── sender_engine.py       # Moteur d'envoi (thread worker + Selenium)\n│   │   ├── scraper_engine.py      # Scraping des URLs de l'annuaire\n│   │   └── selenium_manager.py    # Configuration et gestion de Chrome\n│   ├── data/                      # Couche données\n│   │   ├── database.py            # Base de données SQLite (tables, requêtes)\n│   │   ├── auth_manager.py        # Authentification (bcrypt, inscription, connexion)\n│   │   ├── models.py              # Modèles de données (User, UserProfile, Settings, Stats)\n│   │   ├── profile_manager.py     # Gestion des profils (SQLite)\n│   │   ├── history_manager.py     # Historique des envois (SQLite, détection doublons)\n│   │   ├── blacklist_manager.py   # Liste noire (fichier TXT = NoSQL)\n│   │   └── config_manager.py      # Configuration (fichier JSON = NoSQL)\n│   └── ui/                        # Interface utilisateur (CustomTkinter)\n│       ├── main_window.py         # Fenêtre principale (login → dashboard)\n│       ├── theme.py               # Thème dark-blue et constantes UI\n│       ├── components/            # Composants réutilisables\n│       │   ├── navigation.py\n│       │   ├── stats_widget.py\n│       │   └── log_viewer.py\n│       └── frames/                # Écrans de l'application\n│           ├── login_frame.py\n│           ├── profile_frame.py\n│           ├── sending_frame.py\n│           ├── blacklist_frame.py\n│           ├── logs_frame.py\n│           └── settings_frame.py\n├── tests/                         # Tests automatisés (pytest)\n│   ├── conftest.py\n│   ├── test_models.py\n│   ├── test_database.py\n│   ├── test_auth.py\n│   ├── test_blacklist.py\n│   ├── test_config.py\n│   ├── test_history.py\n│   ├── test_integration.py\n│   └── test_e2e.py\n├── scripts/                       # Scripts CLI legacy\n├── docs/                          # Documentation BTS SIO E6 (voir Sommaire)\n├── data/                          # Données utilisateur (gitignored)\n├── requirements.txt               # Dépendances de production\n├── requirements-dev.txt           # Dépendances de développement\n└── build.spec                     # Configuration PyInstaller\n```\n\n## Choix techniques\n\n### SQL vs NoSQL, hybridation justifiée\n\nLe projet utilise **trois types de stockage** complémentaires, chacun adapté à\nla nature de la donnée :\n\n| Données | Stockage | Justification |\n|---------|----------|---------------|\n| Utilisateurs, profils, historique | **SQLite** (relationnel) | Clés étrangères (`user_id`), agrégations (`COUNT`, `CASE WHEN`), transactions, contraintes `UNIQUE` |\n| Liste noire | **Fichier TXT** (NoSQL plat) | Liste sans relations, éditable manuellement, simple à versionner |\n| Configuration | **Fichier JSON** (NoSQL document) | Paires clé/valeur sans relations, lisible par un humain |\n\n### Sécurité\n\n- **Mots de passe** : hachés avec **bcrypt** (sel aléatoire, 12 rounds). Jamais stockés en clair.\n- **Injection SQL** : requêtes paramétrées (`?`) systématiquement, jamais de `f-string` dans le SQL.\n- **Messages d'erreur** : génériques pour ne pas révéler l'existence d'un compte.\n- **Isolation par utilisateur** : tous les `SELECT` filtrent par `user_id`.\n\n### Architecture\n\n- **Séparation des responsabilités** : `data/` (persistance), `core/` (logique métier), `ui/` (interface)\n- **Communication thread-safe** : 4 queues + 2 events entre le worker d'envoi et l'IHM\n- **Encapsulation POO** : chaque module est une classe avec une responsabilité unique\n\n## Tests\n\n```bash\n# Installer les dépendances de développement\npip install -r requirements-dev.txt\n\n# Lancer tous les tests\npython -m pytest tests/ -v\n```\n\n| Type | Fichiers | Objectif |\n|------|----------|----------|\n| **Unitaires (TU)** | `test_models`, `test_database`, `test_auth`, `test_blacklist`, `test_config`, `test_history` | Tester chaque classe en isolation |\n| **Intégration (TI)** | `test_integration` | Tester les interactions entre modules (auth → profil → historique) |\n| **E2E (TE2E)** | `test_e2e` | Simuler un envoi complet avec mocks Selenium |\n\nVoir [`docs/TESTS.md`](docs/TESTS.md) pour le détail.\n\n## Build (exécutable standalone)\n\n```bash\npip install -r requirements-dev.txt\npyinstaller build.spec\n```\n\nL'exécutable est généré dans le dossier `dist/`.\n\n## Technologies\n\n- **Python 3.11**, langage principal\n- **CustomTkinter**, interface graphique moderne\n- **Selenium** + **WebDriver Manager**, automatisation du navigateur\n- **SQLite**, base de données relationnelle (stdlib Python)\n- **bcrypt**, hachage sécurisé des mots de passe\n- **pytest**, framework de tests\n- **PyInstaller**, packaging en exécutable autonome\n- **Git / GitHub**, versionnage et suivi des problèmes\n\n## Historique des versions\n\n| Période | Évolution |\n|---|---|\n| **Mars 2026** | Authentification, base SQLite, historique de déduplication, suite de tests complète |\n| **Février 2026** | Refonte en application desktop CustomTkinter (interface graphique) |\n| **Octobre 2025** | Ajout de la liste noire, amélioration des logs |\n| **Février 2025** | Version initiale (CLI dans `scripts/`) |\n\n## Licence et responsabilité\n\nCe projet est fourni à des fins éducatives dans le cadre d'un projet de classe\n(BTS SIO, EPSI Bordeaux). L'utilisateur est seul responsable de son utilisation.\nAssurez-vous de respecter les conditions d'utilisation du site French Tech Bordeaux.\n\n## Auteur\n\n**Maxime Louis François Mansiet**, étudiant BTS SIO à l'EPSI Bordeaux\n\n- Portfolio : [maximemansiet.fr](https://maximemansiet.fr)\n- GitHub : [@AirKyzzZ](https://github.com/AirKyzzZ)\n- LinkedIn : [maxime-mansiet](https://linkedin.com/in/maxime-mansiet)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairkyzzz%2Fannfrenchtechsender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fairkyzzz%2Fannfrenchtechsender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairkyzzz%2Fannfrenchtechsender/lists"}