studio/rbxl-importer/sql/001_roblox_assets.sql
min c375ae01ac
All checks were successful
CI / Lint (pull_request) Successful in 1m6s
CI / Build (pull_request) Successful in 2m2s
CI / Secret scan (pull_request) Successful in 26s
CI / PR size check (pull_request) Successful in 7s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
feat(rbxl-import): импорт Roblox .rbxl карт в Rublox-проекты
Тест-фича для МИНа. Полное описание в rbxl-importer/INFO_PROCESS.md.

Backend (rbxl-importer/ на VM 130 S1):
- Python-парсер Roblox Binary (28+ типов значений)
- Asset downloader через Marfusha proxy + .ROBLOSECURITY cookie
- Mesh→GLB конвертер (v1-v5)
- Converter Roblox-классов → project_data
- Flask API: /analyze + /create

Frontend:
- API.js + components/RbxlImportModal.jsx (drag-n-drop)

Тестовый импорт Easy Obby: project_id 2697,
2244 primitives + 742 lua-scripts + 5 ассетов.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 18:24:27 +03:00

92 lines
4.2 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Миграция 001: таблица roblox_assets для кеширования assets Roblox CDN
--
-- Применяется к storys_db.
-- Запускать на S2 VM 117 (service-storys, primary PG).
-- При репликации S2 → S1 миграция доедет автоматически.
BEGIN;
CREATE TABLE IF NOT EXISTS roblox_assets (
-- ID ассета в Roblox (числовой, из rbxassetid://<id>)
rbx_asset_id BIGINT PRIMARY KEY,
-- SHA256 сырого файла (после скачки с CDN, до конверта)
-- Используется для второй дедупликации: разные rbx_asset_id могут указывать
-- на одинаковый файл (Roblox делает редиректы).
sha256_raw CHAR(64) NOT NULL,
-- Тип ассета: 'mesh', 'texture', 'sound', 'csg', 'animation', 'video', 'unknown'
asset_kind VARCHAR(16) NOT NULL,
-- Content-Type как пришёл с CDN
content_type VARCHAR(64) NOT NULL,
-- Размер сырого файла
raw_size_bytes BIGINT NOT NULL,
-- Путь сырого файла в /opt/roblox-assets/raw/<sha256>.bin (или конкретное расширение)
raw_path TEXT NOT NULL,
-- Если делали конверт (mesh→glb, csg→glb) — путь и хеш конвертированного файла.
-- Для остальных типов = NULL.
converted_path TEXT,
converted_sha256 CHAR(64),
converted_size_bytes BIGINT,
-- URL по которому ассет реально отдаётся юзеру (https://assets.rublox.pro/...)
public_url TEXT NOT NULL,
-- Время первой скачки
downloaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Последнее использование (бампается при каждом импорте новой карты)
last_used_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Сколько карт использует этот ассет (для cleanup'а)
refcount INTEGER NOT NULL DEFAULT 0,
-- Метаданные конкретного типа (mesh: vertex count, texture: dimensions)
metadata JSONB DEFAULT '{}'::jsonb,
-- Failed reason если скачка/конверт упал
error_msg TEXT
);
CREATE INDEX IF NOT EXISTS idx_roblox_assets_sha256 ON roblox_assets(sha256_raw);
CREATE INDEX IF NOT EXISTS idx_roblox_assets_kind ON roblox_assets(asset_kind);
CREATE INDEX IF NOT EXISTS idx_roblox_assets_last_used ON roblox_assets(last_used_at);
-- Лог скачек по проектам (для отладки и tracking'а кто чем пользуется)
CREATE TABLE IF NOT EXISTS roblox_asset_usage (
id BIGSERIAL PRIMARY KEY,
project_id INTEGER NOT NULL,
rbx_asset_id BIGINT NOT NULL REFERENCES roblox_assets(rbx_asset_id) ON DELETE CASCADE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(project_id, rbx_asset_id)
);
CREATE INDEX IF NOT EXISTS idx_asset_usage_project ON roblox_asset_usage(project_id);
-- Лог импортов .rbxl (родительская запись для usage)
CREATE TABLE IF NOT EXISTS roblox_imports (
id BIGSERIAL PRIMARY KEY,
project_id INTEGER, -- может быть NULL если ещё не создан
user_id INTEGER NOT NULL, -- кто грузил (МИН только пока)
rbxl_filename TEXT NOT NULL,
rbxl_size BIGINT NOT NULL,
rbxl_sha256 CHAR(64) NOT NULL,
instance_count INTEGER,
class_count INTEGER,
assets_total INTEGER DEFAULT 0,
assets_failed INTEGER DEFAULT 0,
status VARCHAR(16) NOT NULL DEFAULT 'pending', -- pending/parsing/downloading/converting/done/failed
error_msg TEXT,
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
finished_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_imports_user ON roblox_imports(user_id);
CREATE INDEX IF NOT EXISTS idx_imports_status ON roblox_imports(status);
COMMIT;