Commit Graph
533 Commits
Author SHA1 Message Date
openhands c95ad4a37f Reconcile offer_id after every import
CI / check (push) Successful in 40s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m12s
After each single or batch import, walk all catalog items under the
Imported Furniture tree and set offer_id to the furnidata sprite id,
repairing any stale values (e.g. legacy -1 rows). Reports how many
rows were fixed in the API response.
2026-08-18 19:40:17 +02:00
openhands 305a0c42ff Derive catalog offer_id from furnidata sprite id
CI / check (push) Successful in 44s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m19s
Import used a hardcoded offer_id of -1, while the matching
FurnitureData.json entry already carries offerid = spriteId.
Set catalog_items.offer_id to the sprite id on insert and update so
purchases resolve to the correct furni offer.
2026-08-18 19:34:34 +02:00
openhands 7257a7b0f4 Fix duplicate catalog pages from import race condition
CI / check (push) Failing after 49s
CI / release (push) Skipped
CI / deploy (push) Skipped
A concurrent import could create the same catalog sub-page twice
(getOrCreateCategoryPage / getOrCreateImportedParentPage do a
SELECT-then-INSERT with no unique constraint). Deduplicate right after
insert by keeping the lowest-id page and removing the duplicate, while
never deleting a page that already received catalog items.
2026-08-18 19:30:28 +02:00
openhands f285a7cd98 Add performance optimizations and component refactors
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m23s
- Cache read-heavy public API routes via redisCache (leaderboard, values,
  shop, articles, photos, guilds, teams, staff, users, home, radio, badges)
- Add single-flight and bounded-memory cache layer with unit tests
- Parallelize independent DB queries on search, rares, shop, staff, polls
  and profile pages
- Push radio points leaderboard aggregation to SQL with a LIMIT
- Split studio-client and import-furni-client into focused modules
- Clean up next.config.ts
2026-08-17 22:02:21 +02:00
openhands 5b09179404 Add all-in-one Studio merging furni import and catalog management
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m1s
Add a full-viewport /admin/studio workspace that unifies the import and
catalog systems into a single automated flow:

- Furni library browser against official Habbo furnidata with search,
  type/status filters, live previews and pagination
- Catalog structure rail showing where imported furniture lands
- Detail drawer with automatic placement preview (category + price via
  classifyFurni/autoPriceFurni) and one-click import that downloads
  assets, converts SWF to nitro, writes items_base, updates
  FurnitureData.json and creates an auto-priced catalog entry
- Batch auto-import with SSE progress and RCON cache refresh
- Nitro editor integration and imported-item deletion

Extract pure auto-catalog helpers (CATEGORY_PAGE, CLASSNAME_RULES,
classifyFurni, autoPriceFurni) into a client-safe module shared by the
server pipeline and the Studio UI so the preview always matches what the
emulator import applies.
2026-08-15 15:34:07 +02:00
openhands e31f6d985c Add rollback/undo functionality for furniture imports
CI / check (push) Successful in 52s
CI / release (push) Skipped
CI / deploy (push) Successful in 2m8s
- Added LogsFurniImports table to track import history with rollback support
- Implemented rollbackFurniImport() service function to revert imports:
  - Removes items from items_base, catalog_items, FurnitureData.json
  - Deletes asset files (SWF, Nitro, icons) and mirror copies
  - Marks import log as rolled back
