[chuni] Added truncation to long Title and Artist Name values on import #178
@ -1,7 +1,5 @@
|
||||
from core.config import CoreConfig
|
||||
from core.allnet import AllnetServlet, BillingServlet
|
||||
from core.aimedb import AimedbServlette
|
||||
from core.title import TitleServlet
|
||||
from core.utils import Utils
|
||||
from core.mucha import MuchaServlet
|
||||
from core.frontend import FrontendServlet
|
||||
|
@ -120,7 +120,7 @@ class ADBHeader:
|
||||
if self.store_id == 0:
|
||||
raise ADBHeaderException(f"Store ID cannot be 0!")
|
||||
|
||||
if re.fullmatch(r"^A[0-9]{2}[E|X][0-9]{2}[A-HJ-NP-Z][0-9]{4}$", self.keychip_id) is None:
|
||||
if re.fullmatch(r"^A[0-9]{2}[A-Z][0-9]{2}[A-HJ-NP-Z][0-9]{4}$", self.keychip_id) is None:
|
||||
raise ADBHeaderException(f"Keychip ID {self.keychip_id} is invalid!")
|
||||
|
||||
return True
|
||||
|
@ -9,7 +9,8 @@ from starlette.responses import PlainTextResponse
|
||||
from os import environ, path, mkdir, W_OK, access
|
||||
from typing import List
|
||||
|
||||
from core import CoreConfig, TitleServlet, MuchaServlet, AllnetServlet, BillingServlet, AimedbServlette
|
||||
from core import CoreConfig, TitleServlet, MuchaServlet
|
||||
from core.allnet import AllnetServlet, BillingServlet
|
||||
from core.frontend import FrontendServlet
|
||||
|
||||
async def dummy_rt(request: Request):
|
||||
|
@ -232,7 +232,7 @@ class ArcadeData(BaseData):
|
||||
return f"{platform_code}{'-' if dash else ''}{platform_rev:02d}{serial_letter}{serial_num:04d}{append:04d}"
|
||||
|
||||
def validate_keychip_format(self, serial: str) -> bool:
|
||||
# For the 2nd letter, E and X are the only "real" values that have been observed
|
||||
# For the 2nd letter, E and X are the only "real" values that have been observed (A is used for generated keychips)
|
||||
if re.fullmatch(r"^A[0-9]{2}[A-Z][-]?[0-9]{2}[A-HJ-NP-Z][0-9]{4}([0-9]{4})?$", serial) is None:
|
||||
return False
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import logging
|
||||
from os import mkdir, path, access, W_OK
|
||||
from os import mkdir, path, access, W_OK, environ
|
||||
import yaml
|
||||
import asyncio
|
||||
|
||||
@ -25,10 +25,11 @@ if __name__ == "__main__":
|
||||
parser.add_argument("action", type=str, help="create, upgrade, downgrade, create-owner, migrate, create-revision, create-autorevision")
|
||||
args = parser.parse_args()
|
||||
|
||||
environ["ARTEMIS_CFG_DIR"] = args.config
|
||||
|
||||
cfg = CoreConfig()
|
||||
if path.exists(f"{args.config}/core.yaml"):
|
||||
cfg_dict = yaml.safe_load(open(f"{args.config}/core.yaml"))
|
||||
cfg_dict.get("database", {})["loglevel"] = "info"
|
||||
cfg.update(cfg_dict)
|
||||
|
||||
if not path.exists(cfg.server.log_dir):
|
||||
|
@ -81,10 +81,12 @@ The importer for Chunithm will import: Events, Music, Charge Items and Avatar Ac
|
||||
Config file is located in `config/chuni.yaml`.
|
||||
|
||||
| Option | Info |
|
||||
|------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
|------------------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| `news_msg` | If this is set, the news at the top of the main screen will be displayed (up to Chunithm Paradise Lost) |
|
||||
| `name` | If this is set, all players that are not on a team will use this one by default. |
|
||||
| `use_login_bonus`| This is used to enable the login bonuses |
|
||||
| `stock_tickets` | If this is set, specifies tickets to auto-stock at login. Format is a comma-delimited list of IDs. Defaults to None |
|
||||
| `stock_count` | Ignored if stock_tickets is not specified. Number to stock of each ticket. Defaults to 99 |
|
||||
| `crypto` | This option is used to enable the TLS Encryption |
|
||||
|
||||
|
||||
|
@ -8,6 +8,10 @@ team:
|
||||
|
||||
mods:
|
||||
use_login_bonus: True
|
||||
# stock_tickets allows specified ticket IDs to be auto-stocked at login. Format is a comma-delimited string of ticket IDs
|
||||
# note: quanity is not refreshed on "continue" after set - only on subsequent login
|
||||
stock_tickets:
|
||||
stock_count: 99
|
||||
|
||||
version:
|
||||
11:
|
||||
|
3
index.py
3
index.py
@ -6,7 +6,8 @@ import uvicorn
|
||||
import logging
|
||||
import asyncio
|
||||
|
||||
from core import CoreConfig, AimedbServlette
|
||||
from core.config import CoreConfig
|
||||
from core.aimedb import AimedbServlette
|
||||
|
||||
async def launch_main(cfg: CoreConfig, ssl: bool) -> None:
|
||||
if ssl:
|
||||
|
@ -24,20 +24,35 @@ class ChuniBase:
|
||||
|
||||
async def handle_game_login_api_request(self, data: Dict) -> Dict:
|
||||
"""
|
||||
Handles the login bonus logic, required for the game because
|
||||
getUserLoginBonus gets called after getUserItem and therefore the
|
||||
Handles the login bonus and ticket stock logic, required for the game
|
||||
because getUserLoginBonus gets called after getUserItem; therefore the
|
||||
items needs to be inserted in the database before they get requested.
|
||||
|
||||
Adds a bonusCount after a user logged in after 24 hours, makes sure
|
||||
- Adds a stock for each specified ticket (itemKind 5)
|
||||
- Adds a bonusCount after a user logged in after 24 hours, makes sure
|
||||
loginBonus 30 gets looped, only show the login banner every 24 hours,
|
||||
adds the bonus to items (itemKind 6)
|
||||
"""
|
||||
|
||||
user_id = data["userId"]
|
||||
|
||||
# If we want to make certain tickets always available, stock them now
|
||||
if self.game_cfg.mods.stock_tickets:
|
||||
for ticket in self.game_cfg.mods.stock_tickets.split(","):
|
||||
await self.data.item.put_item(
|
||||
user_id,
|
||||
{
|
||||
"itemId": ticket.strip(),
|
||||
"itemKind": 5,
|
||||
"stock": self.game_cfg.mods.stock_count,
|
||||
"isValid": True,
|
||||
},
|
||||
)
|
||||
|
||||
# ignore the login bonus if disabled in config
|
||||
if not self.game_cfg.mods.use_login_bonus:
|
||||
return {"returnCode": 1}
|
||||
|
||||
user_id = data["userId"]
|
||||
login_bonus_presets = await self.data.static.get_login_bonus_presets(self.version)
|
||||
|
||||
for preset in login_bonus_presets:
|
||||
|
@ -53,6 +53,18 @@ class ChuniModsConfig:
|
||||
self.__config, "chuni", "mods", "use_login_bonus", default=True
|
||||
)
|
||||
|
||||
@property
|
||||
def stock_tickets(self) -> str:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "chuni", "mods", "stock_tickets", default=None
|
||||
)
|
||||
|
||||
@property
|
||||
def stock_count(self) -> int:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "chuni", "mods", "stock_count", default=99
|
||||
)
|
||||
|
||||
|
||||
class ChuniVersionConfig:
|
||||
def __init__(self, parent_config: "ChuniConfig") -> None:
|
||||
|
@ -104,7 +104,8 @@ class ChuniNew(ChuniBase):
|
||||
return {"returnCode": "1"}
|
||||
|
||||
async def handle_get_user_map_area_api_request(self, data: Dict) -> Dict:
|
||||
user_map_areas = await self.data.item.get_map_areas(data["userId"])
|
||||
map_area_ids = [int(area["mapAreaId"]) for area in data["mapAreaIdList"]]
|
||||
user_map_areas = await self.data.item.get_map_areas(data["userId"], map_area_ids)
|
||||
|
||||
map_areas = []
|
||||
for map_area in user_map_areas:
|
||||
|
@ -36,10 +36,14 @@ class ChuniReader(BaseReader):
|
||||
if self.opt_dir is not None:
|
||||
data_dirs += self.get_data_directories(self.opt_dir)
|
||||
|
||||
we_diff = "4"
|
||||
if self.version >= ChuniConstants.VER_CHUNITHM_NEW:
|
||||
we_diff = "5"
|
||||
|
||||
for dir in data_dirs:
|
||||
self.logger.info(f"Read from {dir}")
|
||||
await self.read_events(f"{dir}/event")
|
||||
await self.read_music(f"{dir}/music")
|
||||
await self.read_music(f"{dir}/music", we_diff)
|
||||
await self.read_charges(f"{dir}/chargeItem")
|
||||
await self.read_avatar(f"{dir}/avatarAccessory")
|
||||
await self.read_login_bonus(f"{dir}/")
|
||||
@ -138,7 +142,7 @@ class ChuniReader(BaseReader):
|
||||
else:
|
||||
self.logger.warning(f"Failed to insert event {id}")
|
||||
|
||||
async def read_music(self, music_dir: str) -> None:
|
||||
async def read_music(self, music_dir: str, we_diff: str = "4") -> None:
|
||||
for root, dirs, files in walk(music_dir):
|
||||
for dir in dirs:
|
||||
if path.exists(f"{root}/{dir}/Music.xml"):
|
||||
@ -169,7 +173,7 @@ class ChuniReader(BaseReader):
|
||||
chart_type = MusicFumenData.find("type")
|
||||
chart_id = chart_type.find("id").text
|
||||
chart_diff = chart_type.find("str").text
|
||||
if chart_diff == "WorldsEnd" and (chart_id == "4" or chart_id == "5"): # 4 in SDBT, 5 in SDHD
|
||||
if chart_diff == "WorldsEnd" and chart_id == we_diff: # 4 in SDBT, 5 in SDHD
|
||||
level = float(xml_root.find("starDifType").text)
|
||||
we_chara = (
|
||||
xml_root.find("worldsEndTagName")
|
||||
|
@ -533,8 +533,8 @@ class ChuniItemData(BaseData):
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
async def get_map_areas(self, user_id: int) -> Optional[List[Row]]:
|
||||
sql = select(map_area).where(map_area.c.user == user_id)
|
||||
async def get_map_areas(self, user_id: int, map_area_ids: List[int]) -> Optional[List[Row]]:
|
||||
sql = select(map_area).where(map_area.c.user == user_id, map_area.c.mapAreaId.in_(map_area_ids))
|
||||
|
||||
result = await self.execute(sql)
|
||||
if result is None:
|
||||
|
@ -818,7 +818,8 @@ class Mai2Base:
|
||||
}
|
||||
|
||||
async def handle_upload_user_portrait_api_request(self, data: Dict) -> Dict:
|
||||
self.logger.debug(data)
|
||||
self.logger.warning("Portrait uploading not supported at this time.")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPortraitApi'}
|
||||
|
||||
async def handle_upload_user_photo_api_request(self, data: Dict) -> Dict:
|
||||
if not self.game_config.uploads.photos or not self.game_config.uploads.photos_dir:
|
||||
|
Loading…
Reference in New Issue
Block a user