Add noVNC configure flow and helper start scripts

This commit is contained in:
Stefan Heyn 2026-03-04 15:03:56 +01:00
parent a8344734b3
commit 56d2588461
7 changed files with 188 additions and 6 deletions

21
Dockerfile.novnc Normal file
View file

@ -0,0 +1,21 @@
FROM mcr.microsoft.com/playwright/python:v1.52.0-jammy
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
xvfb \
fluxbox \
x11vnc \
novnc \
websockify \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r /app/requirements.txt
COPY main.py /app/main.py
COPY README.md /app/README.md
COPY scripts/start-novnc-configure.sh /app/scripts/start-novnc-configure.sh
RUN chmod +x /app/scripts/start-novnc-configure.sh
ENTRYPOINT ["/app/scripts/start-novnc-configure.sh"]

View file

@ -45,21 +45,59 @@ cd c:\projekte\amazon_invoice_downloader
docker compose build docker compose build
``` ```
Session direkt im Container erzeugen (Ubuntu mit Desktop/X11):
```bash
sudo apt-get update && sudo apt-get install -y x11-xserver-utils
xhost +local:docker
docker compose --profile configure run --rm amazon-invoice-configure
xhost -local:docker
```
Im geöffneten Browser bei Amazon anmelden und danach im Terminal `Enter` drücken.
Die Session liegt anschließend in `./state/storage_state.json`.
Session auf Ubuntu Server ohne GUI (noVNC):
```bash
docker compose --profile configure-novnc up --build amazon-invoice-configure-novnc
```
Dann im Browser auf deinem PC oeffnen:
```text
http://<SERVER-IP>:6080/vnc.html
```
Im noVNC-Fenster bei Amazon einloggen. Die Session wird nach `LOGIN_WAIT_SECONDS` (Standard: 300s) automatisch gespeichert.
Anschließend kannst du den noVNC-Container beenden (`Ctrl+C` im Terminal).
Alternative per Hilfsskript:
```bash
chmod +x ./startConfigure.sh
./startConfigure.sh
```
Rechnungen im Container herunterladen: Rechnungen im Container herunterladen:
```powershell ```powershell
docker compose run --rm amazon-invoice-downloader download --from 2025-01-01 --to 2025-12-31 --headless true docker compose run --rm amazon-invoice-downloader download --from 2025-01-01 --to 2025-12-31 --headless true
``` ```
Alternative per Hilfsskript:
```bash
chmod +x ./startDownload.sh
./startDownload.sh 2025-01-01 2025-12-31
```
Persistente Ordner: Persistente Ordner:
- `./state` -> `/root/.amazon_invoice_downloader` (config + session) - `./state` -> `/root/.amazon_invoice_downloader` (config + session)
- `./downloads` -> `/downloads` (Ausgabedateien) - `./downloads` -> `/downloads` (Ausgabedateien)
Falls du bereits lokal konfiguriert hast, kopiere diese Dateien nach `./state`: Falls noch nicht vorhanden, werden `config.json` und `storage_state.json` beim `configure`-Lauf in `./state` angelegt.
- `config.json`
- `storage_state.json`
Optionaler Zielordner im Container: Optionaler Zielordner im Container:

View file

@ -8,7 +8,48 @@
working_dir: /app working_dir: /app
stdin_open: true stdin_open: true
tty: true tty: true
shm_size: "1gb"
volumes: volumes:
- ./downloads:/downloads - ./downloads:/downloads
- ./state:/root/.amazon_invoice_downloader - ./state:/root/.amazon_invoice_downloader
command: ["-h"] command: ["-h"]
amazon-invoice-configure:
build:
context: .
dockerfile: Dockerfile
image: amazon-invoice-downloader:latest
container_name: amazon-invoice-configure
working_dir: /app
stdin_open: true
tty: true
shm_size: "1gb"
profiles: ["configure"]
environment:
- DISPLAY=${DISPLAY}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- ./state:/root/.amazon_invoice_downloader
- ./downloads:/downloads
command: ["configure", "--marketplace", "de", "--download-dir", "/downloads"]
amazon-invoice-configure-novnc:
build:
context: .
dockerfile: Dockerfile.novnc
image: amazon-invoice-downloader-novnc:latest
container_name: amazon-invoice-configure-novnc
stdin_open: true
tty: true
shm_size: "1gb"
profiles: ["configure-novnc"]
environment:
- MARKETPLACE=de
- DOWNLOAD_DIR=/downloads
- LOGIN_WAIT_SECONDS=300
- NOVNC_PORT=6080
ports:
- "6080:6080"
volumes:
- ./state:/root/.amazon_invoice_downloader
- ./downloads:/downloads

14
main.py
View file

