Commit Graph
30 Commits
Author SHA1 Message Date
openhands d02aaa0d87 perf(studio): cache furni imports and virtualize the furniture grid
CI / check (push) Failing after 22s
CI / deploy (push) Skipped
CI / publish-container (push) Skipped
- Add TTL-based caching for local index lookup, furnidata classnames,
  catalog id set, nitro file presence and import stats
- Invalidate caches after furnace single/batch/clone imports
- Rewrite batch progress with elapsed time, rate and verification chips
- Virtualize the grid with @tanstack/react-virtual and replace the
  Load more button with infinite scroll via an IntersectionObserver
2026-09-13 11:40:55 +02:00
Simo 76f0420d64 feat(import): run catalog synchronizations as durable jobs
CI / check (push) Successful in 57s
CI / deploy (push) Successful in 18s
CI / publish-container (push) Successful in 1m18s
2026-09-11 00:36:22 +02:00
openhands 3e69b72513 feat(catalog): prevent and repair Arcturus emulator data errors
CI / check (push) Failing after 26s
CI / deploy (push) Skipped
CI / publish-container (push) Skipped
Block invalid catalog_items writes at the API level (points currency
allowlist, non-negative prices, positive amount, limited stack >= sold
count, unique sibling order numbers) and auto-assign unique order numbers
on bulk create. Add a catalog-maintenance scan + transactional repair that
fixes pre-existing rows: resets unsupported points_type, clamps negative
costs, sets amount to 1, raises limited_stack, renumbers duplicate orders
and deletes offers with missing page/item references. Surface the issue
count and a fix button in the admin maintenance panel.

Also: add enabled/retired flag to clone sources, classify poster and
currency furniture in item-kind, and remove the obsolete update-Nitrov3.sh.
2026-09-10 11:29:28 +02:00
openhands 8c12fc6c60 refactor(cms): deduplicate shared admin components and fix studio batch completion
CI / check (push) Failing after 1m35s
CI / deploy (push) Skipped
CI / e2e (push) Skipped
- fix(studio): stop markBatchDone infinite recursion so batches complete
- refactor(api): merge api-response into api and drop the duplicate module
- refactor(media): extract shared media loader and URL validator
- refactor(ui): extract shared LoadingSpinner for site and admin groups
- refactor(dates): consolidate raw date formatting into formatDate util
- refactor(logs): share a single generic log-list loader across tables
- refactor(theme): merge both ColorField components and reuse contrast helpers
- refactor(import): extract shared ImportErrorBanner and SearchInput
- chore(): remove dead theme-editor-tabs after inlining tab components
2026-09-05 20:58:42 +02:00
openhands 458972fdfd fix: improve batch import error handling and resilience
CI / check (push) Successful in 1m25s
CI / deploy (push) Successful in 1m57s
CI / e2e (push) Successful in 26s
- Add retries for furnidata fetch (3 attempts, 1s delay)
- Better error messages for user (distinguish 502/400/other)
- Client-side: show detailed error from SSE stream when available
- Remove unused admin-helpers.test.ts
2026-09-04 18:28:14 +02:00
openhands 399c047515 fix: harden admin actions, search, sanitization and repo hygiene
CI / check (push) Successful in 1m21s
CI / deploy (push) Successful in 1m25s
- Split approve/dismiss application workflows with distinct audit logs,
  rate-limited guards and real error logging
- Validate article status/date/id input and stop resetting publishedAt
  on every update
- Validate guild updates (state, forum enums, non-empty name) behind
  rate-limited guard
- Fix scheduled-article publishing (ignore NULL dates, set updatedAt,
  type-safe predicates)
- Harden admin search API (LIKE escaping, query cap, per-user
  rate limit, round-robin result cap) and fix search dialog
  abort/res.ok/loading races
- Lock down HTML sanitizer to an allowlist profile and add XSS tests
- Improve mobile nav accessibility (unique id, dialog role, focus
  management, scroll lock, outside close)
- Log swallowed server errors instead of silent catch blocks
- Remove dead eslint config, drop unused dompurify deps, restore knip
  CI step, add Playwright config with smoke spec
