diva: added all previous commits, added username and password change

- Changed `update_profile()` function to allow a single Dict instead of multiple values
- Added `passwd*` Columns to profile table and added corresponding update/rollback sql scripts
- Added `handle_card_procedure_request()`, `handle_change_name_request ()` and `handle_change_passwd_request()` functions to DivaBase
This commit is contained in:
2023-02-18 21:01:31 +01:00
parent ffc2f4e0cc
commit c99bfda015
18 changed files with 824 additions and 190 deletions

View File

@ -1,6 +1,11 @@
from titles.diva.schema.profile import DivaProfileData
from titles.diva.schema.score import DivaScoreData
from titles.diva.schema.module import DivaModuleData
from titles.diva.schema.customize import DivaCustomizeItemData
from titles.diva.schema.pv_customize import DivaPvCustomizeData
from titles.diva.schema.item import DivaItemData
from titles.diva.schema.static import DivaStaticData
__all__ = [DivaProfileData, DivaScoreData, DivaItemData, DivaStaticData]
__all__ = [DivaProfileData, DivaScoreData, DivaModuleData,
DivaCustomizeItemData, DivaPvCustomizeData, DivaItemData,
DivaStaticData]

View File

@ -0,0 +1,63 @@
from typing import Optional, Dict, List
from sqlalchemy import Table, Column, UniqueConstraint, and_
from sqlalchemy.types import Integer
from sqlalchemy.schema import ForeignKey
from sqlalchemy.dialects.mysql import insert
from core.data.schema import BaseData, metadata
customize = Table(
"diva_profile_customize_item",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("version", Integer, nullable=False),
Column("item_id", Integer, nullable=False),
UniqueConstraint("user", "version", "item_id", name="diva_profile_customize_item_uk"),
mysql_charset='utf8mb4'
)
class DivaCustomizeItemData(BaseData):
def put_customize_item(self, aime_id: int, version: int, item_id: int) -> None:
sql = insert(customize).values(
version=version,
user=aime_id,
item_id=item_id
)
result = self.execute(sql)
if result is None:
self.logger.error(f"{__name__} Failed to insert diva profile customize item! aime id: {aime_id} item: {item_id}")
return None
return result.lastrowid
def get_customize_items(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and an aime id, return all the customize items, not used directly
"""
sql = customize.select(and_(
customize.c.version == version,
customize.c.user == aime_id
))
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_customize_items_have_string(self, aime_id: int, version: int) -> str:
"""
Given a game version and an aime id, return the cstmz_itm_have hex string
required for diva directly
"""
items_list = self.get_customize_items(aime_id, version)
if items_list is None:
items_list = []
item_have = 0
for item in items_list:
item_have |= 1 << item["item_id"]
# convert the int to a 250 digit long hex string
return "{0:0>250}".format(hex(item_have).upper()[2:])

View File

@ -14,20 +14,29 @@ shop = Table(
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("version", Integer, nullable=False),
Column("mdl_eqp_ary", String(32)),
Column("c_itm_eqp_ary", String(59)),
Column("ms_itm_flg_ary", String(59)),
UniqueConstraint("user", "version", name="diva_profile_shop_uk"),
mysql_charset='utf8mb4'
)
class DivaItemData(BaseData):
def put_shop(self, aime_id: int, version: int, mdl_eqp_ary: str) -> None:
class DivaItemData(BaseData):
def put_shop(self, aime_id: int, version: int, mdl_eqp_ary: str,
c_itm_eqp_ary: str, ms_itm_flg_ary: str) -> None:
sql = insert(shop).values(
version=version,
user=aime_id,
mdl_eqp_ary=mdl_eqp_ary
mdl_eqp_ary=mdl_eqp_ary,
c_itm_eqp_ary=c_itm_eqp_ary,
ms_itm_flg_ary=ms_itm_flg_ary
)
conflict = sql.on_duplicate_key_update(
mdl_eqp_ary = sql.inserted.mdl_eqp_ary
mdl_eqp_ary=mdl_eqp_ary,
c_itm_eqp_ary=c_itm_eqp_ary,
ms_itm_flg_ary=ms_itm_flg_ary
)
result = self.execute(conflict)
@ -44,7 +53,8 @@ class DivaItemData(BaseData):
shop.c.version == version,
shop.c.user == aime_id
))
result = self.execute(sql)
if result is None: return None
return result.fetchone()
if result is None:
return None
return result.fetchone()

View File

@ -0,0 +1,63 @@
from typing import Optional, Dict, List
from sqlalchemy import Table, Column, UniqueConstraint, and_
from sqlalchemy.types import Integer
from sqlalchemy.schema import ForeignKey
from sqlalchemy.dialects.mysql import insert
from core.data.schema import BaseData, metadata
module = Table(
"diva_profile_module",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("version", Integer, nullable=False),
Column("module_id", Integer, nullable=False),
UniqueConstraint("user", "version", "module_id", name="diva_profile_module_uk"),
mysql_charset='utf8mb4'
)
class DivaModuleData(BaseData):
def put_module(self, aime_id: int, version: int, module_id: int) -> None:
sql = insert(module).values(
version=version,
user=aime_id,
module_id=module_id
)
result = self.execute(sql)
if result is None:
self.logger.error(f"{__name__} Failed to insert diva profile module! aime id: {aime_id} module: {module_id}")
return None
return result.lastrowid
def get_modules(self, aime_id: int, version: int) -> Optional[List[Dict]]:
"""
Given a game version and an aime id, return all the modules, not used directly
"""
sql = module.select(and_(
module.c.version == version,
module.c.user == aime_id
))
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_modules_have_string(self, aime_id: int, version: int) -> str:
"""
Given a game version and an aime id, return the mdl_have hex string
required for diva directly
"""
module_list = self.get_modules(aime_id, version)
if module_list is None:
module_list = []
module_have = 0
for module in module_list:
module_have |= 1 << module["module_id"]
# convert the int to a 250 digit long hex string
return "{0:0>250}".format(hex(module_have).upper()[2:])

View File

@ -11,7 +11,8 @@ profile = Table(
"diva_profile",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade",
onupdate="cascade"), nullable=False),
Column("version", Integer, nullable=False),
Column("player_name", String(8), nullable=False),
Column("lv_str", String(24), nullable=False, server_default="Dab on 'em"),
@ -23,11 +24,15 @@ profile = Table(
Column("btn_se_vol2", Integer, nullable=False, server_default="100"),
Column("sldr_se_vol2", Integer, nullable=False, server_default="100"),
Column("sort_kind", Integer, nullable=False, server_default="2"),
Column("use_pv_mdl_eqp", String(8), nullable=False, server_default="true"),
Column("use_pv_btn_se_eqp", String(8), nullable=False, server_default="true"),
Column("use_pv_sld_se_eqp", String(8), nullable=False, server_default="false"),
Column("use_pv_chn_sld_se_eqp", String(8), nullable=False, server_default="false"),
Column("use_pv_sldr_tch_se_eqp", String(8), nullable=False, server_default="false"),
Column("use_pv_mdl_eqp", Boolean, nullable=False, server_default="1"),
Column("use_mdl_pri", Boolean, nullable=False, server_default="0"),
Column("use_pv_skn_eqp", Boolean, nullable=False, server_default="0"),
Column("use_pv_btn_se_eqp", Boolean, nullable=False, server_default="1"),
Column("use_pv_sld_se_eqp", Boolean, nullable=False, server_default="0"),
Column("use_pv_chn_sld_se_eqp", Boolean,
nullable=False, server_default="0"),
Column("use_pv_sldr_tch_se_eqp", Boolean,
nullable=False, server_default="0"),
Column("nxt_pv_id", Integer, nullable=False, server_default="708"),
Column("nxt_dffclty", Integer, nullable=False, server_default="2"),
Column("nxt_edtn", Integer, nullable=False, server_default="0"),
@ -37,14 +42,20 @@ profile = Table(
Column("rgo_sts", Integer, nullable=False, server_default="1"),
Column("lv_efct_id", Integer, nullable=False, server_default="0"),
Column("lv_plt_id", Integer, nullable=False, server_default="1"),
Column("my_qst_id", String(128), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
Column("my_qst_sts", String(128), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
Column("passwd_stat", Integer, nullable=False, server_default="0"),
Column("passwd", String(12), nullable=False, server_default="**********"),
Column("my_qst_id", String(
128), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
Column("my_qst_sts", String(
128), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
UniqueConstraint("user", "version", name="diva_profile_uk"),
mysql_charset='utf8mb4'
)
class DivaProfileData(BaseData):
def create_profile(self, version: int, aime_id: int, player_name: str) -> Optional[int]:
def create_profile(self, version: int, aime_id: int,
player_name: str) -> Optional[int]:
"""
Given a game version, aime id, and player_name, create a profile and return it's ID
"""
@ -55,48 +66,46 @@ class DivaProfileData(BaseData):
)
conflict = sql.on_duplicate_key_update(
player_name = sql.inserted.player_name
player_name=sql.inserted.player_name
)
result = self.execute(conflict)
if result is None:
self.logger.error(f"{__name__} Failed to insert diva profile! aime id: {aime_id} username: {player_name}")
self.logger.error(
f"{__name__} Failed to insert diva profile! aime id: {aime_id} username: {player_name}")
return None
return result.lastrowid
def update_profile(self, profile_id: int, lv_num: int, lv_pnt: int, vcld_pts: int, hp_vol: int, btn_se_vol: int, btn_se_vol2: int, sldr_se_vol2: int, sort_kind: int, use_pv_mdl_eqp: str, use_pv_btn_se_eqp: str, use_pv_sld_se_eqp: str, use_pv_chn_sld_se_eqp: str, use_pv_sldr_tch_se_eqp: str, nxt_pv_id: int, nxt_dffclty: int, nxt_edtn: int, dsp_clr_brdr: int, dsp_intrm_rnk: int, dsp_clr_sts: int, rgo_sts: int, lv_efct_id: int, lv_plt_id: int, my_qst_id: str, my_qst_sts: str) -> None:
sql = profile.update(profile.c.user == profile_id).values(
lv_num = lv_num,
lv_pnt = lv_pnt,
vcld_pts = vcld_pts,
hp_vol = hp_vol,
btn_se_vol = btn_se_vol,
btn_se_vol2 = btn_se_vol2,
sldr_se_vol2 = sldr_se_vol2,
sort_kind = sort_kind,
use_pv_mdl_eqp = use_pv_mdl_eqp,
use_pv_btn_se_eqp = use_pv_btn_se_eqp,
use_pv_sld_se_eqp = use_pv_sld_se_eqp,
use_pv_chn_sld_se_eqp = use_pv_chn_sld_se_eqp,
use_pv_sldr_tch_se_eqp = use_pv_sldr_tch_se_eqp,
nxt_pv_id = nxt_pv_id,
nxt_dffclty = nxt_dffclty,
nxt_edtn = nxt_edtn,
dsp_clr_brdr = dsp_clr_brdr,
dsp_intrm_rnk = dsp_intrm_rnk,
dsp_clr_sts = dsp_clr_sts,
rgo_sts = rgo_sts,
lv_efct_id = lv_efct_id,
lv_plt_id = lv_plt_id,
my_qst_id = my_qst_id,
my_qst_sts = my_qst_sts
def update_profile(self, profile_updated: Dict) -> None:
sql = profile.update(profile.c.user == profile_updated["user"]).values(
player_name=profile_updated["player_name"],
lv_num=profile_updated["lv_num"],
lv_pnt=profile_updated["lv_pnt"],
vcld_pts=profile_updated["vcld_pts"],
hp_vol=profile_updated["hp_vol"],
btn_se_vol=profile_updated["btn_se_vol"],
btn_se_vol2=profile_updated["btn_se_vol2"],
sldr_se_vol2=profile_updated["sldr_se_vol2"],
sort_kind=profile_updated["sort_kind"],
nxt_pv_id=profile_updated["nxt_pv_id"],
nxt_dffclty=profile_updated["nxt_dffclty"],
nxt_edtn=profile_updated["nxt_edtn"],
dsp_clr_brdr=profile_updated["dsp_clr_brdr"],
dsp_intrm_rnk=profile_updated["dsp_intrm_rnk"],
dsp_clr_sts=profile_updated["dsp_clr_sts"],
rgo_sts=profile_updated["rgo_sts"],
lv_efct_id=profile_updated["lv_efct_id"],
lv_plt_id=profile_updated["lv_plt_id"],
my_qst_id=profile_updated["my_qst_id"],
my_qst_sts=profile_updated["my_qst_sts"],
passwd_stat=profile_updated["passwd_stat"],
passwd=profile_updated["passwd"]
)
result = self.execute(sql)
if result is None:
self.logger.error(f"update_profile: failed to update profile! profile: {profile_id}")
if result is None:
self.logger.error(
f"update_profile: failed to update profile! profile: {profile_id}")
return None
def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]:
@ -104,10 +113,11 @@ class DivaProfileData(BaseData):
Given a game version and either a profile or aime id, return the profile
"""
sql = profile.select(and_(
profile.c.version == version,
profile.c.user == aime_id
))
profile.c.version == version,
profile.c.user == aime_id
))
result = self.execute(sql)
if result is None: return None
if result is None:
return None
return result.fetchone()

