From 3cbe7f72f0d85d95d61b2703087fc592318f3495 Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Mon, 16 Mar 2026 14:03:16 -0400 Subject: refactor: 24.04 vps compatibility and README re-write --- Dockerfile | 2 +- README.md | 30 +++++++++++++++++++++++++----- src/app.py | 22 ++++++++++++++++------ src/requirements.txt | 6 +++--- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7a213a7..cb2b9df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.13-slim +FROM python:3.12-slim # enable contrib (fonts-ibm-plex) and non-free (fonts-ubuntu) components RUN sed -i 's/^Components: main$/Components: main contrib non-free/' /etc/apt/sources.list.d/debian.sources diff --git a/README.md b/README.md index 140f679..73e02b1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > suckless's sent tool ported to the very sucky web world A web-based reimplementation of [suckless sent](https://tools.suckless.org/sent/) -using pure PHP and vanilla JavaScript. +using Python and vanilla JavaScript. sent0

@@ -17,9 +17,8 @@ using pure PHP and vanilla JavaScript. (same as sent) - **mouse navigation** — left-click right half = next, left half = prev, scroll wheel -- **image upload** — upload images and insert `@filename` references +- **image upload** — upload images and insert `@filename` references (50 MB cap) - **export** — download as `.sent` file for local sent, or export `.pdf` for portability - ## usage ### docker compose (recommended) @@ -37,6 +36,26 @@ docker build -t sent-web . docker run -d -p 3000:3000 --init --name sent-web sent-web ``` +### local python run (without docker) + +Requirements: + +- Python `3.12+` +- `fontconfig` (`fc-list` must be available) +- `libmagic` runtime (`libmagic1` on Ubuntu) + +Setup: + +```sh +cd src +python3.12 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt +gunicorn --bind 0.0.0.0:3000 --workers 2 app:app +``` + +Then open [http://localhost:3000](http://localhost:3000). + ### presentation shortcuts | key | action | @@ -65,11 +84,12 @@ with multiple lines ## technology -- **PHP 8.3** — no framework, just `.php` files +- **Python 3.12+** — Flask backend - **vanilla JavaScript** — no npm, no webpack, no react - **[noir.css](https://github.com/kj-sh604/noir.css)** — classless CSS -- **Apache** — serves it all +- **Gunicorn** — production WSGI server - **fontconfig** — `fc-list` for font enumeration +- **python-magic + libmagic** — content-based upload type checks - **Docker** — containerized with fonts pre-installed ## license diff --git a/src/app.py b/src/app.py index dce80a6..7d75f2b 100644 --- a/src/app.py +++ b/src/app.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# sent-web — app.py import base64 import os @@ -12,6 +11,7 @@ import magic from flask import Flask, Response, jsonify, request, send_file, send_from_directory app = Flask(__name__, static_folder=None) +app.config["MAX_CONTENT_LENGTH"] = 50 * 1024 * 1024 # 50 MB upload cap UPLOAD_DIR = Path(__file__).parent / "uploads" UPLOAD_DIR.mkdir(mode=0o755, exist_ok=True) @@ -84,11 +84,21 @@ def upload(): @app.route("/fonts") def fonts(): - result = subprocess.run( - ["fc-list", "--format=%{family}|%{style}|%{file}\n"], - capture_output=True, - text=True, - ) + try: + result = subprocess.run( + ["fc-list", "--format=%{family}|%{style}|%{file}\n"], + capture_output=True, + text=True, + shell=False, + timeout=10, + check=False, + ) + except (FileNotFoundError, subprocess.TimeoutExpired): + return jsonify([]) + + if result.returncode != 0: + return jsonify([]) + if not result.stdout.strip(): return jsonify([]) diff --git a/src/requirements.txt b/src/requirements.txt index c9d8662..dfce493 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,3 +1,3 @@ -flask>=3.0,<4 -gunicorn>=22,<25 -python-magic>=0.4.27 +flask>=3.0,<3.2 +gunicorn>=22,<24 +python-magic>=0.4.27,<0.5 \ No newline at end of file -- cgit v1.2.3