- Added DELETE /api/admin/import/furni?importId=X endpoint
- Added dry-run support for import validation (?dryrun=1)
- Added updateExisting option to update existing catalog entries
- All TypeScript/Biome checks pass, tests pass (806 passed, 1 pre-existing skip)
2026-08-14 19:42:01 +02:00
openhands 7ef5038a9e Add updateExisting option to furniture import
CI / check (push) Successful in 1m14s
CI / release (push) Skipped
CI / deploy (push) Successful in 2m15s
- Added updateExisting parameter to importSingleFurni and API routes
- When updateExisting=true, existing items are updated (catalog price/page) instead of failing
- Added catalogUpdated flag to ImportSingleResult
- Updates existing catalog entries (price, page) instead of skipping duplicates
2026-08-14 18:35:00 +02:00
openhands f89b8a6adf Fix FurnitureData.json spriteId conflict auto-repair
CI / check (push) Successful in 1m21s
CI / release (push) Skipped
CI / deploy (push) Successful in 2m17s
- Added spriteId conflict resolution to repairFurniData(): keeps first classname per id, removes conflicting entries
- Returns new removedIdConflicts count in repair result
- Updated audit event type and client UI to display removedIdConflicts
- Updated catalog-audit.ts event type and client state type
- When 'Repair FurnitureData.json' is checked, it now fixes id conflicts automatically
2026-08-14 18:23:00 +02:00
openhands 0f35bc8529 Add hCaptcha support alongside Turnstile and reCAPTCHA
CI / check (push) Successful in 1m9s
CI / release (push) Skipped
CI / deploy (push) Successful in 2m6s
- Add hcaptcha_site_key and hcaptcha to captcha_provider options in admin settings
- Update captcha.ts server-side verification for hCaptcha (new endpoint + secret key)
- Add hCaptcha widget rendering in register-form.tsx
- All TypeScript and Biome checks pass
2026-08-14 17:04:34 +02:00
openhands e76c530e4f Fix TypeScript errors and implement furniture import ID integrity with 18+ age verification
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m2s
- Add termsAccepted and ageVerified columns to User table
- Update register schema with new boolean fields
- Fix register form age verification checkbox (th -> t)
- Fix furni-import spriteId declaration order
- Fix batch route variable naming (id -> spriteId)
- Fix catalog-audit import path and ensure correct types
- Hardened import with per-item id conflict checks
- Added audit option for FurnitureData.json spriteId conflicts
- Updated tagline to include Leeftijdsvereiste: 18+
2026-08-14 16:37:00 +02:00
openhands e5ec3c1f06 perf: optimize CMS queries, caching, and asset delivery
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 57s
Database:
- Add missing indexes (users.credits, users_currency(type,amount),
  users_settings.respects_received, camera_web.timestamp,
  messenger_offline.user_id) via migrations 0020/0021
- Use partial .select() everywhere instead of SELECT * (tickets, users,
  rooms, audit logs, catalog tree, polls, radio, password reset)
- Add queryPrepared/queryPreparedOne (server-side prepared statements)
  and switch the login check to a prepared statement; drop dead
  cache options from the pool config
- Raise total_users/total_rooms COUNT(*) cache TTL to 5m

Caching:
- Consolidate the three cache helpers (cached, redisCache, cachedQuery)
  into a single memory-first implementation backed by Redis
- invalidateKey now clears the in-process cache as well as Redis
- Cache homepage sections, news list, and leaderboard tabs; share one
  news_list cache key between homepage and news archive
- siteSettings: in-process cache with TTL so repeated getters no longer
  pay a Redis round-trip per call
- Share a 10s poll cache across all radio SSE connections
- Normalize timestamps after cache reads (Redis JSON round-trip)

Assets:
- Enable AVIF/WebP via images.formats and remove unoptimized from news
  covers and the homepage hero (149KB jpg) with proper sizes/priority
- Support ?format=webp|avif|png in the /imaging proxy via sharp

Other:
- Fix pnpm supply-chain minimumReleaseAge failures by excluding the
  freshly-published packages (next 16.3.1, hookform resolvers 5.8.0,
  resend 6.20.0)
- Remove unused before/after fields from housekeeping AuditEntry
2026-08-14 11:20:37 +02:00
openhands 65e3915a5f feat: replace Redis with DragonflyDB
CI / check (push) Successful in 31s
CI / release (push) Skipped
CI / deploy (push) Successful in 57s
- Replace Redis server with DragonflyDB v1.40.1 (Redis protocol compatible)
- Stop redis-server service, enable dragonfly service on 127.0.0.1:6379
- Configure dragonfly in /etc/dragonfly/dragonfly.conf (bind 127.0.0.1, maxmemory 2gb)
- Update .env: remove REDIS_URL reference

