0
0
mirror of https://github.com/HamletDuFromage/switch-cheats-db.git synced 2025-04-24 08:25:17 +00:00
switch-cheats-db/database_builder.py
2025-04-11 01:21:46 +02:00

199 lines
7.2 KiB
Python

#!/usr/bin/env python3
import rarfile
import zipfile
import cloudscraper
import json
import shutil
from pathlib import Path
from datetime import date, datetime
from bs4 import BeautifulSoup
import process_cheats
def version_parser(version):
year = int(version[4:8])
month = int(version[0:2])
day = int(version[2:4])
return date(year, month, day)
class DatabaseInfo:
def __init__(self):
self.scraper = cloudscraper.create_scraper()
self.database_version_url = "https://github.com/HamletDuFromage/switch-cheats-db/releases/latest/download/VERSION"
self.database_version = self.fetch_database_version()
def fetch_database_version(self):
version = self.scraper.get(self.database_version_url).text
return date.fromisoformat(version)
def get_database_version(self):
return self.database_version
class GbatempCheatsInfo:
def __init__(self):
self.scraper = cloudscraper.create_scraper()
self.page_url = "https://gbatemp.net/download/cheat-codes-sxos-and-ams-main-cheat-file-updated.36311/"
self.gbatemp_version = self.fetch_gbatemp_version()
def fetch_gbatemp_version(self):
page = self.scraper.get(f"{self.page_url}/updates")
soup = BeautifulSoup(page.content, "html.parser")
version = datetime.fromisoformat(soup.find("div", {"class": "block-container"}).find("time").get("datetime"))
return version.date()
def has_new_cheats(self, database_version):
return self.gbatemp_version > database_version
def get_gbatemp_version(self):
return self.gbatemp_version
def get_download_url(self):
return f"{self.page_url}/download"
class HighFPSCheatsInfo:
def __init__(self):
self.scraper = cloudscraper.create_scraper()
self.download_url = "https://github.com/ChanseyIsTheBest/NX-60FPS-RES-GFX-Cheats/archive/refs/heads/main.zip"
self.api_url = "https://api.github.com/repos/ChanseyIsTheBest/NX-60FPS-RES-GFX-Cheats/branches/main"
self.highfps_version = self.fetch_high_FPS_cheats_version()
def fetch_high_FPS_cheats_version(self):
repo_info = self.scraper.get(self.api_url).json()
last_commit_date = repo_info.get("commit").get("commit").get("author").get("date")
return date.fromisoformat(last_commit_date.split("T")[0])
def has_new_cheats(self, database_version):
return self.highfps_version > database_version
def get_high_FPS_version(self):
return self.highfps_version
def get_download_url(self):
return self.download_url
class ArchiveWorker():
def __init__(self):
self.scraper = cloudscraper.create_scraper()
def download_archive(self, url, path):
dl = self.scraper.get(url, allow_redirects=True)
open(path, "wb").write(dl.content)
def extract_archive(self, path, extract_path=None):
if rarfile.is_rarfile(path):
rf = rarfile.RarFile(path)
rf.extractall(path=extract_path)
elif zipfile.is_zipfile(path):
zf = zipfile.ZipFile(path)
zf.extractall(path=extract_path)
else:
return False
return True
def build_cheat_files(self, cheats_path, out_path):
cheats_path = Path(cheats_path)
titles_path = Path(out_path).joinpath("titles")
if not(titles_path.exists()):
titles_path.mkdir(parents=True)
for tid in cheats_path.iterdir():
tid_path = titles_path.joinpath(tid.stem)
tid_path.mkdir()
with open(tid, "r") as cheats_file:
cheats_dict = json.load(cheats_file)
for key, value in cheats_dict.items():
if key == "attribution":
for author, content in value.items():
with open(tid_path.joinpath(author), "w") as attribution_file:
attribution_file.write(content)
else:
cheats = ""
for _, content in value.items():
cheats += content
if cheats:
with open(tid_path.joinpath(f"{key}.txt"), "w") as bid_file:
bid_file.write(cheats)
def touch_all(self, path):
for path in path.rglob("*"):
if path.is_file():
path.touch()
def create_archives(self, out_path):
out_path = Path(out_path)
titles_path = out_path.joinpath("titles")
self.touch_all(titles_path)
shutil.make_archive(str(titles_path.resolve()), "zip", root_dir=out_path, base_dir="titles")
contents_path = titles_path.rename(titles_path.parent.joinpath("contents"))
self.touch_all(contents_path)
shutil.make_archive(str(contents_path.resolve()), "zip", root_dir=out_path, base_dir="contents")
def create_version_file(self, out_path="."):
with open(f"{out_path}/VERSION", "w") as version_file:
version_file.write(str(date.today()))
def count_cheats(cheats_directory):
n_games = 0
n_updates = 0
n_cheats = 0
for json_file in Path(cheats_directory).glob('*.json'):
with open(json_file, 'r') as file:
cheats = json.load(file)
for bid in cheats.values():
n_cheats += len(bid)
n_updates += 1
n_games += 1
readme_file = Path('README.md')
with readme_file.open('r') as file:
lines = file.readlines()
lines[-1] = f"{n_cheats} cheats in {n_games} titles/{n_updates} updates"
with readme_file.open('w') as file:
file.writelines(lines)
if __name__ == '__main__':
cheats_path = "cheats"
cheats_gba_path = "cheats_gbatemp"
cheats_gfx_path = "cheats_gfx"
archive_path = "titles.zip"
database = DatabaseInfo()
database_version = database.get_database_version()
highfps = HighFPSCheatsInfo()
gbatemp = GbatempCheatsInfo()
if gbatemp.has_new_cheats(database_version) or highfps.has_new_cheats(database_version):
#if True:
archive_worker = ArchiveWorker()
print(f"Downloading cheats")
archive_worker.download_archive(gbatemp.get_download_url(), archive_path)
archive_worker.extract_archive(archive_path, "gbatemp")
archive_worker.download_archive(highfps.get_download_url(), archive_path)
archive_worker.extract_archive(archive_path)
print("Processing the cheat sheets")
process_cheats.ProcessCheats("gbatemp/titles", cheats_gba_path)
process_cheats.ProcessCheats("NX-60FPS-RES-GFX-Cheats-main/titles", cheats_gfx_path)
process_cheats.ProcessCheats("gbatemp/titles", cheats_path) # this could be done more elegantly
process_cheats.ProcessCheats("NX-60FPS-RES-GFX-Cheats-main/titles", cheats_path)
print("building complete cheat sheets")
out_path = Path("complete")
out_path.mkdir()
archive_worker.build_cheat_files(cheats_path, out_path)
print("Creating the archives")
archive_worker.create_archives("complete")
archive_worker.create_archives("NX-60FPS-RES-GFX-Cheats-main")
archive_worker.create_archives("gbatemp")
archive_worker.create_version_file()
count_cheats(cheats_path)
else:
print("Everything is already up to date!")