some small refactoring

This commit is contained in:
Reid 2023-09-11 20:00:20 -07:00
parent dd7c66a13b
commit e591b11065
Signed by: reidlab
GPG key ID: 6C9EAA3364F962C8
20 changed files with 957 additions and 40 deletions

View file

@ -130,7 +130,7 @@ pub struct NewLevel {
pub name: String,
pub user_id: i32,
pub description: String,
pub original: i32,
pub original: Option<i32>,
pub game_version: i32,
pub binary_version: i32,
pub password: Option<String>,

View file

@ -31,7 +31,6 @@ pub fn update_account_settings(input: Form<FormUpdateAccountSettings>) -> status
// account verification
let (_user_id_val, account_id_val): (i32, i32);
// password argument is used for the level, so
match helpers::accounts::auth(input.accountID.clone(), input.password.clone(), input.gjp.clone(), input.gjp2.clone()) {
Ok((user_id, account_id)) => {
_user_id_val = user_id;

View file

@ -1 +1,2 @@
pub mod get_levels;
pub mod upload_level;

View file

@ -0,0 +1,439 @@
use rocket::form::Form;
use rocket::http::Status;
use rocket::response::status;
use diesel::prelude::*;
use base64::{Engine as _, engine::general_purpose};
use crate::helpers;
use crate::db;
#[derive(FromForm)]
pub struct FormGetLevels {
page: i64,
str: String,
accountID: Option<i32>,
gjp: Option<String>,
gjp2: Option<String>,
password: Option<String>,
// we have to escape here
r#type: Option<i32>,
featured: Option<i32>,
original: Option<i32>,
coins: Option<i32>,
epic: Option<i32>,
uncompleted: Option<i32>,
onlyCompleted: Option<i32>,
completedLevels: Option<String>,
song: Option<i32>,
customSong: Option<i32>,
twoPlayer: Option<i32>,
star: Option<i32>,
noStar: Option<i32>,
gauntlet: Option<i32>,
len: Option<i32>,
diff: Option<String>,
demonFilter: Option<i32>,
local: Option<i32>
}
#[post("/getGJLevels20.php", data = "<input>")]
pub fn get_levels(input: Form<FormGetLevels>) -> status::Custom<&'static str> {
let connection = &mut db::establish_connection_pg();
use crate::schema::{levels, users};
use crate::models::{Level, User};
let mut can_see_unlisted = false;
let mut query = levels::table.into_boxed();
let mut count_query = levels::table.into_boxed();
if input.str != "" && input.r#type != Some(5) && input.r#type != Some(10) && input.r#type != Some(19) {
match input.str.parse::<i32>() {
Ok(matched_id) => {
can_see_unlisted = true;
query = query.filter(levels::id.eq(matched_id));
count_query = count_query.filter(levels::id.eq(matched_id))
},
Err(_) => {
query = query.filter(levels::name.ilike(input.str.to_owned() + "%"));
count_query = count_query.filter(levels::name.ilike(input.str.to_owned() + "%"))
}
}
}
if let Some(1) = input.featured {
query = query.filter(levels::featured.eq(1));
count_query = count_query.filter(levels::featured.eq(1))
}
if let Some(1) = input.original {
query = query.filter(levels::original.is_null());
count_query = count_query.filter(levels::original.is_null())
}
if let Some(1) = input.coins {
query = query.filter(levels::rated_coins.eq(1).and(levels::coins.ne(0)));
count_query = count_query.filter(levels::rated_coins.eq(1).and(levels::coins.ne(0)))
}
if let Some(1) = input.epic {
query = query.filter(levels::epic.eq(1));
count_query = count_query.filter(levels::epic.eq(1))
}
if let Some(1) = input.uncompleted {
match input.completedLevels.clone() {
Some(completed_levels) => {
let clean_levels: Vec<i32> = completed_levels[1..completed_levels.len() - 1].split(',')
.map(|s| s.parse::<i32>().expect("failed to parse i32"))
.collect();
query = query.filter(levels::id.ne_all(clean_levels.clone()));
count_query = count_query.filter(levels::id.ne_all(clean_levels))
},
None => return status::Custom(Status::Ok, "-1")
}
}
if let Some(1) = input.onlyCompleted {
match input.completedLevels.clone() {
Some(completed_levels) => {
let clean_levels: Vec<i32> = completed_levels[1..completed_levels.len() - 1].split(',')
.map(|s| s.parse::<i32>().expect("failed to parse i32"))
.collect();
query = query.filter(levels::id.eq_any(clean_levels.clone()));
count_query = count_query.filter(levels::id.eq_any(clean_levels))
},
None => return status::Custom(Status::Ok, "-1")
}
}
if let Some(song_id) = input.song {
if let Some(custom_song) = input.customSong {
query = query.filter(levels::song_id.eq(custom_song));
count_query = count_query.filter(levels::song_id.eq(custom_song))
} else {
query = query.filter(levels::song_id.eq(song_id));
count_query = count_query.filter(levels::song_id.eq(song_id));
}
}
if let Some(1) = input.twoPlayer {
query = query.filter(levels::two_player.eq(1));
count_query = count_query.filter(levels::two_player.eq(1))
}
if let Some(1) = input.star {
query = query.filter(levels::stars.is_not_null());
count_query = count_query.filter(levels::stars.is_not_null())
}
if let Some(1) = input.noStar {
query = query.filter(levels::stars.is_null());
count_query = count_query.filter(levels::stars.is_null())
}
if let Some(_gauntlet_id) = input.gauntlet {
unimplemented!("no gauntlet support")
}
if let Some(len) = input.len {
query = query.filter(levels::length.eq(len));
count_query = count_query.filter(levels::length.eq(len))
}
if let Some(diff) = input.diff.clone() {
if diff != "-" {
match diff.as_str() {
"-1" => {
query = query.filter(levels::difficulty.is_null().and(levels::community_difficulty.is_null()));
count_query = count_query.filter(levels::difficulty.is_null().and(levels::community_difficulty.is_null()))
},
"-2" => match input.demonFilter {
Some(demon_filter) => {
match demon_filter {
1 => {
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Easy.to_demon_difficulty()));
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Easy.to_demon_difficulty()))
},
2 => {
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Medium.to_demon_difficulty()));
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Medium.to_demon_difficulty()))
},
3 => {
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Hard.to_demon_difficulty()));
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Hard.to_demon_difficulty()))
},
4 => {
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Insane.to_demon_difficulty()));
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Insane.to_demon_difficulty()))
},
5 => {
query = query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Extreme.to_demon_difficulty()));
count_query = count_query.filter(levels::demon_difficulty.eq::<i32>(crate::difficulty::DemonDifficulty::Extreme.to_demon_difficulty()))
},
_ => panic!("invalid demon filter!")
}
query = query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()))));
count_query = count_query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Demon.to_star_difficulty()))))
},
None => panic!("demon filter option with no demon filter argument")
},
"-3" => {
query = query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()))));
count_query = count_query.filter(diesel::BoolExpressionMethods::or(levels::difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()), levels::difficulty.is_null().and(levels::community_difficulty.eq::<i32>(crate::difficulty::LevelDifficulty::Auto.to_star_difficulty()))))
},
// easy, normal, hard, harder, insane
_ => {
let diffs: Vec<i32> = diff.split(',')
.map(|v| v.parse::<i32>().expect("couldnt parse i32"))
.collect();
query = query.filter(levels::difficulty.eq_any(diffs.clone()).or(levels::difficulty.is_null().and(levels::community_difficulty.eq_any(diffs.clone()))));
count_query = count_query.filter(levels::difficulty.eq_any(diffs.clone()).or(levels::difficulty.is_null().and(levels::community_difficulty.eq_any(diffs))))
}
}
}
}
if let Some(search_type) = input.r#type {
match search_type {
// downloads
1 => {
query = query.order(levels::downloads.desc());
// count query order doesnt matter
},
// likes
2 => {
query = query.order(levels::likes.desc());
// count query order doesnt matter
},
// trending
3 => {
unimplemented!("no trending sort :(");
},
// recent
4 => {
unimplemented!("no recent sort :(")
// count query order doesnt matter
}
// creator levels
5 => {
if let Some(1) = input.local {
if let Some(input_account_id) = input.accountID {
let (user_id_val, _account_id_val): (i32, i32);
match helpers::accounts::auth(input_account_id, input.password.clone(), input.gjp.clone(), input.gjp2.clone()) {
Ok((user_id_val_auth, account_id_val_auth)) => {
user_id_val = user_id_val_auth;
_account_id_val = account_id_val_auth;
},
Err(_) => return status::Custom(Status::Ok, "-1")
};
if user_id_val == input.str.parse::<i32>().expect("couldnt convert query input to i32") {
can_see_unlisted = true;
} else {
return status::Custom(Status::Ok, "-1")
}
}
}
}
// featured
// 17 is gdworld
6 | 17 => {
query = query.filter(levels::featured.eq(1));
count_query = count_query.filter(levels::featured.eq(1))
},
// epic / HoF
16 => {
query = query.filter(levels::epic.eq(1));
count_query = count_query.filter(levels::epic.eq(1))
},
// magic
7 => {
query = query.filter(levels::objects.gt(4000));
count_query = count_query.filter(levels::objects.gt(4000))
},
// map packs 🙄😶
10 | 19 => {
unimplemented!("no map packs yet buddy")
},
// rated
11 => {
query = query.filter(levels::stars.is_not_null());
count_query = count_query.filter(levels::stars.is_not_null())
},
// followed
12 => {
unimplemented!("no followed yet (i actually *could* implement this, but you cant follow yet so its useless)")
},
// friends
13 => {
unimplemented!("no friends")
},
// daily
21 => {
unimplemented!("no daily")
},
// weekly
22 => {
unimplemented!("no weekly")
},
// event (honestly idk what this is i think it got leaked from 2.2 or something)
23 => {
unimplemented!("no event")
},
// default sort
// 15 is gdworld
0 | 15 | _ => {
query = query.order(levels::likes.desc());
// count query order doesnt matter
},
}
}
if !can_see_unlisted {
query = query.filter(levels::unlisted.eq(0));
count_query = count_query.filter(levels::unlisted.eq(0))
}
let mut results: Vec<String> = [].to_vec();
let mut users: Vec<String> = [].to_vec();
let mut songs: Vec<String> = [].to_vec();
let mut hash_data: Vec<(i32, i32, bool)> = [].to_vec();
for result in {
query
.order(levels::created_at.desc())
.offset(input.page * 10)
.limit(10)
.get_results::<Level, >(connection)
.expect("fatal error loading levels")
} {
let user: User = users::table.find(result.user_id).get_result::<User, >(connection).expect("couldnt get user from lvl");
let level: Level = result;
let set_difficulty = match level.difficulty {
Some(diff) => {
Some(helpers::difficulty::LevelDifficulty::new(diff))
},
None => None
};
let community_difficulty = match level.community_difficulty {
Some(diff) => {
Some(helpers::difficulty::LevelDifficulty::new(diff))
},
None => None
};
let difficulty = match set_difficulty {
Some(diff) => {
Some(diff)
},
None => {
match community_difficulty {
Some(diff) => {
Some(diff)
},
None => None
}
}
};
let demon_difficulty = match level.demon_difficulty {
Some(diff) => {
Some(helpers::difficulty::DemonDifficulty::new(diff))
},
None => None
};
results.push(helpers::format::format(hashmap! {
1 => level.id.to_string(),
2 => level.name,
3 => general_purpose::URL_SAFE.encode(level.description),
5 => level.version.to_string(),
6 => user.id.to_string(),
// this argument is weird. its the "difficulty divisor"
// used to be vote count but yeah
8 => 10.to_string(),
9 => (match difficulty {
Some(diff) => diff.to_star_difficulty(),
None => 0
} * 10).to_string(),
10 => level.downloads.to_string(),
12 => (if level.song_id < 50 { level.song_id } else { 0 }).to_string(),
13 => level.game_version.to_string(),
14 => level.likes.to_string(),
16 => (-level.likes).to_string(),
15 => level.length.to_string(),
17 => match difficulty {
Some(diff) => {
if diff == helpers::difficulty::LevelDifficulty::Demon {
1
} else {
0
}
},
None => 0
}.to_string(),
18 => (if let Some(stars) = level.stars { stars } else { 0 }).to_string(),
19 => level.featured.to_string(),
25 => match difficulty {
Some(diff) => {
if diff == helpers::difficulty::LevelDifficulty::Auto {
1
} else {
0
}
},
None => 0
}.to_string(),
30 => (if let Some(original) = level.original { original } else { 0 }).to_string(),
31 => level.two_player.to_string(),
35 => (if level.song_id >= 50 { level.song_id } else { 0 }).to_string(),
37 => level.coins.to_string(),
38 => level.rated_coins.to_string(),
39 => (if let Some(requested_stars) = level.requested_stars { requested_stars } else { 0 }).to_string(),
40 => level.has_ldm.to_string(),
42 => level.epic.to_string(),
43 => match demon_difficulty {
Some(diff) => {
diff
},
None => helpers::difficulty::DemonDifficulty::Hard
}.to_demon_difficulty().to_string(),
45 => level.objects.to_string(),
46 => level.editor_time.to_string(),
47 => level.editor_time_copies.to_string()
}));
users.push(format!("{}:{}:{}", user.id, user.username, {
if user.registered == 1 {
user.account_id.expect("wtf? registered user with no account id.").to_string()
} else {
user.udid.expect("wtf? unregistered user with no udid.")
}
}));
hash_data.push((
level.id,
{ if let Some(stars) = level.stars {
stars
} else {
0
}},
{ if let 1 = level.rated_coins {
true
} else {
println!("{}", "no rated coin");
false
}}
));
};
let level_count = count_query
.count()
.get_result::<i64, >(connection)
.expect("failed to get count of levels");
let search_meta = format!("{}:{}:{}", level_count, input.page * 10, 10);
let response = vec![results.join("|"), users.join("|"), songs.join("|"), search_meta, helpers::encryption::gen_multi(hash_data)].join("#");
println!("{}", response);
return status::Custom(Status::Ok, Box::leak(response.into_boxed_str()))
}
//1:93455181:2:Siinamota:5:1:6:158483568:8:10:9:40:10:2171:12:0:13:21:14:40:17::43:5:25::18:0:19:0:42:0:45:3318:3:QnkgSm9yZ2UwMDFZVCAgcGFyYSBlc2N1Y2hhciBsYSBDYW5jaW9uIE5lY2VzaXRhcyBSZW1wbGF6YXIgZXN0YSA6XSBwYXMgMDAwMDAw:15:1:30:0:31:0:37:1:38:0:39:5:46:1:47:2:35:633211#158483568:Jorge001yt:16248905#1~|~633211~|~2~|~Random Song 04~|~3~|~42023~|~4~|~Zhenmuron~|~5~|~0.31~|~6~|~~|~10~|~http%3A%2F%2Faudio.ngfiles.com%2F633000%2F633211_Random-Song-04.mp3~|~7~|~~|~8~|~1#9999:0:10#d19e918b852b706b20e7fbc31bbb07d92efda123

