From ab2cd510a66157285cd8337f099700377703c157 Mon Sep 17 00:00:00 2001 From: dariusz Date: Mon, 29 Jun 2026 11:47:17 +0200 Subject: [PATCH] style: usun em-dashe z calego repo (zamiana na zwykly mylnik) Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/deploy.yml | 2 +- DEPLOY.md | 6 +++--- PROMPT.md | 20 ++++++++++---------- README.md | 18 +++++++++--------- apps/api/package.json | 2 +- apps/api/src/jobs/jobs.controller.ts | 2 +- apps/api/src/jobs/jobs.service.ts | 4 ++-- apps/web/nginx.conf | 2 +- apps/web/src/App.tsx | 6 +++--- docker-compose.prod.yml | 4 ++-- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index cdc4f1a..122007a 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Sanity — docker dostępny + - name: Sanity - docker dostępny run: docker version && docker compose version - name: Build obrazów diff --git a/DEPLOY.md b/DEPLOY.md index 2c5138d..6281f9c 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -1,4 +1,4 @@ -# Wdrożenie — videodownloader.naurecki.pl +# Wdrożenie - videodownloader.naurecki.pl ## Pipeline Push do `main` uruchamia `.gitea/workflows/deploy.yml` na runnerze Gitea @@ -6,7 +6,7 @@ Push do `main` uruchamia `.gitea/workflows/deploy.yml` na runnerze Gitea i robi `up -d` na demonie Dockera serwera. Serwis `web` (nginx) słucha na `127.0.0.1:8086`, `api` (NestJS) wewnętrznie + diagnostycznie na `127.0.0.1:3105`. -## Reverse proxy (Apache) — jednorazowo na serwerze +## Reverse proxy (Apache) - jednorazowo na serwerze Plik `/etc/apache2/sites-available/videodownloader.naurecki.pl.conf`: ```apache @@ -31,5 +31,5 @@ sudo certbot --apache -d videodownloader.naurecki.pl --redirect -n \ --agree-tos -m dariusz@naurecki.pl ``` -DNS: `*.naurecki.pl` (wildcard) już wskazuje serwer — bez dodatkowej konfiguracji. +DNS: `*.naurecki.pl` (wildcard) już wskazuje serwer - bez dodatkowej konfiguracji. diff --git a/PROMPT.md b/PROMPT.md index f58e34c..4c14e4b 100644 --- a/PROMPT.md +++ b/PROMPT.md @@ -7,33 +7,33 @@ Dokument zawiera (1) gotowy **prompt** do wygenerowania aplikacji od zera oraz ## 1. Master-prompt (do odtworzenia aplikacji) -> Zbuduj webową aplikację SPA „Video & Sound Downloader Pro” — webowy odpowiednik +> Zbuduj webową aplikację SPA „Video & Sound Downloader Pro” - webowy odpowiednik > desktopowego narzędzia łączącego `yt-dlp` i `FFmpeg`. **Stack: backend NestJS > (TypeScript), frontend React + Vite (TypeScript).** Monorepo `apps/api`, `apps/web`. > > **Backend (NestJS):** -> - `POST /api/probe` — przyjmuje `{ url }`, uruchamia `yt-dlp -J` i zwraca tytuł, +> - `POST /api/probe` - przyjmuje `{ url }`, uruchamia `yt-dlp -J` i zwraca tytuł, > miniaturę, czas trwania, dostępne jakości oraz listę języków napisów. -> - `POST /api/jobs` — `{ url, mode, format, subtitles }`, gdzie `mode ∈ +> - `POST /api/jobs` - `{ url, mode, format, subtitles }`, gdzie `mode ∈ > {mp3, mp4, playlist, facebook}`. Tworzy job w katalogu tymczasowym, uruchamia > `yt-dlp` (+ `ffmpeg`) z argumentami zależnymi od trybu i zwraca `jobId`. -> - `GET /api/jobs/:id/events` — strumień **SSE** z liniami logu i procentem postępu +> - `GET /api/jobs/:id/events` - strumień **SSE** z liniami logu i procentem postępu > (parsowanie `--newline --progress`); zdarzenia `log`, `progress`, `done`, `error`. -> - `GET /api/jobs/:id/file` — strumień gotowego pliku do przeglądarki, po wysłaniu +> - `GET /api/jobs/:id/file` - strumień gotowego pliku do przeglądarki, po wysłaniu > sprzątnięcie katalogu joba (TTL-cleanup dla porzuconych). -> - `DELETE /api/jobs/:id` — STOP: zabija proces yt-dlp/ffmpeg joba. -> - Joby w pamięci (EventEmitter) — bez bazy, lekko i „portable”. +> - `DELETE /api/jobs/:id` - STOP: zabija proces yt-dlp/ffmpeg joba. +> - Joby w pamięci (EventEmitter) - bez bazy, lekko i „portable”. > - Mapowanie trybów: `mp3` → `-x --audio-format mp3 --audio-quality `; > `mp4`/`facebook` → `-f "bv*[height<=H]+ba/b" --merge-output-format mp4`; > `playlist` → `--yes-playlist`, wynik pakowany do ZIP. Napisy: > `--write-subs --sub-langs all --embed-subs` (bez auto-napisów: `--no-write-auto-subs`). > -> **Frontend (React) — odwzoruj 1:1 zrzut ekranu desktopu:** +> **Frontend (React) - odwzoruj 1:1 zrzut ekranu desktopu:** > ciemny motyw, akcenty niebieskie. Nagłówek z ikoną i wersją; pole **Link** z > przyciskiem wklejenia ze schowka; sekcja **„Wybierz opcję”** z 4 kafelkami > (MP3 / MP4 / PLAYLISTA / FACEBOOK, ikony i kolory jak na zrzucie, aktywny kafel > podświetlony); **„Jakość / Format”** jako dropdown zależny od trybu; w miejscu -> „Zapisz do” — informacja o pobraniu przez przeglądarkę; duży przycisk +> „Zapisz do” - informacja o pobraniu przez przeglądarkę; duży przycisk > **„POBIERZ …”** + **STOP**; **banner trybu testowego**; panel **Log** na żywo > (z SSE); stopka **Wsparcie** / **O mnie**. > @@ -56,7 +56,7 @@ Dokument zawiera (1) gotowy **prompt** do wygenerowania aplikacji od zera oraz | 6 | **CI/CD** | `.gitea/workflows/deploy.yml`: push `main` → build + `up -d` (docker.sock). | | 7 | **Reverse proxy** | vhost Apache `videodownloader.naurecki.pl` → `127.0.0.1:8086`. | | 8 | **SSL** | `certbot --apache -d videodownloader.naurecki.pl`. | -| 9 | **DNS** | Gotowe — `*.naurecki.pl` (wildcard) już wskazuje `212.109.167.206`. | +| 9 | **DNS** | Gotowe - `*.naurecki.pl` (wildcard) już wskazuje `212.109.167.206`. | | 10 | **Weryfikacja** | `https://videodownloader.naurecki.pl` + test pobrania. | **Ustalenia infrastrukturalne** (zweryfikowane na serwerze): diff --git a/README.md b/README.md index a55bea5..e7e3864 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Video & Sound Downloader Pro — wersja web (SPA) +# Video & Sound Downloader Pro - wersja web (SPA) Webowy odpowiednik desktopowego narzędzia **Video & Sound Downloader Pro v6.5.6**. Łączy `yt-dlp` + `FFmpeg` w jednym panelu: pobieranie audio (MP3), wideo (MP4), -całych playlist oraz materiałów z Facebooka — bez wpisywania komend i bez ręcznej +całych playlist oraz materiałów z Facebooka - bez wpisywania komend i bez ręcznej konwersji. Backend: **NestJS**, frontend: **React (Vite)**. Obraz portowany jest do Dockera i wdrażany na `https://videodownloader.naurecki.pl`. @@ -17,10 +17,10 @@ Dockera i wdrażany na `https://videodownloader.naurecki.pl`. ``` videodownloader/ ├── apps/ -│ ├── api/ # NestJS — joby pobierania, yt-dlp+ffmpeg, postęp SSE +│ ├── api/ # NestJS - joby pobierania, yt-dlp+ffmpeg, postęp SSE │ │ ├── src/ │ │ └── Dockerfile # node + python3 + yt-dlp + ffmpeg -│ └── web/ # React + Vite (TS) — UI odwzorowany ze zrzutu +│ └── web/ # React + Vite (TS) - UI odwzorowany ze zrzutu │ ├── src/ │ ├── nginx.conf # serwuje statyki + proxy /api (+ SSE bez buforowania) │ └── Dockerfile @@ -36,15 +36,15 @@ Ruch publiczny: `Apache (vhost videodownloader.naurecki.pl, SSL)` → `127.0.0.1 - **Pole Link** z przyciskiem „wklej ze schowka”. - **4 tryby**: `MP3` (pobierz dźwięk), `MP4` (pobierz wideo), `PLAYLISTA` (pobierz całą listę → ZIP), `FACEBOOK` (pobierz wideo). -- **Jakość / Format** — lista zależna od trybu (MP3 320/256/192/128 kbps; +- **Jakość / Format** - lista zależna od trybu (MP3 320/256/192/128 kbps; MP4 2160/1440/1080/720/480p). -- **Napisy** — opcja pobrania dostępnych napisów (`--write-subs --embed-subs`); +- **Napisy** - opcja pobrania dostępnych napisów (`--write-subs --embed-subs`); zgodnie z oryginałem **nie** dotyczy automatycznie generowanych napisów YouTube. - Duży przycisk **POBIERZ** + **STOP** (przerwanie joba). -- **Log na żywo** (SSE) — komunikaty postępu, konwersji i scalania audio/wideo. +- **Log na żywo** (SSE) - komunikaty postępu, konwersji i scalania audio/wideo. - Przyciski **Wsparcie** / **O mnie** oraz informacja o wersji **yt-dlp** z przyciskiem „Sprawdź aktualizacje”. -- **Auto-aktualizacja yt-dlp** — API sprawdza i aktualizuje yt-dlp (`yt-dlp -U`) +- **Auto-aktualizacja yt-dlp** - API sprawdza i aktualizuje yt-dlp (`yt-dlp -U`) przy starcie oraz cyklicznie (domyślnie co 24 h; `YTDLP_AUTO_UPDATE`, `YTDLP_UPDATE_INTERVAL_H`). Ręczne wymuszenie: `POST /api/ytdlp/update`. @@ -67,4 +67,4 @@ Wymaga lokalnie `yt-dlp` i `ffmpeg` w PATH (w produkcji są w obrazie). Push do `main` → runner Gitea (`.gitea/workflows/deploy.yml`) buduje obrazy z `docker-compose.prod.yml` i robi `up -d` na demonie Dockera serwera. Konfiguracja -reverse proxy + SSL — patrz [DEPLOY.md](DEPLOY.md). +reverse proxy + SSL - patrz [DEPLOY.md](DEPLOY.md). diff --git a/apps/api/package.json b/apps/api/package.json index 638b96b..40688ad 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,7 +1,7 @@ { "name": "vsd-api", "version": "6.5.6", - "description": "Video & Sound Downloader Pro — API (NestJS)", + "description": "Video & Sound Downloader Pro - API (NestJS)", "license": "UNLICENSED", "scripts": { "build": "nest build", diff --git a/apps/api/src/jobs/jobs.controller.ts b/apps/api/src/jobs/jobs.controller.ts index 370e47c..0635308 100644 --- a/apps/api/src/jobs/jobs.controller.ts +++ b/apps/api/src/jobs/jobs.controller.ts @@ -30,7 +30,7 @@ export class JobsController { @Sse(':id/events') events(@Param('id') id: string): Observable { - // Bez pola `type` — inaczej Nest emituje nazwane zdarzenia (event: ), + // Bez pola `type` - inaczej Nest emituje nazwane zdarzenia (event: ), // a przeglądarkowy EventSource.onmessage reaguje tylko na domyślne „message”. return this.jobs.events(id).pipe( map((ev) => ({ data: JSON.stringify(ev) }) as MessageEvent), diff --git a/apps/api/src/jobs/jobs.service.ts b/apps/api/src/jobs/jobs.service.ts index 9dd0139..caa8b9c 100644 --- a/apps/api/src/jobs/jobs.service.ts +++ b/apps/api/src/jobs/jobs.service.ts @@ -129,7 +129,7 @@ export class JobsService { if (entries.length === 1) { const p = path.join(job.workDir, entries[0]); const st = await fs.stat(p); - this.emit(job, { kind: 'log', line: `OK: gotowy plik — ${entries[0]} (${fmtSize(st.size)})` }); + this.emit(job, { kind: 'log', line: `OK: gotowy plik - ${entries[0]} (${fmtSize(st.size)})` }); return { path: p, name: entries[0], size: st.size }; } @@ -147,7 +147,7 @@ export class JobsService { void archive.finalize(); }); const st = await fs.stat(zipPath); - this.emit(job, { kind: 'log', line: `OK: gotowe archiwum — ${zipName} (${fmtSize(st.size)})` }); + this.emit(job, { kind: 'log', line: `OK: gotowe archiwum - ${zipName} (${fmtSize(st.size)})` }); return { path: zipPath, name: zipName, size: st.size }; } diff --git a/apps/web/nginx.conf b/apps/web/nginx.conf index 9a1982b..3cbcb8c 100644 --- a/apps/web/nginx.conf +++ b/apps/web/nginx.conf @@ -4,7 +4,7 @@ server { root /usr/share/nginx/html; index index.html; - # API + SSE (strumień logów) — bez buforowania, długie timeouty na pobieranie + # API + SSE (strumień logów) - bez buforowania, długie timeouty na pobieranie location /api/ { proxy_pass http://api:3000; proxy_http_version 1.1; diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 2a4e1d9..2bd3e5f 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -151,7 +151,7 @@ export default function App() { } setBusy(true); setProgress(0); - setLog([`Start: ${def.title} — ${url.trim()}`]); + setLog([`Start: ${def.title} - ${url.trim()}`]); try { const res = await fetch('/api/jobs', { method: 'POST', @@ -303,7 +303,7 @@ export default function App() {

- Napisy dotyczą tylko faktycznie dostępnych napisów — nie obejmują + Napisy dotyczą tylko faktycznie dostępnych napisów - nie obejmują automatycznie generowanych napisów YouTube. Gotowy plik pobiera się przez przeglądarkę (folder „Pobrane”).

@@ -358,7 +358,7 @@ export default function App() {