Improve database reliability:
- Fix catalog-tree.ts: remove CAST(page_id AS CHAR) to enable index usage (122 rows vs 78k full scan)
- Fix catalog-repair.ts: replace sql.raw() string interpolation with parameterized sql queries using quoteIdentifier()
- Improve redis retry resilience: change retryStrategy to not give up after 3 attempts, enabling automatic reconnect after server restart

Update documentation:
- Update README: replace Redis references with DragonflyDB, add DragonflyDB setup section, update performance features list, update architecture diagram
- biome and typecheck pass clean
2026-08-12 14:34:29 +02:00
openhands c808c59fce fix: replace jsonc with jsonc-parser and cleanup build config
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Failing after 1m31s
2026-08-11 16:53:03 +02:00
openhands e867b675fc fix: replace jsonc with jsonc-parser and cleanup build config 2026-08-11 16:50:10 +02:00
Simo 4a6fcd050e fix: preserve user figures in avatar imager
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 44s
2026-08-09 21:48:43 +02:00
openhands 0aef27efc4 fix: omit default params in avatar URL for cleaner URLs
CI / check (push) Successful in 33s
CI / deploy (push) Successful in 1m4s
CI / release (push) Skipped
- getAvatarUrl now omits direction=2, head_direction=3, size=m when they match defaults
- URL now matches: figure=xxx&effect=14&img_format=apng
2026-08-09 20:03:26 +02:00
openhands 3213126a12 fix: make getAvatarUrl auto-convert figure strings
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 58s
- Update getAvatarUrl in imager.ts to use getNewFormatFigure for automatic conversion
- Update me/page.tsx to use avatarImageUrl (which also converts)
- This ensures all avatar URLs use the short epicnabbo.nl format
2026-08-09 19:57:22 +02:00
openhands 2f708bcf11 feat: filter figure parts (exclude shoes, waist, dedupe head)
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m3s
- Default convertFigureString now excludes shoes (ha-), waist (wa-), and duplicate head
- Added ConvertFigureOptions to customize filtering
- Updated tests to reflect new defaults
2026-08-09 19:50:24 +02:00
openhands 7a2c0fd4d4 fix: resolve TypeScript and lint issues
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 58s
- Fix proxy routes to use resolveImagerBase instead of removed resolveUpstreamBase
- Fix avatarImageUrl type signature to use AvatarOptions
- Run biome formatter
2026-08-09 19:42:02 +02:00
openhands fc7e6ca248 feat: switch avatar imager to epicnabbo.nl with figure conversion
- Update imager to use epicnabbo.nl by default with effect=14 and img_format=apng
- Add figure string converter (old Habbo format -> epicnabbo.nl short format)
- Update avatarImageUrl to auto-convert figure strings
- Update online-users-widget to use new avatarImageUrl
- Add tests for imager and figure conversion
2026-08-09 19:38:04 +02:00
openhands 4993b75608 perf: self-host fonts, drop unused generated code and add swf tests
CI / check (push) Successful in 25s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
- Self-host Nunito and Pixelify Sans via next/font instead of Google Fonts CDN
  (removes render-blocking external stylesheets and preconnects)
