"""
Copyright (C) 2025 283375
This file is part of "arcaea-apk-assets" (stated as "this program" below).
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see .
"""
from __future__ import annotations
import abc
import dataclasses
import re
from typing import ClassVar
__all__ = [
"ArcaeaApkAsset",
"ArcaeaApkAssetJacket",
"ArcaeaApkAssetList",
"ArcaeaApkAssetPartnerIcon",
]
@dataclasses.dataclass
class ArcaeaApkAsset(metaclass=abc.ABCMeta):
PATTERN: ClassVar[re.Pattern]
zip_filename: str
@classmethod
def _get_match(cls, string: str) -> re.Match | None:
return cls.PATTERN.match(string)
@classmethod
@abc.abstractmethod
def from_zip_filename(
cls,
asset_zip_filename: str,
) -> ArcaeaApkAsset | None: ...
@dataclasses.dataclass
class ArcaeaApkAssetJacket(ArcaeaApkAsset):
PATTERN = re.compile(
r"^assets/songs/(?P.*)/(1080_)?(?P\d|base)(_(?P.*))?\.(jpg|png)",
)
song_id: str
rating_class: str | None
lang: str | None
@classmethod
def from_zip_filename(cls, asset_zip_filename: str) -> ArcaeaApkAssetJacket | None:
match = cls._get_match(asset_zip_filename)
if match is None:
return None
return cls(
zip_filename=asset_zip_filename,
song_id=match.group("raw_song_id").replace("dl_", ""),
rating_class=(
None
if match.group("raw_rating_class") == "base"
else match.group("raw_rating_class")
),
lang=match.group("lang"),
)
@dataclasses.dataclass
class ArcaeaApkAssetPartnerIcon(ArcaeaApkAsset):
PATTERN = re.compile(r"^assets/char/(?P\d+u?)_icon\.(jpg|png)")
char_id: str
@classmethod
def from_zip_filename(
cls,
asset_zip_filename: str,
) -> ArcaeaApkAssetPartnerIcon | None:
match = cls._get_match(asset_zip_filename)
if match is None:
return None
return cls(
zip_filename=asset_zip_filename,
char_id=match.group("char_id"),
)
@dataclasses.dataclass
class ArcaeaApkAssetList(ArcaeaApkAsset):
PATTERN = re.compile(r"^assets/songs/(?P(pack|song)list|unlocks)")
filename: str
@classmethod
def from_zip_filename(cls, asset_zip_filename: str) -> ArcaeaApkAssetList | None:
match = cls._get_match(asset_zip_filename)
if match is None:
return None
return cls(
zip_filename=asset_zip_filename,
filename=match.group("filename"),
)