Implement needed handlers to get to the initial download

`/api/start`
`/api/dummy/login`
`/apt/user`
`/api/purchase`
This commit is contained in:
Ethan O'Brien 2024-02-23 13:28:44 -06:00
parent f48ae94c0e
commit 9ce5f9bd42
12 changed files with 740 additions and 1 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
asset_server/node_modules/
asset_server/resources/
target/
*.db

136
Cargo.lock generated
View file

@ -254,6 +254,27 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "allocator-api2"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -359,6 +380,20 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.0",
]
[[package]]
name = "convert_case"
version = "0.4.0"
@ -483,12 +518,28 @@ version = "0.0.1"
dependencies = [
"actix-web",
"base64",
"chrono",
"hex",
"json",
"lazy_static",
"openssl",
"rand",
"reqwest",
"rusqlite",
]
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
version = "2.0.1"
@ -634,6 +685,19 @@ name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "hashlink"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
dependencies = [
"hashbrown",
]
[[package]]
name = "hermit-abi"
@ -641,6 +705,12 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "http"
version = "0.2.11"
@ -712,6 +782,29 @@ dependencies = [
"tokio-native-tls",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "idna"
version = "0.5.0"
@ -783,6 +876,17 @@ version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libsqlite3-sys"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
@ -879,6 +983,15 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
@ -1139,6 +1252,20 @@ dependencies = [
"winreg",
]
[[package]]
name = "rusqlite"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d"
dependencies = [
"bitflags 2.4.2",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"smallvec",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@ -1648,6 +1775,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.0",
]
[[package]]
name = "windows-sys"
version = "0.48.0"

View file

@ -5,8 +5,12 @@ edition = "2021"
[dependencies]
actix-web = { version = "4.5.1", features = [ "openssl" ] }
rusqlite = { version = "0.30.0", features = ["bundled"] }
openssl = { version = "0.10" }
base64 = "0.21.5"
reqwest = { version = "0.11", features = ["blocking"] }
json = "0.12.4"
rand = "0.8.5"
lazy_static = "1.4.0"
chrono = "0.4.31"
hex = "0.4.3"

View file

@ -2,15 +2,28 @@ mod encryption;
mod router;
use actix_web::{
post,
get,
HttpResponse,
HttpRequest,
web,
dev::Service
};
#[post("/api/start")]
async fn start_start(req: HttpRequest, body: String) -> HttpResponse { router::start::start(req, body) }
#[post("/api/start/assetHash")]
async fn start_assethash(req: HttpRequest, body: String) -> HttpResponse { router::start::asset_hash(req, body) }
#[post("/api/dummy/login")]
async fn dummy_login(req: HttpRequest, body: String) -> HttpResponse { router::login::dummy(req, body) }
#[get("/api/user")]
async fn user(req: HttpRequest) -> HttpResponse { router::user::user(req) }
#[get("/api/purchase")]
async fn purchase(req: HttpRequest) -> HttpResponse { router::purchase::purchase(req) }
async fn log_unknown_request(req: HttpRequest) -> HttpResponse {
println!("Unhandled request: {}", req.path());
HttpResponse::Ok().body("ok")
@ -25,7 +38,11 @@ async fn main() -> std::io::Result<()> {
println!("Request: {}", req.path());
srv.call(req)
})
.service(purchase)
.service(start_start)
.service(start_assethash)
.service(user)
.service(dummy_login)
.default_service(web::route().to(log_unknown_request)))
.bind(("0.0.0.0", 8080))?
.run();

View file

@ -1,2 +1,6 @@
pub mod start;
pub mod global;
pub mod login;
pub mod userdata;
pub mod user;
pub mod purchase;

View file