- Remove stale mariadb entry from serverExternalPackages (app uses mysql2)
- Exclude unused src/generated Prisma client from typecheck and remove it
- Add unit tests for swf-parser, effectmap and figuremap (0% coverage -> 90%+)
2026-08-09 12:12:02 +02:00
openhands ae1393d3e3 refactor: clean up duplicate imports and dead code
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m7s
- Merge type and value imports from the same module into single imports
- Remove dead import-badges action (flow uses /api/admin/import/badges)
- Remove unused babel-plugin-react-compiler devDependency
- Remove stray test.txt file
- Update knip config: track css imports, drop redundant ignore entries
- Update contract test to drop obsolete dead-action assertion
2026-08-09 11:51:26 +02:00
openhands 304cfb5be7 fix test expectation for accent foreground contrast
CI / check (push) Failing after 24s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-08 21:49:24 +02:00
openhands 02abf8f88c export parseHex, relativeLuminance, softLightSurface for testing 2026-08-08 21:46:40 +02:00
openhands ebd2ff131c inport fix
CI / check (push) Failing after 13s
CI / release (push) Skipped
CI / deploy (push) Skipped
2026-08-08 21:39:52 +02:00
openhands 6a67fb6e83 refactor: remove additional dead exports and unused actions
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
Remove buildFontUrl, measureText, uncached, invalidateCache, fetchJsonWithFlareSolver, upsertPermission, deletePermission, bulkImportPermissions, clearAllPermissions, bulkDeletePermissions, bulkDeletePhotos, userReplyTicket, closeTicketByUser. Update staff-smoke-contract test for bulkDeletePhotos removal.
2026-08-07 19:19:05 +02:00
openhands 24bf8eabb9 refactor: remove dead code and unused exports
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
Delete proxy-auth.ts, types/index.ts, staff-user.ts+test, local-imports.ts+test (only used by their own tests). Remove unused foundation exports: sanitizeFilename, canonicalizeFormValue, canonicalizeFormData, ConflictError, getRequestStore, getClientIp, elapsed. Remove stale TODO comments from rank-authority.ts and notice.ts. Fix biome lint warnings in catalog-repair.ts.
2026-08-07 18:55:02 +02:00
openhands 82e8448f26 test: add unit tests for pure logic modules
Add 22 test files covering imager, soundtracks, browser-headers, source-keys (figure/pet/effect), effect-source, plus catalog-translations, catalog-layouts, client-translation-files, translations-utils, and various admin/services/helpers modules. Total test count increases by 120+.
2026-08-07 18:53:59 +02:00
openhands 51ef7602ca perf: migrate pages to Cache Components via root layout opt-out
Remove the per-route 'export const instant = false' opt-outs now that the root layout carries the single Cache Components opt-out. Child pages inherit the opt-out, so admin/mod/radio leaf pages that only access cached or DB data stay instant while runtime-dependent pages remain dynamic. Update the staff-smoke contract test to assert the root-layout contract.
2026-08-07 18:51:45 +02:00
openhands f792c276b7 test: add unit tests for furni import helpers and catalog cache
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Failing after 17s
Added tests for:
- classifyFurni: prefix matching, type-based classification, fallback
- autoPriceFurni: CF_/rare_/default pricing rules
- resetCatalogPageCache: smoke test
2026-08-06 20:33:03 +02:00
openhands aee099339c perf: optimize import batch performance with caching + validation
CI / check (push) Successful in 32s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s
Import speed improvements:
- In-memory catalog page ID cache (5min TTL) eliminates N+1 DB lookups
  when batch importing many items in the same category
- resetCatalogPageCache() exported and called after bulk re-organize
  operations (PUT route) to prevent stale page IDs
- Nitro file size validation (≥128 bytes) before DB commit — rejects
  corrupt/empty .nitro files that would break the client
- batchLookupByClassnames now uses Promise.all for parallel cache lookups
  instead of sequential awaits (10x faster for 50+ items)
- Auto-cleanup of corrupt nitro files on validation failure
2026-08-06 20:27:06 +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 4c93dc38c6 feat: add verified retro sources, remove broken/duplicate sources
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 43s
Added verified working retro hotel sources from VindRetros.nl:
- YabboHotel: 52,663 room + 707 wall items furnidata (no nitro/icons yet)
- Habblet City: full furnidata + nitro + icons (all working)

Removed offline/unreachable sources:
- Leet.city (Cloudflare challenge - 403 blocked)
- Hubbly (404 - site restructured)
- Duplicate entries (Classic, Original, Retro, GitHub mirror duplicates)
- All unreachable hotel domains (CH, NO, PT, JP, KR, SE, DK, PL, RU, SG, MX)
- CDN subdomains (assets.habbo.com, cdn.habbo.com - DNS unresolvable)

