Files
KKAFIO/test.py
2024-10-08 01:11:25 +01:00

236 lines
7.8 KiB
Python

import concurrent.futures
import requests
import json
import patoolib
import logging
import shutil
from bs4 import BeautifulSoup
from pathlib import Path
from util.config import Config
from util.file_manager import FileManager
from modules.create_backup import CreateBackup
from modules.fc_kks import FilterConvertKKS
from modules.install_chara import InstallChara
from modules.remove_chara import RemoveChara
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
CWD = Path.cwd()
TEST_PATH = CWD / "test"
GAMEPATH = TEST_PATH / "Koikatsu Party"
BACKUP_PATH = TEST_PATH / "Backup"
DOWNLOAD_PATH = TEST_PATH / "Downloads"
if TEST_PATH.exists() and TEST_PATH.is_dir():
shutil.rmtree(TEST_PATH)
paths_to_check = [
TEST_PATH,
BACKUP_PATH,
DOWNLOAD_PATH,
GAMEPATH / "UserData",
GAMEPATH / "BepInEx",
GAMEPATH / "mods",
GAMEPATH / "UserData" / "chara" / "male",
GAMEPATH / "UserData" / "chara" / "female",
GAMEPATH / "UserData" / "coordinate",
GAMEPATH / "UserData" / "Overlays"
]
for path in paths_to_check:
path.mkdir(parents=True, exist_ok=True)
def create_config():
"""Creates and saves the configuration file."""
data = {
"Core": {"GamePath": str(GAMEPATH)},
"CreateBackup": {
"Enable": True,
"OutputPath": str(BACKUP_PATH),
"BepInEx": False,
"Filename": "koikatsu_backup",
"mods": False,
"UserData": False,
},
"FilterConvertKKS": {
"Convert": True,
"InputPath": str(DOWNLOAD_PATH),
"Enable": True,
},
"InstallChara": {
"Password": "Skip",
"FileConflicts": "Skip",
"Enable": True,
"InputPath": str(DOWNLOAD_PATH),
},
"RemoveChara": {
"Enable": True,
"InputPath": str(DOWNLOAD_PATH),
},
}
config_path = TEST_PATH / 'config/config.json'
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, "w") as f:
json.dump(data, f, indent=4)
return Config(config_path)
CONFIG = create_config()
FILE_MANAGER = FileManager(CONFIG)
def valid_link(link_button):
"""Check if a link is a valid download button."""
return link_button.text == 'Download' and link_button.get('href')
def get_card_urls(bepis_url: str) -> list[str]:
"""Extract card download URLs from a bepis page."""
try:
response = requests.get(bepis_url)
response.raise_for_status()
except requests.RequestException as e:
logger.error(f"Error fetching {bepis_url}: {e}")
return []
soup = BeautifulSoup(response.text, 'html.parser')
link_buttons = soup.find_all('a', class_='btn btn-primary btn-sm')
return ['https://db.bepis.moe' + link_button.get('href') for link_button in link_buttons if valid_link(link_button)]
def download_card(card_url: str) -> Path:
"""Download a card from a given URL."""
card_name = Path(card_url).name
card_path = DOWNLOAD_PATH / card_name
try:
with requests.get(card_url, stream=True) as response:
response.raise_for_status()
with open(card_path, "wb") as out_file:
out_file.write(response.content)
logger.info(f"Downloaded {card_name}")
return card_path
except requests.RequestException as e:
logger.error(f"Error downloading {card_url}: {e}")
return None
def download(bepis_url: str):
"""Download all cards from a given bepis URL using a thread pool."""
download_urls = get_card_urls(bepis_url)
with concurrent.futures.ThreadPoolExecutor() as executor:
results = list(executor.map(download_card, download_urls))
return set(filter(None, results))
def create_zipmods():
zipmod_paths = set()
for i in range(10):
path = DOWNLOAD_PATH / f'test_{i}.zipmod'
path.touch()
zipmod_paths.add(path)
return zipmod_paths
def test_fckss(kk_cards, kks_cards):
"""Test FilterConvertKKS functionality."""
fckss = FilterConvertKKS(CONFIG, FILE_MANAGER)
fckss.run()
filter_path = DOWNLOAD_PATH / '_KKS_card_'
conversion_path = DOWNLOAD_PATH / '_KKS_to_KK_'
assert filter_path.exists(), "Filter path does not exist."
assert conversion_path.exists(), "Conversion path does not exist."
for kk_path in kk_cards:
card_name = kk_path.name
filtered_kks_path = filter_path / card_name
converted_kks_path = conversion_path / f"KKS2KK_{card_name}"
assert not filtered_kks_path.exists(), f"{filtered_kks_path} exists but should not."
assert not converted_kks_path.exists(), f"{converted_kks_path} exists but should not."
for kks_path in kks_cards:
card_name = kks_path.name
filtered_kks_path = filter_path / card_name
converted_kks_path = conversion_path / f"KKS2KK_{card_name}"
assert filtered_kks_path.exists(), f"{filtered_kks_path} does not exist."
assert converted_kks_path.exists(), f"{converted_kks_path} does not exist."
kk_cards.add(converted_kks_path)
def test_install(kk_cards, coordinates, zipmods):
"""Test character installation."""
install_chara = InstallChara(CONFIG, FILE_MANAGER)
install_chara.run()
chara_path = GAMEPATH / 'UserData' / 'chara' / 'female'
coordinates_path = GAMEPATH / 'UserData' / 'coordinate'
zipmods_path = GAMEPATH / 'mods'
for card in kk_cards:
assert (chara_path / card.name).exists(), f"{card.name} not found in installed cards."
for coordinate in coordinates:
assert (coordinates_path / coordinate.name).exists(), f"{coordinate.name} not found in installed coordinates."
for zipmod in zipmods:
assert (zipmods_path / zipmod.name).exists(), f"{zipmod.name} not found in mods."
def test_backup(kk_cards, coordinates, zipmods):
"""Test backup functionality."""
create_backup = CreateBackup(CONFIG, FILE_MANAGER)
create_backup.run()
koikatsu_backup = BACKUP_PATH / 'koikatsu_backup.7z'
assert koikatsu_backup.exists(), "Backup file does not exist."
outdir = BACKUP_PATH / 'outdir'
patoolib.extract_archive(str(koikatsu_backup), outdir=str(outdir))
for card in kk_cards:
assert (outdir / "UserData" / "chara" / "female" / card.name).exists(), f"{card.name} missing in chara backup."
for coordinate in coordinates:
assert (outdir / "UserData" / "coordinate" / coordinate.name).exists(), f"{coordinate.name} missing in coordinate backup."
for zipmod in zipmods:
assert (outdir / 'mods' / zipmod.name).exists(), f"{zipmod.name} missing in mods backup."
def test_remove():
"""Test character removal."""
remove_chara = RemoveChara(CONFIG, FILE_MANAGER)
remove_chara.run()
chara_path = GAMEPATH / 'UserData' / 'chara' / 'female'
coordinate_path = GAMEPATH / 'UserData' / 'coordinate'
zipmod_path = GAMEPATH / 'mods'
assert not list(chara_path.iterdir()), "Chara directory not empty after removal."
assert not list(coordinate_path.iterdir()), "Coordinate directory not empty after removal."
assert not list(zipmod_path.iterdir()), "Mods directory not empty after removal."
def main():
"""Main function to run all tests."""
kk_cards = download('https://db.bepis.moe/koikatsu?type=steam&orderby=popularity')
kks_cards = download('https://db.bepis.moe/koikatsu?type=sunshine&orderby=popularity')
coordinates = download('https://db.bepis.moe/kkclothing?orderby=popularity')
zipmods = create_zipmods()
if kk_cards and kks_cards:
test_fckss(kk_cards, kks_cards)
test_install(kk_cards, coordinates, zipmods)
test_backup(kk_cards, coordinates, zipmods)
test_remove()
shutil.rmtree(TEST_PATH)
else:
logger.error("No cards downloaded. Exiting.")
if __name__ == '__main__':
main()