@ -17,6 +17,7 @@ pub fn timestamp() -> u64 {
}
pub fn send(data: JsonValue) -> HttpResponse {
//println!("{}", json::stringify(data.clone()));
let encrypted = encryption::encrypt_packet(&json::stringify(data)).unwrap();
let resp = encrypted.into_bytes();

24
src/router/login.rs Normal file
View file

@ -0,0 +1,24 @@
use json;
use json::object;
use crate::router::global;
//use crate::encryption;
use actix_web::{HttpResponse, HttpRequest, http::header::HeaderValue};
use crate::router::userdata;
//First time login handler
pub fn dummy(req: HttpRequest, _body: String) -> HttpResponse {
//let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
let blank_header = HeaderValue::from_static("");
let key = req.headers().get("a6573cbe").unwrap_or(&blank_header).to_str().unwrap_or("");
let user = userdata::get_acc(key, "");
println!("new uid: {}", user["user"]["id"].clone());
let resp = object!{
"code": 0,
"server_time": global::timestamp(),
"data": {
"user_id": user["user"]["id"].clone()
}
};
global::send(resp)
}

277
src/router/purchase.rs Normal file
View file

@ -0,0 +1,277 @@
use json;
use json::object;
use crate::router::global;
use actix_web::{HttpResponse, HttpRequest};
pub fn purchase(_req: HttpRequest) -> HttpResponse {
let resp = object!{
"code": 0,
"server_time": global::timestamp(),
"data": {
"product_list": [//Client will error if this is an empty array
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.promo.4199",
"name": "6000 Love Gems",
"description": "6000 Paid Love Gems",
"thumbnail_url": null,
"charge_gem": 6000,
"free_gem": 0,
"campaign_type": 2,
"campaign_mode": 5,
"priority": 1,
"price": "999999.99",
"currency_code": "USD",
"formatted_price": "USD$999999.99",
"consumable": 0,
"limited_count": 2,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": "2024-02-01 00:00:00",
"end_datetime": "2024-02-29 23:59:59",
"total_gem": 6000
}
]
}
};
global::send(resp)
}
/*
resp.data = {
"product_list": [
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.promo.4199",
"name": "6000 Love Gems",
"description": "6000 Paid Love Gems",
"thumbnail_url": null,
"charge_gem": 6000,
"free_gem": 0,
"campaign_type": 2,
"campaign_mode": 5,
"priority": 1,
"price": "34.99",
"currency_code": "USD",
"formatted_price": "USD$34.99",
"consumable": 0,
"limited_count": 2,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": "2024-02-01 00:00:00",
"end_datetime": "2024-02-29 23:59:59",
"total_gem": 6000
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.promo.8499",
"name": "13000 Love Gems",
"description": "13000 Paid Love Gems",
"thumbnail_url": null,
"charge_gem": 13000,
"free_gem": 0,
"campaign_type": 2,
"campaign_mode": 5,
"priority": 2,
"price": "69.99",
"currency_code": "USD",
"formatted_price": "USD$69.99",
"consumable": 0,
"limited_count": 2,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": "2024-02-01 00:00:00",
"end_datetime": "2024-02-29 23:59:59",
"total_gem": 13000
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.299",
"name": "140 Love Gems",
"description": "140 Paid Love Gems",
"thumbnail_url": null,
"charge_gem": 140,
"free_gem": 0,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 11,
"price": "0.99",
"currency_code": "USD",
"formatted_price": "USD$0.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 140
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.499",
"name": "430 Love Gems",
"description": "420 Paid Love Gems + 10 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 420,
"free_gem": 10,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 12,
"price": "2.99",
"currency_code": "USD",
"formatted_price": "USD$2.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 430
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.899",
"name": "910 Love Gems",
"description": "870 Paid Love Gems + 40 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 870,
"free_gem": 40,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 13,
"price": "6.99",
"currency_code": "USD",
"formatted_price": "USD$6.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 910
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.1299",
"name": "1380 Love Gems",
"description": "1310 Paid Love Gems + 70 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 1310,
"free_gem": 70,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 14,
"price": "9.99",
"currency_code": "USD",
"formatted_price": "USD$9.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 1380
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.2499",
"name": "2700 Love Gems",
"description": "2530 Paid Love Gems + 170 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 2530,
"free_gem": 170,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 15,
"price": "19.99",
"currency_code": "USD",
"formatted_price": "USD$19.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 2700
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.4199",
"name": "4800 Love Gems",
"description": "4460 Paid Love Gems + 340 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 4460,
"free_gem": 340,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 16,
"price": "34.99",
"currency_code": "USD",
"formatted_price": "USD$34.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 4800
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.6499",
"name": "7500 Love Gems",
"description": "6730 Paid Love Gems + 770 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 6730,
"free_gem": 770,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 17,
"price": "49.99",
"currency_code": "USD",
"formatted_price": "USD$49.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 7500
},
{
"product_id": "com.bushiroad.global.lovelive.sif2.google.gem.8499",
"name": "10100 Love Gems",
"description": "8910 Paid Love Gems + 1190 Free LoveGems",
"thumbnail_url": null,
"charge_gem": 8910,
"free_gem": 1190,
"campaign_type": 0,
"campaign_mode": 0,
"priority": 18,
"price": "69.99",
"currency_code": "USD",
"formatted_price": "USD$69.99",
"consumable": 1,
"limited_count": 0,
"product_type": 0,
"amenity_label": null,
"ticket_valid_days": null,
"ticket_issuing_gem": null,
"start_datetime": null,
"end_datetime": null,
"total_gem": 10100
}
]
}
*/

View file

