chuni: add opt to reader

This commit is contained in:
2025-04-08 00:41:49 -04:00
parent a7077fb41c
commit e16bfc713a
3 changed files with 102 additions and 33 deletions

View File

@ -0,0 +1,30 @@
"""chuni_nameplate_add_opt
Revision ID: ae364c078429
Revises: 5cf98cfe52ad
Create Date: 2025-04-08 00:22:22.370660
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'ae364c078429'
down_revision = '5cf98cfe52ad'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('chuni_static_nameplate', sa.Column('opt', sa.BIGINT(), nullable=True))
op.create_foreign_key(None, 'chuni_static_nameplate', 'chuni_static_opt', ['opt'], ['id'], onupdate='cascade', ondelete='SET NULL')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint("chuni_static_nameplate_ibfk_1", 'chuni_static_nameplate', type_='foreignkey')
op.drop_column('chuni_static_nameplate', 'opt')
# ### end Alembic commands ###

View File

@ -78,7 +78,7 @@ class ChuniReader(BaseReader):
is_enabled = True if (disableFlag is None or disableFlag.text == "false") else False is_enabled = True if (disableFlag is None or disableFlag.text == "false") else False
result = await self.data.static.put_login_bonus_preset( result = await self.data.static.put_login_bonus_preset(
self.version, id, name, is_enabled self.version, id, name, is_enabled, opt_id
) )
if result is not None: if result is not None:
@ -125,6 +125,7 @@ class ChuniReader(BaseReader):
item_num, item_num,
need_login_day_count, need_login_day_count,
login_bonus_category_type, login_bonus_category_type,
opt_id
) )
if result is not None: if result is not None:
@ -149,7 +150,7 @@ class ChuniReader(BaseReader):
event_type = substances.find("type").text event_type = substances.find("type").text
result = await self.data.static.put_event( result = await self.data.static.put_event(
self.version, id, event_type, name self.version, id, event_type, name, opt_id
) )
if result is not None: if result is not None:
self.logger.info(f"Inserted event {id}") self.logger.info(f"Inserted event {id}")
@ -221,6 +222,7 @@ class ChuniReader(BaseReader):
genre, genre,
jacket_path, jacket_path,
we_chara, we_chara,
opt_id
) )
if result is not None: if result is not None:
@ -254,6 +256,7 @@ class ChuniReader(BaseReader):
expirationDays, expirationDays,
consumeType, consumeType,
sellingAppeal, sellingAppeal,
opt_id
) )
if result is not None: if result is not None:
@ -286,7 +289,7 @@ class ChuniReader(BaseReader):
self.copy_image(texturePath, f"{root}/{dir}", "titles/chuni/img/avatar/") self.copy_image(texturePath, f"{root}/{dir}", "titles/chuni/img/avatar/")
result = await self.data.static.put_avatar( result = await self.data.static.put_avatar(
self.version, id, name, category, iconPath, texturePath, is_enabled, defaultHave, sortName self.version, id, name, category, iconPath, texturePath, is_enabled, defaultHave, sortName, opt_id
) )
if result is not None: if result is not None:
@ -315,7 +318,7 @@ class ChuniReader(BaseReader):
self.copy_image(texturePath, f"{root}/{dir}", "titles/chuni/img/nameplate/") self.copy_image(texturePath, f"{root}/{dir}", "titles/chuni/img/nameplate/")
result = await self.data.static.put_nameplate( result = await self.data.static.put_nameplate(
self.version, id, name, texturePath, is_enabled, defaultHave, sortName self.version, id, name, texturePath, is_enabled, defaultHave, sortName, opt_id
) )
if result is not None: if result is not None:
@ -340,7 +343,7 @@ class ChuniReader(BaseReader):
defaultHave = xml_root.find("defaultHave").text == 'true' defaultHave = xml_root.find("defaultHave").text == 'true'
result = await self.data.static.put_trophy( result = await self.data.static.put_trophy(
self.version, id, name, rareType, is_enabled, defaultHave self.version, id, name, rareType, is_enabled, defaultHave, opt_id
) )
if result is not None: if result is not None:
@ -387,7 +390,7 @@ class ChuniReader(BaseReader):
self.logger.warning(f"Unable to location character {id} images") self.logger.warning(f"Unable to location character {id} images")
result = await self.data.static.put_character( result = await self.data.static.put_character(
self.version, id, name, sortName, worksName, rareType, imagePath1, imagePath2, imagePath3, is_enabled, defaultHave self.version, id, name, sortName, worksName, rareType, imagePath1, imagePath2, imagePath3, is_enabled, defaultHave, opt_id
) )
if result is not None: if result is not None:
@ -415,7 +418,7 @@ class ChuniReader(BaseReader):
is_enabled = True if (disableFlag is None or disableFlag.text == "false") else False is_enabled = True if (disableFlag is None or disableFlag.text == "false") else False
result = await self.data.static.put_map_icon( result = await self.data.static.put_map_icon(
self.version, id, name, sortName, iconPath, is_enabled, defaultHave self.version, id, name, sortName, iconPath, is_enabled, defaultHave, opt_id
) )
if result is not None: if result is not None:
@ -443,7 +446,7 @@ class ChuniReader(BaseReader):
is_enabled = True if (disableFlag is None or disableFlag.text == "false") else False is_enabled = True if (disableFlag is None or disableFlag.text == "false") else False
result = await self.data.static.put_system_voice( result = await self.data.static.put_system_voice(
self.version, id, name, sortName, imagePath, is_enabled, defaultHave self.version, id, name, sortName, imagePath, is_enabled, defaultHave, opt_id
) )
if result is not None: if result is not None:
@ -490,6 +493,8 @@ class ChuniReader(BaseReader):
if not opt_id: if not opt_id:
self.logger.error(f"Failed to put opt folder info for {opt_folder}") self.logger.error(f"Failed to put opt folder info for {opt_folder}")
return None return None
else:
opt_id = opt_id['id']
self.logger.info(f"Opt folder {opt_folder} (Database ID {opt_id}) contains {data_config['Version']['Name']} v{data_config['Version']['VerMajor']}.{data_config['Version']['VerMinor']}.{opt_seq}") self.logger.info(f"Opt folder {opt_folder} (Database ID {opt_id}) contains {data_config['Version']['Name']} v{data_config['Version']['VerMajor']}.{data_config['Version']['VerMinor']}.{opt_seq}")
return opt_id return opt_id

View File

@ -13,6 +13,7 @@ from sqlalchemy.schema import ForeignKey
from sqlalchemy.sql import func, select from sqlalchemy.sql import func, select
from sqlalchemy.dialects.mysql import insert from sqlalchemy.dialects.mysql import insert
from datetime import datetime from datetime import datetime
from sqlalchemy.sql.functions import coalesce
from core.data.schema import BaseData, metadata from core.data.schema import BaseData, metadata
@ -107,6 +108,7 @@ nameplate = Table(
Column("isEnabled", Boolean, server_default="1"), Column("isEnabled", Boolean, server_default="1"),
Column("defaultHave", Boolean, server_default="0"), Column("defaultHave", Boolean, server_default="0"),
Column("sortName", String(255)), Column("sortName", String(255)),
Column("opt", ForeignKey("chuni_static_opt.id", ondelete="SET NULL", onupdate="cascade")),
UniqueConstraint("version", "nameplateId", name="chuni_static_nameplate_uk"), UniqueConstraint("version", "nameplateId", name="chuni_static_nameplate_uk"),
mysql_charset="utf8mb4", mysql_charset="utf8mb4",
) )
@ -299,6 +301,7 @@ class ChuniStaticData(BaseData):
item_num: int, item_num: int,
need_login_day_count: int, need_login_day_count: int,
login_bonus_category_type: int, login_bonus_category_type: int,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(login_bonus).values( sql = insert(login_bonus).values(
version=version, version=version,
@ -310,6 +313,7 @@ class ChuniStaticData(BaseData):
itemNum=item_num, itemNum=item_num,
needLoginDayCount=need_login_day_count, needLoginDayCount=need_login_day_count,
loginBonusCategoryType=login_bonus_category_type, loginBonusCategoryType=login_bonus_category_type,
opt=coalesce(login_bonus.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -318,6 +322,7 @@ class ChuniStaticData(BaseData):
itemNum=item_num, itemNum=item_num,
needLoginDayCount=need_login_day_count, needLoginDayCount=need_login_day_count,
loginBonusCategoryType=login_bonus_category_type, loginBonusCategoryType=login_bonus_category_type,
opt=coalesce(login_bonus.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -359,17 +364,19 @@ class ChuniStaticData(BaseData):
return result.fetchone() return result.fetchone()
async def put_login_bonus_preset( async def put_login_bonus_preset(
self, version: int, preset_id: int, preset_name: str, isEnabled: bool self, version: int, preset_id: int, preset_name: str, isEnabled: bool, opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(login_bonus_preset).values( sql = insert(login_bonus_preset).values(
presetId=preset_id, presetId=preset_id,
version=version, version=version,
presetName=preset_name, presetName=preset_name,
isEnabled=isEnabled, isEnabled=isEnabled,
opt=coalesce(login_bonus_preset.c.opt, opt_id)
) )
# Chuni has a habbit of including duplicates in it's opt files, so only update opt if it's null
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
presetName=preset_name, isEnabled=isEnabled presetName=preset_name, isEnabled=isEnabled, opt=coalesce(login_bonus_preset.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -393,13 +400,13 @@ class ChuniStaticData(BaseData):
return result.fetchall() return result.fetchall()
async def put_event( async def put_event(
self, version: int, event_id: int, type: int, name: str self, version: int, event_id: int, type: int, name: str, opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(events).values( sql = insert(events).values(
version=version, eventId=event_id, type=type, name=name version=version, eventId=event_id, type=type, name=name, opt=coalesce(events.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update(name=name) conflict = sql.on_duplicate_key_update(name=name, opt=coalesce(events.c.opt, opt_id))
result = await self.execute(conflict) result = await self.execute(conflict)
if result is None: if result is None:
@ -467,6 +474,7 @@ class ChuniStaticData(BaseData):
genre: str, genre: str,
jacketPath: str, jacketPath: str,
we_tag: str, we_tag: str,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(music).values( sql = insert(music).values(
version=version, version=version,
@ -478,6 +486,7 @@ class ChuniStaticData(BaseData):
genre=genre, genre=genre,
jacketPath=jacketPath, jacketPath=jacketPath,
worldsEndTag=we_tag, worldsEndTag=we_tag,
opt=coalesce(music.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -487,6 +496,7 @@ class ChuniStaticData(BaseData):
genre=genre, genre=genre,
jacketPath=jacketPath, jacketPath=jacketPath,
worldsEndTag=we_tag, worldsEndTag=we_tag,
opt=coalesce(music.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -502,6 +512,7 @@ class ChuniStaticData(BaseData):
expiration_days: int, expiration_days: int,
consume_type: int, consume_type: int,
selling_appeal: bool, selling_appeal: bool,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(charge).values( sql = insert(charge).values(
version=version, version=version,
@ -510,6 +521,7 @@ class ChuniStaticData(BaseData):
expirationDays=expiration_days, expirationDays=expiration_days,
consumeType=consume_type, consumeType=consume_type,
sellingAppeal=selling_appeal, sellingAppeal=selling_appeal,
opt=coalesce(charge.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -517,6 +529,7 @@ class ChuniStaticData(BaseData):
expirationDays=expiration_days, expirationDays=expiration_days,
consumeType=consume_type, consumeType=consume_type,
sellingAppeal=selling_appeal, sellingAppeal=selling_appeal,
opt=coalesce(charge.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -584,7 +597,8 @@ class ChuniStaticData(BaseData):
texturePath: str, texturePath: str,
isEnabled: int, isEnabled: int,
defaultHave: int, defaultHave: int,
sortName: str sortName: str,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(avatar).values( sql = insert(avatar).values(
version=version, version=version,
@ -595,7 +609,8 @@ class ChuniStaticData(BaseData):
texturePath=texturePath, texturePath=texturePath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave, defaultHave=defaultHave,
sortName=sortName sortName=sortName,
opt=coalesce(avatar.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -605,7 +620,8 @@ class ChuniStaticData(BaseData):
texturePath=texturePath, texturePath=texturePath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave, defaultHave=defaultHave,
sortName=sortName sortName=sortName,
opt=coalesce(avatar.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -632,7 +648,8 @@ class ChuniStaticData(BaseData):
texturePath: str, texturePath: str,
isEnabled: int, isEnabled: int,
defaultHave: int, defaultHave: int,
sortName: str sortName: str,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(nameplate).values( sql = insert(nameplate).values(
version=version, version=version,
@ -641,7 +658,8 @@ class ChuniStaticData(BaseData):
texturePath=texturePath, texturePath=texturePath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave, defaultHave=defaultHave,
sortName=sortName sortName=sortName,
opt=coalesce(nameplate.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -649,7 +667,8 @@ class ChuniStaticData(BaseData):
texturePath=texturePath, texturePath=texturePath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave, defaultHave=defaultHave,
sortName=sortName sortName=sortName,
opt=coalesce(nameplate.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -676,6 +695,7 @@ class ChuniStaticData(BaseData):
rareType: int, rareType: int,
isEnabled: int, isEnabled: int,
defaultHave: int, defaultHave: int,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(trophy).values( sql = insert(trophy).values(
version=version, version=version,
@ -683,14 +703,16 @@ class ChuniStaticData(BaseData):
name=name, name=name,
rareType=rareType, rareType=rareType,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(trophy.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
name=name, name=name,
rareType=rareType, rareType=rareType,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(trophy.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -718,6 +740,7 @@ class ChuniStaticData(BaseData):
iconPath: str, iconPath: str,
isEnabled: int, isEnabled: int,
defaultHave: int, defaultHave: int,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(map_icon).values( sql = insert(map_icon).values(
version=version, version=version,
@ -726,7 +749,8 @@ class ChuniStaticData(BaseData):
sortName=sortName, sortName=sortName,
iconPath=iconPath, iconPath=iconPath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(map_icon.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -734,7 +758,8 @@ class ChuniStaticData(BaseData):
sortName=sortName, sortName=sortName,
iconPath=iconPath, iconPath=iconPath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(map_icon.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -762,6 +787,7 @@ class ChuniStaticData(BaseData):
imagePath: str, imagePath: str,
isEnabled: int, isEnabled: int,
defaultHave: int, defaultHave: int,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(system_voice).values( sql = insert(system_voice).values(
version=version, version=version,
@ -770,7 +796,8 @@ class ChuniStaticData(BaseData):
sortName=sortName, sortName=sortName,
imagePath=imagePath, imagePath=imagePath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(system_voice.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -778,7 +805,8 @@ class ChuniStaticData(BaseData):
sortName=sortName, sortName=sortName,
imagePath=imagePath, imagePath=imagePath,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(system_voice.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -809,7 +837,8 @@ class ChuniStaticData(BaseData):
imagePath2: str, imagePath2: str,
imagePath3: str, imagePath3: str,
isEnabled: int, isEnabled: int,
defaultHave: int defaultHave: int,
opt_id: int = None
) -> Optional[int]: ) -> Optional[int]:
sql = insert(character).values( sql = insert(character).values(
version=version, version=version,
@ -822,7 +851,8 @@ class ChuniStaticData(BaseData):
imagePath2=imagePath2, imagePath2=imagePath2,
imagePath3=imagePath3, imagePath3=imagePath3,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(character.c.opt, opt_id)
) )
conflict = sql.on_duplicate_key_update( conflict = sql.on_duplicate_key_update(
@ -834,7 +864,8 @@ class ChuniStaticData(BaseData):
imagePath2=imagePath2, imagePath2=imagePath2,
imagePath3=imagePath3, imagePath3=imagePath3,
isEnabled=isEnabled, isEnabled=isEnabled,
defaultHave=defaultHave defaultHave=defaultHave,
opt=coalesce(character.c.opt, opt_id)
) )
result = await self.execute(conflict) result = await self.execute(conflict)
@ -858,12 +889,14 @@ class ChuniStaticData(BaseData):
version: int, version: int,
gacha_id: int, gacha_id: int,
gacha_name: int, gacha_name: int,
opt_id: int = None,
**gacha_data, **gacha_data,
) -> Optional[int]: ) -> Optional[int]:
sql = insert(gachas).values( sql = insert(gachas).values(
version=version, version=version,
gachaId=gacha_id, gachaId=gacha_id,
gachaName=gacha_name, gachaName=gacha_name,
opt=coalesce(gachas.c.opt, opt_id),
**gacha_data, **gacha_data,
) )
@ -871,6 +904,7 @@ class ChuniStaticData(BaseData):
version=version, version=version,
gachaId=gacha_id, gachaId=gacha_id,
gachaName=gacha_name, gachaName=gacha_name,
opt=coalesce(gachas.c.opt, opt_id),
**gacha_data, **gacha_data,
) )
@ -940,10 +974,10 @@ class ChuniStaticData(BaseData):
return None return None
return result.fetchone() return result.fetchone()
async def put_card(self, version: int, card_id: int, **card_data) -> Optional[int]: async def put_card(self, version: int, card_id: int, opt_id: int = None,**card_data) -> Optional[int]:
sql = insert(cards).values(version=version, cardId=card_id, **card_data) sql = insert(cards).values(version=version, cardId=card_id, opt=coalesce(cards.c.opt, opt_id), **card_data)
conflict = sql.on_duplicate_key_update(**card_data) conflict = sql.on_duplicate_key_update(opt=coalesce(cards.c.opt, opt_id), **card_data)
result = await self.execute(conflict) result = await self.execute(conflict)
if result is None: if result is None: