Onglet « Carte et corrections » : glisser une photo ou une vidéo, placer les médias sans position, masquer des zones de trace (pour un voyage, ou zone privée pour tous). Corrections notées dans voyage.toml ([positions], [corrections]) ou site.toml ([confidentialite]), appliquées par les pages ; les originaux ne changent pas. L'extraction garde les médias datés sans position pour qu'on puisse les placer. Accès : clé d'accès aléatoire à chaque lancement, session par cookie HttpOnly/SameSite=Strict, mot de passe facultatif (rtg mot-de-passe, empreinte scrypt hors du site, blocage après 5 échecs), accès réseau seulement avec mot de passe (--distant), HTTPS possible (--certificat, --cle), Content-Security-Policy et interdiction des cadres. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mf2kATMtqVABHSYdxJMnim
113 lines
5.3 KiB
Python
113 lines
5.3 KiB
Python
"""Commande `rtg`.
|
||
|
||
rtg generer [VOYAGE…] tout faire (sources, positions, vidéos, photos, pages, accueil)
|
||
rtg etat avancement de chaque voyage
|
||
rtg analyser VOYAGE ce que RTG trouve dans les sources d'un voyage
|
||
rtg compresser VOYAGE seulement les vidéos
|
||
rtg accueil seulement la page d'accueil et la carte globale
|
||
rtg migrer écrire site.toml et les voyage.toml depuis l'existant
|
||
rtg verifier tout ce dont RTG a besoin est-il installé ?
|
||
rtg interface ouvrir l'interface dans le navigateur
|
||
rtg mot-de-passe définir le mot de passe de l'interface (accès distant)
|
||
|
||
La racine du site est le premier dossier, en remontant depuis le dossier
|
||
courant, qui contient site.toml (sinon le dossier courant) ; --racine la force.
|
||
"""
|
||
import argparse
|
||
import os
|
||
import sys
|
||
|
||
from rtg import __version__
|
||
|
||
|
||
def main(argv=None):
|
||
p = argparse.ArgumentParser(prog="rtg", description="RoadTripsGenerator : site web de road-trips.")
|
||
p.add_argument("--version", action="version", version=f"rtg {__version__}")
|
||
p.add_argument("--racine", help="racine du site (défaut : recherche de site.toml)")
|
||
sp = p.add_subparsers(dest="commande", required=True)
|
||
|
||
g = sp.add_parser("generer", help="générer un, plusieurs ou tous les voyages, puis l'accueil")
|
||
g.add_argument("voyages", nargs="*", help="dossiers des voyages (défaut : tous)")
|
||
g.add_argument("--sans-compression", action="store_true", help="ne pas encoder les vidéos")
|
||
g.add_argument("--force", action="store_true", help="tout refaire, même ce qui est à jour")
|
||
g.add_argument("--mymaps-maj", action="store_true", help="récupérer à nouveau les cartes My Maps")
|
||
|
||
sp.add_parser("etat", help="avancement de chaque voyage")
|
||
|
||
a = sp.add_parser("analyser", help="inventaire des sources d'un voyage")
|
||
a.add_argument("voyage")
|
||
|
||
c = sp.add_parser("compresser", help="encoder les vidéos d'un voyage")
|
||
c.add_argument("voyage")
|
||
c.add_argument("--force", action="store_true")
|
||
|
||
ac = sp.add_parser("accueil", help="régénérer l'accueil et la carte globale")
|
||
ac.add_argument("--mymaps-maj", action="store_true")
|
||
|
||
sp.add_parser("migrer", help="écrire site.toml et voyage.toml depuis l'organisation actuelle")
|
||
sp.add_parser("verifier", help="contrôler que Python, exiftool et ffmpeg sont bien installés")
|
||
|
||
i = sp.add_parser("interface", help="ouvrir l'interface dans le navigateur")
|
||
i.add_argument("--port", type=int, default=8765)
|
||
i.add_argument("--sans-navigateur", action="store_true", help="ne pas ouvrir le navigateur")
|
||
i.add_argument("--distant", action="store_true",
|
||
help="accepter les connexions depuis le réseau (mot de passe obligatoire)")
|
||
i.add_argument("--certificat", help="certificat TLS (PEM) pour servir en HTTPS")
|
||
i.add_argument("--cle", help="clé privée du certificat TLS (PEM)")
|
||
|
||
mp = sp.add_parser("mot-de-passe", help="définir ou supprimer le mot de passe de l'interface")
|
||
mp.add_argument("--supprimer", action="store_true")
|
||
|
||
args = p.parse_args(argv)
|
||
|
||
if args.commande == "mot-de-passe":
|
||
from rtg import acces
|
||
if args.supprimer:
|
||
print("✅ Mot de passe supprimé." if acces.supprimer() else "ℹ️ Aucun mot de passe défini.")
|
||
return
|
||
import getpass
|
||
mdp = getpass.getpass("Nouveau mot de passe : ")
|
||
if mdp != getpass.getpass("Le même, encore une fois : "):
|
||
sys.exit("❌ Les deux saisies diffèrent.")
|
||
try:
|
||
print(f"✅ Mot de passe enregistré ({acces.definir(mdp)}).")
|
||
except ValueError as e:
|
||
sys.exit(f"❌ {e}")
|
||
return
|
||
|
||
if args.commande == "verifier":
|
||
# Avant tout autre import : doit fonctionner même si un module manque.
|
||
from rtg.verifier import verifier
|
||
sys.exit(0 if verifier() else 1)
|
||
|
||
from rtg import accueil, site, sources, video
|
||
from rtg.config import reglages_site, reglages_voyage, trouver_racine
|
||
racine = os.path.abspath(args.racine) if args.racine else trouver_racine(".")
|
||
|
||
try:
|
||
if args.commande == "generer":
|
||
ok = site.generer(racine, args.voyages, compression=not args.sans_compression,
|
||
force=args.force, mymaps_maj=args.mymaps_maj)
|
||
sys.exit(0 if ok else 1)
|
||
elif args.commande == "etat":
|
||
site.etat(racine)
|
||
elif args.commande == "analyser":
|
||
site.analyser(args.voyage, racine)
|
||
elif args.commande == "compresser":
|
||
v = os.path.abspath(args.voyage)
|
||
cfg = reglages_voyage(v, reglages_site(racine))
|
||
sys.exit(0 if video.compresser(v, cfg, sources.analyser(v, cfg), force=args.force) else 1)
|
||
elif args.commande == "accueil":
|
||
accueil.generer(racine, reglages_site(racine), args.mymaps_maj)
|
||
elif args.commande == "migrer":
|
||
site.migrer(racine)
|
||
elif args.commande == "interface":
|
||
from rtg.interface.serveur import lancer
|
||
if bool(args.certificat) != bool(args.cle):
|
||
sys.exit("❌ --certificat et --cle vont ensemble.")
|
||
lancer(racine, args.port, ouvrir=not args.sans_navigateur, distant=args.distant,
|
||
certificat=args.certificat, cle=args.cle)
|
||
except KeyboardInterrupt:
|
||
print("\nInterrompu.")
|
||
sys.exit(130)
|