1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
"""
Required columsn for a maps.db to be valid for Tachi
hash
title
artist
effector
level
diff_shortname
path
folderid -> Same chart different difficulties just need to have the same value
"""
import argparse
import requests
import json
import sqlite3
import os
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
}
NAUTICA_URL="https://ksm.dev/app/songs"
SCHEMA = """CREATE TABLE Charts (
internalId TEXT PRIMARY KEY,
hash TEXT NOT NULL,
title TEXT NOT NULL,
artist TEXT NOT NULL,
effector TEXT,
level INTEGER,
diff_shortname TEXT,
path TEXT NOT NULL,
folderid INTEGER
);
"""
DIFF_NAME_MAP = {
1 : "NOV",
2: "ADV",
3: "EXH",
4: "INF"
}
def create_maps_db_if_not_exists(filepath: str):
if os.path.exists(filepath):
print("[DB] Maps DB already exists, skipping creation")
return
print("[DB] Creating new maps.db file")
conn = sqlite3.connect(filepath)
cursor = conn.cursor()
cursor.execute(SCHEMA)
conn.commit()
conn.close()
def get_nautica_num_pages():
response = requests.get(NAUTICA_URL, headers=headers)
resp_obj = json.loads(response.text)
return int(resp_obj["meta"]["last_page"])
def get_next_available_folder_id(db_path: str):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("SELECT MAX(folderid) FROM Charts")
result = cursor.fetchone()
if result and result[0] is not None:
return result[0] + 1
else:
return 1
def chart_already_processed(db_path: str, internal_id: str):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("SELECT 1 FROM Charts WHERE internalId = ?", (internal_id,))
result = cursor.fetchone()
conn.close()
return result is not None
def download_and_generate_charts():
pass
def get_charts_from_page(page_num: int, db_path: str):
charts = []
response = requests.get(NAUTICA_URL + "?page="+str(page_num), headers=headers)
resp_page_obj = json.loads(response.text)
folder_id = get_next_available_folder_id(db_path)
for entry in resp_page_obj["data"]:
title = entry["title"]
artist = entry["artist"]
download_url = entry["cdn_download_url"]
for chart in entry["charts"]:
difficulty = int(chart["difficulty"])
level = chart["level"]
if chart_already_processed(chart["id"]):
print(f"[SKIP] {title} - {difficulty} already exists. Skipping...")
continue
effector = chart["effector"]
diff_shortname = DIFF_NAME_MAP[difficulty]
charts.append({
"internalId": chart["id"],
"title": title,
"artist": artist,
"effector": effector,
"level": level,
"diff_shortname": diff_shortname,
"path": "/charts/blahblah",
"folderid": folder_id
})
folder_id += 1
return charts
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="nautica_to_maps",
description="Converts ALL charts on Nautica (ksm.dev) to a USC maps.db file",
)
parser.add_argument("--db", help="Path to existing maps.db if none-specified this script will search in current working dir or create a new one")
args = parser.parse_args()
db_path = args.db
if not db_path:
db_path = "maps.db"
create_maps_db_if_not_exists(db_path)
print(get_charts_from_page(1, db_path))
|