mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-24 08:07:45 +00:00
Run cargo fmt
This commit is contained in:
parent
f7a5940f20
commit
40ef6b8193
8 changed files with 171 additions and 146 deletions
|
@ -1,16 +1,12 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use axum::{
|
|
||||||
Json,
|
|
||||||
Router, routing::get,
|
|
||||||
extract::Form
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use axum::response::{Html, Redirect};
|
use axum::response::{Html, Redirect};
|
||||||
use axum::routing::post;
|
use axum::routing::post;
|
||||||
|
use axum::{Json, Router, extract::Form, routing::get};
|
||||||
use kawari::config::{Config, get_config};
|
use kawari::config::{Config, get_config};
|
||||||
use minijinja::{Environment, context};
|
|
||||||
use kawari::setup_default_environment;
|
use kawari::setup_default_environment;
|
||||||
|
use minijinja::{Environment, context};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct GateStatus {
|
struct GateStatus {
|
||||||
|
@ -56,10 +52,7 @@ async fn apply(Form(input): Form<Input>) -> Redirect {
|
||||||
config.boot_patches_location = boot_patch_location;
|
config.boot_patches_location = boot_patch_location;
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_json::to_writer(
|
serde_json::to_writer(&std::fs::File::create("config.json").unwrap(), &config)
|
||||||
&std::fs::File::create("config.json").unwrap(),
|
|
||||||
&config,
|
|
||||||
)
|
|
||||||
.expect("TODO: panic message");
|
.expect("TODO: panic message");
|
||||||
|
|
||||||
Redirect::to("/")
|
Redirect::to("/")
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use axum::{
|
use axum::{Json, Router, routing::get};
|
||||||
Json,
|
|
||||||
Router, routing::get,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use kawari::config::{Config, get_config};
|
use kawari::config::{Config, get_config};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct GateStatus {
|
struct GateStatus {
|
||||||
|
@ -17,7 +14,7 @@ async fn get_login_status() -> Json<GateStatus> {
|
||||||
|
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
Json(GateStatus {
|
Json(GateStatus {
|
||||||
status: config.login_open.into()
|
status: config.login_open.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,14 +23,14 @@ async fn get_world_status() -> Json<GateStatus> {
|
||||||
|
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
Json(GateStatus {
|
Json(GateStatus {
|
||||||
status: config.login_open.into()
|
status: config.login_open.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct Banner {
|
struct Banner {
|
||||||
link: String,
|
link: String,
|
||||||
lsb_banner: String
|
lsb_banner: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
@ -42,7 +39,7 @@ struct NewsItem {
|
||||||
id: String,
|
id: String,
|
||||||
tag: String,
|
tag: String,
|
||||||
title: String,
|
title: String,
|
||||||
url: String
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use axum::{Form, Router, routing::get};
|
|
||||||
use axum::extract::Query;
|
use axum::extract::Query;
|
||||||
use axum::response::Html;
|
use axum::response::Html;
|
||||||
use axum::routing::post;
|
use axum::routing::post;
|
||||||
use rand::distributions::Alphanumeric;
|
use axum::{Form, Router, routing::get};
|
||||||
use rand::Rng;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use kawari::generate_sid;
|
use kawari::generate_sid;
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::distributions::Alphanumeric;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -17,11 +17,13 @@ struct Params {
|
||||||
isft: String,
|
isft: String,
|
||||||
cssmode: String,
|
cssmode: String,
|
||||||
isnew: String,
|
isnew: String,
|
||||||
launchver: String
|
launchver: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn top(Query(params): Query<Params>) -> Html<&'static str> {
|
async fn top(Query(params): Query<Params>) -> Html<&'static str> {
|
||||||
Html("\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html lang=en-GB id=gb>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><form action=\"login.send\" method=\"post\" name=\"mainForm\">\r\n\t\r\n\t\t\r\n\t\t<input type=\"hidden\" name=\"_STORED_\" value=\"42f06e5f4194001a9ad61c8481f435e8b9eac79242f9221d463aa492ab2b3373655adadff3e72dd16a798ee8a222c519848743c97084f1af71854f06050a1f2813e5c3aaf66e5f0ef24dc18588a8cf06758992e42035f7e4f99f85c8b6082200dcabc6a37c7f76ce542eefc1f1798da5e23fd4b46ed17489de5eb8e8a222c5198487433bff5f3433c061ded661b3f33b5f2d2807f5db74747f4dfe8f1fe89f9388f717347bbea9e9ec2931bb6fdc4b11648dfa9e726cdf690d74970a36f7482c12593a5ad7b966c4cf14655e11641f0bb67b8e807377edfa81055480da52031e0ba86ec52f991eb3cb8913c8f807287f3cb5ac4143326f33a4503cf31e021c8f41a5eec01870e0004acc0d0bf2bed65da5eeae3703ae878c20bd7f1167745e96770979146463fa40235e6bba8bdac1273dcbc1256cda0caacbdaad\">\n\r\n\t\t\r\n\t\t<div class=\"form-item type-id\">\r\n\t\t\t<label class=\"item-label\" for=\"sqexid\"><span class=\"label-image-text\" title=\"Square Enix ID\"></span></label>\r\n\t\t\t<input class=\"item-input\" name=\"sqexid\" id=\"sqexid\" type=\"text\" value=\"\" tabindex=\"1\" placeholder=\"ID (Required)\" maxLength=\"16\"\r\n\t\t\t\r\n\t\t\t\t />\r\n\t\t\t\r\n\t\t</div>\r\n\r\n\t\t <div class=\"form-item type-pw\">\r\n\t\t\t<label class=\"item-label\" for=\"password\"><span class=\"label-image-text\" title=\"Square Enix Password\"></span></label>\r\n\t\t\t<input class=\"item-password\" name=\"password\" id=\"password\" type=\"password\" value=\"\" tabindex=\"2\" placeholder=\"Password (Required)\" maxLength=\"32\" autocomplete=\"off\"/>\r\n\t\t</div>\r\n\t\r\n\t\t<div class=\"form-item type-otpw\">\r\n\t\t\t<label class=\"item-label\" for=\"otppw\"><span class=\"label-image-text\" title=\"One-Time Password\"></span></label>\r\n\t\t\t<input class=\"item-otpw\" name=\"otppw\" id=\"otppw\" type=\"text\" value=\"\" tabindex=\"3\" autocomplete=\"off\" maxLength=\"6\" placeholder=\"Password (Optional)\" />\r\n\t\t</div>\r\n\r\n\t\t\r\n\t\t<div class=\"form-item type-remember-id\">\r\n\t\t\t<input name=\"saveid\" id=\"saveid\" type=\"checkbox\" value=\"1\" class=\"item-checkbox\" tabindex=\"4\" />\r\n\t\t\t<label class=\"item-checkbox-label\" for=\"saveid\"><span class=\"label-checkbox-image-text\" title=\"Remember Square Enix ID\"></span></label>\r\n\t\t</div>\r\n\t\t\r\n\r\n\t\t<div class=\"form-item type-submit\">\r\n\t\t\t<button class=\"item-button\" type=\"submit\" tabindex=\"5\" onClick=\"ctrEvent('mainForm')\" id=\"btLogin\"><span class=\"button-image-text\" title=\"Login\"></span></button>\r\n\t\t</div>\r\n\r\n\t</form>\r\n</div>\r\n</body>\r\n</html>\r\n\r\n</html>")
|
Html(
|
||||||
|
"\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html lang=en-GB id=gb>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><form action=\"login.send\" method=\"post\" name=\"mainForm\">\r\n\t\r\n\t\t\r\n\t\t<input type=\"hidden\" name=\"_STORED_\" value=\"42f06e5f4194001a9ad61c8481f435e8b9eac79242f9221d463aa492ab2b3373655adadff3e72dd16a798ee8a222c519848743c97084f1af71854f06050a1f2813e5c3aaf66e5f0ef24dc18588a8cf06758992e42035f7e4f99f85c8b6082200dcabc6a37c7f76ce542eefc1f1798da5e23fd4b46ed17489de5eb8e8a222c5198487433bff5f3433c061ded661b3f33b5f2d2807f5db74747f4dfe8f1fe89f9388f717347bbea9e9ec2931bb6fdc4b11648dfa9e726cdf690d74970a36f7482c12593a5ad7b966c4cf14655e11641f0bb67b8e807377edfa81055480da52031e0ba86ec52f991eb3cb8913c8f807287f3cb5ac4143326f33a4503cf31e021c8f41a5eec01870e0004acc0d0bf2bed65da5eeae3703ae878c20bd7f1167745e96770979146463fa40235e6bba8bdac1273dcbc1256cda0caacbdaad\">\n\r\n\t\t\r\n\t\t<div class=\"form-item type-id\">\r\n\t\t\t<label class=\"item-label\" for=\"sqexid\"><span class=\"label-image-text\" title=\"Square Enix ID\"></span></label>\r\n\t\t\t<input class=\"item-input\" name=\"sqexid\" id=\"sqexid\" type=\"text\" value=\"\" tabindex=\"1\" placeholder=\"ID (Required)\" maxLength=\"16\"\r\n\t\t\t\r\n\t\t\t\t />\r\n\t\t\t\r\n\t\t</div>\r\n\r\n\t\t <div class=\"form-item type-pw\">\r\n\t\t\t<label class=\"item-label\" for=\"password\"><span class=\"label-image-text\" title=\"Square Enix Password\"></span></label>\r\n\t\t\t<input class=\"item-password\" name=\"password\" id=\"password\" type=\"password\" value=\"\" tabindex=\"2\" placeholder=\"Password (Required)\" maxLength=\"32\" autocomplete=\"off\"/>\r\n\t\t</div>\r\n\t\r\n\t\t<div class=\"form-item type-otpw\">\r\n\t\t\t<label class=\"item-label\" for=\"otppw\"><span class=\"label-image-text\" title=\"One-Time Password\"></span></label>\r\n\t\t\t<input class=\"item-otpw\" name=\"otppw\" id=\"otppw\" type=\"text\" value=\"\" tabindex=\"3\" autocomplete=\"off\" maxLength=\"6\" placeholder=\"Password (Optional)\" />\r\n\t\t</div>\r\n\r\n\t\t\r\n\t\t<div class=\"form-item type-remember-id\">\r\n\t\t\t<input name=\"saveid\" id=\"saveid\" type=\"checkbox\" value=\"1\" class=\"item-checkbox\" tabindex=\"4\" />\r\n\t\t\t<label class=\"item-checkbox-label\" for=\"saveid\"><span class=\"label-checkbox-image-text\" title=\"Remember Square Enix ID\"></span></label>\r\n\t\t</div>\r\n\t\t\r\n\r\n\t\t<div class=\"form-item type-submit\">\r\n\t\t\t<button class=\"item-button\" type=\"submit\" tabindex=\"5\" onClick=\"ctrEvent('mainForm')\" id=\"btLogin\"><span class=\"button-image-text\" title=\"Login\"></span></button>\r\n\t\t</div>\r\n\r\n\t</form>\r\n</div>\r\n</body>\r\n</html>\r\n\r\n</html>",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -30,12 +32,14 @@ struct Input {
|
||||||
_STORED_: String,
|
_STORED_: String,
|
||||||
sqexid: String,
|
sqexid: String,
|
||||||
password: String,
|
password: String,
|
||||||
otppw: String
|
otppw: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login_send(Form(input): Form<Input>) -> Html<String> {
|
async fn login_send(Form(input): Form<Input>) -> Html<String> {
|
||||||
let sid = generate_sid();
|
let sid = generate_sid();
|
||||||
Html(format!("window.external.user(\"login=auth,ok,sid,{sid},terms,1,region,2,etmadd,0,playable,1,ps3pkg,0,maxex,4,product,1\");"))
|
Html(format!(
|
||||||
|
"window.external.user(\"login=auth,ok,sid,{sid},terms,1,region,2,etmadd,0,playable,1,ps3pkg,0,maxex,4,product,1\");"
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
|
@ -2,22 +2,22 @@ use std::cmp::Ordering;
|
||||||
use std::fs::read_dir;
|
use std::fs::read_dir;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use axum::{Form, Json, Router, routing::get};
|
|
||||||
use axum::extract::Query;
|
|
||||||
use axum::response::Html;
|
|
||||||
use axum::routing::post;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use kawari::config::{Config, get_config};
|
|
||||||
use axum::extract::Path;
|
use axum::extract::Path;
|
||||||
use axum::response::IntoResponse;
|
use axum::extract::Query;
|
||||||
use axum::http::{HeaderMap, StatusCode};
|
use axum::http::{HeaderMap, StatusCode};
|
||||||
use minijinja::filters::list;
|
use axum::response::Html;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
use axum::routing::post;
|
||||||
|
use axum::{Form, Json, Router, routing::get};
|
||||||
|
use kawari::config::{Config, get_config};
|
||||||
use kawari::patchlist::{PatchEntry, PatchList, PatchType};
|
use kawari::patchlist::{PatchEntry, PatchList, PatchType};
|
||||||
|
use minijinja::filters::list;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
fn list_patch_files(dir_path: &str) -> Vec<String> {
|
fn list_patch_files(dir_path: &str) -> Vec<String> {
|
||||||
// If the dir doesn't exist, pretend there is no patch files
|
// If the dir doesn't exist, pretend there is no patch files
|
||||||
let Ok(dir) = read_dir(dir_path) else {
|
let Ok(dir) = read_dir(dir_path) else {
|
||||||
return Vec::new()
|
return Vec::new();
|
||||||
};
|
};
|
||||||
let mut entries: Vec<_> = dir.flatten().collect();
|
let mut entries: Vec<_> = dir.flatten().collect();
|
||||||
entries.sort_by_key(|dir| dir.path());
|
entries.sort_by_key(|dir| dir.path());
|
||||||
|
@ -38,20 +38,37 @@ fn list_patch_files(dir_path: &str) -> Vec<String> {
|
||||||
.collect();
|
.collect();
|
||||||
game_patches.sort_by(|a, b| {
|
game_patches.sort_by(|a, b| {
|
||||||
// Ignore H/D in front of filenames
|
// Ignore H/D in front of filenames
|
||||||
let mut a_path = a.as_path().file_name().unwrap().to_str().unwrap().to_string();
|
let mut a_path = a
|
||||||
|
.as_path()
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
if a_path.starts_with("H") {
|
if a_path.starts_with("H") {
|
||||||
return Ordering::Less;
|
return Ordering::Less;
|
||||||
}
|
}
|
||||||
let mut b_path = b.as_path().file_name().unwrap().to_str().unwrap().to_string();
|
let mut b_path = b
|
||||||
|
.as_path()
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
/*if b_path.starts_with("H") {
|
/*if b_path.starts_with("H") {
|
||||||
return Ordering::Greater;
|
return Ordering::Greater;
|
||||||
}*/
|
}*/
|
||||||
a_path.partial_cmp(&b_path).unwrap()
|
a_path.partial_cmp(&b_path).unwrap()
|
||||||
}); // ensure we're actually installing them in the correct order
|
}); // ensure we're actually installing them in the correct order
|
||||||
game_patches.iter().map(|x| x.file_stem().unwrap().to_str().unwrap().to_string() ).collect()
|
game_patches
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.file_stem().unwrap().to_str().unwrap().to_string())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn verify_session(Path((platform, game_version, sid)): Path<(String, String, String)>) -> impl IntoResponse {
|
async fn verify_session(
|
||||||
|
Path((platform, game_version, sid)): Path<(String, String, String)>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
if !config.supports_platform(&platform) {
|
if !config.supports_platform(&platform) {
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
||||||
|
@ -63,7 +80,6 @@ async fn verify_session(Path((platform, game_version, sid)): Path<(String, Strin
|
||||||
(headers).into_response()
|
(headers).into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) -> impl IntoResponse {
|
async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) -> impl IntoResponse {
|
||||||
tracing::info!("Verifying boot components...");
|
tracing::info!("Verifying boot components...");
|
||||||
|
|
||||||
|
@ -85,8 +101,7 @@ async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) ->
|
||||||
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
|
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
|
||||||
patch_type: PatchType::Boot,
|
patch_type: PatchType::Boot,
|
||||||
requested_version: boot_version.clone(),
|
requested_version: boot_version.clone(),
|
||||||
patches: vec![
|
patches: vec![PatchEntry {
|
||||||
PatchEntry {
|
|
||||||
url: format!("http://{}", patch).to_string(),
|
url: format!("http://{}", patch).to_string(),
|
||||||
version: "2023.09.15.0000.0000".to_string(),
|
version: "2023.09.15.0000.0000".to_string(),
|
||||||
hash_block_size: 50000000,
|
hash_block_size: 50000000,
|
||||||
|
@ -95,8 +110,7 @@ async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) ->
|
||||||
hashes: vec![],
|
hashes: vec![],
|
||||||
unknown_a: 0,
|
unknown_a: 0,
|
||||||
unknown_b: 0,
|
unknown_b: 0,
|
||||||
}
|
}],
|
||||||
]
|
|
||||||
};
|
};
|
||||||
let patch_list_str = patch_list.to_string();
|
let patch_list_str = patch_list.to_string();
|
||||||
return patch_list_str.into_response();
|
return patch_list_str.into_response();
|
||||||
|
@ -112,8 +126,14 @@ async fn main() {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/http/:platform/ffxivneo_release_game/:game_version/:sid", post(verify_session))
|
.route(
|
||||||
.route("/http/:platform/ffxivneo_release_boot/*boot_version", get(verify_boot)); // NOTE: for future programmers, this is a wildcard because axum hates the /version/?time=blah format.
|
"/http/:platform/ffxivneo_release_game/:game_version/:sid",
|
||||||
|
post(verify_session),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/http/:platform/ffxivneo_release_boot/*boot_version",
|
||||||
|
get(verify_boot),
|
||||||
|
); // NOTE: for future programmers, this is a wildcard because axum hates the /version/?time=blah format.
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 6900));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 6900));
|
||||||
tracing::info!("Patch server started on {}", addr);
|
tracing::info!("Patch server started on {}", addr);
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use axum::{
|
|
||||||
Json,
|
|
||||||
Router, routing::get,
|
|
||||||
extract::Form
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use axum::response::{Html, Redirect};
|
use axum::response::{Html, Redirect};
|
||||||
use axum::routing::post;
|
use axum::routing::post;
|
||||||
|
use axum::{Json, Router, extract::Form, routing::get};
|
||||||
use kawari::config::{Config, get_config};
|
use kawari::config::{Config, get_config};
|
||||||
use minijinja::{Environment, context};
|
|
||||||
use kawari::setup_default_environment;
|
use kawari::setup_default_environment;
|
||||||
|
use minijinja::{Environment, context};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct GateStatus {
|
struct GateStatus {
|
||||||
|
@ -22,7 +18,7 @@ async fn root() -> Html<String> {
|
||||||
|
|
||||||
let environment = setup_default_environment();
|
let environment = setup_default_environment();
|
||||||
let template = environment.get_template("web.html").unwrap();
|
let template = environment.get_template("web.html").unwrap();
|
||||||
Html(template.render(context! { }).unwrap())
|
Html(template.render(context! {}).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login() -> Html<String> {
|
async fn login() -> Html<String> {
|
||||||
|
@ -30,7 +26,7 @@ async fn login() -> Html<String> {
|
||||||
|
|
||||||
let environment = setup_default_environment();
|
let environment = setup_default_environment();
|
||||||
let template = environment.get_template("login.html").unwrap();
|
let template = environment.get_template("login.html").unwrap();
|
||||||
Html(template.render(context! { }).unwrap())
|
Html(template.render(context! {}).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn register() -> Html<String> {
|
async fn register() -> Html<String> {
|
||||||
|
@ -38,7 +34,7 @@ async fn register() -> Html<String> {
|
||||||
|
|
||||||
let environment = setup_default_environment();
|
let environment = setup_default_environment();
|
||||||
let template = environment.get_template("register.html").unwrap();
|
let template = environment.get_template("register.html").unwrap();
|
||||||
Html(template.render(context! { }).unwrap())
|
Html(template.render(context! {}).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn world_status() -> Html<String> {
|
async fn world_status() -> Html<String> {
|
||||||
|
@ -46,7 +42,11 @@ async fn world_status() -> Html<String> {
|
||||||
|
|
||||||
let environment = setup_default_environment();
|
let environment = setup_default_environment();
|
||||||
let template = environment.get_template("worldstatus.html").unwrap();
|
let template = environment.get_template("worldstatus.html").unwrap();
|
||||||
Html(template.render(context! { login_open => config.login_open, worlds_open => config.worlds_open }).unwrap())
|
Html(
|
||||||
|
template
|
||||||
|
.render(context! { login_open => config.login_open, worlds_open => config.worlds_open })
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -60,10 +60,7 @@ async fn apply(Form(input): Form<Input>) -> Redirect {
|
||||||
|
|
||||||
let mut config = get_config();
|
let mut config = get_config();
|
||||||
|
|
||||||
serde_json::to_writer(
|
serde_json::to_writer(&std::fs::File::create("config.json").unwrap(), &config)
|
||||||
&std::fs::File::create("config.json").unwrap(),
|
|
||||||
&config,
|
|
||||||
)
|
|
||||||
.expect("TODO: panic message");
|
.expect("TODO: panic message");
|
||||||
|
|
||||||
Redirect::to("/")
|
Redirect::to("/")
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub struct Config {
|
||||||
pub supported_platforms: Vec<String>,
|
pub supported_platforms: Vec<String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub boot_patches_location: String
|
pub boot_patches_location: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
|
@ -21,7 +21,7 @@ impl Default for Config {
|
||||||
worlds_open: false,
|
worlds_open: false,
|
||||||
login_open: false,
|
login_open: false,
|
||||||
boot_patches_location: String::new(),
|
boot_patches_location: String::new(),
|
||||||
supported_platforms: default_supported_platforms()
|
supported_platforms: default_supported_platforms(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -1,6 +1,6 @@
|
||||||
use minijinja::Environment;
|
use minijinja::Environment;
|
||||||
use rand::distributions::Alphanumeric;
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use rand::distributions::Alphanumeric;
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod patchlist;
|
pub mod patchlist;
|
||||||
|
@ -16,11 +16,19 @@ pub fn generate_sid() -> String {
|
||||||
|
|
||||||
pub fn setup_default_environment() -> Environment<'static> {
|
pub fn setup_default_environment() -> Environment<'static> {
|
||||||
let mut env = Environment::new();
|
let mut env = Environment::new();
|
||||||
env.add_template("admin.html", include_str!("../templates/admin.html")).unwrap();
|
env.add_template("admin.html", include_str!("../templates/admin.html"))
|
||||||
env.add_template("web.html", include_str!("../templates/web.html")).unwrap();
|
.unwrap();
|
||||||
env.add_template("login.html", include_str!("../templates/login.html")).unwrap();
|
env.add_template("web.html", include_str!("../templates/web.html"))
|
||||||
env.add_template("register.html", include_str!("../templates/register.html")).unwrap();
|
.unwrap();
|
||||||
env.add_template("worldstatus.html", include_str!("../templates/worldstatus.html")).unwrap();
|
env.add_template("login.html", include_str!("../templates/login.html"))
|
||||||
|
.unwrap();
|
||||||
|
env.add_template("register.html", include_str!("../templates/register.html"))
|
||||||
|
.unwrap();
|
||||||
|
env.add_template(
|
||||||
|
"worldstatus.html",
|
||||||
|
include_str!("../templates/worldstatus.html"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
env
|
env
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ pub enum PatchType {
|
||||||
/// Corresponds to 4e9a232b
|
/// Corresponds to 4e9a232b
|
||||||
Boot,
|
Boot,
|
||||||
/// Corresponds to 2b5cbc63
|
/// Corresponds to 2b5cbc63
|
||||||
Game
|
Game,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PatchList {
|
pub struct PatchList {
|
||||||
|
@ -22,7 +22,7 @@ pub struct PatchList {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub patch_type: PatchType,
|
pub patch_type: PatchType,
|
||||||
pub requested_version: String,
|
pub requested_version: String,
|
||||||
pub patches: Vec<PatchEntry>
|
pub patches: Vec<PatchEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PatchList {
|
impl PatchList {
|
||||||
|
@ -34,7 +34,15 @@ impl PatchList {
|
||||||
str.push_str(&self.id);
|
str.push_str(&self.id);
|
||||||
str.push_str("\r\n");
|
str.push_str("\r\n");
|
||||||
str.push_str("Content-Type: application/octet-stream\r\n");
|
str.push_str("Content-Type: application/octet-stream\r\n");
|
||||||
str.push_str(&format!("Content-Location: ffxivpatch/{}/metainfo/{}.http\r\n", if self.patch_type == PatchType::Boot { "2b5cbc63" } else { "4e9a232b" }, self.requested_version));
|
str.push_str(&format!(
|
||||||
|
"Content-Location: ffxivpatch/{}/metainfo/{}.http\r\n",
|
||||||
|
if self.patch_type == PatchType::Boot {
|
||||||
|
"2b5cbc63"
|
||||||
|
} else {
|
||||||
|
"4e9a232b"
|
||||||
|
},
|
||||||
|
self.requested_version
|
||||||
|
));
|
||||||
|
|
||||||
let mut total_patch_size = 0;
|
let mut total_patch_size = 0;
|
||||||
for patch in &self.patches {
|
for patch in &self.patches {
|
||||||
|
@ -115,18 +123,17 @@ mod tests {
|
||||||
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
|
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
|
||||||
requested_version: "D2023.04.28.0000.0001".to_string(),
|
requested_version: "D2023.04.28.0000.0001".to_string(),
|
||||||
patch_type: PatchType::Boot,
|
patch_type: PatchType::Boot,
|
||||||
patches: vec![
|
patches: vec![PatchEntry {
|
||||||
PatchEntry {
|
url: "http://patch-dl.ffxiv.com/boot/2b5cbc63/D2023.09.14.0000.0001.patch"
|
||||||
url: "http://patch-dl.ffxiv.com/boot/2b5cbc63/D2023.09.14.0000.0001.patch".to_string(),
|
.to_string(),
|
||||||
version: "2023.09.14.0000.0001".to_string(),
|
version: "2023.09.14.0000.0001".to_string(),
|
||||||
hash_block_size: 0,
|
hash_block_size: 0,
|
||||||
length: 22221335,
|
length: 22221335,
|
||||||
size_on_disk: 69674819,
|
size_on_disk: 69674819,
|
||||||
hashes: vec![],
|
hashes: vec![],
|
||||||
unknown_a: 19,
|
unknown_a: 19,
|
||||||
unknown_b: 18
|
unknown_b: 18,
|
||||||
}
|
}],
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(patch_list.to_string(), test_case);
|
assert_eq!(patch_list.to_string(), test_case);
|
||||||
|
@ -153,9 +160,9 @@ mod tests {
|
||||||
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
|
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
|
||||||
requested_version: "2023.07.26.0000.0000".to_string(),
|
requested_version: "2023.07.26.0000.0000".to_string(),
|
||||||
patch_type: PatchType::Game,
|
patch_type: PatchType::Game,
|
||||||
patches: vec![
|
patches: vec![PatchEntry {
|
||||||
PatchEntry {
|
url: "http://patch-dl.ffxiv.com/game/4e9a232b/D2023.09.15.0000.0000.patch"
|
||||||
url: "http://patch-dl.ffxiv.com/game/4e9a232b/D2023.09.15.0000.0000.patch".to_string(),
|
.to_string(),
|
||||||
version: "2023.09.15.0000.0000".to_string(),
|
version: "2023.09.15.0000.0000".to_string(),
|
||||||
hash_block_size: 50000000,
|
hash_block_size: 50000000,
|
||||||
length: 1479062470,
|
length: 1479062470,
|
||||||
|
@ -192,10 +199,9 @@ mod tests {
|
||||||
"4561eb6f954d80cdb1ece3cc4d58cbd864bf2b50".to_string(),
|
"4561eb6f954d80cdb1ece3cc4d58cbd864bf2b50".to_string(),
|
||||||
"de94175c4db39a11d5334aefc7a99434eea8e4f9".to_string(),
|
"de94175c4db39a11d5334aefc7a99434eea8e4f9".to_string(),
|
||||||
"55dd7215f24441d6e47d1f9b32cebdb041f2157f".to_string(),
|
"55dd7215f24441d6e47d1f9b32cebdb041f2157f".to_string(),
|
||||||
"2ca09db645cfeefa41a04251dfcb13587418347a".to_string()
|
"2ca09db645cfeefa41a04251dfcb13587418347a".to_string(),
|
||||||
],
|
],
|
||||||
}
|
}],
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(patch_list.to_string(), test_case);
|
assert_eq!(patch_list.to_string(), test_case);
|
||||||
|
|
Loading…
Add table
Reference in a new issue