Final: 13 verified working sources with 200 status furnidata:
- 9 official Habbo hotels (COM, NL, DE, FR, ES, FI, BR, TR, IT)
- 3 retro sources (YabboHotel, Wibbo, Hubba.cc)
- 1 full retro source with nitro/icons (Habblet City)
2026-08-06 19:56:59 +02:00
openhands 7149fb146b fix: cleanup clone sources - remove offline sources, keep verified ones
CI / check (push) Successful in 36s
CI / release (push) Skipped
CI / deploy (push) Successful in 39s
Connectivity verification revealed:
- New hotels (CH, NO, PT, JP, KR, SE, DK, PL, RU, SG, MX) are unreachable
  (DNS/connection failures - hotel likely discontinued or region-locked)
- CDN subdomains (assets.habbo.com, cdn.habbo.com, nitro.habbo.com, etc.)
  return 000 (unresolvable) - not valid furnidata endpoints

Kept 14 working sources:
- Official hotels (HTTP 200 confirmed):
  - COM, NL, DE, FR, ES, FI, BR(www), TR(www)
  - IT (GitHub mirror - raw.githubusercontent.com)
- Retro sources (HTTP 200 for furnidata):
  - Wibbo, Hubba.cc (nitro.hubba.cc works)
  - Habblet City (all endpoints work)
  - Leet (now leet.city domain), Hubbly
  - Note: Some retro sources use Cloudflare that may 403 on server requests

Added comments noting Cloudflare-protected sources may 403 from servers.
2026-08-06 19:23:46 +02:00
openhands cfcb245c40 fix: remove broken/non-responsive sources, keep only verified working URLs
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 47s
Connectivity check revealed 66 sources were broken/unresponsive:
- Many new hotels (CH, NO, PT, JP, KR, SE, DK, PL, RU, SG, MX) returned errors
- Retro/community sources (Essian, Hubbly, Sodaho, Nitro Dev, etc.) are offline
- Many CDN subdomains (nitro.habbo.com, archive.habbo.com, etc.) are unreachable

Kept 16 verified working sources with 200 status codes:
- Habbo IT (GitHub mirror)
- Habbo COM, NL, DE, FR, ES, FI, BR, TR
- Wibbo, Hubba.cc, Leet (retro sources with valid furnidata)
- Habbo Original, Classic, Retro variants (working backup URLs)

Reduced from 59 to 16 sources, removing all dead/non-responsive URLs.
2026-08-06 19:13:47 +02:00
openhands c2e48a8a0e feat: expand clone import presets with 45+ additional hotel sources
CI / check (push) Successful in 30s
CI / release (push) Skipped
CI / deploy (push) Successful in 44s
Added many more hotels and asset sources for import:
- Official Habbo hotels: CH, NO, PT, JP, KR, SE, DK, PL, RU, SG, MX
- Additional retro/hotmart-style sources with nitro/icon support
- Multiple CDN variants (Habbo Assets, Nitro CDN, Web, API, etc.)
- Alt-region variants for all existing hotels

Total sources expanded from 14 to 59 DEFAULT_SOURCES, providing
much wider coverage for furni/icon imports across different
Habbo hotels and retro communities.
2026-08-06 19:08:10 +02:00
openhands af8aaaa512 fix: rebuild asset sets after repair to accurately report stillMissing
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m4s
2026-08-05 17:17:25 +02:00
openhands 00b5a6f5c3 feat: add back Leet and Hubbly presets
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 40s
2026-08-05 16:45:37 +02:00
openhands 02ad9c21f2 feat: remove non-working hotel presets, add verified custom hotels
CI / check (push) Successful in 33s
CI / release (push) Skipped
CI / deploy (push) Successful in 46s
2026-08-05 16:42:27 +02:00
openhands 101c73df1b feat: add 25 more hotel presets to clone sources
CI / check (push) Successful in 34s
CI / release (push) Skipped
CI / deploy (push) Successful in 46s
2026-08-05 16:28:00 +02:00
openhands d1dafba2c9 feat(clone): add more hotel presets for furnidata sources
CI / check (push) Successful in 32s
CI / release (push) Skipped
CI / deploy (push) Successful in 43s
- Added 8 official Habbo hotel presets (NL, DE, FR, ES, FI, BR, TR, COM)
  alongside the existing IT preset, each with their habbo_gamedata_hotel
  mapping so official furnidata enrichment uses the correct locale