2026-09-04 13:04:08 +02:00
openhands 52516a368d fix: skip heavy post-import consolidation on non-final clone chunks
CI / runtime-diagnostics (push) Skipped
CI / check (push) Successful in 38s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m2s
The flush after every 400-item chunk was running expensive operations
(reconcileOfferIds, rebuildCatalog, verifySpriteIds, rcon updates) which
caused the import to hang after ~800 items. Now only the final chunk
triggers the full consolidation. Also raised the per-request limit from
500 to 5000 items.
2026-09-01 18:29:06 +02:00
openhands f70d96b81c fix: prevent import hanging by adding abort signals and idle timeouts
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
- Furni batch: wire request.signal to abort controller, send post_import
  progress events, skip post-import steps when aborted
- Clone sync-all: pre-fetch furnidata once per source instead of per item
  (eliminates 2000+ redundant DB reads + HTTP requests)
- SSE client: add 60s idle timeout to prevent infinite hangs when server
  stops responding
2026-08-31 18:11:54 +02:00
openhands 5311ee1fb8 Force catalog_items.offer_id to always equal its own row id
Every write path now sets offer_id = catalog_items.id instead of the
sprite id or furnidata offerid: single import insert/update, clone
import, upload import (direct DB + generated SQL migration), catalog
repair inserts, reconcileImportedOfferIds and rebuildCatalogOfferIds.

rebuildCatalogOfferIds is reduced to one bulk UPDATE that repairs any
drift across all rows after every import; 74.838 legacy rows were
repaired on the live database with this change.
2026-08-23 13:42:47 +02:00
openhands 8bb339cc49 feat: auto-translate furnidata per import (nl/en/de/fr/es/tr/it)
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
Generate localized FurnitureData_<lang>.json files from the master
FurnitureData.json + official Habbo hotel translations. Fetches per-hotel
furnidata with in-memory cache (6h TTL), maps by classname (* variant
aware), and overrides name/description where a translation exists.

Full rebuild after every batch/batch-regen/clone import and as admin
GET ?action=build-languages; single imports patch incrementally via
patchLocalizedFurniDataEntries. Failures are best-effort and never fail
the import itself. Files are written to every configured gamedata write
path (primary + mirrors) so /gamedata/config/FurnitureData_<lang>.json
is available for per-language Nitro clients.

New service: src/lib/services/furni-data-i18n.ts with
buildLocalizedFurniDataFiles, patchLocalizedFurniDataEntries,
FURNIDATA_LANGUAGES (nl/en/de/fr/es/tr/it) and applyTranslationsForTest.
2026-08-21 14:16:37 +02:00
openhands 984b5bf793 feat: auto-repair sprite_id drift after every import
CI / check (push) Successful in 28s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
The emulator sends items_base.sprite_id to the client and Nitro resolves
the furniture by looking up that id in FurnitureData.json. Legacy rows
where sprite_id drifted from the id made the client render a completely
different item (e.g. a wired or custom asset instead of the purchased
furniture).

Add verifyAndFixSpriteIds() which repairs any row whose sprite_id no
longer matches its id while the local furnidata carries the item under
that id, and run it after every import path (single, batch, batch-regen,
clone) next to the offer_id rebuild.
2026-08-21 14:02:42 +02:00
openhands 4b7cb519df fix: furniture interaction detection and automatic catalog offer_id rebuild
Interaction detection:
- Trust SWF-derived sit/lay/stand flags only when the logic XML actually
  contains action data (new hasActions metadata); otherwise fall back to
  keyword detection so custom furni without <action> nodes are still
  classified correctly
- Add French/Dutch/German/Spanish/Italian keywords (chaise, banquette,
  stoel, silla, sedia, stuhl, tafel, mesa, ...) to sit/lay/stand detection
  with token-boundary matching to avoid false positives like bedside_table
- Unify interaction_modes_count priority: mechanic fixed modes, then raw
  animation state count, then sit/lay fallback, then keyword default
- Detect mechanic type even when real flags are not used

Catalog integrity:
- Skip duplicate catalog_items inserts in clone and upload imports
- Re-check live catalog rows before applying generated repair SQL
- Add rebuildCatalogOfferIds() which rebuilds every catalog_items.offer_id
  from the local FurnitureData.json (matched by entry id, then classname)
  and run it after every import path (single, batch, batch-regen, clone)
