mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
Post work PR #?
This commit is contained in:
@@ -19,6 +19,7 @@ All notable changes to Bambuddy will be documented in this file.
|
||||
- **Dutch (nl) is now a supported interface language (#2891, requested and contributed by @Igiegel)** — Adds `nl` as the fourteenth locale, listed as "Nederlands" in the language picker. The translation was contributed as a file on the issue and needed three corrections before it could be wired up, all of which the parity gate found. First, the nine `stats.timeframe.*` entries had their **keys** translated along with their values (`'today'` had become `'vandaag'`), which would have left the Statistics timeframe selector resolving nothing and rendering raw key names for every Dutch user — the values were kept and the keys restored. Second, the file was translated against an older `en.ts` and was 84 leaves short, missing the Filament Track Switch feed prompts, the AI-detection status strings, the no-3MF internal-history banner, the batch-order stranded-plate notices, the Avery starting-position field and the whole `locationHaSensors` section from #2824; those were translated and added. Rather than splice them in, `nl.ts` was regenerated from the `en.ts` skeleton with the contributor's strings carried over, so its structure, key order and section comments now match the reference locale exactly and a future diff against `en.ts` reads as content rather than as reordering. Third, 229 leaves were identical to English; each was checked individually and all were kept, because Dutch takes most technical UI vocabulary verbatim — printer, filament, status, nozzle, timelapse, dashboard — and Dutch slicer users use the English feature names (support, ironing, prime tower, gap fill) untranslated. Those 123 distinct values are now listed explicitly in a `NL_COGNATES` allow-list in `check-i18n-parity.mjs`, the same shape the other twelve locales use, so the exemption is an enumerated translator decision rather than a blanket skip. Parity green at 6264 leaves across all 14 locales.
|
||||
|
||||
### Changed
|
||||
- **The MakerWorld integration is now a model-provider package, so a second model site is an implementation rather than a second copy of the feature ([PR #2845](https://github.com/maziggy/bambuddy/pull/2845) by @pascalheidmann)** — `services/makerworld.py` was a single 635-line module that owned everything from URL parsing to the presigned S3 download, and the routes called it by name, so Thingiverse or Printables would have meant a second route file beside the first. It is now an interface: a `ModelProvider` descriptor carrying identity, host patterns, the credentials it needs, its library folder, its permissions and its SSRF allowlists, plus a per-request `ProviderService` that does the transport — with MakerWorld as the first implementation and a registry that hands a pasted URL to whichever provider claims it. Nothing about the MakerWorld flow changes: the endpoints and their request and response shapes are unchanged, the new `source_type` field defaults to `makerworld` so existing callers send exactly what they sent before, and the transport moved verbatim — thirteen of the eighteen functions are byte-identical by AST comparison, including the CDN allowlist, the 200 MB download cap and the certifi-pinned TLS context that keeps S3 downloads working on Windows. Four things did change. Bambu Cloud credential storage moved out of `routes/cloud.py` into `services/bambu_cloud_credentials.py`, because a feature package that has to import a route module to read a stored token is a dependency pointing the wrong way; the cloud endpoints themselves did not move. An import naming a provider that is not registered is now refused before anything happens, where it used to create the destination folder on its way to failing. "Your Bambu sign-in expired" is now an explicit flag the provider sets rather than something inferred from whether an error message happened to be present, so a network failure or a rate limit can no longer be reported to you as an expired sign-in. And each request is authorised against the permission of the provider it actually named instead of MakerWorld's — latent while MakerWorld is the only one registered, wrong on the day it is not.
|
||||
- **Updating now repairs a service file that was written before the `--loop asyncio` pin existed (#3001)** — `install.sh` has pinned the loop since 2026-07-05 (#1896), but nothing has ever rewritten an *existing* service file: `install/update.sh` does a `git reset --hard`, a pip install, a frontend build and a restart, and never touches the unit. uvloop has been in every native venv since `uvicorn[standard]` entered `requirements.txt` on 2025-11-28, and uvicorn's `--loop auto` prefers it, so every native install created in that seven-month window has been running on uvloop ever since and no amount of updating has changed that. It cost them every RTSP camera on 1.2.5.4, and before that it left them exposed to a Virtual Printer FTP upload being silently truncated into a corrupt `.gcode.3mf` — which is why #1896 shipped a ZIP-validation backstop alongside the pin, since the pin could never reach the installs that already existed. Both update scripts now add the missing flag themselves: `update.sh` to the systemd unit, `update_macos.sh` to the launchd plist, in each case while the service is stopped so the repair takes effect on the same restart. Only the one flag is ever inserted — a hand-edited port, extra hardening, `ExecStartPre` lines and everything else stay byte-identical, and the file is copied to a timestamped backup first. Anything that is not a single-line unit invoking uvicorn directly is described rather than edited: a wrapper script, an `ExecStart` continued across lines, several `ExecStart` lines, a unit that is not writable, or a service carrying systemd drop-ins, since a drop-in may be what defines `ExecStart` and editing the fragment would then change nothing while reporting success. A loop pinned deliberately is also left alone — someone who wrote `--loop uvloop` on purpose gets no argument, only the startup warning. The check reads the *effective* `ExecStart` from systemd rather than the file, so a drop-in that already pins the loop counts and the repair is idempotent.
|
||||
- **Bambuddy now says so at startup when it is running on uvloop (#3001)** — every unit file this project ships pins `--loop asyncio`, added for #1896 because uvloop's SSL layer can drop buffered data and truncate a Virtual Printer FTP upload into a corrupt `.gcode.3mf` that is acked `226` and forwarded to a printer. Two populations run a unit nobody here wrote and therefore have no such pin: the Proxmox VE Helper-Scripts LXC, which composes its own `ExecStart`, and native installs created before that fix landed on 2026-07-05, which never gained the flag because `install/update.sh` does not rewrite unit files. Neither had any way to know. #3001 only surfaced them because losing every camera at once is loud; a truncated upload is silent, and there is nothing to notice until a print fails from a file that was corrupt on arrival. Startup now logs one WARNING naming the loop, the risk and the exact flag to add. It is a warning and not a refusal: a server that answers requests beats a purist one that will not boot, and by the time any application code runs uvicorn has already chosen its loop. The check asks the running loop what it is rather than whether uvloop imports — uvloop is a hard dependency here, since `requirements.txt` pins `uvicorn[standard]`, so its presence says nothing about what is in use — and it matches on the module name so that asking the question never imports uvloop on a host that lacks it.
|
||||
- **The spool form is wider, and its colour, weight and cost fields have their own tab** — The Printers tab is a model list beside a detail pane, which needs the room. Colour, spool weights, price, category and storage location move out of the bottom of a long scroll into a **Color & Cost** tab, laid out in two columns rather than one short field per row. Filament identity and the slicer preset stay on the first tab.
|
||||
|
||||
@@ -529,7 +529,7 @@ class MakerWorldService(ProviderService):
|
||||
Validates that the URL's host is one of the declared thumbnail hosts
|
||||
(SSRF guard — symmetric to :meth:`download_3mf`; both allowlists are
|
||||
fed from the provider descriptor by ``build_service``). Caps
|
||||
payload at 5 MB. Returns ``(bytes, content_type)``; content type
|
||||
payload at 10 MB. Returns ``(bytes, content_type)``; content type
|
||||
defaults to ``image/jpeg`` if the upstream didn't set one.
|
||||
"""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user