View file

@ -141,7 +141,7 @@ pub fn upload_level(input: Form<FormUploadLevel>) -> status::Custom<&'static str
length.eq(level_length_val),
objects.eq(objects_val as i32),
coins.eq(coins_val as i32),
has_ldm.eq(input.ldm.unwrap_or(0)),
has_ldm.eq(input.ldm.unwrap_or(0).clamp(0, 1)),
two_player.eq(two_player_val)
))
.get_result::<Level, >(connection)
@ -156,7 +156,7 @@ pub fn upload_level(input: Form<FormUploadLevel>) -> status::Custom<&'static str
name: helpers::clean::clean_basic(&input.levelName).chars().take(20).collect(),
user_id: user_id_val,
description: description_val.chars().take(140).collect(),
original: input.original.unwrap_or(0),
original: input.original,
game_version: input.gameVersion,
binary_version: input.binaryVersion.unwrap_or(0),
password: input.password.clone(),

View file

@ -38,31 +38,33 @@ pub fn get_users(input: Form<FormGetUsers>) -> status::Custom<&'static str> {
.get_results::<User, >(connection)
.expect("Fatal error loading users")
} {
let user: User = result;
let formatted_result = helpers::format::format(hashmap! {
1 => result.username,
2 => result.id.to_string(),
3 => result.stars.to_string(),
4 => result.demons.to_string(),
8 => result.creator_points.to_string(),
1 => user.username,
2 => user.id.to_string(),
3 => user.stars.to_string(),
4 => user.demons.to_string(),
8 => user.creator_points.to_string(),
9 => {
vec![
result.cube,
result.ship,
result.ball,
result.ufo,
result.wave,
result.robot
][result.icon_type as usize].to_string()
user.cube,
user.ship,
user.ball,
user.ufo,
user.wave,
user.robot
][user.icon_type as usize].to_string()
},
10 => result.color1.to_string(),
11 => result.color2.to_string(),
13 => result.coins.to_string(),
14 => result.icon_type.to_string(),
15 => result.special.to_string(),
10 => user.color1.to_string(),
11 => user.color2.to_string(),
13 => user.coins.to_string(),
14 => user.icon_type.to_string(),
15 => user.special.to_string(),
16 => {
match result.account_id {
match user.account_id {
Some(account_id_value) => account_id_value.to_string(),
None => match result.udid {
None => match user.udid {
Some(udid_value) => udid_value.to_string(),
None => panic!("user has no account_id or udid?!?!?")
}
@ -83,7 +85,7 @@ pub fn get_users(input: Form<FormGetUsers>) -> status::Custom<&'static str> {
let amount = query_users_count
.count()
.get_result::<i64>(connection)
.expect("Error querying user count");
.expect("error querying user count");
let response = if results.is_empty() {
String::from("-1")

View file

@ -1,3 +1,4 @@
#[derive(PartialEq, Copy, Clone)]
pub enum LevelDifficulty {
Auto,
Easy,
@ -9,7 +10,32 @@ pub enum LevelDifficulty {
}
impl LevelDifficulty {
pub fn to_star_difficulty(&self) -> i32 {
pub fn new(value: i32) -> LevelDifficulty {
match value {
0 => LevelDifficulty::Auto,
1 => LevelDifficulty::Easy,
2 => LevelDifficulty::Normal,
3 => LevelDifficulty::Hard,
4 => LevelDifficulty::Harder,
5 => LevelDifficulty::Insane,
6 => LevelDifficulty::Demon,
_ => panic!("invalid level difficulty")
}
}
pub fn value(self) -> i32 {
match self {
LevelDifficulty::Auto => 0,
LevelDifficulty::Easy => 1,
LevelDifficulty::Normal => 2,
LevelDifficulty::Hard => 3,
LevelDifficulty::Harder => 4,
LevelDifficulty::Insane => 5,
LevelDifficulty::Demon => 6,
}
}
pub fn to_star_difficulty(self) -> i32 {
match self {
LevelDifficulty::Auto => 5,
LevelDifficulty::Easy => 1,
@ -20,4 +46,59 @@ impl LevelDifficulty {
LevelDifficulty::Demon => 5,
}
}
pub fn stars_to_diff(stars: i32) -> Self {
match stars {
1 => LevelDifficulty::Auto,
2 => LevelDifficulty::Easy,
3 => LevelDifficulty::Normal,
4 | 5 => LevelDifficulty::Hard,
6 | 7 => LevelDifficulty::Harder,
8 | 9 => LevelDifficulty::Insane,
10 => LevelDifficulty::Demon,
_ => panic!("invalid difficulty!")
}
}
}
pub enum DemonDifficulty {
Easy,
Medium,
Hard,
Insane,
Extreme
}
impl DemonDifficulty {
pub fn new(value: i32) -> DemonDifficulty {
match value {
0 => DemonDifficulty::Easy,
1 => DemonDifficulty::Medium,
2 => DemonDifficulty::Hard,
3 => DemonDifficulty::Insane,
4 => DemonDifficulty::Extreme,
5 => DemonDifficulty::Insane,
_ => panic!("invalid demon difficulty")
}
}
pub fn value(self) -> i32 {
match self {
DemonDifficulty::Easy => 0,
DemonDifficulty::Medium => 1,
DemonDifficulty::Hard => 2,
DemonDifficulty::Insane => 3,
DemonDifficulty::Extreme => 4
}
}
pub fn to_demon_difficulty(self) -> i32 {
match self {
DemonDifficulty::Easy => 3,
DemonDifficulty::Medium => 4,
DemonDifficulty::Hard => 0,
DemonDifficulty::Insane => 5,
DemonDifficulty::Extreme => 6
}
}
}

View file

@ -27,4 +27,24 @@ pub fn decode_gjp(gjp: String) -> String {
let base64_decoded = String::from_utf8(general_purpose::STANDARD.decode(gjp).expect("couldn't decode base64")).expect("invalid UTF-8 sequence (how)");
let xor_decoded = cyclic_xor_string(&base64_decoded, "37526");
return xor_decoded
}
pub fn gen_multi(level_hash_data: Vec<(i32, i32, bool)>) -> String {
let mut input_str = String::new();
for (_index, val) in level_hash_data.iter().enumerate() {
let (level_id, stars, coins) = val;
let level_id_str = level_id.to_string();
input_str.push(level_id_str.chars().nth(0).unwrap());
input_str.push(level_id_str.chars().last().unwrap());
input_str.push_str(&stars.to_string());
input_str.push_str(if *coins { "1" } else { "0" });
}
let mut bytes: Vec<u8> = Vec::new();
bytes.extend(input_str.as_bytes().to_vec());
bytes.extend("xI25fpAapCQg".as_bytes().to_vec());
return Sha1::default().digest(bytes.as_mut_slice()).to_hex();
}

View file

@ -12,7 +12,7 @@ pub fn format(map: HashMap<i32, impl ToString>) -> String {
}
}
if !result.ends_with(":") {
if result.ends_with(":") {
result.pop();
}

View file

@ -5,6 +5,8 @@ use base64::{Engine as _, engine::general_purpose};
use flate2::read::GzDecoder;
use std::collections::HashMap;
pub static DEFAULT_EXTRA_STRING: LazyLock<String> = LazyLock::new(|| {
let string = String::from("29_29_29_40_29_29_29_29_29_29_29_29_29_29_29_29");
@ -19,7 +21,6 @@ macro_rules! object_prop_bool {
};
}
use std::collections::HashMap;
#[derive(Clone)]
pub struct ObjectData {
@ -54,8 +55,8 @@ pub enum PortalSpeed {
VeryFast
}
impl PortalSpeed {
pub fn portal_speed(&self) -> f64 {
impl Into<f64> for PortalSpeed {
fn into(self) -> f64 {
match self {
PortalSpeed::Slow => 251.16,
PortalSpeed::Normal => 311.58,
@ -78,12 +79,12 @@ pub fn id_to_portal_speed(id: i32) -> Option<PortalSpeed> {
}
pub fn get_seconds_from_xpos(pos: f64, start_speed: PortalSpeed, portals: Vec<ObjectData>) -> f64 {
let mut speed;
let mut speed: f64;
let mut last_obj_pos = 0.0;
let mut last_segment = 0.0;
let mut segments = 0.0;
speed = start_speed.portal_speed();
speed = start_speed.into();
if portals.is_empty() {
return pos / speed
@ -97,7 +98,7 @@ pub fn get_seconds_from_xpos(pos: f64, start_speed: PortalSpeed, portals: Vec<Ob
last_segment = s;
segments += s;
speed = id_to_portal_speed(portal.id()).expect("not a portal").portal_speed();
speed = id_to_portal_speed(portal.id()).expect("not a portal").into();
last_obj_pos = portal.x()
}

View file

@ -5,6 +5,11 @@
#[macro_use] extern crate rocket;
use std::fs;
use std::path::{Path, PathBuf};
use rocket::fs::NamedFile;
use rocket_dyn_templates::{ Template };
mod db;
use db::*;
@ -15,6 +20,9 @@ use helpers::*;
mod endpoints;
use endpoints::*;
mod template_endpoints;
use template_endpoints::*;
mod config;
use config::*;
@ -23,15 +31,28 @@ fn index() -> String {
return String::from("gdps-server | https://git.reidlab.online/reidlab/gdps-server");
}
#[get("/<file..>")]
async fn files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("public/").join(file)).await.ok()
}
#[launch]
fn rocket() -> _ {
fs::create_dir_all(&CONFIG.db.data_folder).expect("failed to create data directory!");
// this is a bit scuffed
fs::create_dir_all(&CONFIG.db.data_folder).expect("failed to create data directory! (probably a permission err)");
fs::create_dir_all(format!("{}/levels", &CONFIG.db.data_folder)).expect("failed to create data directory for levels");
rocket::build()
.configure(rocket::Config::figment().merge(("port", CONFIG.general.port)))
// actual website
.mount("/", routes![
index,
template_endpoints::index::index
])
// assets
.mount("/", routes![
files
])
// GEOMETRY DASH https://www.youtube.com/watch?v=_pLrtsf5yfE
.mount(CONFIG.general.append_path.as_str(), routes![
endpoints::accounts::login_account::login_account,
endpoints::accounts::register_account::register_account,
@ -39,6 +60,9 @@ fn rocket() -> _ {
endpoints::users::get_users::get_users,
endpoints::levels::get_levels::get_levels,
endpoints::levels::upload_level::upload_level
])
// so templates work i think
.attach(Template::fairing())
}

View file

@ -0,0 +1 @@
pub mod index;

View file

@ -0,0 +1,18 @@
use rocket_dyn_templates::{Template, context};
use rand::Rng;
#[get("/")]
pub fn index() -> Template {
let silly_strings: Vec<&str> = vec![
"the trianges consume",
"geomtry das"
];
let mut rng = rand::thread_rng();
let random_index = rng.gen_range(0..silly_strings.len());
let silly_string = silly_strings[random_index];
Template::render("index", context! { silly_string: silly_string })
}