- Habbo (IT) renamed to Habbo (IT) for clarity
- Wibbo, Hubba, Soda Ho, Leet, Hubbly, Habblet City presets unchanged
2026-08-05 16:24:57 +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 79b82e0a31 fix: badge import uses configured gamedata root for ExternalTexts.json
CI / check (push) Successful in 30s
CI / release (push) Skipped
CI / deploy (push) Successful in 44s
- import-badge.ts, badges route, and badges edit route now resolve
  ExternalTexts.json via getGamedataRoot() instead of the hardcoded
  public/nitro-assets/gamedata/ path
- writeBadgeToExternalTexts creates the file (and parent dirs) when
  missing, so fresh deployments no longer fail with ENOENT
- upload-import SQL maker now classifies furni via classifyFurni and
  generates correct category sub-pages (imp_<catKey>) instead of
  hardcoded imp_other
2026-08-05 15:34:40 +02:00
openhands 4d4cbd2211 fix: SQL maker creates wrong categories and badge import fails when ExternalTexts.json missing
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m5s
- writeSqlMigration now classifies furni via classifyFurni and generates
  correct category sub-pages (imp_<catKey>) instead of hardcoded imp_other
- writeSqlMigration generates idempotent INSERT...SELECT WHERE NOT EXISTS
  for parent and category catalog_pages, with correct numeric page_id
- writeBadgeToExternalTexts creates ExternalTexts.json (and parent dirs)
  when missing instead of failing with ENOENT
2026-08-05 15:25:07 +02:00
openhands 1851653afb fix(import): support HTML-wrapped clone furnidata and skip empty icon sources
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 42s
Leet serves its furnidata as HTML with the JSON embedded in a <pre>
block, and Cloudflare blocks Node's direct fetch. Extract the JSON
payload from the HTML (direct or via the FlareSolverr fallback) before
giving up on a Cloudflare challenge.

Also skip the standalone icon download when a clone source has no
iconBaseUrl configured (Habbo, Hubba, Fresh, Kyzegs, RidgeRP), which
previously produced invalid relative URLs like /xxx_icon.png and a
flood of download errors before falling back to extracting the icon
from the .nitro bundle.
2026-08-05 12:10:02 +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 742536820a fix(ci): update smoke contract for custom db:migrate runner
CI / check (push) Successful in 29s
CI / deploy (push) Successful in 1m8s
CI / release (push) Skipped
2026-08-05 11:25:18 +02:00
openhands dd708a64fb fix(import): make effects and figure/clothing import work on deployment
- resolveGamedataFile: detect Windows drive/UNC paths explicitly instead of
  path.win32.isAbsolute (which is true for any /-prefixed path on Linux), so
  /nitro-assets URLs are no longer returned verbatim; add deployment gamedata
  root fallback (/var/www/Gamedata/config) and keep public/Gamedata/config.
- effect/figure import dirs now resolve via site settings then the gamedata
  root bundled dir, instead of hardcoded public paths.
- effect list falls back to the local EffectMap when the official habbo.com
  endpoint is unreachable, keeping the admin import page usable.
- update staff smoke contract for db:migrate and instant=false (Cache
  Components migration).
2026-08-05 11:10:16 +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 a2b0752076 fix: catch FlareSolverr fallback errors in fetchSourceFurnidata
CI / check (push) Successful in 26s
CI / release (push) Skipped
CI / deploy (push) Successful in 47s
Previously, if FlareSolverr itself failed (timeout, connection error),
the error would propagate as generic 'network error'. Now it throws
a descriptive error message.
2026-08-04 19:27:08 +02:00