2026-08-21 13:39:21 +02:00
openhands 6021a91ef7 fix: harden furni import pipeline for production
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 57s
- importSingleFurni: actually update an existing item instead of failing on a primary key INSERT collision; refuse to reassign a spriteId owned by a different classname
- reconcileFurniDataWithItemsBase: also sync each entry's offerid to the DB sprite id, not just the id
- Move the full-table interaction_modes_count verification out of the per-item import hot path and run it once per batch/single import
- clone-import: apply the auto-detected interaction_type (was hardcoded 'default'), set FurnitureData offerid and catalog_items.offer_id to the new local sprite id (was the source hotel's id / -1)
- clone batch route: run the same post-import reconcile/verify/ownership/RCON consolidation as the furni batch route
- upload-import: set offer_id to the allocated id in both the direct insert and the generated SQL migration (was -1)
- generateCatalogSql: use the classname as catalog_name and the item id as offer_id so rows match the app-managed import convention
- stats + missing-nitro endpoints: match catalog membership via item_ids instead of the catalog_name join, so translated display names no longer break counts
- deleteImportedItem/rollback: delete catalog rows by the canonical item_ids link only
- classifyFurni: wall items always classify as 'walls' before prefix rules (rare_/val_/xmas_) can misfile them
2026-08-20 11:48:51 +02:00
openhands a1775fbf1e perf: enable source-specific asset downloads and make nitro/icon URLs optional
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 48s
Import improvements:
- importSingleFurni now accepts sourceSwfBaseUrl, nitroBaseUrl, iconBaseUrl
  params to try source-specific asset downloads before falling back to
  the official Habbo CDN (images.habbo.com)
- Source-specific URL cascade:
  1. Try sourceSwfBaseUrl/hof_furni/{rev}/{name}.swf
  2. Try sourceNitroBaseUrl/{name}.nitro (pre-made nitro bundles)
  3. Fallback to images.habbo.com/dcr/hof_furni/{rev}/{name}.swf
- Same fallback chain for icon downloads
- Clone sources can now have empty nitroBaseUrl/iconBaseUrl (retro
  hotels without nitro support)
- Added VirtualCity source (verified SWF downloads via virtualc.nl/dcr)
- Added sourceSwfBaseUrl field to CloneSource interface
- Both batch and single import routes pass source params through
- Clone POST route accepts sourceSwfBaseUrl, makes nitro/icon optional
- Nitro fallback download tries .nitro files before SWF conversion
2026-08-06 20:19:54 +02:00
openhands 1b817fe434 fix: resolve critical bugs and improve admin panel reliability
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s
- Fix missing await in pets API route causing empty responses
- Fix updateSetting to use upsert pattern instead of update-only
- Create missing /api/admin/sounds/upload route (upload was broken)
- Wire bulk delete actions in catalog table
- Replace native confirm() with useConfirmDialog() across rooms and clone pages
- Add error logging to silent catch blocks in radio actions and audit route
- Add graceful degradation to devops health endpoint
- Add cache eviction to clone icon route to prevent memory leak
- Internationalize hardcoded Italian strings to English
- Remove placeholder created_at fields from prefix API responses
- Remove dead code and fix type errors in translations and import pages
- Standardize PERMS import path in analytics export route
2026-08-06 18:32:55 +02:00
openhands 936053cca6 feat(clone): add hotel field to clone source presets
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 47s
- CloneSource interface now has a hotel field (maps to habbo_gamedata_hotel)
- DEFAULT_SOURCES presets include their associated hotel (it/com)
- When cloning from a source with a hotel configured, habbo_gamedata_hotel
  is set automatically so official furnidata enrichment uses the correct locale
- Clone source form UI now has a hotel select dropdown
- Source list shows the hotel label when configured
- Clone API route passes hotel through to upsertSource
2026-08-05 16:21:45 +02:00
openhands 172941c542 perf(import): parallelize ID allocation and raise clone concurrency to 10
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 41s
Replace the serialized SELECT MAX + INSERT id-allocation chains for
items_base and catalog_items with a lazy-seeded in-process counter so
concurrent clone workers no longer queue on a global lock per item.
Re-seeds after 60s idle to avoid colliding with externally added rows.
Raise the clone import concurrency default from 6 to the batch cap of 10.
2026-08-05 11:37:17 +02:00
openhands dc8fb8a6ed feat: speed up admin clone import and enable Cache Components
- Clone import: defer FurnitureData.json writes and append all entries in a
  single batched write instead of one read-modify-write per item, removing
  the main serialization bottleneck for large batches.
- Clone import: raise SSE batch concurrency cap from 5 to 10 and bump the
  clone client/route default from 2 to 6.
- Add a flush hook to runSseBatch so callers can batch deferred work before
  batch_complete is emitted, and surface flush errors as an error event.
- Enable Next.js Cache Components (instant: false opt-out) and silence the
  related build warnings in next.config.ts.
- Switch isomorphic-dompurify to dompurify and refresh dependencies.
2026-08-05 11:10:16 +02:00
openhands 1fd6f7146b fix: improve error handling for Cloudflare-protected clone sources
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 54s
- Detect HTML responses from FlareSolverr and throw descriptive error
  instead of letting JSON.parse fail with cryptic 'Unexpected token' error
- Add try/catch to clone/route.ts GET handler to return 502 with
  clear message instead of Internal Server Error 500
- Add FLARESOLVERR_URL to .env
2026-08-04 19:21:31 +02:00
SimoandCursor 9aa4f331bf refactor(db): migrate app pages and APIs from Prisma facade to Drizzle (4)
Co-authored-by: Cursor <[email protected]>
2026-08-01 14:15:36 +02:00
openhands 17847545dd Improvements: remove dead config, fix ESM, add URL validation, unify types, add missing logging
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 1m52s
- Remove .prettierrc (dead config, Biome replaces Prettier)
- Rename lighthouserc.json to lighthouserc.cjs with module.exports for ESM compat
- Add logger.warn to empty catch blocks in auth, register, site-settings, prisma-cache, redis, security, rate-limit
- Unify ActionResult type: action-helper.ts uses 'ok' consistent with safe-action-shared.ts
- Add noUnusedLocals + noUnusedParameters to tsconfig + fix 25 pre-existing unused vars
- Replace barrel export src/types/index.ts with direct @/types/common imports
- Make trustHost conditional (development only) in auth.ts
- Add pre-flight URL validation to update-Nitrov3.sh to catch image.library.url misconfigurations
- Improve NITRO_IMAGE_LIBRARY_URL content validation in pre-flight & post-compute checks
2026-07-26 20:28:11 +02:00
SimoandCursor ed7db6e048 feat: public events/polls, friends graph, captcha, SSE hardening, and admin UX
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 2m55s
Ship product gaps: register/vote pages, friend add/accept/decline/remove, email verify TTL, captcha on login/forgot, soft-fail user actions, SSE abort/shared client, Commando Centrum error toasts, admin delete for events/polls, and IT/NL i18n fills.

Co-authored-by: Cursor <[email protected]>
2026-07-21 21:08:33 +02:00
SimoandCursor 2ff08e5127 chore: patch deps, CSP style nonces, otplib 13, and PR CI
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 1m35s
Co-authored-by: Cursor <[email protected]>
2026-07-21 20:46:02 +02:00
openhands 804daeffca feat: add .nitro upload + sync-all + repair-icons features
Deploy / release (push) Skipped
Deploy / deploy (push) Failing after 32s
- Upload .nitro bundles directly with full DB, catalog, and furnidata integration
- Generate SQL migration files on upload (optional)
- Auto-sync missing furniture from all configured clone sources (SSE batch)
- Repair missing icons by extracting from local .nitro or downloading from sources
- All behind ASSETS_IMPORT permission
2026-07-21 14:53:26 +02:00
openhands df38dccbf1 style: format code biome
Local Build and Deploy / deploy (push) Failing after 46s
2026-07-13 21:57:41 +02:00
openhands 2e4ed76121 style: format code with prettier
Local Build and Deploy / deploy (push) Successful in 49s
2026-07-12 21:07:34 +02:00
remco e85e4d74ea revert fb8e77bb68
Local Build and Deploy / deploy (push) Successful in 1m11s
revert style: clean up code with prettier and eslint
2026-07-12 21:02:03 +02:00
openhands fb8e77bb68 style: clean up code with prettier and eslint 2026-07-12 20:31:05 +02:00
Simo c0ffc74f9b fix: externalize lzma for import build
Local Build and Deploy / deploy (push) Successful in 49s
2026-07-12 19:15:08 +02:00
Simo eb759f54bf feat: connect guarded asset import api 2026-07-12 19:12:25 +02:00