Backend:
- POST /api/v1/upload: multipart file upload with caption + hashtags
- Validates file size against DB config limits (image/video separate)
- Checks user ban status and event upload lock
- Saves original to disk under {media_path}/originals/{slug}/
- Tracks user total_upload_bytes for quota enforcement
- Extracts hashtags from caption text and explicit CSV field
- Upserts hashtags and links them to uploads
- PATCH /api/v1/upload/{id}: edit caption and hashtags (owner only)
- DELETE /api/v1/upload/{id}: soft-delete (owner only)
- GET /api/v1/stream: SSE endpoint with 30s keepalive
- Broadcasts new-upload events to all connected clients
- Uses tokio broadcast channel for fan-out
Services:
- CompressionWorker: Tokio semaphore-bounded (concurrency=2) background processor
- Images: resize to 800px wide JPEG preview via image crate
- PNG originals: lossless compression via oxipng
- Videos: ffmpeg thumbnail extraction (1 frame at 1s, scaled to 800px)
- Updates upload record with preview_path/thumbnail_path on completion
Models:
- Upload with full CRUD (create, find, update caption, soft delete, set paths)
- Hashtag with upsert, link/unlink, extract_hashtags() text parser
- UploadDto for API serialization with like/comment counts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
38 lines
1.0 KiB
TOML
38 lines
1.0 KiB
TOML
[package]
|
|
name = "eventsnap-backend"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
|
|
[dependencies]
|
|
axum = { version = "0.8", features = ["multipart"] }
|
|
tokio = { version = "1", features = ["full"] }
|
|
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "uuid", "chrono", "macros", "migrate"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
tower = "0.5"
|
|
tower-http = { version = "0.6", features = ["trace", "cors", "compression-full", "fs"] }
|
|
tower_governor = "0.4"
|
|
jsonwebtoken = "9"
|
|
bcrypt = "0.15"
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
chrono = { version = "0.4", features = ["serde"] }
|
|
tokio-stream = { version = "0.1", features = ["sync"] }
|
|
futures = "0.3"
|
|
sha2 = "0.10"
|
|
rand = "0.9"
|
|
anyhow = "1"
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
dotenvy = "0.15"
|
|
sysinfo = "0.32"
|
|
image = "0.25"
|
|
oxipng = "9"
|
|
async_zip = { version = "0.0.17", features = ["tokio", "deflate"] }
|
|
minijinja = "2"
|
|
|
|
[profile.release]
|
|
opt-level = 3
|
|
lto = true
|
|
codegen-units = 1
|
|
strip = true
|