Javis OS
Javis OS는 기업가를 돕는 에이전시 AI로, 업무를 지원하고 함께 성장합니다
튜니지아 공공 입찰 공고를 매일 제공, 분야·주별 정렬, 마감일·보증금 표시, 무료·가입 필요 없음
Les nouveaux appels d'offres publics tunisiens chaque jour (source officielle HAICOP), triés par métier et par gouvernorat, avec date limite et caution. Gratuit, sans inscription. طلبات العروض العمومي
비즈니스HTML · PythonGitHub @Ah6259온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Les nouveaux appels d'offres publics tunisiens chaque jour, tries par metier et par gouvernorat (source officielle HAICOP)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Site gratuit, sans inscription : chaque jour, les nouveaux appels d'offres publics tunisiens,
triés par métier et par gouvernorat, avec la date limite (en rouge à moins de 7 jours),
la caution provisoire et le lien vers la fiche officielle. Français + arabe (?lang=ar).
Aussi : recherche par mots-clés (français et arabe, sans souci d'accents), résumé traduit des objets
(arabe -> français et inversement, glossaire maison, « traduction automatique approximative »), rappels « J-7 … J-1 /
Dernier jour » et section « Clôturent bientôt », ventes aux enchères de la Douane tunisienne (encheres/),
publication gratuite d'appels d'offres par les entreprises privées (publier/), alerte Telegram quotidienne.
Partie payante « Alertes Pro » (abonnement/) : alertes personnalisées (métiers + gouvernorats) chaque matin sur Telegram,
25 DT/mois ou 199 DT/an, sans essai gratuit (depuis le 20/10/2026), sans renouvellement automatique. La consultation reste gratuite.
| Étape | Fichier | Rôle |
|---|---|---|
| 1 | robot/lire_haicop.py | lit lentement les nouvelles fiches (1 page / 2,5 s), les classe par métier et gouvernorat → donnees/appels-offres.json |
| 1 b | robot/lire_douane.py | lit 1 page par jour de la Douane tunisienne (ventes aux enchères publiques) → donnees/encheres.json |
| 1 c | robot/prives.py | lit les réponses du formulaire Google des entreprises (CSV publié), les contrôle → donnees/prives.json |
| 2 | robot/construire_site.py | fabrique les 40 pages : accueil, 10 métiers, 26 gouvernorats, à propos, publier, enchères, sitemap.xml ; résumés traduits par robot/glossaire.py |
| 3 | tools/test_site.mjs + tools/test_pannes.py | tests (le robot ne publie rien si un test échoue) |
| 4 | robot/telegram.py | UN message court groupé sur le canal Telegram (nouveaux par métier + « ⏰ Clôturent dans 2 jours ») ; mémoire donnees/telegram-envoyes.json |
| 5 | .github/workflows/maj.yml | fait 1 → 4 chaque jour à 6h05 (heure de Tunis) puis commit ; GitHub Pages republie |
Réglages d'Ahmed : un seul fichier, robot/reglages.py (adresse publique du canal Telegram, du canal WhatsApp,
du formulaire Google et de son CSV). Vide = bouton caché / « Bientôt ». Les jetons secrets ne vont JAMAIS dans ce fichier.
Pages : index.html, metier/<métier>/, gouvernorat/<gouvernorat>/, a-propos/, publier/, encheres/, abonnement/, abonnement/conditions/.
Fichiers à la main : assets/style.css, assets/page.js (langue, en-tête, pied), assets/app.js (filtres, tri,
recherche, étiquettes J-N, dates selon le téléphone du visiteur), assets/logo.svg, assets/og-image-v6.jpg (source : tools/og-image.html).
Photo du bandeau : mosaïque de 4 vraies photos prises en Tunisie (BTP, informatique, santé, port de Radès), car les
marchés publics ne sont pas que la construction : assets/photos/marches-publics-mosaique.jpg (ordinateur, 4 côte à côte) et
-carre.jpg (téléphone, 2 × 2). Wikimedia Commons : Habib M'henni (CC BY 4.0 et CC BY-SA 3.0), Touzrimounir (CC BY-SA 4.0),
M. Rais (CC BY-SA 3.0) ; crédit de chaque photo sous le bandeau, dans « À propos » et sur l'image d'aperçu ; preuves hors dépôt.
Toutes les pages : translate="no" + <meta name="google" content="notranslate"> (Chrome proposait de traduire en anglais).
Icônes de métier et carte de la Tunisie : SVG faits maison.
Votre avis (accueil #avis, lien « Votre avis » dans le pied de page de toutes les pages) : note facultative (😀🙂😐🙁),
message (obligatoire, ≤ 1000 caractères), e-mail facultatif ; envoyé seulement au clic à Formspree (formulaire mwlpakqj,
commun à tous les sites d'Ahmed) avec les champs cachés site = « Alertes appels d'offres Tunisie » et page.
Code : assets/avis.js ; section : constante AVIS dans construire_site.py ; test : node tools/test_avis.mjs (envoi simulé).
python robot/lire_haicop.py --max 40
python robot/lire_douane.py
python robot/prives.py
python robot/telegram.py --essai (affiche le message Telegram sans l'envoyer)
python robot/construire_site.py
npm install --no-save --no-package-lock jsdom (une fois par PC)
node tools/test_site.mjs
node tools/test_sw.mjs
node tools/test_avis.mjs
python tools/test_pannes.py
bash tools/captures.sh (captures téléphone 340/390 px, FR + AR, dans captures/)
alertesaotunisie./newbot → nom « Alertes AO Tunisie », identifiant finissant par bot → il donne un jeton
(ne le donner à personne, ne jamais le coller dans le chat ni dans un fichier).appels-offres-tunisie → Settings → Secrets and variables → Actions → New repository secret :
TELEGRAM_BOT_TOKEN = le jeton ; TELEGRAM_CANAL = @alertesaotunisie (l'adresse du canal avec @).robot/reglages.py : TELEGRAM_CANAL_URL = "https://t.me/alertesaotunisie" → le bouton « Recevoir les alertes
sur Telegram » apparaît sur le site au prochain passage du robot.Sans ces secrets, le robot ne fait rien (et ne sonne pas en échec). Un appel d'offres n'est jamais annoncé deux fois.
Les abonnés ne sont jamais dans ce dépôt public : ils sont dans le dépôt privé Ah6259/appels-offres-abonnes
(voir son README : activer un abonné depuis l'application GitHub du téléphone, bouton activer-abonne).
TELEGRAM_BOT_TOKEN.robot/reglages.py : TELEGRAM_ROBOT_ALERTES = "AlertesAOTunisieBot".pour_activer) : son code reste « en attente » (rien n'est envoyé)
jusqu'au paiement. Plus d'essai gratuit depuis le 20/10/2026 (décision d'Ahmed) : l'action essai n'existe plus.activer-abonne, action paye, code + mois (1 ou 12) → facture ; le résumé
donne le CODE et un lien WhatsApp pour l'envoyer au client → le client envoie /start CODE au robot.
Nouvel abonné qui paie directement : action paye, code vide, avec nom, téléphone, métiers et gouvernorats.WhatsApp ne permet pas à un robot gratuit de publier dans un canal. Il faudra : créer un canal WhatsApp
(Actus → Canaux → Créer un canal), mettre son adresse dans WHATSAPP_CANAL_URL (robot/reglages.py) pour afficher
le bouton, puis recopier chaque jour le message Telegram (ou plus tard l'API WhatsApp Business, payante).
https://forms.google.com → Formulaire vide, titre « Publier un appel d'offres — Alertes appels d'offres Tunisie ». Paramètres → Réponses : ne pas collecter les adresses e-mail. Créer ces questions, dans cet ordre et avec ces mots (le robot reconnaît les colonnes grâce à eux) :
| Question | Type | Obligatoire |
|---|---|---|
| Nom de l'entreprise | Réponse courte | oui |
| Objet de l'appel d'offres | Réponse courte (15 à 300 caractères) | oui |
| Description (facultatif) | Paragraphe | non |
| Métier | Liste déroulante : BTP / génie civil, Électricité, Informatique, Fournitures et mobilier, Nettoyage / gardiennage, Alimentation, Médical / pharmacie, Transport / véhicules, Études / conseil, Autres | oui |
| Gouvernorat | Liste déroulante : Ariana, Béja, Ben Arous, Bizerte, Gabès, Gafsa, Jendouba, Kairouan, Kasserine, Kébili, Le Kef, Mahdia, La Manouba, Médenine, Monastir, Nabeul, Sfax, Sidi Bouzid, Siliana, Sousse, Tataouine, Tozeur, Tunis, Zaghouan, Plusieurs gouvernorats, Toute la Tunisie | oui |
| Date limite de réception des offres | Date | oui |
| Contact pour les candidats (e-mail ou téléphone de l'entreprise) | Réponse courte | oui |
| Je certifie que ces informations sont exactes et j'accepte leur publication | Cases à cocher (une case « Oui ») | oui |
Onglet Réponses → icône Sheets → Créer une feuille de calcul. Dans la feuille : Fichier → Paramètres → Paramètres régionaux France (dates jj/mm/aaaa).
Feuille : Fichier → Partager → Publier sur le Web → feuille « Réponses au formulaire 1 » → format CSV →
Publier → copier l'adresse (https://docs.google.com/spreadsheets/d/e/…/pub?…output=csv) dans CSV_PRIVES_URL.
Formulaire → Envoyer → lien → « Raccourcir l'URL » → copier () dans .
Objectif : le site reste en vie et honnête même si la source tombe en panne ou si personne ne s'en occupe.
Ce qui tourne tout seul
maj.yml chaque jour : lecture HAICOP → construction → tests → commit. Le ?v= des fichiers CSS/JS est
calculé automatiquement (empreinte des fichiers) : les téléphones ne gardent jamais un ancien style.battement-de-coeur.yml le 1er du mois : petit commit pour que GitHub ne mette pas les robots en pause
(pause automatique après 60 jours sans activité).tests.yml à chaque envoi (push) : les tests (site, service worker, pannes).maj-site (jamais deux commits en même temps).Ce qui protège le site
Source en panne, liste vide, < 30 % du volume habituel, format des fiches changé (champs introuvables) : c'est une panne, jamais « aucun appel d'offres ». Les anciennes annonces sont gardées ; seules les annonces dont la date limite est passée disparaissent (calcul fait aussi avec la date du téléphone du visiteur).
Fichier de données illisible, vide ou qui fond de plus de moitié : reprise de donnees/appels-offres.sauvegarde.json.
Sans sauvegarde : le site déjà publié n'est pas touché.
Bandeau daté « La source officielle n'a pas pu être lue depuis le … » dès que la dernière lecture réussie a 2 jours ou plus (vérifié dans la page ET par le JavaScript selon la date du visiteur). La pastille « Mis à jour le … » donne toujours la date de la dernière lecture réussie.
Textes de la source échappés, liens non officiels remplacés par le lien HAICOP de la fiche.
Ventes aux enchères (Douane) : page injoignable, tableau introuvable, < 30 % des lignes d'avant = panne ; anciennes ventes gardées (les expirées disparaissent), bandeau daté sur la page enchères après 2 jours sans lecture, « échec » au journal.
Entreprises privées : CSV injoignable, vide, corrompu ou colonnes changées = les publications déjà acceptées sont gardées. Les réponses refusées ne sont jamais publiées (seule la raison est gardée, sans leur contenu).
Telegram : secrets absents = rien ; Telegram en erreur = « échec » au journal, le site n'est pas touché, et les messages non partis repartent au passage suivant (jamais deux fois le même appel d'offres).
Réglages mal écrits (robot/reglages.py) : ignorés, bouton caché, « échec » au journal.
Sécurité : robots.txt (moteurs de recherche oui, robots d'IA et aspirateurs non), noai, CSP stricte en balise meta,
anti-iframe, protection légère contre la copie (numéros Tender, liens et champs restent copiables), aucun secret dans le
dépôt (vérifié par le test). Limite : un site GitHub Pages en sous-dossier n'a pas son propre robots.txt pour les robots
(seul ah6259.github.io/robots.txt compte) → le copier dans un dépôt Ah6259.github.io, ou plus tard avec un nom de domaine.
Ce qu'un visiteur voit peut toujours être recopié : la vraie protection = © + preuves datées.
Installation sur le téléphone : sw.js (service worker) = réseau d'abord pour les pages et les données (le cache
ne sert que hors connexion : jamais une vieille liste quand Internet marche) ; CSS/JS versionnés (?v=) = cache puis mise à jour.
Si un téléphone garde une vieille version : changer dans .
Ce qui alerte
donnees/etat-source.json.Quoi faire si une alerte arrive
lire_fiche() dans robot/lire_haicop.py, puis relancer les deux tests ;maj-appels-offres → « Run workflow »
(ou gh workflow run maj.yml -R Ah6259/appels-offres-tunisie).LICENSE « tous droits réservés ». Les annonces viennent du portail officiel de la HAICOP ; chaque carte renvoie à la fiche officielle, seule à faire foi.
https://forms.gle/…FORMULAIRE_PRIVES_URLEnsuite tout est automatique : chaque jour le robot contrôle (champs obligatoires, date limite à venir et ≤ 180 jours, pas de lien, pas de HTML, pas de publicité, pas de doublon, ≤ 3 par entreprise et par jour) et publie avec la mention « Publié par l'entreprise — non vérifié par HAICOP ». Pour retirer une annonce : supprimer sa ligne dans la feuille.
CACHE_VERSIONsw.js