mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-05-09 08:25:54 +02:00
[PR #1099] [MERGED] Feature/makerworld #1163
Labels
No labels
A1
automated
automated
bug
bug
Closed due to inactivity
contrib
dependencies
dependencies
duplicate
enhancement
feedback
hold
invalid
Notes
P1S
pull-request
security
ThumbsUp
user-report
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/bambuddy-maziggy-1#1163
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/maziggy/bambuddy/pull/1099
Author: @maziggy
Created: 4/23/2026
Status: ✅ Merged
Merged: 4/23/2026
Merged by: @maziggy
Base:
dev← Head:feature/makerworld📝 Commits (4)
b7cb328feat(makerworld): URL-paste import and print for MakerWorld models42e9dc5feat(makerworld): ship working URL-paste import via api.bambulab.com iot-service8a8216cMerge branch 'dev' into feature/makerworld6ea6aa1- frontend/src/App.tsx — removed the 3 stale lines (kept the 3 equivalents). TSC + Vite both clean.📊 Changes
29 files changed (+12776 additions, -3 deletions)
View changed files
📝
CHANGELOG.md(+7 -0)📝
README.md(+10 -0)📝
backend/app/api/routes/library.py(+103 -0)➕
backend/app/api/routes/makerworld.py(+394 -0)📝
backend/app/core/database.py(+36 -0)📝
backend/app/core/permissions.py(+13 -0)📝
backend/app/main.py(+9 -0)📝
backend/app/models/library.py(+8 -0)➕
backend/app/schemas/makerworld.py(+111 -0)➕
backend/app/services/makerworld.py(+555 -0)📝
backend/tests/integration/test_auth_api.py(+2 -1)➕
backend/tests/unit/services/test_makerworld.py(+625 -0)➕
backend/tests/unit/test_makerworld_routes.py(+446 -0)📝
frontend/src/App.tsx(+2 -0)➕
frontend/src/__tests__/pages/MakerworldPage.test.tsx(+321 -0)📝
frontend/src/api/client.ts(+60 -0)📝
frontend/src/components/Layout.tsx(+2 -1)📝
frontend/src/i18n/locales/de.ts(+51 -0)📝
frontend/src/i18n/locales/en.ts(+51 -0)📝
frontend/src/i18n/locales/fr.ts(+50 -0)...and 9 more files
📄 Description
feat(makerworld): ship working URL-paste import via api.bambulab.com iot-service
The MakerWorld integration shipped in 0.2.4b1 dev was broken for most
public models: the makerworld.com/design-service path returns "Please
log in to download models" even with a valid Bambu Cloud bearer,
because it's cookie-gated behind Cloudflare. Published reverse-
engineering projects work around this by pasting browser cookies; we
route around it entirely by using the api.bambulab.com/iot-service
endpoint (documented by Pr0zak/YASTL#51), which accepts the same
bearer Bambuddy already has and returns a presigned S3 URL.
Working flow:
GET api.bambulab.com/v1/design-service/design/{id} → metadata
GET api.bambulab.com/v1/iot-service/api/user/profile/{pid}?model_id=
Authorization: Bearer {cloud_token} → signed S3 URL
urllib.request (no redirects, no query re-encoding) → bytes
Notes on each step:
- The model_id query param is the alphanumeric string from the
design response (e.g. US2bb73b106683e5), NOT the integer designId
from the /models/{N} URL. The import route fetches design metadata
first to get it.
- S3 presigned URLs MUST be fetched with urllib (not httpx/curl_cffi)
because the signature is computed over exact query-string bytes;
any normalising encoder breaks it with SignatureDoesNotMatch 400s
(YASTL#52 hit the same issue). Wrapped in a no-redirect opener so
the .amazonaws.com host allowlist guarantee isn't bypassed by a
302 elsewhere.
- The canonical source_url now includes profile_id so different
plates of the same model get distinct library entries. Older rows
from dev builds keep the model-level URL; the resolve endpoint's
"already imported" check LIKEs both shapes.
UI rebuild:
- Per-plate Save + Save & Slice in Bambu Studio / OrcaSlicer (the
plate is unsliced source, so "Print Now" was misleading and is
replaced by an explicit slicer hand-off).
- Import all plates with sequential progress.
- Folder picker (default: auto-created top-level "MakerWorld"
folder, created on first import, folder tree invalidated so
File Manager shows it immediately).
- Image gallery per plate with keyboard-navigable lightbox.
- Recent imports sidebar (sticky on lg+, vertical list with
jump-to-library / slicer / open-on-makerworld icons).
- Inline follow-up actions on imported plate rows so the user
doesn't scroll back to a top-of-page card.
- Per-plate delete via the standard ConfirmModal (no window.confirm).
- Elapsed-time + phase label during import so the 10-30s synchronous
POST doesn't feel frozen.
- URL-change detection drops the preview when the pasted URL
diverges from the resolved one.
Security hardening (found in review):
- DOMPurify.sanitize on the MakerWorld HTML summary before
dangerouslySetInnerHTML (user-authored content).
- tags in that HTML routed through the thumbnail proxy so
the SPA's img-src 'self' data: blob: CSP isn't widened.
- /makerworld/thumbnail uses follow_redirects=False (the host
allowlist only covers the initial URL).
- 3MF CDN fetch strips the bearer (signed URL is the credential).
- S3 fetch uses a no-op HTTPRedirectHandler for the same reason.
- Upstream filename is os.path.basename'd before persisting.
Tests: 46 backend service unit tests, 19 route tests, 12 frontend
tests — all passing. All user-facing strings localised across the
8 UI languages.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.