#!/usr/bin/env python """Genera web-next/sql/item_data.sql a partir de los DB2 del cliente 3.4.3. USO: /root/NightSpire/.venv/bin/python /root/db2_to_sql.py (el python del sistema no tiene pip/venv; usa SIEMPRE el del proyecto) En 3.4.3 no existe `item_template`: los datos van en DB2 del cliente. Locales: los nombres salen de /ItemSparse.db2. Basta con dejar el ItemSparse.db2 de cada idioma en /root// — el resto de tablas (ItemAppearance, ItemModifiedAppearance) NO dependen del idioma y se leen del primer locale que exista. Si falta un locale, su columna queda a NULL. Ficheros que necesita: /root/esES/ItemSparse.db2, ItemAppearance.db2, ItemModifiedAppearance.db2 /root/enUS/ItemSparse.db2 (opcional; para name_en) /root/ItemSparse.dbd (definiciones oficiales de WoWDBDefs) /root/wdc_db2.py, /root/itemsparse.py """ import os import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import wdc_db2 from itemsparse import ItemSparse DBD = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ItemSparse.dbd') OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'item_data.sql') # (columna_sql, carpeta). Añadir aquí si aparecen más idiomas. LOCALES = [('name_es', '/root/esES'), ('name_en', '/root/enUS')] def load_names(folder): path = f'{folder}/ItemSparse.db2' if not os.path.exists(path): print(f' (sin {path}: esa columna queda NULL)', file=sys.stderr) return {} t = ItemSparse(path, DBD) return {i: r for i, r in t.rows} def esc(s): return s.replace('\\', '\\\\').replace("'", "''") per_locale = {} for col, folder in LOCALES: print(f'{col}: leyendo {folder}', file=sys.stderr) per_locale[col] = load_names(folder) base_folder = next((f for _c, f in LOCALES if os.path.exists(f'{f}/ItemAppearance.db2')), None) if not base_folder: sys.exit('falta ItemAppearance.db2 en algún locale') # displayId: ItemModifiedAppearance.ItemID -> ItemAppearanceID -> ItemDisplayInfoID. # No depende del idioma. Solo lo tienen los equipables. ia = {rid: row for rid, row in wdc_db2.DB2(f'{base_folder}/ItemAppearance.db2').rows} display = {} for _rid, row in wdc_db2.DB2(f'{base_folder}/ItemModifiedAppearance.db2').rows: item_id, app_id, order = row[1], row[3], row[4] if app_id in ia: prev = display.get(item_id) if prev is None or order < prev[0]: display[item_id] = (order, ia[app_id][1]) display = {k: v[1] for k, v in display.items()} print(f'displayId: {len(display)} ítems equipables', file=sys.stderr) name_cols = [c for c, _f in LOCALES] entries = sorted({e for m in per_locale.values() for e in m}) with open(OUT, 'w', encoding='utf-8') as out: cols_sql = ',\n'.join( f" `{c}` varchar(255) DEFAULT NULL COMMENT 'nombre en {c[-2:]}'" for c in name_cols) out.write(f"""-- Datos de ítems del cliente 3.4.3, extraídos de los DB2. NO editar a mano: -- regenerar con `/root/NightSpire/.venv/bin/python /root/db2_to_sql.py`. -- En 3.4.3 no existe `item_template` (los datos viven en DB2 del cliente). -- Parseado con las definiciones oficiales de WoWDBDefs (layout D532973D). -- Los nombres son los de Blizzard en 3.4.3: ~4% difieren de los del catálogo -- antiguo de la tienda por revisiones de traducción de Blizzard. DROP TABLE IF EXISTS `home_item_data`; CREATE TABLE `home_item_data` ( `entry` int unsigned NOT NULL COMMENT 'item id de WoW', {cols_sql}, `quality` tinyint unsigned NOT NULL COMMENT '0 pobre .. 6 artefacto, 7 reliquia', `item_level` smallint unsigned NOT NULL, `inventory_type` tinyint unsigned NOT NULL COMMENT '0 = no equipable', `display_id` int unsigned DEFAULT NULL COMMENT 'ItemDisplayInfoID; NULL si no es equipable', PRIMARY KEY (`entry`), KEY `idx_name_es` (`name_es`(64)), KEY `idx_quality` (`quality`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; """) rows = [] for entry in entries: names = [] any_name = False for c in name_cols: r = per_locale[c].get(entry) n = (r or {}).get('Display_lang') or '' names.append(f"'{esc(n)}'" if n else 'NULL') any_name = any_name or bool(n) if not any_name: continue # ítems internos sin nombre en ningún idioma ref = next((per_locale[c][entry] for c in name_cols if entry in per_locale[c]), {}) rows.append('(%d,%s,%d,%d,%d,%s)' % ( entry, ','.join(names), ref.get('OverallQualityID', 0) or 0, ref.get('ItemLevel', 0) or 0, ref.get('InventoryType', 0) or 0, display.get(entry, 'NULL'))) cols = ','.join(f'`{c}`' for c in name_cols) for i in range(0, len(rows), 500): out.write(f'INSERT INTO `home_item_data` (`entry`,{cols},`quality`,`item_level`,`inventory_type`,`display_id`) VALUES\n') out.write(',\n'.join(rows[i:i + 500])) out.write(';\n') print(f'escritas {len(rows)} filas en {OUT}', file=sys.stderr)