# Drive commun

PWA de partage de cours pour un groupe de formation. Tout est stocké en **fichiers texte** sur le serveur, les conversions (PDF/DOCX → texte, texte → PDF) sont faites par le serveur.

- Mobile et ordinateur, installable sur l'écran d'accueil (iOS / Android / Mac / Windows)
- Ajout depuis Apple Notes (collage structuré ou Raccourci Apple), téléversement TXT / Markdown / PDF / Word
- Lecture, modification, renommage, téléchargement PDF ou TXT
- Regroupement par mois (du plus récent au plus ancien), matières, épinglés
- Recherche plein texte, historique des versions, corbeille 30 jours, journal d'activité
- Mot de passe partagé, thème sombre, lecture hors-ligne des cours déjà ouverts, export .zip complet

## Lancer en local

```bash
npm install
cp .env.example .env      # puis mets un DRIVE_PASSWORD
npm start                 # http://localhost:3000
```

## Structure

```
server/
  index.js        serveur Express (API + fichiers statiques)
  config.js       variables d'environnement
  auth.js         mot de passe partagé, cookie de session, anti brute-force
  storage.js      index.json + courses/*.txt + history/ + corbeille + recherche + activité
  convert.js      PDF/DOCX/TXT → texte, texte → PDF (pdfkit)
  routes/         auth.js, courses.js
public/
  index.html, manifest.webmanifest, sw.js (service worker)
  css/app.css
  js/             app.js (démarrage), router, state, api, ui, text, modals, shell
  js/views/       list, reader, editor, history, trash, activity, subjects, login
  icons/
data/             (créé au démarrage, à sauvegarder)
  index.json      métadonnées
  courses/        un .txt par cours
  history/<id>/   versions précédentes (30 max)
  activity.jsonl  journal
deploy/           nginx.conf, backup.sh
```

Astuce : un fichier `.txt` déposé à la main dans `data/courses/` est importé automatiquement au redémarrage (son nom devient le titre).

## API (pour les Raccourcis Apple ou des scripts)

Authentification : cookie (via l'app) **ou** en-tête `Authorization: Bearer <DRIVE_PASSWORD>`.
En-tête optionnel `X-Author: Prénom` pour signer.

| Méthode | Route | Rôle |
|---|---|---|
| GET | `/api/courses` | liste (`?trash=1` pour la corbeille) |
| GET | `/api/courses/:id` | métadonnées + contenu |
| POST | `/api/courses` | créer `{ title?, content, subject?, date? }` |
| POST | `/api/courses/upload` | multipart `files[]` (TXT/MD/PDF/DOCX) + `subject`, `date` |
| PATCH | `/api/courses/:id` | `{ content?, title?, subject?, date?, favorite?, baseUpdatedAt? }` (409 si conflit) |
| DELETE | `/api/courses/:id` | corbeille (`?permanent=1` pour effacer) |
| POST | `/api/courses/:id/restore` | sortir de la corbeille |
| GET | `/api/courses/:id/pdf` / `/txt` | téléchargement (`?inline=1` pour afficher) |
| GET | `/api/courses/:id/history` | versions ; `/history/:stamp` contenu ; `POST …/restore` |
| GET | `/api/search?q=` | recherche plein texte |
| GET | `/api/activity` | journal |
| GET | `/api/export.zip` | tous les cours, un dossier par matière |

### Raccourci Apple « Envoyer vers le Drive »

Dans l'app Raccourcis (iPhone / iPad / Mac) :

1. **Recevoir** `Texte` depuis la feuille de partage.
2. **Obtenir le texte** à partir de l'entrée du raccourci.
3. **Obtenir le contenu de l'URL** :
   - URL : `https://drive.mondomaine.fr/api/courses`
   - Méthode : `POST`, corps : `JSON`
   - Champs : `content` = le texte de l'étape 2, `source` = `raccourci` (et `title` si tu veux)
   - En-têtes : `Authorization` = `Bearer <mot de passe>`, `X-Author` = ton prénom
4. (optionnel) **Afficher une notification** « Cours ajouté ».

Ensuite, dans Notes : Partager → le raccourci. Sur Android, l'app est aussi cible de partage (Partager → Drive).

## Déploiement sur OVH

Il faut **Node.js ≥ 18**, donc un **VPS** (ou un hébergement web OVH avec Node.js activé). HTTPS est obligatoire pour la PWA et le presse-papiers.

### VPS (Debian / Ubuntu) avec pm2 + nginx

```bash
# 1. Node 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs nginx certbot python3-certbot-nginx

# 2. L'application
sudo mkdir -p /opt/drive && sudo chown $USER /opt/drive
# copier le projet dans /opt/drive (git clone, scp ou rsync — sans node_modules ni data)
cd /opt/drive
npm ci --omit=dev
cp .env.example .env && nano .env      # DRIVE_PASSWORD, APP_NAME, TRUST_PROXY=1

# 3. Démarrage automatique
sudo npm install -g pm2
pm2 start ecosystem.config.js
pm2 save && pm2 startup                # exécuter la commande affichée

# 4. nginx + HTTPS
sudo cp deploy/nginx.conf /etc/nginx/sites-available/drive
sudo nano /etc/nginx/sites-available/drive   # mettre ton domaine
sudo ln -s /etc/nginx/sites-available/drive /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d drive.mondomaine.fr
```

Le DNS du domaine (zone OVH) doit pointer vers l'IP du VPS (enregistrement A).

Mise à jour : copier les nouveaux fichiers puis `pm2 restart drive-commun`.
Sauvegarde : `deploy/backup.sh` (cron quotidien) archive le dossier `data/`.

### Docker

```bash
cp .env.example .env && nano .env
docker compose up -d --build     # écoute sur 127.0.0.1:3000, nginx devant comme ci-dessus
```

## Variables d'environnement

| Variable | Défaut | Rôle |
|---|---|---|
| `PORT` | 3000 | port d'écoute |
| `DRIVE_PASSWORD` | (vide = ouvert) | mot de passe partagé |
| `APP_NAME` | Drive commun | nom affiché |
| `DATA_DIR` | ./data | dossier de stockage |
| `MAX_UPLOAD_MB` | 25 | taille max d'un fichier |
| `TRASH_RETENTION_DAYS` | 30 | conservation dans la corbeille |
| `TRUST_PROXY` | 0 | mettre `1` derrière nginx |
| `SESSION_SECRET` | dérivé du mot de passe | changer pour déconnecter tout le monde |

## Notes

- Le texte des cours accepte une mise en forme légère : `# Titre`, `## Sous-titre`, listes `-` ou `1.`, `**gras**`, `[ ]` / `[x]` pour les cases, `---` pour un trait. Le collage depuis Notes la produit automatiquement.
- Le PDF généré utilise Helvetica : les emojis ne sont pas rendus, les flèches et symboles courants sont remplacés.
- Les PDF scannés (images) n'ont pas de texte : la conversion signale « aucun texte trouvé ».