@ -2,7 +2,8 @@ use json;
use json::object;
use crate::router::global;
use crate::encryption;
use actix_web::{HttpResponse, HttpRequest};
use actix_web::{HttpResponse, HttpRequest, http::header::HeaderValue};
use crate::router::userdata;
pub fn asset_hash(_req: HttpRequest, body: String) -> HttpResponse {
let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
@ -18,3 +19,29 @@ pub fn asset_hash(_req: HttpRequest, body: String) -> HttpResponse {
};
global::send(resp)
}
pub fn start(req: HttpRequest, body: String) -> HttpResponse {
let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
if body["asset_version"].to_string() != global::ASSET_VERSION {
println!("Warning! Asset version is not what was expected. (Did the app update?)");
}
let blank_header = HeaderValue::from_static("");
let key = req.headers().get("a6573cbe").unwrap_or(&blank_header).to_str().unwrap_or("");
let uid = req.headers().get("aoharu-user-id").unwrap_or(&blank_header).to_str().unwrap_or("");
let mut user = userdata::get_acc(key, uid);
user["user"]["last_login_time"] = global::timestamp().into();
user["stamina"]["last_updated_time"] = global::timestamp().into();
userdata::save_acc(key, uid, user);
let resp = object!{
"code": 0,
"server_time": global::timestamp(),
"data": {
"asset_hash": global::ASSET_HASH,
"token": hex::encode("Hello") //what is this?
}
};
global::send(resp)
}

20
src/router/user.rs Normal file
View file

@ -0,0 +1,20 @@
use json;
use json::object;
use crate::router::global;
use actix_web::{HttpResponse, HttpRequest, http::header::HeaderValue};
use crate::router::userdata;
pub fn user(req: HttpRequest) -> HttpResponse {
let blank_header = HeaderValue::from_static("");
let key = req.headers().get("a6573cbe").unwrap_or(&blank_header).to_str().unwrap_or("");
let uid = req.headers().get("aoharu-user-id").unwrap_or(&blank_header).to_str().unwrap_or("");
let user = userdata::get_acc(key, uid);
let resp = object!{
"code": 0,
"server_time": global::timestamp(),
"data": user
};
global::send(resp)
}

167
src/router/userdata/mod.rs Normal file
View file