@ -1,6 +1,7 @@
import argparse import argparse
import json import json
import re import re
import time
from dataclasses import dataclass from dataclasses import dataclass
from datetime import date, datetime from datetime import date, datetime
from pathlib import Path from pathlib import Path
@ -278,6 +279,13 @@ def configure(args) -> None:
page = context.new_page() page = context.new_page()
page.goto(f"https://www.amazon.{args.marketplace}/your-orders/orders", wait_until="domcontentloaded") page.goto(f"https://www.amazon.{args.marketplace}/your-orders/orders", wait_until="domcontentloaded")
print("Bitte im Browser bei Amazon einloggen.") print("Bitte im Browser bei Amazon einloggen.")
if args.login_wait_seconds > 0:
print(
f"Warte {args.login_wait_seconds} Sekunden auf Login, "
"danach wird die Session automatisch gespeichert."
)
time.sleep(args.login_wait_seconds)
else:
print("Wenn Bestellungen sichtbar sind, Enter druecken.") print("Wenn Bestellungen sichtbar sind, Enter druecken.")
input() input()
context.storage_state(path=str(STORAGE_STATE_PATH)) context.storage_state(path=str(STORAGE_STATE_PATH))
@ -457,6 +465,12 @@ def build_parser() -> argparse.ArgumentParser:
p_config.add_argument("--marketplace", default="de", help="z. B. de, com, co.uk") p_config.add_argument("--marketplace", default="de", help="z. B. de, com, co.uk")
p_config.add_argument("--download-dir", default="~/Downloads/amazon_rechnungen") p_config.add_argument("--download-dir", default="~/Downloads/amazon_rechnungen")
p_config.add_argument("--headless", action="store_true", help="Standard fuer Download-Lauf im Headless-Mode") p_config.add_argument("--headless", action="store_true", help="Standard fuer Download-Lauf im Headless-Mode")
p_config.add_argument(
"--login-wait-seconds",
type=int,
default=0,
help="Optional: wartet X Sekunden vor Session-Speicherung (fuer noVNC/Serverbetrieb).",
)
p_config.set_defaults(func=configure) p_config.set_defaults(func=configure)
p_dl = sub.add_parser("download", help="Rechnungen nach Zeitraum herunterladen") p_dl = sub.add_parser("download", help="Rechnungen nach Zeitraum herunterladen")

View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euo pipefail
DISPLAY_NUM=${DISPLAY_NUM:-:99}
VNC_PORT=${VNC_PORT:-5900}
NOVNC_PORT=${NOVNC_PORT:-6080}
MARKETPLACE=${MARKETPLACE:-de}
DOWNLOAD_DIR=${DOWNLOAD_DIR:-/downloads}
LOGIN_WAIT_SECONDS=${LOGIN_WAIT_SECONDS:-300}
Xvfb "$DISPLAY_NUM" -screen 0 1920x1080x24 &
fluxbox -display "$DISPLAY_NUM" &
x11vnc -display "$DISPLAY_NUM" -forever -shared -rfbport "$VNC_PORT" -nopw &
/usr/share/novnc/utils/novnc_proxy --vnc localhost:"$VNC_PORT" --listen "$NOVNC_PORT" &
export DISPLAY="$DISPLAY_NUM"
echo "noVNC bereit unter: http://<SERVER-IP>:$NOVNC_PORT/vnc.html"
echo "Melde dich bei Amazon an. Session wird nach $LOGIN_WAIT_SECONDS Sekunden gespeichert."
python /app/main.py configure --marketplace "$MARKETPLACE" --download-dir "$DOWNLOAD_DIR" --login-wait-seconds "$LOGIN_WAIT_SECONDS"

22
startConfigure.sh Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
MARKETPLACE="${MARKETPLACE:-de}"
LOGIN_WAIT_SECONDS="${LOGIN_WAIT_SECONDS:-300}"
NOVNC_PORT="${NOVNC_PORT:-6080}"
DOWNLOAD_DIR="${DOWNLOAD_DIR:-/downloads}"
mkdir -p state downloads
export MARKETPLACE
export LOGIN_WAIT_SECONDS
export NOVNC_PORT
export DOWNLOAD_DIR
echo "Starte noVNC-Configure auf Port ${NOVNC_PORT} ..."
echo "Oeffne im Browser: http://<SERVER-IP>:${NOVNC_PORT}/vnc.html"
docker compose --profile configure-novnc up --build amazon-invoice-configure-novnc

25
startDownload.sh Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
if [[ $# -lt 2 ]]; then
echo "Usage: $0 <FROM_YYYY-MM-DD> <TO_YYYY-MM-DD> [additional args]"
echo "Beispiel: $0 2025-01-01 2025-12-31 --debug --debug-json /downloads/debug-run.json"
exit 1
fi
DATE_FROM="$1"
DATE_TO="$2"
shift 2
mkdir -p state downloads
docker compose run --rm amazon-invoice-downloader \
download \
--from "$DATE_FROM" \
--to "$DATE_TO" \
--output /downloads \
--headless true \
"$@"