|
3 | 3 | All notable changes to RustChan will be documented in this file. |
4 | 4 |
|
5 | 5 | --- |
| 6 | +## [1.1.0] |
| 7 | + |
| 8 | +## Architecture Refactor |
| 9 | + |
| 10 | +This release restructures the codebase for maintainability. No user-facing |
| 11 | +behavior has changed. Every route, every feature, every pixel is identical. |
| 12 | +The only difference is where the code lives. |
| 13 | + |
| 14 | +### The problem |
| 15 | + |
| 16 | +`main.rs` had grown to 1,757 lines and owned everything from the HTTP router |
| 17 | +to the ASCII startup banner. `handlers/admin.rs` hit 4,576 lines with 33 |
| 18 | +handler functions covering auth, backups, bans, reports, settings, and more. |
| 19 | +Both files were becoming difficult to navigate and risky to modify. |
| 20 | + |
| 21 | +### What changed |
| 22 | + |
| 23 | +**Phase 1 — Cleanup** |
| 24 | + |
| 25 | +- Removed unused `src/theme-init.js` (dead duplicate of `static/theme-init.js`) |
| 26 | +- Moved `validate_password()` from `main.rs` to `utils/crypto.rs` alongside |
| 27 | + the other credential helpers |
| 28 | +- Moved `first_run_check()` and `get_per_board_stats()` from `main.rs` into |
| 29 | + the `db` module, eliminating the only raw SQL that lived outside `db/` |
| 30 | + |
| 31 | +**Phase 2 — Background work** |
| 32 | + |
| 33 | +- Moved `evict_thumb_cache()` from `main.rs` to `workers/mod.rs` where it |
| 34 | + belongs alongside the other background maintenance operations |
| 35 | + |
| 36 | +**Phase 3 — Console extraction** |
| 37 | + |
| 38 | +- Created `src/server/` directory for server infrastructure |
| 39 | +- Extracted terminal stats, keyboard console, startup banner, and all `kb_*` |
| 40 | + helpers to `server/console.rs` (~350 lines) |
| 41 | + |
| 42 | +**Phase 4 — CLI extraction** |
| 43 | + |
| 44 | +- Moved `Cli`, `Command`, `AdminAction` clap types and `run_admin()` to |
| 45 | + `server/cli.rs` (~250 lines) |
| 46 | + |
| 47 | +**Phase 5 — Server extraction** |
| 48 | + |
| 49 | +- Moved `run_server()`, `build_router()`, all 7 background task spawns, |
| 50 | + static asset handlers, HSTS middleware, request tracking, `ScopedDecrement`, |
| 51 | + and global atomics to `server/server.rs` (~800 lines) |
| 52 | +- `main.rs` is now ~50 lines: runtime construction, CLI parsing, dispatch |
| 53 | + |
| 54 | +**Phase 6 — Admin handler decomposition** |
| 55 | + |
| 56 | +- Converted `handlers/admin.rs` to a module folder (`handlers/admin/`) |
| 57 | +- Extracted `backup.rs` — all backup and restore handlers (~2,500 lines) |
| 58 | +- Extracted `auth.rs` — login, logout, session management |
| 59 | +- Extracted `moderation.rs` — bans, reports, appeals, word filters, mod log |
| 60 | +- Extracted `content.rs` — post/thread actions, board management |
| 61 | +- Extracted `settings.rs` — site settings, VACUUM, admin panel |
| 62 | +- `admin/mod.rs` now contains only shared session helpers and re-exports |
| 63 | + |
| 64 | +### By the numbers |
| 65 | + |
| 66 | +``` |
| 67 | +File Before After |
| 68 | +main.rs 1,757 lines ~50 lines |
| 69 | +handlers/admin.rs 4,576 lines split across 6 files |
| 70 | +server/ (new) — ~1,400 lines total |
| 71 | +db/ unchanged + 2 functions from main.rs |
| 72 | +workers/ unchanged + evict_thumb_cache |
| 73 | +utils/crypto.rs unchanged + validate_password |
| 74 | +``` |
| 75 | + |
| 76 | +### What was not changed |
| 77 | + |
| 78 | +`db/`, `templates/`, `utils/`, `media/`, `config.rs`, `error.rs`, `models.rs`, |
| 79 | +`detect.rs`, `handlers/board.rs`, `handlers/thread.rs`, and `middleware/` are |
| 80 | +all untouched. They were already well-structured. |
| 81 | +``` |
| 82 | +
|
| 83 | +## New Module: src/media/ |
| 84 | +
|
| 85 | +### media/ffmpeg.rs — FFmpeg detection and subprocess execution |
| 86 | +
|
| 87 | +- Added detect_ffmpeg() for checking FFmpeg availability (synchronous, suitable for spawn_blocking) |
| 88 | +- Added run_ffmpeg() shared executor used by all FFmpeg calls |
| 89 | +- Added ffmpeg_image_to_webp() with quality 85 and metadata stripping |
| 90 | +- Added ffmpeg_gif_to_webm() using VP9 codec, CRF 30, zero bitrate target, metadata stripped |
| 91 | +- Added ffmpeg_thumbnail() extracting first frame as WebP at quality 80 with aspect-preserving scale |
| 92 | +- Added probe_video_codec() via ffprobe subprocess (moved from utils/files.rs) |
| 93 | +- Added ffmpeg_transcode_to_webm() using path-based API (replaces old bytes-in/bytes-out version) |
| 94 | +- Added ffmpeg_audio_waveform() using path-based API (same refactor as above) |
| 95 | +
|
| 96 | +### media/convert.rs — Per-format conversion logic |
| 97 | +
|
| 98 | +- Added ConversionAction enum: ToWebp, ToWebm, ToWebpIfSmaller, KeepAsIs |
| 99 | +- Added conversion_action() mapping each MIME type to the correct action |
| 100 | +- Added convert_file() as the main entry point for all conversions |
| 101 | +- PNG to WebP is attempted but original PNG is kept if WebP is larger |
| 102 | +- All conversions use atomic temp-then-rename strategy |
| 103 | +- FFmpeg failures fall back to original file with a warning (never panics, never returns 500) |
| 104 | +
|
| 105 | +### media/thumbnail.rs — WebP thumbnail generation |
| 106 | +
|
| 107 | +- All thumbnails output as .webp |
| 108 | +- SVG placeholders used for video without FFmpeg, audio, and SVG sources |
| 109 | +- Added generate_thumbnail() as unified entry point |
| 110 | +- Added image crate fallback path for when FFmpeg is unavailable (decode, resize, save as WebP) |
| 111 | +- Added thumbnail_output_path() for determining correct output path and extension |
| 112 | +- Added write_placeholder() for generating static SVG placeholders by kind |
| 113 | +
|
| 114 | +### media/exif.rs — EXIF orientation handling (new file) |
| 115 | +
|
| 116 | +- Moved read_exif_orientation and apply_exif_orientation from utils/files.rs |
| 117 | +
|
| 118 | +### media/mod.rs — Public API |
| 119 | +
|
| 120 | +- Added ProcessedMedia struct with file_path, thumbnail_path, mime_type, was_converted, original_size, final_size |
| 121 | +- Added MediaProcessor::new() with FFmpeg detection and warning log if not found |
| 122 | +- Added MediaProcessor::new_with_ffmpeg() as lightweight constructor for request handlers |
| 123 | +- Added MediaProcessor::process_upload() for conversion and thumbnail generation (never propagates FFmpeg errors) |
| 124 | +- Added MediaProcessor::generate_thumbnail() for standalone thumbnail regeneration |
| 125 | +- Registered submodules: convert, ffmpeg, thumbnail, exif |
| 126 | +
|
| 127 | +--- |
| 128 | +
|
| 129 | +## Modified Files |
| 130 | +
|
| 131 | +### src/utils/files.rs |
| 132 | +
|
| 133 | +- Extended detect_mime_type with BMP, TIFF (LE and BE), and SVG detection including BOM stripping |
| 134 | +- Rewrote save_upload to delegate conversion and thumbnailing to MediaProcessor |
| 135 | +- GIF to WebM conversions now set processing_pending = false (converted inline, no background job) |
| 136 | +- MP4 and WebM uploads still set processing_pending = true as before |
| 137 | +- Removed dead functions: generate_video_thumb, ffmpeg_first_frame, generate_video_placeholder, generate_audio_placeholder, generate_image_thumb |
| 138 | +- Removed relocated functions: ffprobe_video_codec, probe_video_codec, ffmpeg_transcode_webm, transcode_to_webm, ffmpeg_audio_waveform, gen_waveform_png |
| 139 | +- EXIF functions kept as thin private delegates to crate::media::exif for backward compatibility |
| 140 | +- Added mime_to_ext_pub() public wrapper for use by media/convert.rs |
| 141 | +- Added apply_thumb_exif_orientation() for post-hoc EXIF correction on image crate thumbnails |
| 142 | +- Added tests for BMP, TIFF LE, TIFF BE, SVG detection and new mime_to_ext mappings |
| 143 | +
|
| 144 | +### src/models.rs |
| 145 | +
|
| 146 | +- Updated from_ext to include bmp, tiff, tif, and svg |
| 147 | +
|
| 148 | +### src/lib.rs and src/main.rs |
| 149 | +
|
| 150 | +- Registered new media module |
| 151 | +
|
| 152 | +### src/workers/mod.rs |
| 153 | +
|
| 154 | +- Updated probe_video_codec call to use crate::media::ffmpeg::probe_video_codec |
| 155 | +- Replaced in-memory transcode_to_webm with path-based ffmpeg_transcode_to_webm using temp file persist |
| 156 | +- Replaced in-memory gen_waveform_png with path-based ffmpeg_audio_waveform using temp file persist |
| 157 | +- File bytes now read from disk only for SHA-256 dedup step |
| 158 | +
|
| 159 | +### Cargo.toml |
| 160 | +
|
| 161 | +- Added bmp and tiff features to the image crate dependency |
| 162 | +
|
6 | 163 |
|
7 | 164 | ## [1.0.13] — 2026-03-08 |
8 | 165 |
|
|
0 commit comments