- Python 64.4%
- JavaScript 15.8%
- HTML 13%
- CSS 6.2%
- Dockerfile 0.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| backend | ||
| frontend | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| PROVIDER_TEMPLATE.md | ||
| README.md | ||
| requirements.txt | ||
📦 STL Hoarder
Automatically sync your purchased 3D print files from MyMiniFactory and Cults3D.
Features
- Multi-provider support — MyMiniFactory (OAuth + collections) and Cults3D (API key + orders)
- Multi-account support — connect multiple accounts per provider
- Automatic sync — configurable cron schedule (default: every 6 hours)
- Organized downloads — files sorted by
provider/creator/object_name/ - Deduplication — SQLite database tracks what's been downloaded
- File extension filtering — per-account filters to only download specific file types
- Cookie management — browser session cookies for downloads with expiration warnings
- Notifications — webhook and email alerts on sync completion
- Web UI — status dashboard, manual sync, download history
- Plugin architecture — drop-in custom providers without rebuilding
- Dynamic UI — settings generated from provider config (no hard-coding)
- Auto cookie refresh — Playwright browser automation keeps cookies fresh
- OAuth token refresh — automatic token renewal on expiry
Quick Start
docker compose up -d
Then visit http://localhost:8484
MyMiniFactory Setup
- Click + Add Account → select MyMiniFactory
- Enter your OAuth client key and secret (get from MMF developer settings)
- Click Connect to authorize
- Click 🍪 Cookies and paste your browser session cookies
- Add purchased files to a MyMiniFactory collection (e.g., "Save for later")
- Hit Sync Now or wait for the scheduled sync
Cults3D Setup
- Click + Add Account → select Cults3D
- Enter your username and API key (generate at https://cults3d.com/en/api/keys)
- Click 🍪 Cookies and paste your browser session cookies
- Hit Sync Now — all orders will auto-download
File Extension Filtering
Each account can filter downloads by file extension:
- Click ⚙️ Settings on an account
- Enter extensions in the File Extension Filter field:
.zip, .stl, .3mf - Leave blank to download all files
Use cases:
- Only download model files:
.stl, .3mf, .obj - Only download archives:
.zip, .7z, .rar - Skip documentation: filter out
.pdf, .txt, .md
Download Reliability
STL Hoarder automatically retries failed downloads:
- 3 retry attempts per file with exponential backoff (2s, 4s, 8s)
- Failed downloads are logged and included in notifications
- Sync status reflects partial failures:
success,partial, orerror - Next scheduled sync will attempt failed files again (dedupe prevents re-downloading successful files)
Configuration
Environment variables in docker-compose.yml:
| Variable | Default | Description |
|---|---|---|
STL_BASE_URL |
http://localhost:8484 |
Public URL for OAuth callbacks |
STL_SYNC_SCHEDULE |
0 */6 * * * |
Cron expression for auto-sync |
STL_DOWNLOAD_DIR |
/downloads |
Container path for downloads |
STL_DATA_DIR |
/data |
Container path for database |
STL_WEBHOOK_URL |
(empty) | Webhook URL for sync notifications (POST JSON) |
STL_WEBHOOK_MODE |
batch |
Webhook mode: batch (all files at end) or per_file (webhook per download) |
STL_SMTP_HOST |
(empty) | SMTP server for email notifications |
STL_SMTP_PORT |
587 |
SMTP port (typically 587 for TLS) |
STL_SMTP_USER |
(empty) | SMTP authentication username |
STL_SMTP_PASSWORD |
(empty) | SMTP authentication password |
STL_SMTP_FROM |
(empty) | Email sender address |
STL_SMTP_TO |
(empty) | Email recipient(s) (comma-separated) |
STL_COOKIE_REFRESH_SCHEDULE |
0 */4 * * * |
Cron expression for cookie refresh checks |
STL_DEBUG |
false |
Enable debug mode (saves screenshots on login failures to /downloads/debug/) |
Notification Examples
Webhook (Discord, Slack, n8n, etc.):
- STL_WEBHOOK_URL=https://discord.com/api/webhooks/your-webhook-id
Email (Gmail with App Password):
- STL_SMTP_HOST=smtp.gmail.com
- STL_SMTP_PORT=587
- STL_SMTP_USER=your-email@gmail.com
- STL_SMTP_PASSWORD=your-app-password
- STL_SMTP_FROM=stl-hoarder@example.com
- STL_SMTP_TO=you@example.com
FileFlows Integration:
Point the webhook to your FileFlows instance to trigger flows automatically:
- STL_WEBHOOK_URL=http://fileflows:5000/api/webhook/stl-hoarder
- STL_WEBHOOK_MODE=per_file # Send webhook immediately after each file downloads
Webhook modes:
batch(default): One webhook at sync completion with all files in afilesarrayper_file: One webhook per downloaded file (real-time processing)
Batch mode payload (one webhook with all files):
{
"account": "Main Account",
"provider": "myminifactory",
"status": "success",
"files_downloaded": 2,
"files_skipped": 5,
"files_failed": 0,
"files": [
{
"path": "/downloads/myminifactory/CreatorName/Looters - Goblin Reclaimers/Looters - Goblin Reclaimers.zip",
"filename": "Looters - Goblin Reclaimers.zip",
"creator": "CreatorName",
"object_name": "Looters - Goblin Reclaimers",
"object_id": "12345",
"provider": "myminifactory",
"size_bytes": 52428800,
"sha256": "abc123..."
}
],
"failed": [
{
"filename": "BrokenModel.zip",
"creator": "SomeCreator",
"object_name": "Broken Model",
"error": "HTTP 404: File not found"
}
]
}
Status values:
success— All files downloaded successfullypartial— Some files downloaded, some failed (includesfailedarray)error— Sync completely failed
Per-file mode payload (one webhook per file):
{
"account": "Main Account",
"provider": "myminifactory",
"event": "file_downloaded",
"file": {
"path": "/downloads/myminifactory/CreatorName/Looters - Goblin Reclaimers/Looters - Goblin Reclaimers.zip",
"filename": "Looters - Goblin Reclaimers.zip",
"creator": "CreatorName",
"object_name": "Looters - Goblin Reclaimers",
"object_id": "12345",
"provider": "myminifactory",
"size_bytes": 52428800,
"sha256": "abc123..."
}
}
Use per_file mode for real-time processing as files arrive. Use batch mode to process all files together after sync completes.
Failed downloads: Files that fail after 3 retry attempts are included in the failed array with error details. Email notifications show the first 10 failures.
Custom Providers
STL Hoarder supports drop-in provider plugins. No rebuild required.
- Create a provider
.pyfile followingPROVIDER_TEMPLATE.md - Mount a host directory to
/app/backend/providers/custom/:volumes: - ./custom_providers:/app/backend/providers/custom - Drop your file in and restart the container
- The provider appears in the UI automatically
See the Provider Template for full documentation.
Download Structure
/downloads/
myminifactory/
CreatorName/
ObjectName/
file1.stl
file2.stl
cults3d/
CreatorName/
ObjectName/
model.zip
Roadmap
v1.0.0 ✅ (Current)
- MyMiniFactory provider (OAuth + collections sync)
- Cults3D provider (API key + orders sync)
- Drop-in provider plugin system with auto-discovery
- Dynamic UI generated from provider config
- Auto cookie refresh via Playwright browser automation
- OAuth token auto-refresh with DB persistence
- Cookie expiration warnings
- Admin panel with database management
- Real-time download progress tracking
- Pause/resume download queue
- Email/webhook notifications (batch + per-file modes)
- File extension filtering per account
- Retry logic with exponential backoff
- Failed download tracking and reporting
- Custom providers via mounted volume (no rebuild)
- Debug mode with failure screenshots
Future
- Printables provider
- Thangs provider
- Thingiverse provider
- Community provider contributions welcome!