@ -0,0 +1,167 @@
use rusqlite::{Connection, params};
use std::sync::{Mutex, MutexGuard};
use lazy_static::lazy_static;
use json::{JsonValue, array};
//use base64::{Engine as _, engine::general_purpose};
lazy_static! {
pub static ref ENGINE: Mutex<Option<Connection>> = Mutex::new(None);
}
fn init(engine: &mut MutexGuard<'_, Option<Connection>>) {
let conn = Connection::open("userdata.db").unwrap();
conn.execute("PRAGMA foreign_keys = ON;", ()).unwrap();
engine.replace(conn);
}
fn create_uid_store(conn: &Connection) {
match conn.prepare("SELECT jsondata FROM uids") {
Ok(_) => {}
Err(_) => {
conn.execute(
"CREATE TABLE uids (
jsondata TEXT NOT NULL
)",
(), // empty list of parameters.
).unwrap();
init_data(conn, "uids", array![]);
}
}
store_data(conn, "uids", array![]);
}
fn acc_exists(conn: &Connection, key: i64) -> bool {
conn.prepare(&format!("SELECT jsondata FROM _{}_", key)).is_ok()
}
fn store_data(conn: &Connection, key: &str, value: JsonValue) {
conn.execute(
&format!("UPDATE {} SET jsondata=?1", key),
params!(json::stringify(value))
).unwrap();
}
fn init_data(conn: &Connection, key: &str, value: JsonValue) {
conn.execute(
&format!("INSERT INTO {} (jsondata) VALUES (?1)", key),
params!(json::stringify(value))
).unwrap();
}
use rand::Rng;
fn get_uids(conn: &Connection) -> JsonValue {
let mut stmt = conn.prepare("SELECT jsondata FROM uids").unwrap();
let result: Result<String, rusqlite::Error> = stmt.query_row([], |row| row.get(0));
json::parse(&result.unwrap()).unwrap()
}
fn generate_uid(conn: &Connection) -> i64 {
create_uid_store(conn);
let mut rng = rand::thread_rng();
let random_number = rng.gen_range(100_000_000_000_000..=999_999_999_999_999);
let mut existing_ids = get_uids(conn);
//the chances of this...?
if existing_ids.contains(random_number) {
return generate_uid(conn);
}
existing_ids.push(random_number).unwrap();
store_data(conn, "uids", existing_ids);
random_number
}
fn create_acc(conn: &Connection, uid: i64) {
let key = &uid.to_string();
conn.execute(
&format!("CREATE TABLE _{}_ (
jsondata TEXT NOT NULL
)", key),
(),
).unwrap();
let mut data = json::parse(include_str!("new_user.json")).unwrap();
data["user"]["id"] = uid.into();
init_data(conn, &format!("_{}_", key), data);
}
//a6573cbe is the name of the header - todo - more secure than just uid
pub fn get_acc(_a6573cbe: &str, uid: &str) -> JsonValue {
//let decoded = general_purpose::STANDARD.decode(a6573cbe).unwrap();
//let header = String::from_utf8_lossy(&decoded);
loop {
match ENGINE.lock() {
Ok(mut result) => {
if result.is_none() {
init(&mut result);
}
let conn = result.as_ref().unwrap();
let key: i64;
/*
if header.starts_with("0") {
key = generate_uid(conn);
create_acc(conn, key);
} else {
key = header[..15].parse::<i64>().unwrap();//.unwrap_or(generate_uid(conn));
}*/
if uid == "" {
key = generate_uid(conn);
create_acc(conn, key);
} else {
key = uid.parse::<i64>().unwrap();
}
if !acc_exists(conn, key) {
create_acc(conn, key);
}
let mut stmt = conn.prepare(&format!("SELECT jsondata FROM _{}_", key)).unwrap();
let result: Result<String, rusqlite::Error> = stmt.query_row([], |row| row.get(0));
let rv = json::parse(&result.unwrap()).unwrap();
return rv;
}
Err(_) => {
std::thread::sleep(std::time::Duration::from_millis(15));
}
}
}
}
pub fn save_acc(_a6573cbe: &str, uid: &str, data: JsonValue) {
//let decoded = general_purpose::STANDARD.decode(a6573cbe).unwrap();
//let header = String::from_utf8_lossy(&decoded);
loop {
match ENGINE.lock() {
Ok(mut result) => {
if result.is_none() {
init(&mut result);
}
let conn = result.as_ref().unwrap();
let key: i64;
/*
if header.starts_with("0") {
key = generate_uid(conn);
create_acc(conn, key);
} else {
key = header[..15].parse::<i64>().unwrap();//.unwrap_or(generate_uid(conn));
}*/
if uid == "" {
key = generate_uid(conn);
create_acc(conn, key);
} else {
key = uid.parse::<i64>().unwrap();
}
if !acc_exists(conn, key) {
create_acc(conn, key);
}
store_data(conn, &format!("_{}_", key), data);
break;
}
Err(_) => {
std::thread::sleep(std::time::Duration::from_millis(15));
}
}
}
}

View file

@ -0,0 +1,61 @@
{
"user": {
"id": 0,
"name": "Tutorial in progress",
"comment": "Lean and Play!",
"exp": 0,
"main_deck_slot": 1,
"favorite_master_card_id": 0,
"favorite_card_evolve": 0,
"guest_smile_master_card_id": 0,
"guest_cool_master_card_id": 0,
"guest_pure_master_card_id": 0,
"friend_request_disabled" :1,
"master_title_ids": [0,0],
"profile_settings": [1,2,3,4,5,6,7],
"sif_user_id": 0,
"ss_user_id": 0,
"birthday": "",
"last_login_time": 0
},
"gem": {
"total": 0,
"charge": 0,
"free": 0
},
"card_list": [],
"deck_list": [
{"slot": 1,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 2,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 3,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 4,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 5,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 6,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 7,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 8,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 9,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 10,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]},
{"slot": 100,"leader_role": 0,"main_card_ids": [0,0,0,0,0,0,0,0,0]}
],
"stamina": {
"stamina": 100,
"last_updated_time": 0
},
"character_list": [],
"tutorial_step": 0,
"item_list": [],
"point_list": [],
"story_list": [],
"live_list": [],
"live_mission_list": [],
"master_music_ids": [1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1014,1015,1016,1017,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1035,1037,1038,1039,1040,1041,1042,1044,1045,1046,1047,1048,1049,1050,1054,1055,1057,1058,1059,1060,1061,1062,1063,1064,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1123,1124,1126,1127,1128,1129,1130,1131,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3121,3122,3123,3124,3125,3126,3127,3128,3129,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4059,4060,4061,4064,4065,4066,4067,4068,4069,4071,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4110,4111,4112,4113,4114,4115,4116,5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,9001,9002,9003,9004,9005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032],
"event_point_list": [],
"start_time": null,
"master_title_ids": [],
"lottery_list": [],
"shop_list": [],
"function_lock_list": [],
"movie": null,
"subscription_list": [],
"membership": []
}