View File

@ -0,0 +1,69 @@
from typing import Optional, Dict, List
from sqlalchemy import Table, Column, UniqueConstraint, and_
from sqlalchemy.types import Integer, String
from sqlalchemy.schema import ForeignKey
from sqlalchemy.dialects.mysql import insert
from core.data.schema import BaseData, metadata
pv_customize = Table(
"diva_profile_pv_customize",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("version", Integer, nullable=False),
Column("pv_id", Integer, nullable=False),
Column("mdl_eqp_ary", String(14), server_default="-999,-999,-999"),
Column("c_itm_eqp_ary", String(59), server_default="-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999"),
Column("ms_itm_flg_ary", String(59), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
Column("skin", Integer, server_default="-1"),
Column("btn_se", Integer, server_default="-1"),
Column("sld_se", Integer, server_default="-1"),
Column("chsld_se", Integer, server_default="-1"),
Column("sldtch_se", Integer, server_default="-1"),
UniqueConstraint("user", "version", "pv_id", name="diva_profile_pv_customize_uk"),
mysql_charset='utf8mb4'
)
class DivaPvCustomizeData(BaseData):
def put_pv_customize(self, aime_id: int, version: int, pv_id: int,
mdl_eqp_ary: str, c_itm_eqp_ary: str,
ms_itm_flg_ary: str) -> Optional[int]:
sql = insert(pv_customize).values(
version=version,
user=aime_id,
pv_id=pv_id,
mdl_eqp_ary=mdl_eqp_ary,
c_itm_eqp_ary=c_itm_eqp_ary,
ms_itm_flg_ary=ms_itm_flg_ary,
)
conflict = sql.on_duplicate_key_update(
pv_id=pv_id,
mdl_eqp_ary=mdl_eqp_ary,
c_itm_eqp_ary=c_itm_eqp_ary,
ms_itm_flg_ary=ms_itm_flg_ary,
)
result = self.execute(conflict)
if result is None:
self.logger.error(f"{__name__} Failed to insert diva pv customize! aime id: {aime_id}")
return None
return result.lastrowid
def get_pv_customize(self, aime_id: int,
pv_id: int) -> Optional[List[Dict]]:
"""
Given either a profile or aime id, return a Pv Customize row
"""
sql = pv_customize.select(and_(
pv_customize.c.user == aime_id,
pv_customize.c.pv_id == pv_id
))
result = self.execute(sql)
if result is None:
return None
return result.fetchone()

View File

@ -1,7 +1,7 @@
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
from sqlalchemy.types import Integer, String, TIMESTAMP, JSON, Boolean
from sqlalchemy.schema import ForeignKey
from sqlalchemy.sql import func
from sqlalchemy.sql import func, select
from sqlalchemy.dialects.mysql import insert
from typing import Optional, List, Dict, Any
@ -16,6 +16,7 @@ score = Table(
Column("version", Integer),
Column("pv_id", Integer),
Column("difficulty", Integer),
Column("edition", Integer),
Column("score", Integer),
Column("atn_pnt", Integer),
Column("clr_kind", Integer),
@ -26,7 +27,7 @@ score = Table(
Column("sad", Integer),
Column("worst", Integer),
Column("max_combo", Integer),
UniqueConstraint("user", "pv_id", "difficulty", name="diva_score_uk"),
UniqueConstraint("user", "pv_id", "difficulty", "edition", name="diva_score_uk"),
mysql_charset='utf8mb4'
)
@ -38,6 +39,7 @@ playlog = Table(
Column("version", Integer),
Column("pv_id", Integer),
Column("difficulty", Integer),
Column("edition", Integer),
Column("score", Integer),
Column("atn_pnt", Integer),
Column("clr_kind", Integer),
@ -52,90 +54,144 @@ playlog = Table(
mysql_charset='utf8mb4'
)
class DivaScoreData(BaseData):
def put_best_score(self, user_id: int, game_version: int, song_id: int, difficulty: int, song_score: int, atn_pnt: int,
clr_kind: int, sort_kind:int, cool: int, fine: int, safe: int, sad: int, worst: int, max_combo: int) -> Optional[int]:
def put_best_score(self, user_id: int, game_version: int, song_id: int,
difficulty: int, edition: int, song_score: int,
atn_pnt: int, clr_kind: int, sort_kind: int,
cool: int, fine: int, safe: int, sad: int,
worst: int, max_combo: int) -> Optional[int]:
"""
Update the user's best score for a chart
"""
sql = insert(score).values(
user=user_id,
version=game_version,
pv_id = song_id,
pv_id=song_id,
difficulty=difficulty,
edition=edition,
score=song_score,
atn_pnt = atn_pnt,
clr_kind = clr_kind,
sort_kind = sort_kind,
cool = cool,
fine = fine,
safe = safe,
sad = sad,
worst = worst,
max_combo = max_combo,
atn_pnt=atn_pnt,
clr_kind=clr_kind,
sort_kind=sort_kind,
cool=cool,
fine=fine,
safe=safe,
sad=sad,
worst=worst,
max_combo=max_combo,
)
conflict = sql.on_duplicate_key_update(
score=song_score,
atn_pnt = atn_pnt,
clr_kind = clr_kind,
sort_kind = sort_kind,
cool = cool,
fine = fine,
safe = safe,
sad = sad,
worst = worst,
max_combo = max_combo,
atn_pnt=atn_pnt,
clr_kind=clr_kind,
sort_kind=sort_kind,
cool=cool,
fine=fine,
safe=safe,
sad=sad,
worst=worst,
max_combo=max_combo,
)
result = self.execute(conflict)
if result is None:
self.logger.error(f"{__name__} failed to insert best score! profile: {user_id}, song: {song_id}")
self.logger.error(
f"{__name__} failed to insert best score! profile: {user_id}, song: {song_id}")
return None
return result.lastrowid
def put_playlog(self, user_id: int, game_version: int, song_id: int, difficulty: int, song_score: int, atn_pnt: int,
clr_kind: int, sort_kind:int, cool: int, fine: int, safe: int, sad: int, worst: int, max_combo: int) -> Optional[int]:
def put_playlog(self, user_id: int, game_version: int, song_id: int,
difficulty: int, edition: int, song_score: int,
atn_pnt: int, clr_kind: int, sort_kind: int,
cool: int, fine: int, safe: int, sad: int,
worst: int, max_combo: int) -> Optional[int]:
"""
Add an entry to the user's play log
"""
sql = playlog.insert().values(
user=user_id,
version=game_version,
pv_id = song_id,
pv_id=song_id,
difficulty=difficulty,
edition=edition,
score=song_score,
atn_pnt = atn_pnt,
clr_kind = clr_kind,
sort_kind = sort_kind,
cool = cool,
fine = fine,
safe = safe,
sad = sad,
worst = worst,
max_combo = max_combo
atn_pnt=atn_pnt,
clr_kind=clr_kind,
sort_kind=sort_kind,
cool=cool,
fine=fine,
safe=safe,
sad=sad,
worst=worst,
max_combo=max_combo
)
result = self.execute(sql)
if result is None:
self.logger.error(f"{__name__} failed to insert playlog! profile: {user_id}, song: {song_id}, chart: {difficulty}")
self.logger.error(
f"{__name__} failed to insert playlog! profile: {user_id}, song: {song_id}, chart: {difficulty}")
return None
return result.lastrowid
def get_best_score(self, user_id: int, pv_id: int, chart_id: int) -> Optional[Dict]:
def get_best_user_score(self, user_id: int, pv_id: int, difficulty: int,
edition: int) -> Optional[Dict]:
sql = score.select(
and_(score.c.user == user_id, score.c.pv_id == pv_id, score.c.difficulty == chart_id)
and_(score.c.user == user_id,
score.c.pv_id == pv_id,
score.c.difficulty == difficulty,
score.c.edition == edition)
)
result = self.execute(sql)
if result is None: return None
if result is None:
return None
return result.fetchone()
def get_best_scores(self, user_id: int) -> Optional[Dict]:
def get_top3_scores(self, pv_id: int, difficulty: int,
edition: int) -> Optional[List[Dict]]:
sql = score.select(
and_(score.c.pv_id == pv_id,
score.c.difficulty == difficulty,
score.c.edition == edition)
).order_by(score.c.score.desc()).limit(3)
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def get_global_ranking(self, user_id: int, pv_id: int, difficulty: int,
edition: int) -> Optional[List]:
# get the subquery max score of a user with pv_id, difficulty and
# edition
sql_sub = select([score.c.score]).filter(
score.c.user == user_id,
score.c.pv_id == pv_id,
score.c.difficulty == difficulty,
score.c.edition == edition
).scalar_subquery()
# Perform the main query, also rename the resulting column to ranking
sql = select(func.count(score.c.id).label("ranking")).filter(
score.c.score >= sql_sub,
score.c.pv_id == pv_id,
score.c.difficulty == difficulty,
score.c.edition == edition
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def get_best_scores(self, user_id: int) -> Optional[List]:
sql = score.select(score.c.user == user_id)
result = self.execute(sql)
if result is None: return None
if result is None:
return None
return result.fetchall()

View File

@ -132,11 +132,25 @@ class DivaStaticData(BaseData):
if result is None: return None
return result.lastrowid
def get_enabled_shop(self, version: int) -> Optional[List[Row]]:
sql = select(shop).where(and_(shop.c.version == version, shop.c.enabled == True))
def get_enabled_shop(self, version: int, shopId: int) -> Optional[Row]:
sql = select(shop).where(and_(
shop.c.version == version,
shop.c.shopId == shopId,
shop.c.enabled == True))
result = self.execute(sql)
if result is None: return None
if result is None:
return None
return result.fetchone()
def get_enabled_shops(self, version: int) -> Optional[List[Row]]:
sql = select(shop).where(and_(
shop.c.version == version,
shop.c.enabled == True))
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_items(self, version: int, itemId: int, name: str, type: int, points: int, unknown_0: int, start_date: str, end_date: str) -> Optional[int]:
@ -158,12 +172,26 @@ class DivaStaticData(BaseData):
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_enabled_items(self, version: int) -> Optional[List[Row]]:
sql = select(items).where(and_(items.c.version == version, items.c.enabled == True))
def get_enabled_item(self, version: int, itemId: int) -> Optional[Row]:
sql = select(items).where(and_(
items.c.version == version,
items.c.itemId == itemId,
items.c.enabled == True))
result = self.execute(sql)
if result is None: return None
if result is None:
return None
return result.fetchone()
def get_enabled_items(self, version: int) -> Optional[List[Row]]:
sql = select(items).where(and_(
items.c.version == version,
items.c.enabled == True))
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_music(self, version: int, song: int, chart: int, title: str, arranger: str, illustrator: str,