mirror of
https://git.ethanthesleepy.one/ethanaobrien/ew
synced 2025-11-26 19:25:44 +08:00
Compare commits
12 Commits
v1.0.0
...
3343d4fdd6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3343d4fdd6 | ||
|
|
6b34316bad | ||
|
|
9686f3a6ef | ||
|
|
1172b4bd11 | ||
|
|
8da6938fb3 | ||
|
|
76c870547c | ||
|
|
038a651202 | ||
|
|
4aa00fd3d8 | ||
|
|
222021382f | ||
|
|
1a736155e3 | ||
|
|
e27a020cfb | ||
|
|
b082def65c |
1674
Cargo.lock
generated
1674
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
32
Cargo.toml
32
Cargo.toml
@@ -1,30 +1,30 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ew"
|
name = "ew"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "4.9.0" }
|
actix-web = "4.12"
|
||||||
rusqlite = { version = "0.32.1", features = ["bundled"] }
|
rusqlite = { version = "0.37.0", features = ["bundled"] }
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
clap = { version = "4.5.37", features = ["derive"]}
|
||||||
reqwest = { version = "0.12", features = ["blocking"] }
|
|
||||||
clap = { version = "4.5.21", features = ["derive"]}
|
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
json = "0.12.4"
|
json = "0.12.4"
|
||||||
rand = "0.8.5"
|
rand = "0.9.2"
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.42"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
md5 = "0.7.0"
|
md5 = "0.8.0"
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
sha1 = "0.10.6"
|
sha1 = "0.10.6"
|
||||||
substring = "1.4.5"
|
substring = "1.4.5"
|
||||||
uuid = { version = "1.11.0", features = ["v7"] }
|
uuid = { version = "1.18.1", features = ["v7"] }
|
||||||
rsa = "0.9.6"
|
rsa = { version = "0.9.9", features = ["sha1"] }
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.9"
|
||||||
include-flate-codegen = "0.3.0"
|
include-flate-codegen = "0.3.1"
|
||||||
libflate = "2.1.0"
|
libflate = "2.2.1"
|
||||||
serde_json = "1.0.133"
|
cbc = { version = "0.1.2", features = ["alloc"] }
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
aes = "0.8.4"
|
||||||
|
pem = "3.0.6"
|
||||||
|
ureq = "3.1.4"
|
||||||
|
|||||||
@@ -1,53 +1,44 @@
|
|||||||
use openssl::symm::{Cipher, Crypter, Mode};
|
|
||||||
use openssl::error::ErrorStack;
|
|
||||||
use base64::{Engine as _, engine::general_purpose};
|
use base64::{Engine as _, engine::general_purpose};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use aes::cipher::BlockEncryptMut;
|
||||||
|
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit};
|
||||||
|
|
||||||
|
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
||||||
|
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
||||||
|
|
||||||
const IV_LENGTH: usize = 16;
|
const IV_LENGTH: usize = 16;
|
||||||
const KEY: &str = "3559b435f24b297a79c68b9709ef2125";
|
const KEY: &str = "3559b435f24b297a79c68b9709ef2125";
|
||||||
|
|
||||||
pub fn decrypt_packet(base64_input: &str) -> Result<String, ErrorStack> {
|
pub fn decrypt_packet(base64_input: &str) -> Result<String, String> {
|
||||||
if base64_input.len() < IV_LENGTH + 1 {
|
if base64_input.len() < IV_LENGTH + 1 {
|
||||||
return Ok(String::new());
|
return Ok(String::new());
|
||||||
}
|
}
|
||||||
let base64_buffer = general_purpose::STANDARD.decode(base64_input).unwrap();
|
let base64_buffer = general_purpose::STANDARD.decode(base64_input).unwrap();
|
||||||
|
|
||||||
let decryption_iv = &base64_buffer[..IV_LENGTH];
|
let decryption_iv = &base64_buffer[..IV_LENGTH];
|
||||||
let ciphertext = &base64_buffer[IV_LENGTH..];
|
let mut ciphertext = base64_buffer[IV_LENGTH..].to_vec();
|
||||||
|
|
||||||
let cipher = Cipher::aes_256_cbc();
|
let decrypted_data = Aes256CbcDec::new(KEY.as_bytes().into(), decryption_iv.into())
|
||||||
let mut decrypter = Crypter::new(cipher, Mode::Decrypt, KEY.as_bytes(), Some(decryption_iv))?;
|
.decrypt_padded_mut::<Pkcs7>(&mut ciphertext).ok()
|
||||||
|
.ok_or(String::from("uhoh"))?;
|
||||||
|
|
||||||
let mut decrypted_data = vec![0u8; ciphertext.len() + cipher.block_size()];
|
Ok(String::from_utf8(decrypted_data.to_vec()).unwrap())
|
||||||
let mut decrypted_len = decrypter.update(ciphertext, &mut decrypted_data)?;
|
|
||||||
decrypted_len += decrypter.finalize(&mut decrypted_data[decrypted_len..])?;
|
|
||||||
|
|
||||||
decrypted_data.truncate(decrypted_len);
|
|
||||||
|
|
||||||
Ok(String::from_utf8(decrypted_data).unwrap())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt_packet(input: &str) -> Result<String, ErrorStack> {
|
pub fn encrypt_packet(input: &str) -> Result<String, String> {
|
||||||
let cipher = Cipher::aes_256_cbc();
|
|
||||||
let encryption_iv = generate_random_iv();
|
let encryption_iv = generate_random_iv();
|
||||||
|
|
||||||
let mut encrypter = Crypter::new(cipher, Mode::Encrypt, KEY.as_bytes(), Some(&encryption_iv))?;
|
let encrypted = Aes256CbcEnc::new(KEY.as_bytes().into(), encryption_iv.as_slice().into())
|
||||||
|
.encrypt_padded_vec_mut::<Pkcs7>(input.as_bytes());
|
||||||
|
|
||||||
let mut encrypted_data = vec![0u8; input.len() + cipher.block_size()];
|
|
||||||
let mut encrypted_len = encrypter.update(input.as_bytes(), &mut encrypted_data)?;
|
|
||||||
|
|
||||||
encrypted_len += encrypter.finalize(&mut encrypted_data[encrypted_len..])?;
|
|
||||||
|
|
||||||
encrypted_data.truncate(encrypted_len);
|
|
||||||
|
|
||||||
let mut result = encryption_iv.to_vec();
|
let mut result = encryption_iv.to_vec();
|
||||||
result.extend_from_slice(&encrypted_data);
|
result.extend_from_slice(&encrypted);
|
||||||
|
|
||||||
Ok(general_purpose::STANDARD.encode(&result))
|
Ok(general_purpose::STANDARD.encode(&result))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_random_iv() -> Vec<u8> {
|
fn generate_random_iv() -> Vec<u8> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let mut bytes = vec![0u8; IV_LENGTH];
|
let mut bytes = vec![0u8; IV_LENGTH];
|
||||||
rng.fill(&mut bytes[..]);
|
rng.fill(&mut bytes[..]);
|
||||||
bytes
|
bytes
|
||||||
|
|||||||
23
src/main.rs
23
src/main.rs
@@ -31,6 +31,26 @@ async fn js(_req: HttpRequest) -> HttpResponse {
|
|||||||
.insert_header(ContentType(mime::APPLICATION_JAVASCRIPT_UTF_8))
|
.insert_header(ContentType(mime::APPLICATION_JAVASCRIPT_UTF_8))
|
||||||
.body(include_file!("webui/dist/index.js"))
|
.body(include_file!("webui/dist/index.js"))
|
||||||
}
|
}
|
||||||
|
#[get("/maintenance/maintenance.json")]
|
||||||
|
async fn maintenance(_req: HttpRequest) -> HttpResponse {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.insert_header(ContentType(mime::APPLICATION_JSON))
|
||||||
|
.body(r#"{"opened_at":"2024-02-05 02:00:00","closed_at":"2024-02-05 04:00:00","message":":(","server":1,"gamelib":0}"#)
|
||||||
|
}
|
||||||
|
fn handle_assets(req: HttpRequest) -> HttpResponse {
|
||||||
|
HttpResponse::SeeOther()
|
||||||
|
.insert_header(("location", format!("https://sif2.sif.moe{}", req.path())))
|
||||||
|
.body("")
|
||||||
|
}
|
||||||
|
#[get("/Android/{hash}/{file}")]
|
||||||
|
async fn files_jp(req: HttpRequest) -> HttpResponse {
|
||||||
|
handle_assets(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/Android/{lang}/{hash}/{file}")]
|
||||||
|
async fn files_gl(req: HttpRequest) -> HttpResponse {
|
||||||
|
handle_assets(req)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
@@ -110,7 +130,10 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> {
|
|||||||
})
|
})
|
||||||
.app_data(web::PayloadConfig::default().limit(1024 * 1024 * 25))
|
.app_data(web::PayloadConfig::default().limit(1024 * 1024 * 25))
|
||||||
.service(css)
|
.service(css)
|
||||||
|
.service(maintenance)
|
||||||
.service(js)
|
.service(js)
|
||||||
|
.service(files_jp)
|
||||||
|
.service(files_gl)
|
||||||
.default_service(web::route().to(router::request))
|
.default_service(web::route().to(router::request))
|
||||||
).bind(("0.0.0.0", port))?.run();
|
).bind(("0.0.0.0", port))?.run();
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ fn save_event_data(key: &str, event_id: u32, data: JsonValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_random_song() -> JsonValue {
|
fn get_random_song() -> JsonValue {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let random_number = rng.gen_range(0..=databases::LIVES.len());
|
let random_number = rng.random_range(0..=databases::LIVES.len());
|
||||||
object!{
|
object!{
|
||||||
song: databases::LIVES[random_number]["masterMusicId"].clone(),
|
song: databases::LIVES[random_number]["masterMusicId"].clone(),
|
||||||
score: (databases::LIVES[random_number]["scoreC"].as_f64().unwrap() * 1.75).round() as i64
|
score: (databases::LIVES[random_number]["scoreC"].as_f64().unwrap() * 1.75).round() as i64
|
||||||
@@ -101,16 +101,17 @@ pub fn event(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
let key = global::get_login(req.headers(), &body);
|
let key = global::get_login(req.headers(), &body);
|
||||||
|
|
||||||
let body = &encryption::decrypt_packet(&body).unwrap();
|
let body = &encryption::decrypt_packet(&body).unwrap();
|
||||||
let body: EventGet = serde_json::from_str(body).unwrap();
|
let body = json::parse(&body).unwrap();
|
||||||
|
|
||||||
let mut event = get_event_data(&key, body.master_event_id);
|
let master_event_id = body["master_event_id"].as_u32().unwrap();
|
||||||
|
let mut event = get_event_data(&key, master_event_id);
|
||||||
|
|
||||||
let is_star_event = STAR_EVENT_IDS.contains(&body.master_event_id);
|
let is_star_event = STAR_EVENT_IDS.contains(&master_event_id);
|
||||||
|
|
||||||
if is_star_event {
|
if is_star_event {
|
||||||
let user = userdata::get_acc(&key);
|
let user = userdata::get_acc(&key);
|
||||||
let old = event["star_event"]["star_level"].as_i64().unwrap();
|
let old = event["star_event"]["star_level"].as_i64().unwrap();
|
||||||
event["star_event"]["star_level"] = get_star_rank(get_points(body.master_event_id, &user)).into();
|
event["star_event"]["star_level"] = get_star_rank(get_points(master_event_id, &user)).into();
|
||||||
let leveled = old != event["star_event"]["star_level"].as_i64().unwrap();
|
let leveled = old != event["star_event"]["star_level"].as_i64().unwrap();
|
||||||
|
|
||||||
let mut all_clear = 1;
|
let mut all_clear = 1;
|
||||||
@@ -126,18 +127,18 @@ pub fn event(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
switch_music(&mut event, 3);
|
switch_music(&mut event, 3);
|
||||||
switch_music(&mut event, 4);
|
switch_music(&mut event, 4);
|
||||||
switch_music(&mut event, 5);
|
switch_music(&mut event, 5);
|
||||||
save_event_data(&key, body.master_event_id, event.clone());
|
save_event_data(&key, master_event_id, event.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
event["point_ranking"]["point"] = get_points(body.master_event_id, &user).into();
|
event["point_ranking"]["point"] = get_points(master_event_id, &user).into();
|
||||||
event["point_ranking"]["rank"] = get_rank(body.master_event_id, user["user"]["id"].as_u64().unwrap()).into();
|
event["point_ranking"]["rank"] = get_rank(master_event_id, user["user"]["id"].as_u64().unwrap()).into();
|
||||||
|
|
||||||
if leveled {
|
if leveled {
|
||||||
save_event_data(&key, body.master_event_id, event.clone());
|
save_event_data(&key, master_event_id, event.clone());
|
||||||
event["star_event"]["is_star_event_update"] = 1.into();
|
event["star_event"]["is_star_event_update"] = 1.into();
|
||||||
} else {
|
} else {
|
||||||
save_event_data(&key, body.master_event_id, event.clone());
|
save_event_data(&key, master_event_id, event.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,17 +150,18 @@ pub fn star_event(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
let user = userdata::get_acc(&key);
|
let user = userdata::get_acc(&key);
|
||||||
|
|
||||||
let body = &encryption::decrypt_packet(&body).unwrap();
|
let body = &encryption::decrypt_packet(&body).unwrap();
|
||||||
let body: StarEvent = serde_json::from_str(body).unwrap();
|
let body = json::parse(&body).unwrap();
|
||||||
|
let master_event_id = body["master_event_id"].as_u32().unwrap();
|
||||||
|
|
||||||
let mut event = get_event_data(&key, body.master_event_id);
|
let mut event = get_event_data(&key, master_event_id);
|
||||||
|
|
||||||
let mut star_event = event["star_event"].clone();
|
let mut star_event = event["star_event"].clone();
|
||||||
star_event["is_inherited_level_reward"] = 0.into();
|
star_event["is_inherited_level_reward"] = 0.into();
|
||||||
|
|
||||||
event["star_event"]["star_level"] = get_star_rank(get_points(body.master_event_id, &user)).into();
|
event["star_event"]["star_level"] = get_star_rank(get_points(master_event_id, &user)).into();
|
||||||
star_event["is_star_level_up"] = 1.into();
|
star_event["is_star_level_up"] = 1.into();
|
||||||
|
|
||||||
save_event_data(&key, body.master_event_id, event.clone());
|
save_event_data(&key, master_event_id, event.clone());
|
||||||
|
|
||||||
Some(object!{
|
Some(object!{
|
||||||
star_event: star_event,
|
star_event: star_event,
|
||||||
@@ -172,15 +174,16 @@ pub fn change_target_music(req: HttpRequest, body: String) -> Option<JsonValue>
|
|||||||
let key = global::get_login(req.headers(), &body);
|
let key = global::get_login(req.headers(), &body);
|
||||||
|
|
||||||
let body = &encryption::decrypt_packet(&body).unwrap();
|
let body = &encryption::decrypt_packet(&body).unwrap();
|
||||||
let body: StarEventChangeTargetMusic = serde_json::from_str(body).unwrap();
|
let body = json::parse(&body).unwrap();
|
||||||
|
let master_event_id = body["master_event_id"].as_u32().unwrap();
|
||||||
|
|
||||||
let mut event = get_event_data(&key, body.master_event_id);
|
let mut event = get_event_data(&key, master_event_id);
|
||||||
|
|
||||||
event["star_event"]["music_change_count"] = (event["star_event"]["music_change_count"].as_i32().unwrap() + 1).into();
|
event["star_event"]["music_change_count"] = (event["star_event"]["music_change_count"].as_i32().unwrap() + 1).into();
|
||||||
|
|
||||||
switch_music(&mut event, body.position as i32);
|
switch_music(&mut event, body["position"].as_i32().unwrap());
|
||||||
|
|
||||||
save_event_data(&key, body.master_event_id, event.clone());
|
save_event_data(&key, master_event_id, event.clone());
|
||||||
|
|
||||||
Some(event["star_event"].clone())
|
Some(event["star_event"].clone())
|
||||||
}
|
}
|
||||||
@@ -189,17 +192,18 @@ pub fn set_member(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
let key = global::get_login(req.headers(), &body);
|
let key = global::get_login(req.headers(), &body);
|
||||||
|
|
||||||
let body = &encryption::decrypt_packet(&body).unwrap();
|
let body = &encryption::decrypt_packet(&body).unwrap();
|
||||||
let body: EventSetMember = serde_json::from_str(body).unwrap();
|
let body = json::parse(&body).unwrap();
|
||||||
|
let master_event_id = body["master_event_id"].as_u32().unwrap();
|
||||||
|
|
||||||
let mut event = get_event_data(&key, body.master_event_id);
|
let mut event = get_event_data(&key, master_event_id);
|
||||||
|
|
||||||
event["member_ranking"] = object!{
|
event["member_ranking"] = object!{
|
||||||
master_character_id: body.master_character_id,
|
master_character_id: body["master_character_id"].clone(),
|
||||||
rank: 0,
|
rank: 0,
|
||||||
point: 0
|
point: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
save_event_data(&key, body.master_event_id, event.clone());
|
save_event_data(&key, master_event_id, event.clone());
|
||||||
|
|
||||||
Some(object!{
|
Some(object!{
|
||||||
event_member: event["member_ranking"].clone()
|
event_member: event["member_ranking"].clone()
|
||||||
@@ -221,17 +225,18 @@ fn get_rank(event: u32, user_id: u64) -> u32 {
|
|||||||
|
|
||||||
pub async fn ranking(_req: HttpRequest, body: String) -> Option<JsonValue> {
|
pub async fn ranking(_req: HttpRequest, body: String) -> Option<JsonValue> {
|
||||||
let body = &encryption::decrypt_packet(&body).unwrap();
|
let body = &encryption::decrypt_packet(&body).unwrap();
|
||||||
let body: EventRankingGet = serde_json::from_str(body).unwrap();
|
let body = json::parse(&body).unwrap();
|
||||||
let scores = crate::router::event_ranking::get_scores_json().await[body.master_event_id.to_string()].clone();
|
let master_event_id = body["master_event_id"].as_u32().unwrap();
|
||||||
|
let scores = crate::router::event_ranking::get_scores_json().await[master_event_id as usize].clone();
|
||||||
let mut rv = array![];
|
let mut rv = array![];
|
||||||
let mut i=1;
|
let mut i=1;
|
||||||
let start = if body.user_id == 0 { body.start_rank } else { get_rank(body.master_event_id, body.user_id) };
|
let start = if body["user_id"] == 0 { body["start_rank"].as_u32().unwrap() } else { get_rank(master_event_id, body["user_id"].as_u64().unwrap()) };
|
||||||
for score in scores.members() {
|
for score in scores.members() {
|
||||||
if i >= start && start + body.count >= i {
|
if i >= start && start + body["count"].as_u32().unwrap() >= i {
|
||||||
rv.push(score.clone()).unwrap();
|
rv.push(score.clone()).unwrap();
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
if start + body.count >= i {
|
if start + body["count"].as_u32().unwrap() >= i {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,41 +370,3 @@ pub fn event_end(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
pub fn event_skip(req: HttpRequest, body: String) -> Option<JsonValue> {
|
pub fn event_skip(req: HttpRequest, body: String) -> Option<JsonValue> {
|
||||||
event_live(req, body, true)
|
event_live(req, body, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start request structs
|
|
||||||
// These start with CJsonSendParam in the source
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct StarEventChangeTargetMusic {
|
|
||||||
master_event_id: u32,
|
|
||||||
position: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct EventGet {
|
|
||||||
master_event_id: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct EventSetMember {
|
|
||||||
master_event_id: u32,
|
|
||||||
master_character_id: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct StarEvent {
|
|
||||||
master_event_id: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct EventRankingGet {
|
|
||||||
master_event_id: u32,
|
|
||||||
ranking_type: i32,
|
|
||||||
ranking_group_type: i32,
|
|
||||||
user_id: u64,
|
|
||||||
start_rank: u32,
|
|
||||||
count: u32,
|
|
||||||
group_id: u64
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub const FRIEND_LIMIT: usize = 40;
|
|||||||
pub fn friend(req: HttpRequest, body: String) -> Option<JsonValue> {
|
pub fn friend(req: HttpRequest, body: String) -> Option<JsonValue> {
|
||||||
let key = global::get_login(req.headers(), &body);
|
let key = global::get_login(req.headers(), &body);
|
||||||
let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
|
let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
|
||||||
|
let user_id = userdata::get_acc(&key)["user"]["id"].as_i64().unwrap();
|
||||||
let friends = userdata::get_acc_friends(&key);
|
let friends = userdata::get_acc_friends(&key);
|
||||||
|
|
||||||
let mut rv = array![];
|
let mut rv = array![];
|
||||||
@@ -24,7 +25,9 @@ pub fn friend(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for uid in rv_data.members() {
|
for uid in rv_data.members() {
|
||||||
rv.push(global::get_user(uid.as_i64().unwrap(), &friends, false)).unwrap();
|
let mut user = global::get_user(uid.as_i64().unwrap(), &friends, false);
|
||||||
|
user["user"]["last_login_time"] = global::set_time(user["user"]["last_login_time"].as_u64().unwrap_or(0), user_id, false).into();
|
||||||
|
rv.push(user).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(object!{
|
Some(object!{
|
||||||
@@ -52,10 +55,11 @@ pub fn recommend(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
|
|
||||||
let mut rv = array![];
|
let mut rv = array![];
|
||||||
for uid in random.members() {
|
for uid in random.members() {
|
||||||
let user = global::get_user(uid.as_i64().unwrap(), &friends, false);
|
let mut user = global::get_user(uid.as_i64().unwrap(), &friends, false);
|
||||||
if user["user"]["friend_request_disabled"] == 1 || user.is_empty() {
|
if user["user"]["friend_request_disabled"] == 1 || user.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
user["user"]["last_login_time"] = global::set_time(user["user"]["last_login_time"].as_u64().unwrap_or(0), user_id, false).into();
|
||||||
rv.push(user).unwrap();
|
rv.push(user).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,11 +106,11 @@ pub fn timestamp_since_midnight() -> u64 {
|
|||||||
unix_timestamp.as_secs() - midnight
|
unix_timestamp.as_secs() - midnight
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_time(data: &JsonValue, server_data: &mut JsonValue, token: &str, max_time: u64) {
|
fn init_time(current_time: u64, server_data: &mut JsonValue, token: &str, max_time: u64, max: bool) {
|
||||||
let mut edited = false;
|
let mut edited = false;
|
||||||
let default_time = 1709272800;
|
let default_time = 1709272800;
|
||||||
|
|
||||||
if max_time > 10 && max_time < data["server_time"].as_u64().unwrap_or(0) && server_data["server_time"].as_u64().unwrap_or(0) < max_time {
|
if max_time > 10 && max_time < current_time && server_data["server_time"].as_u64().unwrap_or(0) < max_time && max {
|
||||||
server_data["server_time_set"] = timestamp().into();
|
server_data["server_time_set"] = timestamp().into();
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
@@ -123,36 +123,37 @@ fn init_time(data: &JsonValue, server_data: &mut JsonValue, token: &str, max_tim
|
|||||||
server_data["server_time"] = default_time.into();
|
server_data["server_time"] = default_time.into();
|
||||||
edited = true;
|
edited = true;
|
||||||
}
|
}
|
||||||
if edited {
|
if edited && max {
|
||||||
userdata::save_server_data(token, server_data.clone());
|
userdata::save_server_data(token, server_data.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_time(data: &mut JsonValue, uid: i64) {
|
pub fn set_time(current_time: u64, uid: i64, max: bool) -> u64 {
|
||||||
let max_time = crate::get_args().max_time;
|
let max_time = crate::get_args().max_time;
|
||||||
if uid == 0 {
|
if uid == 0 {
|
||||||
if max_time > 10 && max_time < data["server_time"].as_u64().unwrap_or(0) {
|
if max_time > 10 && max_time < current_time {
|
||||||
data["server_time"] = max_time.into();
|
return max_time;
|
||||||
|
} else {
|
||||||
|
return timestamp();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
let token = userdata::get_login_token(uid);
|
let token = userdata::get_login_token(uid);
|
||||||
let mut server_data = userdata::get_server_data(&token);
|
let mut server_data = userdata::get_server_data(&token);
|
||||||
init_time(data, &mut server_data, &token, max_time);
|
init_time(current_time, &mut server_data, &token, max_time, max);
|
||||||
|
|
||||||
let time_set = server_data["server_time_set"].as_u64().unwrap_or(timestamp());
|
let time_set = server_data["server_time_set"].as_u64().unwrap_or(timestamp());
|
||||||
let server_time = server_data["server_time"].as_u64().unwrap_or(0);//1711741114
|
let server_time = server_data["server_time"].as_u64().unwrap_or(0);//1711741114
|
||||||
if server_time == 0 {
|
if server_time == 0 {
|
||||||
return;
|
return current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
let time_since_set = timestamp() - time_set;
|
let time_since_set = current_time - time_set;
|
||||||
data["server_time"] = (server_time + time_since_set).into();
|
return server_time + time_since_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(mut data: JsonValue, uid: i64, headers: &HeaderMap) -> HttpResponse {
|
pub fn send(mut data: JsonValue, uid: i64, headers: &HeaderMap) -> HttpResponse {
|
||||||
//println!("{}", json::stringify(data.clone()));
|
//println!("{}", json::stringify(data.clone()));
|
||||||
set_time(&mut data, uid);
|
data["server_time"] = set_time(data["server_time"].as_u64().unwrap_or(0), uid, true).into();
|
||||||
|
|
||||||
if !data["data"]["item_list"].is_empty() || !data["data"]["updated_value_list"]["item_list"].is_empty() {
|
if !data["data"]["item_list"].is_empty() || !data["data"]["updated_value_list"]["item_list"].is_empty() {
|
||||||
items::check_for_region(&mut data, headers);
|
items::check_for_region(&mut data, headers);
|
||||||
|
|||||||
@@ -8,10 +8,9 @@ use hmac::{Hmac, Mac};
|
|||||||
use rusqlite::params;
|
use rusqlite::params;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use openssl::pkey::PKey;
|
use sha1::Digest;
|
||||||
use openssl::rsa::Rsa;
|
use rsa::{RsaPublicKey, Pkcs1v15Sign};
|
||||||
use openssl::hash::MessageDigest;
|
use rsa::pkcs8::DecodePublicKey;
|
||||||
use openssl::sign::Verifier;
|
|
||||||
|
|
||||||
use crate::router::global;
|
use crate::router::global;
|
||||||
use crate::router::userdata;
|
use crate::router::userdata;
|
||||||
@@ -56,19 +55,14 @@ fn create_acc(cert: &str) -> String {
|
|||||||
uuid
|
uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_signature(signature: &[u8], message: &[u8], public_key: &[u8]) -> bool {
|
fn verify_signature(signature: &[u8], message: &[u8], public_key: &str) -> bool {
|
||||||
let rsa_public_key = match Rsa::public_key_from_pem(public_key) {
|
let pem = pem::parse(public_key).unwrap();
|
||||||
Ok(key) => key,
|
let public_key = RsaPublicKey::from_public_key_der(&pem.contents()).unwrap();
|
||||||
Err(_) => return false,
|
let digest = Sha1::digest(message);
|
||||||
};
|
|
||||||
let pkey = match PKey::from_rsa(rsa_public_key) {
|
|
||||||
Ok(pkey) => pkey,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
|
||||||
let mut verifier = Verifier::new(MessageDigest::sha1(), &pkey).unwrap();
|
|
||||||
verifier.update(message).unwrap();
|
|
||||||
|
|
||||||
verifier.verify(signature).is_ok()
|
public_key
|
||||||
|
.verify(Pkcs1v15Sign::new::<Sha1>(), &digest, signature)
|
||||||
|
.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_uuid(user_id: i64) {
|
pub fn delete_uuid(user_id: i64) {
|
||||||
@@ -97,7 +91,7 @@ pub fn get_uuid(headers: &HeaderMap, body: &str) -> String {
|
|||||||
|
|
||||||
let decoded = general_purpose::STANDARD.decode(login).unwrap_or_default();
|
let decoded = general_purpose::STANDARD.decode(login).unwrap_or_default();
|
||||||
|
|
||||||
if verify_signature(&decoded, encoded.as_bytes(), cert.as_bytes()) {
|
if verify_signature(&decoded, encoded.as_bytes(), &cert) {
|
||||||
DATABASE.lock_and_select("SELECT uuid FROM users WHERE user_id=?1;", params!(uid)).unwrap()
|
DATABASE.lock_and_select("SELECT uuid FROM users WHERE user_id=?1;", params!(uid)).unwrap()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
|
|||||||
@@ -24,6 +24,18 @@ pub fn remove_gems(user: &mut JsonValue, amount: i64) {
|
|||||||
user["gem"]["total"] = (free + paid).into();
|
user["gem"]["total"] = (free + paid).into();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_paid_gems(user: &mut JsonValue, amount: i64) {
|
||||||
|
let free = user["gem"]["free"].as_i64().unwrap();
|
||||||
|
let mut paid = user["gem"]["charge"].as_i64().unwrap();
|
||||||
|
|
||||||
|
paid -= amount;
|
||||||
|
if paid < 0 {
|
||||||
|
paid = 0;
|
||||||
|
}
|
||||||
|
user["gem"]["charge"] = paid.into();
|
||||||
|
user["gem"]["total"] = (free + paid).into();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_region(headers: &HeaderMap) -> bool {
|
pub fn get_region(headers: &HeaderMap) -> bool {
|
||||||
let blank_header = HeaderValue::from_static("");
|
let blank_header = HeaderValue::from_static("");
|
||||||
let asset_version = headers.get("aoharu-asset-version").unwrap_or(&blank_header).to_str().unwrap_or("");
|
let asset_version = headers.get("aoharu-asset-version").unwrap_or(&blank_header).to_str().unwrap_or("");
|
||||||
@@ -110,6 +122,8 @@ pub fn use_item(item: &JsonValue, multiplier: i64, user: &mut JsonValue) {
|
|||||||
// Is anything really ever free...?
|
// Is anything really ever free...?
|
||||||
} else if item["consumeType"] == 1 {
|
} else if item["consumeType"] == 1 {
|
||||||
remove_gems(user, item["amount"].as_i64().unwrap());
|
remove_gems(user, item["amount"].as_i64().unwrap());
|
||||||
|
} else if item["consumeType"] == 2 {
|
||||||
|
remove_paid_gems(user, item["amount"].as_i64().unwrap());
|
||||||
} else if item["consumeType"] == 4 {
|
} else if item["consumeType"] == 4 {
|
||||||
use_itemm(item["value"].as_i64().unwrap(), item["amount"].as_i64().unwrap() * multiplier, user);
|
use_itemm(item["value"].as_i64().unwrap(), item["amount"].as_i64().unwrap() * multiplier, user);
|
||||||
} else {
|
} else {
|
||||||
@@ -230,7 +244,7 @@ fn random_number(lowest: usize, highest: usize) -> usize {
|
|||||||
}
|
}
|
||||||
assert!(lowest < highest);
|
assert!(lowest < highest);
|
||||||
|
|
||||||
rand::thread_rng().gen_range(lowest..highest + 1)
|
rand::rng().random_range(lowest..highest + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gift_item_basic(id: i32, value: i64, ty_pe: i32, reason: &str, user: &mut JsonValue) -> JsonValue {
|
pub fn gift_item_basic(id: i32, value: i64, ty_pe: i32, reason: &str, user: &mut JsonValue) -> JsonValue {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fn random_number(lowest: usize, highest: usize) -> usize {
|
|||||||
}
|
}
|
||||||
assert!(lowest < highest);
|
assert!(lowest < highest);
|
||||||
|
|
||||||
rand::thread_rng().gen_range(lowest..highest + 1)
|
rand::rng().random_range(lowest..highest + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn guest(req: HttpRequest, body: String) -> Option<JsonValue> {
|
pub fn guest(req: HttpRequest, body: String) -> Option<JsonValue> {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ fn get_random_card(item: &JsonValue, rv: &mut JsonValue, rng: &mut rand::rngs::T
|
|||||||
|
|
||||||
let mut random_id = 0;
|
let mut random_id = 0;
|
||||||
while random_id == 0 {
|
while random_id == 0 {
|
||||||
let card = rng.gen_range(1..databases::POOL[lottery_id.to_string()][databases::POOL[lottery_id.to_string()].len() - 1].as_i64().unwrap() + 1);
|
let card = rng.random_range(1..databases::POOL[lottery_id.to_string()][databases::POOL[lottery_id.to_string()].len() - 1].as_i64().unwrap() + 1);
|
||||||
if get_card_master_id(lottery_id.to_string(), card.to_string()).is_some() {
|
if get_card_master_id(lottery_id.to_string(), card.to_string()).is_some() {
|
||||||
random_id = card;
|
random_id = card;
|
||||||
break;
|
break;
|
||||||
@@ -63,7 +63,7 @@ fn get_random_card(item: &JsonValue, rv: &mut JsonValue, rng: &mut rand::rngs::T
|
|||||||
|
|
||||||
fn get_random_cards(id: i64, mut count: usize) -> JsonValue {
|
fn get_random_cards(id: i64, mut count: usize) -> JsonValue {
|
||||||
let total_ratio: i64 = databases::RARITY[id.to_string()].members().map(|item| if item["ensured"].as_i32().unwrap() == 1 { 0 } else { item["ratio"].as_i64().unwrap() }).sum();
|
let total_ratio: i64 = databases::RARITY[id.to_string()].members().map(|item| if item["ensured"].as_i32().unwrap() == 1 { 0 } else { item["ratio"].as_i64().unwrap() }).sum();
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let mut rv = array![];
|
let mut rv = array![];
|
||||||
let mut promised = false;
|
let mut promised = false;
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ fn get_random_cards(id: i64, mut count: usize) -> JsonValue {
|
|||||||
count -= 1;
|
count -= 1;
|
||||||
}
|
}
|
||||||
for _i in 0..count {
|
for _i in 0..count {
|
||||||
let random_number: i64 = rng.gen_range(1..total_ratio + 1);
|
let random_number: i64 = rng.random_range(1..total_ratio + 1);
|
||||||
let mut cumulative_ratio = 0;
|
let mut cumulative_ratio = 0;
|
||||||
for item in databases::RARITY[id.to_string()].members() {
|
for item in databases::RARITY[id.to_string()].members() {
|
||||||
cumulative_ratio += item["ratio"].as_i64().unwrap();
|
cumulative_ratio += item["ratio"].as_i64().unwrap();
|
||||||
@@ -118,12 +118,7 @@ pub fn lottery_post(req: HttpRequest, body: String) -> Option<JsonValue> {
|
|||||||
consumeType: price["consumeType"].clone()
|
consumeType: price["consumeType"].clone()
|
||||||
}, 1, &mut user);
|
}, 1, &mut user);
|
||||||
|
|
||||||
let mut count = price["count"].as_usize().unwrap();
|
let count = price["count"].as_usize().unwrap();
|
||||||
|
|
||||||
// This is a temporary easter egg, not meant to stay
|
|
||||||
if lottery_id == 4110044 {
|
|
||||||
count = 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cardstogive = get_random_cards(lottery_id, count);
|
let cardstogive = get_random_cards(lottery_id, count);
|
||||||
|
|
||||||
|
|||||||
@@ -331,10 +331,12 @@ async fn npps4_req(sha_id: String) -> Option<JsonValue> {
|
|||||||
let url = format!("{}/ewexport?sha1={}", host, sha_id);
|
let url = format!("{}/ewexport?sha1={}", host, sha_id);
|
||||||
println!("Polling NPPS4 at {}", host);
|
println!("Polling NPPS4 at {}", host);
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let body = ureq::get(&url)
|
||||||
let response = client.get(url);
|
.call().ok()?
|
||||||
let response_body = response.send().await.ok()?.text().await.ok()?;
|
.body_mut()
|
||||||
json::parse(&response_body).ok()
|
.read_to_string().ok()?;
|
||||||
|
|
||||||
|
json::parse(&body).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_sif_data(current: &JsonValue) -> JsonValue {
|
fn clean_sif_data(current: &JsonValue) -> JsonValue {
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ fn get_key(auth_key: &str) -> i64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_uid() -> i64 {
|
fn generate_uid() -> i64 {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let random_number = rng.gen_range(100_000_000_000_000..=999_999_999_999_999);
|
let random_number = rng.random_range(100_000_000_000_000..=999_999_999_999_999);
|
||||||
//the chances of this...?
|
//the chances of this...?
|
||||||
if acc_exists(random_number) {
|
if acc_exists(random_number) {
|
||||||
return generate_uid();
|
return generate_uid();
|
||||||
@@ -301,7 +301,7 @@ pub fn save_acc_sif(auth_key: &str, data: JsonValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_salt() -> Vec<u8> {
|
fn generate_salt() -> Vec<u8> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let mut bytes = vec![0u8; 16];
|
let mut bytes = vec![0u8; 16];
|
||||||
rng.fill(&mut bytes[..]);
|
rng.fill(&mut bytes[..]);
|
||||||
bytes
|
bytes
|
||||||
|
|||||||
Reference in New Issue
Block a user