diff --git a/titles/idac/index.py b/titles/idac/index.py index 03d4a5c..00d90b1 100644 --- a/titles/idac/index.py +++ b/titles/idac/index.py @@ -30,34 +30,37 @@ class IDACServlet(BaseServlet): yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}")) ) + self.logger = logging.getLogger("idac") + + if not hasattr(self.logger, "inited"): + log_fmt_str = "[%(asctime)s] IDAC | %(levelname)s | %(message)s" + log_fmt = logging.Formatter(log_fmt_str) + fileHandler = TimedRotatingFileHandler( + "{0}/{1}.log".format(self.core_cfg.server.log_dir, "idac"), + encoding="utf8", + when="d", + backupCount=10, + ) + + fileHandler.setFormatter(log_fmt) + + consoleHandler = logging.StreamHandler() + consoleHandler.setFormatter(log_fmt) + + self.logger.addHandler(fileHandler) + self.logger.addHandler(consoleHandler) + + self.logger.setLevel(self.game_cfg.server.loglevel) + coloredlogs.install( + level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str + ) + self.logger.inited = True + self.versions = [ IDACBase(core_cfg, self.game_cfg), IDACSeason2(core_cfg, self.game_cfg) ] - self.logger = logging.getLogger("idac") - log_fmt_str = "[%(asctime)s] IDAC | %(levelname)s | %(message)s" - log_fmt = logging.Formatter(log_fmt_str) - fileHandler = TimedRotatingFileHandler( - "{0}/{1}.log".format(self.core_cfg.server.log_dir, "idac"), - encoding="utf8", - when="d", - backupCount=10, - ) - - fileHandler.setFormatter(log_fmt) - - consoleHandler = logging.StreamHandler() - consoleHandler.setFormatter(log_fmt) - - self.logger.addHandler(fileHandler) - self.logger.addHandler(consoleHandler) - - self.logger.setLevel(self.game_cfg.server.loglevel) - coloredlogs.install( - level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str - ) - @classmethod def is_game_enabled(cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str) -> bool: game_cfg = IDACConfig() diff --git a/titles/idac/read.py b/titles/idac/read.py index 486260e..16db6d9 100644 --- a/titles/idac/read.py +++ b/titles/idac/read.py @@ -143,6 +143,10 @@ class IDACReader(BaseReader): # check if the table has a version column if "version" in table.c: data["version"] = self.version + + # remain compatible with old profile dumps + if "asset_version" in data: + data.pop("asset_version", None) sql = insert(table).values( **data diff --git a/titles/idac/schema/rounds.py b/titles/idac/schema/rounds.py index 4eb42ac..4e68b17 100644 --- a/titles/idac/schema/rounds.py +++ b/titles/idac/schema/rounds.py @@ -123,7 +123,10 @@ class IDACOnlineRounds(BaseData): sql = select(round_details).where(round_details.c.round_id_in_json == round_id) result = await self.execute(sql) - if result is None: + # check if the round already exists + existing_round = result.fetchone() if result else None + + if existing_round is None: tmp = { "round_id_in_json": round_id, "name": round_data["round_event_nm"], @@ -137,7 +140,6 @@ class IDACOnlineRounds(BaseData): return result.lastrowid - rid = result.fetchone() - return rid["id"] + return existing_round["id"] # TODO: get top five players of last round event for Boot/GetConfigData diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 299f2ba..f5363e8 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -29,48 +29,55 @@ class IDACSeason2(IDACBase): self.stamp_info = defaultdict(list) if self.game_config.stamp.enable: enabled_stamps = self.game_config.stamp.enabled_stamps - for game_ver in enabled_stamps.keys(): - for stamp in enabled_stamps[game_ver][:3]: - if not os.path.exists(f"./titles/idac/data/stamp/{stamp}.json"): - self.logger.warning( - f"Stamp {stamp} is enabled but does not exist!" - ) - continue - with open( - f"./titles/idac/data/stamp/{stamp}.json", encoding="UTF-8" - ) as f: - self.logger.debug(f"Loading stamp {stamp}") - self.stamp_info[game_ver].append(self._fix_dates(json.load(f))) + if isinstance(enabled_stamps, Dict): + for game_ver in enabled_stamps.keys(): + for stamp in enabled_stamps[game_ver][:3]: + if not os.path.exists(f"./titles/idac/data/stamp/{stamp}.json"): + self.logger.warning( + f"Stamp {stamp} is enabled but does not exist!" + ) + continue + + with open( + f"./titles/idac/data/stamp/{stamp}.json", encoding="UTF-8" + ) as f: + self.logger.debug(f"Loading stamp {stamp}") + self.stamp_info[game_ver].append(self._fix_dates(json.load(f))) + else: + self.logger.warning("Stamp configuration is invalid, please update your idac.yaml config!") # load the user configured time trial (only one) for each game version self.timetrial_event = {} self.timetrial_event_id = {} if self.game_config.timetrial.enable: enabled_timetrial = self.game_config.timetrial.enabled_timetrial - for game_ver in enabled_timetrial.keys(): - timetrial = enabled_timetrial[game_ver] - if timetrial is not None: - if not os.path.exists( - f"./titles/idac/data/timetrial/{timetrial}.json" - ): - self.logger.warning( - f"Timetrial {timetrial} is enabled but does not exist!" - ) - else: - self.logger.debug(f"Loading timetrial {timetrial}") - with open( - f"./titles/idac/data/timetrial/{timetrial}.json", - encoding="UTF-8", - ) as f: - self.timetrial_event[game_ver] = self._fix_dates( - json.load(f) + if isinstance(enabled_timetrial, Dict): + for game_ver in enabled_timetrial.keys(): + timetrial = enabled_timetrial[game_ver] + if timetrial is not None: + if not os.path.exists( + f"./titles/idac/data/timetrial/{timetrial}.json" + ): + self.logger.warning( + f"Timetrial {timetrial} is enabled but does not exist!" ) + else: + self.logger.debug(f"Loading timetrial {timetrial}") + with open( + f"./titles/idac/data/timetrial/{timetrial}.json", + encoding="UTF-8", + ) as f: + self.timetrial_event[game_ver] = self._fix_dates( + json.load(f) + ) - # required for saving - self.timetrial_event_id[game_ver] = self.timetrial_event.get( - game_ver - ).get("timetrial_event_id") + # required for saving + self.timetrial_event_id[game_ver] = self.timetrial_event.get( + game_ver + ).get("timetrial_event_id") + else: + self.logger.warning("Timetrial configuration is invalid, please update your idac.yaml config!") # load the user configured round event (only one) asyncio.create_task(self._load_round_event()) @@ -345,7 +352,7 @@ class IDACSeason2(IDACBase): "last_round_event": self.last_round_event, "last_round_event_ranking": self.last_round_event_ranking, "round_event_exp": [], - "stamp_info": self.stamp_info[ver_str], + "stamp_info": self.stamp_info.get(ver_str, []), # 0 = use default data, 1+ = server version of timereleasedata response "timerelease_no": self.timerelease_no, # 0 = use default data, 1+ = server version of gachadata response @@ -513,7 +520,7 @@ class IDACSeason2(IDACBase): "theory_close_version": "9.99.99", # unlocks the version specific special mode "special_mode_data": special_mode_data, - "timetrial_event_data": self.timetrial_event[ver_str], + "timetrial_event_data": self.timetrial_event.get(ver_str, {}), "number_lottery_data": [ { "m_number_lottery_win_number_no": 10, @@ -1325,14 +1332,15 @@ class IDACSeason2(IDACBase): # get the user's timetrial event data timetrial_event_data = {} - timetrial = await self.data.item.get_timetrial_event( - user_id, self.timetrial_event_id[ver_str] - ) - if timetrial is not None: - timetrial_event_data = { - "timetrial_event_id": timetrial["timetrial_event_id"], - "point": timetrial["point"], - } + if ver_str in self.timetrial_event_id: + timetrial = await self.data.item.get_timetrial_event( + user_id, self.timetrial_event_id[ver_str] + ) + if timetrial is not None: + timetrial_event_data = { + "timetrial_event_id": timetrial["timetrial_event_id"], + "point": timetrial["point"], + } # check if the battle gift event is active if self.battle_gift_event: @@ -2075,9 +2083,17 @@ class IDACSeason2(IDACBase): ver_str = self._headers_to_version(headers) # update the timetrial event points - await self.data.item.put_timetrial_event( - user_id, self.timetrial_event_id[ver_str], event_point - ) + timetrial_event_data = {} + if ver_str in self.timetrial_event_id: + timetrial_event_id = self.timetrial_event_id[ver_str] + await self.data.item.put_timetrial_event( + user_id, timetrial_event_id, event_point + ) + + timetrial_event_data = { + "timetrial_event_id": timetrial_event_id, + "point": event_point, + } # update the tips play count tips = await self.data.profile.get_profile_tips(user_id, self.version) @@ -2087,8 +2103,6 @@ class IDACSeason2(IDACBase): {"timetrial_play_count": tips["timetrial_play_count"] + 1}, ) - ver_str = self._headers_to_version(headers) - return { "status_code": "0", "course_rank": course_rank, @@ -2096,10 +2110,7 @@ class IDACSeason2(IDACBase): "location_course_store_rank": course_rank, "car_use_count": [], "maker_use_count": [], - "timetrial_event_data": { - "timetrial_event_id": self.timetrial_event_id[ver_str], - "point": event_point, - }, + "timetrial_event_data": timetrial_event_data, } async def handle_user_updatestoryresult_request(self, data: Dict, headers: Dict):