diff --git a/res/agreement/DEFAULT.xml b/res/agreement/DEFAULT.xml
index 68055bb..c80b4cc 100644
--- a/res/agreement/DEFAULT.xml
+++ b/res/agreement/DEFAULT.xml
@@ -1 +1 @@
-USenEnglish2014-09-29T20:07:35NINTENDO-NETWORK-EULA0300USenEspañol2014-09-29T20:07:35NINTENDO-NETWORK-EULA0300
\ No newline at end of file
+USenEnglish2014-09-29T20:07:35NINTENDO-NETWORK-EULA0300USenEspañol2014-09-29T20:07:35NINTENDO-NETWORK-EULA0300
diff --git a/res/agreement/EVIL.xml b/res/agreement/EVIL.xml
new file mode 100644
index 0000000..e69de29
diff --git a/src/nnid/agreements.rs b/src/nnid/agreements.rs
index 16e9700..e1ca61f 100644
--- a/src/nnid/agreements.rs
+++ b/src/nnid/agreements.rs
@@ -1,12 +1,38 @@
use std::{env, io};
+use std::collections::HashSet;
+use gxhash::HashMap;
+use once_cell::sync::Lazy;
use rocket::fs::NamedFile;
-use rocket::get;
+use rocket::{get, Request};
+use rocket::http::Status;
+use rocket::request::{FromRequest, Outcome};
use rocket::response::content::RawXml;
use tokio::fs::try_exists;
+use tokio::sync::RwLock;
+use tonic::async_trait;
use crate::dsresponse::Ds;
+pub static EVIL_AGREEMENT_THING: Lazy>> = Lazy::new(|| Default::default());
+
+pub struct CFIP(pub String);
+
+#[async_trait]
+impl<'r> FromRequest<'r> for CFIP{
+ type Error = ();
+
+ async fn from_request(request: &'r Request<'_>) -> Outcome {
+ match request.headers().get("CF-Connecting-IP").next(){
+ Some(v) => Outcome::Success(Self(v.to_owned())),
+ None => Outcome::Error((Status::ImATeapot, ()))
+ }
+ }
+}
+
+
#[get("/v1/api/content/agreements/Nintendo-Network-EULA//@latest")]
-pub async fn get_agreement(lang: &str) -> io::Result>>{
+pub async fn get_agreement(lang: &str, ip: CFIP) -> io::Result>>{
+
+
let base_path = {
// if this crashes then something is wrong with the server setup so crashing here is fine imo
let mut path = env::current_dir().unwrap();
@@ -17,27 +43,38 @@ pub async fn get_agreement(lang: &str) -> io::Result>>{
path
};
- let requested_file_path = {
- let mut path = base_path.clone();
+ if EVIL_AGREEMENT_THING.read().await.contains(&ip.0) {
+ let requested_file_path = {
+ let mut path = base_path.clone();
- path.push(format!("{}.xml", lang));
-
- path
- };
-
-
-
- if try_exists(&requested_file_path).await.is_ok_and(|v| v == true){
- Ok(Ds(RawXml(NamedFile::open(&requested_file_path).await?)))
- } else {
- let fallback_path = {
- let mut path = base_path;
-
- path.push("DEFAULT.xml");
+ path.push(format!("{}.xml", lang));
path
};
- Ok(Ds(RawXml(NamedFile::open(&fallback_path).await?)))
+
+ if try_exists(&requested_file_path).await.is_ok_and(|v| v == true) {
+ Ok(Ds(RawXml(NamedFile::open(&requested_file_path).await?)))
+ } else {
+ let fallback_path = {
+ let mut path = base_path;
+
+ path.push("DEFAULT.xml");
+
+ path
+ };
+
+ Ok(Ds(RawXml(NamedFile::open(&fallback_path).await?)))
+ }
+ } else {
+ let path = {
+ let mut path = base_path;
+
+ path.push("EVIL.xml");
+
+ path
+ };
+
+ Ok(Ds(RawXml(NamedFile::open(&path).await?)))
}
}
\ No newline at end of file
diff --git a/src/nnid/oauth/generate_token.rs b/src/nnid/oauth/generate_token.rs
index 9f12bbd..2baf374 100644
--- a/src/nnid/oauth/generate_token.rs
+++ b/src/nnid/oauth/generate_token.rs
@@ -3,6 +3,7 @@ use rocket::form::Form;
use serde::{Serialize};
use crate::account::account::User;
use crate::error::{Error, Errors};
+use crate::nnid::agreements::{CFIP, EVIL_AGREEMENT_THING};
use crate::nnid::oauth::generate_token::token_type::{AUTH_REFRESH_TOKEN, AUTH_TOKEN};
use crate::nnid::oauth::TokenData;
use crate::Pool;
@@ -26,12 +27,21 @@ const ACCOUNT_ID_OR_PASSWORD_ERRORS: Errors = Errors{
const ACCOUNT_BANNED_ERRORS: Errors = Errors{
error: &[
Error{
- code: "0123",
+ code: "0122",
message: "Device has been banned by game server"
}
]
};
+
+const REREAD_EULA_EXTRABANNED_ERRORS: Errors = Errors{
+ error: &[
+ Error{
+ code: "0109",
+ message: "REREAD THE EULA LOL"
+ }
+ ]
+};
#[derive(FromForm)]
pub struct TokenRequestData<'a>{
grant_type: &'a str,
@@ -90,7 +100,7 @@ pub struct TokenRequestReturnData{
}
#[post("/v1/api/oauth20/access_token/generate", data="")]
-pub async fn generate_token(pool: &State, data: Form>) -> Result, Option>>{
+pub async fn generate_token(pool: &State, data: Form>, ip: CFIP) -> Result, Option>>{
let pool = pool.inner();
let user = User::get_by_username(data.user_id, pool).await
@@ -101,6 +111,14 @@ pub async fn generate_token(pool: &State, data: Form>
}
if user.account_level < 0{
+ if user.account_level == -2 {
+ return Err(Some(REREAD_EULA_EXTRABANNED_ERRORS));
+ }
+ if user.account_level == -3{
+ EVIL_AGREEMENT_THING.write().await.insert(ip.0);
+
+ return Err(Some(REREAD_EULA_EXTRABANNED_ERRORS));
+ }
return Err(Some(ACCOUNT_BANNED_ERRORS));
}