mirror of
https://github.com/qwerfd2/Groove_Coaster_2_Server.git
synced 2025-12-22 03:30:18 +00:00
Update
This commit is contained in:
@@ -9,13 +9,13 @@ from api.database import player_database, accounts, results, devices, whitelists
|
|||||||
from api.misc import crc32_decimal
|
from api.misc import crc32_decimal
|
||||||
|
|
||||||
TABLE_MAP = {
|
TABLE_MAP = {
|
||||||
"accounts": (accounts, ["id", "username", "password_hash", "save_crc", "save_timestamp", "save_id", "coin_mp", "title", "avatar", "created_at", "updated_at"]),
|
"accounts": (accounts, ["id", "username", "password_hash", "save_crc", "save_timestamp", "save_id", "coin_mp", "title", "avatar", "mobile_delta", "arcade_delta", "total_delta", "created_at", "updated_at"]),
|
||||||
"results": (results, ["id", "device_id", "stts", "song_id", "mode", "avatar", "score", "high_score", "play_rslt", "item", "os", "os_ver", "ver", "created_at", "updated_at"]),
|
"results": (results, ["id", "device_id", "stts", "song_id", "mode", "avatar", "score", "high_score", "play_rslt", "item", "os", "os_ver", "ver", "created_at"]),
|
||||||
"devices": (devices, ["device_id", "user_id", "my_stage", "my_avatar", "item", "daily_day", "coin", "lvl", "title", "avatar", "mobile_sum", "arcade_sum", "total_sum", "created_at", "updated_at", "last_login_at"]),
|
"devices": (devices, ["device_id", "user_id", "my_stage", "my_avatar", "item", "daily_day", "coin", "lvl", "title", "avatar", "created_at", "updated_at", "last_login_at"]),
|
||||||
"whitelist": (whitelists, ["id", "device_id"]),
|
"whitelist": (whitelists, ["id", "device_id"]),
|
||||||
"blacklist": (blacklists, ["id", "ban_terms", "reason"]),
|
"blacklist": (blacklists, ["id", "ban_terms", "reason"]),
|
||||||
"batch_tokens": (batch_tokens, ["id", "batch_token", "expire_at", "uses_left", "auth_id", "created_at", "updated_at"]),
|
"batch_tokens": (batch_tokens, ["id", "batch_token", "expire_at", "uses_left", "auth_id", "created_at", "updated_at"]),
|
||||||
"binds": (binds, ["id", "user_id", "bind_account", "bind_code", "is_verified", "auth_token", "created_at", "updated_at"]),
|
"binds": (binds, ["id", "user_id", "bind_account", "bind_code", "is_verified", "auth_token", "bind_date"]),
|
||||||
"webs": (webs, ["id", "user_id", "permission", "web_token", "last_save_export", "created_at", "updated_at"]),
|
"webs": (webs, ["id", "user_id", "permission", "web_token", "last_save_export", "created_at", "updated_at"]),
|
||||||
"logs": (logs, ["id", "user_id", "filename", "filesize", "timestamp"]),
|
"logs": (logs, ["id", "user_id", "filename", "filesize", "timestamp"]),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,16 @@ async def batch_handler(request: Request):
|
|||||||
if result['expire_at'] < int(time.time()):
|
if result['expire_at'] < int(time.time()):
|
||||||
return HTMLResponse(content="Token expired", status_code=400)
|
return HTMLResponse(content="Token expired", status_code=400)
|
||||||
|
|
||||||
if result['uses_left'] <= 0:
|
uses_left = result['uses_left']
|
||||||
return HTMLResponse(content="No uses left for this token", status_code=400)
|
if uses_left > 0:
|
||||||
|
uses_left -= 1
|
||||||
|
|
||||||
|
else:
|
||||||
|
uses_left = -1
|
||||||
|
return HTMLResponse(content="No uses left", status_code=400)
|
||||||
|
|
||||||
update_query = batch_tokens.update().where(batch_tokens.c.token == token).values(
|
update_query = batch_tokens.update().where(batch_tokens.c.token == token).values(
|
||||||
uses_left=result['uses_left'] - 1,
|
uses_left=uses_left,
|
||||||
updated_at=datetime.utcnow()
|
updated_at=datetime.utcnow()
|
||||||
)
|
)
|
||||||
await player_database.execute(update_query)
|
await player_database.execute(update_query)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ async def serve_file(request: Request):
|
|||||||
if not filename.endswith(".zip") and not filename.endswith(".pak"):
|
if not filename.endswith(".zip") and not filename.endswith(".pak"):
|
||||||
return Response("Unauthorized", status_code=403)
|
return Response("Unauthorized", status_code=403)
|
||||||
|
|
||||||
existing_batch_token = select(batch_tokens).where(batch_tokens.c.batch_token == auth_token)
|
existing_batch_token = select(batch_tokens).where((batch_tokens.c.batch_token == auth_token) & (batch_tokens.c.uses_left > -1))
|
||||||
batch_result = await player_database.fetch_one(existing_batch_token)
|
batch_result = await player_database.fetch_one(existing_batch_token)
|
||||||
if batch_result:
|
if batch_result:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import secrets
|
|||||||
import bcrypt
|
import bcrypt
|
||||||
import hashlib
|
import hashlib
|
||||||
import re
|
import re
|
||||||
import aiofiles
|
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from config import MODEL, TUNEFILE, SKIN, AUTHORIZATION_NEEDED, AUTHORIZATION_MODE, GRANDFATHERED_ACCOUNT_LIMIT
|
from config import MODEL, TUNEFILE, SKIN, AUTHORIZATION_NEEDED, AUTHORIZATION_MODE, GRANDFATHERED_ACCOUNT_LIMIT, BIND_SALT
|
||||||
from api.database import get_bind, check_whitelist, check_blacklist, decrypt_fields_to_user_info, user_id_to_user_info_simple
|
from api.database import get_bind, check_whitelist, check_blacklist, decrypt_fields_to_user_info, user_id_to_user_info_simple
|
||||||
|
|
||||||
FMAX_VER = None
|
FMAX_VER = None
|
||||||
@@ -66,7 +65,6 @@ def verify_password(password, hashed_password):
|
|||||||
if type(hashed_password) == str:
|
if type(hashed_password) == str:
|
||||||
hashed_password = hashed_password.encode('utf-8')
|
hashed_password = hashed_password.encode('utf-8')
|
||||||
|
|
||||||
print("hashed_password:", hashed_password)
|
|
||||||
return bcrypt.checkpw(password.encode('utf-8'), hashed_password)
|
return bcrypt.checkpw(password.encode('utf-8'), hashed_password)
|
||||||
|
|
||||||
def is_alphanumeric(username):
|
def is_alphanumeric(username):
|
||||||
@@ -281,12 +279,11 @@ async def should_serve_web(user_id):
|
|||||||
return should_serve
|
return should_serve
|
||||||
|
|
||||||
async def generate_salt(user_id):
|
async def generate_salt(user_id):
|
||||||
SALT = "jHENR3wq$zX9@LpO"
|
|
||||||
user_info = await user_id_to_user_info_simple(user_id)
|
user_info = await user_id_to_user_info_simple(user_id)
|
||||||
user_pw_hash = user_info['password_hash']
|
user_pw_hash = user_info['password_hash']
|
||||||
username = user_info['username']
|
username = user_info['username']
|
||||||
|
|
||||||
combined = f"{username}{user_id}{user_pw_hash}{SALT}".encode('utf-8')
|
combined = f"{username}{user_id}{user_pw_hash}{BIND_SALT}".encode('utf-8')
|
||||||
crc32_hash = binascii.crc32(combined) & 0xFFFFFFFF
|
crc32_hash = binascii.crc32(combined) & 0xFFFFFFFF
|
||||||
return str(crc32_hash)
|
return str(crc32_hash)
|
||||||
|
|
||||||
|
|||||||
@@ -259,8 +259,6 @@ async def user_ranking_individual(request: Request):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print("toital_count: " + str(total_count))
|
|
||||||
|
|
||||||
return JSONResponse(payload)
|
return JSONResponse(payload)
|
||||||
|
|
||||||
async def user_ranking_total(request: Request):
|
async def user_ranking_total(request: Request):
|
||||||
@@ -316,7 +314,6 @@ async def user_ranking_total(request: Request):
|
|||||||
await write_rank_cache(cache_key, records, expire_seconds=120)
|
await write_rank_cache(cache_key, records, expire_seconds=120)
|
||||||
|
|
||||||
total_count = len(records)
|
total_count = len(records)
|
||||||
print("total_count fetched: " + str(total_count))
|
|
||||||
for index, record in enumerate(records):
|
for index, record in enumerate(records):
|
||||||
if index >= page_number * page_count and index < (page_number + 1) * page_count:
|
if index >= page_number * page_count and index < (page_number + 1) * page_count:
|
||||||
rank_user = await user_id_to_user_info_simple(record["id"])
|
rank_user = await user_id_to_user_info_simple(record["id"])
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ async def api_shop_player_data(request: Request):
|
|||||||
item_id for item_id in range(item_low_end, item_high_end)
|
item_id for item_id in range(item_low_end, item_high_end)
|
||||||
]
|
]
|
||||||
|
|
||||||
print(my_stage)
|
|
||||||
if 700 in my_stage and os.path.isfile('./files/4max_ver.txt'):
|
if 700 in my_stage and os.path.isfile('./files/4max_ver.txt'):
|
||||||
is_fmax_purchased = True
|
is_fmax_purchased = True
|
||||||
|
|
||||||
@@ -263,7 +262,6 @@ async def api_shop_purchase_item(request: Request):
|
|||||||
return JSONResponse({"state": 0, "message": "EXTRA already owned. Exit the shop and it will be added to the game."}, status_code=400)
|
return JSONResponse({"state": 0, "message": "EXTRA already owned. Exit the shop and it will be added to the game."}, status_code=400)
|
||||||
|
|
||||||
if price > device_info['coin']:
|
if price > device_info['coin']:
|
||||||
print("Insufficient coins for purchase.")
|
|
||||||
return JSONResponse({"state": 0, "message": "Insufficient coins."}, status_code=400)
|
return JSONResponse({"state": 0, "message": "Insufficient coins."}, status_code=400)
|
||||||
|
|
||||||
new_coin_amount = device_info['coin'] - price
|
new_coin_amount = device_info['coin'] - price
|
||||||
|
|||||||
@@ -113,8 +113,6 @@ async def start(request: Request):
|
|||||||
my_stage, my_avatar = await get_user_entitlement_from_devices(user_id)
|
my_stage, my_avatar = await get_user_entitlement_from_devices(user_id)
|
||||||
coin = device_info['coin'] if device_info is not None else 0
|
coin = device_info['coin'] if device_info is not None else 0
|
||||||
|
|
||||||
print("user has entitlements:", my_stage, my_avatar)
|
|
||||||
|
|
||||||
elif device_info:
|
elif device_info:
|
||||||
# This is a guest user with existing data
|
# This is a guest user with existing data
|
||||||
my_avatar = set(device_info['my_avatar']) if device_info['my_avatar'] else START_AVATARS
|
my_avatar = set(device_info['my_avatar']) if device_info['my_avatar'] else START_AVATARS
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ SMTP_PASSWORD = "test"
|
|||||||
# For auth mode 2
|
# For auth mode 2
|
||||||
DISCORD_BOT_SECRET = "test"
|
DISCORD_BOT_SECRET = "test"
|
||||||
DISCORD_BOT_API_KEY = "test"
|
DISCORD_BOT_API_KEY = "test"
|
||||||
|
BIND_SALT = "SET YOUR SALT HERE"
|
||||||
|
|
||||||
# Daily download limit per account in bytes (only activates for AUTHORIZATION_MODE 1 and 2)
|
# Daily download limit per account in bytes (only activates for AUTHORIZATION_MODE 1 and 2)
|
||||||
|
|
||||||
|
|||||||
@@ -73,9 +73,9 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="mainNavbar">
|
<div class="collapse navbar-collapse" id="mainNavbar">
|
||||||
<ul class="navbar-nav ms-4">
|
<ul class="navbar-nav ms-4">
|
||||||
<li class="nav-item"><a class="nav-link" href="#" id="usersTab">Users</a></li>
|
<li class="nav-item"><a class="nav-link" href="#" id="accountsTab">Accounts</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#" id="resultsTab">Results</a></li>
|
<li class="nav-item"><a class="nav-link" href="#" id="resultsTab">Results</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#" id="dailyRewardsTab">DailyRewards</a></li>
|
<li class="nav-item"><a class="nav-link" href="#" id="devicesTab">Devices</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#" id="whitelistTab">Whitelist</a></li>
|
<li class="nav-item"><a class="nav-link" href="#" id="whitelistTab">Whitelist</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#" id="blacklistTab">Blacklist</a></li>
|
<li class="nav-item"><a class="nav-link" href="#" id="blacklistTab">Blacklist</a></li>
|
||||||
<li class="nav-item"><a class="nav-link" href="#" id="batchTokensTab">BatchTokens</a></li>
|
<li class="nav-item"><a class="nav-link" href="#" id="batchTokensTab">BatchTokens</a></li>
|
||||||
@@ -196,7 +196,7 @@ function showTable(tabName) {
|
|||||||
responsiveLayout: "collapse",
|
responsiveLayout: "collapse",
|
||||||
sortMode: "remote",
|
sortMode: "remote",
|
||||||
autoColumnsDefinitions: function(definitions){
|
autoColumnsDefinitions: function(definitions){
|
||||||
if (tabName === "users") {
|
if (tabName === "accounts") {
|
||||||
definitions.push({
|
definitions.push({
|
||||||
title: "data",
|
title: "data",
|
||||||
field: "__data",
|
field: "__data",
|
||||||
@@ -281,7 +281,7 @@ function showTable(tabName) {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
if (col.field !== "id" && col.field !== "objectId" && col.field !== "__delete" && col.field !== "__data") {
|
if (col.field !== "id" && col.field !== "__delete" && col.field !== "__data") {
|
||||||
col.editor = function(cell, onRendered, success, cancel){
|
col.editor = function(cell, onRendered, success, cancel){
|
||||||
const value = cell.getValue();
|
const value = cell.getValue();
|
||||||
let input;
|
let input;
|
||||||
@@ -473,13 +473,13 @@ document.getElementById('dataModalSaveBtn').onclick = async function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementById('usersTab').onclick = () => showTable("users");
|
document.getElementById('accountsTab').onclick = () => showTable("accounts");
|
||||||
document.getElementById('resultsTab').onclick = () => showTable("results");
|
document.getElementById('resultsTab').onclick = () => showTable("results");
|
||||||
document.getElementById('dailyRewardsTab').onclick = () => showTable("daily_rewards");
|
document.getElementById('devicesTab').onclick = () => showTable("devices");
|
||||||
document.getElementById('whitelistTab').onclick = () => showTable("whitelist");
|
document.getElementById('whitelistTab').onclick = () => showTable("whitelist");
|
||||||
document.getElementById('blacklistTab').onclick = () => showTable("blacklist");
|
document.getElementById('blacklistTab').onclick = () => showTable("blacklist");
|
||||||
document.getElementById('batchTokensTab').onclick = () => showTable("batch_tokens");
|
document.getElementById('batchTokensTab').onclick = () => showTable("batch_tokens");
|
||||||
document.getElementById('bindTab').onclick = () => showTable("bind");
|
document.getElementById('bindTab').onclick = () => showTable("binds");
|
||||||
document.getElementById('logsTab').onclick = () => showTable("logs");
|
document.getElementById('logsTab').onclick = () => showTable("logs");
|
||||||
|
|
||||||
document.getElementById('logoutBtn').addEventListener('click', function() {
|
document.getElementById('logoutBtn').addEventListener('click', function() {
|
||||||
@@ -570,12 +570,12 @@ document.getElementById('insertRowForm').onsubmit = async function(e) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const validTabs = ["users", "results", "daily_rewards", "whitelist", "blacklist", "batch_tokens", "bind", "logs"];
|
const validTabs = ["accounts", "results", "devices", "whitelist", "blacklist", "batch_tokens", "binds", "logs"];
|
||||||
const lastTab = getCookie("lastTab");
|
const lastTab = getCookie("lastTab");
|
||||||
if (validTabs.includes(lastTab)) {
|
if (validTabs.includes(lastTab)) {
|
||||||
showTable(lastTab);
|
showTable(lastTab);
|
||||||
} else {
|
} else {
|
||||||
showTable("users");
|
showTable("accounts");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCookie(name) {
|
function getCookie(name) {
|
||||||
|
|||||||
@@ -161,8 +161,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", fetchUserData);
|
document.addEventListener("DOMContentLoaded", fetchUserData);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user