custom errors
61
Cargo.lock
generated
|
@ -122,6 +122,16 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.16.0"
|
||||
|
@ -432,6 +442,19 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"log",
|
||||
"regex-automata 0.4.6",
|
||||
"regex-syntax 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.26"
|
||||
|
@ -1154,6 +1177,41 @@ dependencies = [
|
|||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "8.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "8.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32"
|
||||
dependencies = [
|
||||
"globset",
|
||||
"sha2",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
|
@ -1564,11 +1622,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "traque"
|
||||
version = "0.1.0"
|
||||
version = "0.2.4"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rocket",
|
||||
"rocket_dyn_templates",
|
||||
"rust-embed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "traque"
|
||||
version = "0.1.0"
|
||||
version = "0.2.4"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -8,6 +8,10 @@ edition = "2021"
|
|||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
|
||||
[dependencies.rust-embed]
|
||||
version = "8.4.0"
|
||||
features = ["include-exclude"]
|
||||
|
||||
[dependencies.rocket]
|
||||
version = "0.5.0"
|
||||
features = ["json"]
|
||||
|
|
29
src/main.rs
|
@ -3,13 +3,16 @@ extern crate rocket;
|
|||
use rocket::{
|
||||
fairing::AdHoc,
|
||||
fs::{relative, FileServer},
|
||||
response::stream::Event,
|
||||
http::Status,
|
||||
response::{content, stream::Event},
|
||||
tokio::{
|
||||
self, select,
|
||||
time::{self, Duration},
|
||||
},
|
||||
Request,
|
||||
};
|
||||
use rocket_dyn_templates::Template;
|
||||
use rust_embed::Embed;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
sync::{Arc, RwLock},
|
||||
|
@ -68,6 +71,27 @@ fn clean_expired_evt(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Embed)]
|
||||
#[folder = "static/errors"]
|
||||
#[include = "*.html"]
|
||||
#[exclude = "*.jpg"]
|
||||
struct ErrorPages;
|
||||
|
||||
#[catch(default)]
|
||||
fn handler(status: Status, _: &Request) -> content::RawHtml<String> {
|
||||
content::RawHtml(
|
||||
std::str::from_utf8(
|
||||
ErrorPages::get(format!("{}.html", status.code).as_str())
|
||||
//501 not implemented
|
||||
.unwrap_or(ErrorPages::get("501.html").unwrap())
|
||||
.data
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
#[launch]
|
||||
async fn rocket() -> _ {
|
||||
let rocket = rocket::build();
|
||||
|
@ -106,7 +130,8 @@ async fn rocket() -> _ {
|
|||
.manage(admin_evt_queue.clone())
|
||||
.mount("/", routes![index])
|
||||
.mount("/track", track::routes())
|
||||
.mount("/admin", admin::routes());
|
||||
.mount("/admin", admin::routes())
|
||||
.register("/", catchers![handler]);
|
||||
if config.serve_static {
|
||||
rocket = rocket.mount("/", FileServer::from(relative!("static")));
|
||||
}
|
||||
|
|
196
src/track.rs
|
@ -1,4 +1,5 @@
|
|||
use rocket::{
|
||||
http::Status,
|
||||
response::stream::{Event, EventStream},
|
||||
tokio::{
|
||||
self, select,
|
||||
|
@ -10,15 +11,20 @@ use rocket_dyn_templates::{context, Template};
|
|||
|
||||
use crate::global::{TrackedState::*, *};
|
||||
|
||||
#[get("/")]
|
||||
fn no_id() -> Status {
|
||||
Status::ImATeapot
|
||||
}
|
||||
|
||||
#[get("/<id>?<gpslog>&<dbg>")]
|
||||
fn tracked_view(
|
||||
id: &str,
|
||||
gpslog: Option<bool>,
|
||||
dbg: Option<bool>,
|
||||
tracking: &State<Tracking>,
|
||||
) -> Option<Template> {
|
||||
) -> Result<Template, Status> {
|
||||
if let Some(tracked) = tracking.get(&id.to_string()) {
|
||||
Some(Template::render(
|
||||
Ok(Template::render(
|
||||
match tracked.read().unwrap().state {
|
||||
Vieux { .. } => "vieux",
|
||||
Conscrit { .. } => "conscrit",
|
||||
|
@ -31,7 +37,7 @@ fn tracked_view(
|
|||
},
|
||||
))
|
||||
} else {
|
||||
None
|
||||
Err(Status::BadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,10 +47,10 @@ fn tracked_events<'a>(
|
|||
evt_queue: &'a State<TrackingEventQueue>,
|
||||
config: &State<Config>,
|
||||
mut shutdown: Shutdown,
|
||||
) -> Option<EventStream![Event + 'a]> {
|
||||
) -> Result<EventStream![Event + 'a], Status> {
|
||||
if evt_queue.contains_key(&id.to_string()) {
|
||||
let timeout = Duration::from_millis(config.event_timeout);
|
||||
Some(EventStream! {
|
||||
Ok(EventStream! {
|
||||
let mut interval = time::interval(timeout);
|
||||
loop {
|
||||
select!{
|
||||
|
@ -59,7 +65,7 @@ fn tracked_events<'a>(
|
|||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
Err(Status::BadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,10 +77,13 @@ fn store_pos(
|
|||
tracking: &State<Tracking>,
|
||||
evt_queues: &State<TrackingEventQueue>,
|
||||
admin_queue: &State<AdminEventQueue>,
|
||||
) {
|
||||
) -> Status {
|
||||
if let Some(tracked) = tracking.get(&id.to_string()) {
|
||||
tracked.write().unwrap().pos = (lat, long);
|
||||
state_update(&tracked.read().unwrap(), &evt_queues, &admin_queue);
|
||||
Status::Accepted
|
||||
} else {
|
||||
Status::BadRequest
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,19 +95,23 @@ fn set_state(
|
|||
tracking: &State<Tracking>,
|
||||
evt_queues: &State<TrackingEventQueue>,
|
||||
admin_queue: &State<AdminEventQueue>,
|
||||
) -> Option<()> {
|
||||
let tracked = &mut tracking.get(&id.to_string()).unwrap().write().unwrap();
|
||||
if let Vieux {
|
||||
ref mut invisible,
|
||||
ref mut color,
|
||||
} = tracked.state
|
||||
{
|
||||
*invisible = inv;
|
||||
*color = col;
|
||||
state_update(&tracked, &evt_queues, &admin_queue);
|
||||
Some(())
|
||||
) -> Status {
|
||||
if let Some(tracked) = tracking.get(&id.to_string()) {
|
||||
let tracked = &mut tracked.write().unwrap();
|
||||
if let Vieux {
|
||||
ref mut invisible,
|
||||
ref mut color,
|
||||
} = tracked.state
|
||||
{
|
||||
*invisible = inv;
|
||||
*color = col;
|
||||
state_update(&tracked, &evt_queues, &admin_queue);
|
||||
Status::Accepted
|
||||
} else {
|
||||
Status::MethodNotAllowed
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Status::BadRequest
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,43 +122,47 @@ pub async fn activate_invisibility(
|
|||
evt_queues: &State<TrackingEventQueue>,
|
||||
admin_queue: &State<AdminEventQueue>,
|
||||
config: &State<Config>,
|
||||
) -> Option<()> {
|
||||
let tracked = &mut tracking.get(&id.to_string()).unwrap().write().unwrap();
|
||||
if let Conscrit {
|
||||
ref mut invisible,
|
||||
ref mut invisibility_codes,
|
||||
..
|
||||
} = tracked.state
|
||||
{
|
||||
if *invisibility_codes > 0 {
|
||||
*invisibility_codes -= 1;
|
||||
*invisible = true;
|
||||
state_update(&tracked, &evt_queues, &admin_queue);
|
||||
let track_clone = (*tracking).clone();
|
||||
let queue_clone = (*evt_queues).clone();
|
||||
let admin_clone = (*admin_queue).clone();
|
||||
let id_str = id.to_string();
|
||||
let timeout = Duration::from_millis(config.bonus_timeout);
|
||||
tokio::spawn(async move {
|
||||
sleep(timeout).await;
|
||||
if let Conscrit {
|
||||
ref mut invisible, ..
|
||||
} = track_clone.get(&id_str).unwrap().write().unwrap().state
|
||||
{
|
||||
*invisible = false;
|
||||
}
|
||||
state_update(
|
||||
&track_clone.get(&id_str).unwrap().read().unwrap(),
|
||||
&queue_clone,
|
||||
&admin_clone,
|
||||
);
|
||||
});
|
||||
Some(())
|
||||
) -> Status {
|
||||
if let Some(tracked) = tracking.get(&id.to_string()) {
|
||||
let tracked = &mut tracked.write().unwrap();
|
||||
if let Conscrit {
|
||||
ref mut invisible,
|
||||
ref mut invisibility_codes,
|
||||
..
|
||||
} = tracked.state
|
||||
{
|
||||
if *invisibility_codes > 0 {
|
||||
*invisibility_codes -= 1;
|
||||
*invisible = true;
|
||||
state_update(&tracked, &evt_queues, &admin_queue);
|
||||
let track_clone = (*tracking).clone();
|
||||
let queue_clone = (*evt_queues).clone();
|
||||
let admin_clone = (*admin_queue).clone();
|
||||
let id_str = id.to_string();
|
||||
let timeout = Duration::from_millis(config.bonus_timeout);
|
||||
tokio::spawn(async move {
|
||||
sleep(timeout).await;
|
||||
if let Conscrit {
|
||||
ref mut invisible, ..
|
||||
} = track_clone.get(&id_str).unwrap().write().unwrap().state
|
||||
{
|
||||
*invisible = false;
|
||||
}
|
||||
state_update(
|
||||
&track_clone.get(&id_str).unwrap().read().unwrap(),
|
||||
&queue_clone,
|
||||
&admin_clone,
|
||||
);
|
||||
});
|
||||
Status::Accepted
|
||||
} else {
|
||||
Status::PaymentRequired
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Status::MethodNotAllowed
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Status::BadRequest
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,43 +173,47 @@ pub async fn activate_blur(
|
|||
evt_queues: &State<TrackingEventQueue>,
|
||||
admin_queue: &State<AdminEventQueue>,
|
||||
config: &State<Config>,
|
||||
) -> Option<()> {
|
||||
let tracked = &mut tracking.get(&id.to_string()).unwrap().write().unwrap();
|
||||
if let Conscrit {
|
||||
ref mut blurred,
|
||||
ref mut blur_codes,
|
||||
..
|
||||
} = tracked.state
|
||||
{
|
||||
if *blur_codes > 0 {
|
||||
*blur_codes -= 1;
|
||||
*blurred = true;
|
||||
state_update(&tracked, &evt_queues, &admin_queue);
|
||||
let track_clone = (*tracking).clone();
|
||||
let queue_clone = (*evt_queues).clone();
|
||||
let admin_clone = (*admin_queue).clone();
|
||||
let id_str = id.to_string();
|
||||
let timeout = Duration::from_millis(config.bonus_timeout);
|
||||
tokio::spawn(async move {
|
||||
sleep(timeout).await;
|
||||
if let Conscrit {
|
||||
ref mut blurred, ..
|
||||
} = track_clone.get(&id_str).unwrap().write().unwrap().state
|
||||
{
|
||||
*blurred = false;
|
||||
}
|
||||
state_update(
|
||||
&track_clone.get(&id_str).unwrap().read().unwrap(),
|
||||
&queue_clone,
|
||||
&admin_clone,
|
||||
);
|
||||
});
|
||||
Some(())
|
||||
) -> Status {
|
||||
if let Some(tracked) = tracking.get(&id.to_string()) {
|
||||
let tracked = &mut tracked.write().unwrap();
|
||||
if let Conscrit {
|
||||
ref mut blurred,
|
||||
ref mut blur_codes,
|
||||
..
|
||||
} = tracked.state
|
||||
{
|
||||
if *blur_codes > 0 {
|
||||
*blur_codes -= 1;
|
||||
*blurred = true;
|
||||
state_update(&tracked, &evt_queues, &admin_queue);
|
||||
let track_clone = (*tracking).clone();
|
||||
let queue_clone = (*evt_queues).clone();
|
||||
let admin_clone = (*admin_queue).clone();
|
||||
let id_str = id.to_string();
|
||||
let timeout = Duration::from_millis(config.bonus_timeout);
|
||||
tokio::spawn(async move {
|
||||
sleep(timeout).await;
|
||||
if let Conscrit {
|
||||
ref mut blurred, ..
|
||||
} = track_clone.get(&id_str).unwrap().write().unwrap().state
|
||||
{
|
||||
*blurred = false;
|
||||
}
|
||||
state_update(
|
||||
&track_clone.get(&id_str).unwrap().read().unwrap(),
|
||||
&queue_clone,
|
||||
&admin_clone,
|
||||
);
|
||||
});
|
||||
Status::Accepted
|
||||
} else {
|
||||
Status::PaymentRequired
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Status::MethodNotAllowed
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Status::BadRequest
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,5 +225,6 @@ pub fn routes() -> Vec<Route> {
|
|||
set_state,
|
||||
activate_invisibility,
|
||||
activate_blur,
|
||||
no_id,
|
||||
]
|
||||
}
|
||||
|
|
19
static/errors/400.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>400 Bad Request</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>400 Bad Request</h1>
|
||||
<img src="/errors/cat/400.jpg"/>
|
||||
<p>Conscrit ! Cet identifiant ne correspond à aucune équipe.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/401.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>401 Unauthorized</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>401 Unauthorized</h1>
|
||||
<img src="/errors/cat/401.jpg"/>
|
||||
<p>Il faut s'identifié pour accéder à cette ressource.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/402.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>402 Payment Required</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>402 Payment Required</h1>
|
||||
<img src="/errors/cat/402.jpg"/>
|
||||
<p>Toute les utilisations de ce bonus ont été utilisées.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/404.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>404 Not Found</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>404 Not Found</h1>
|
||||
<img src="/errors/cat/404.jpg"/>
|
||||
<p>Page non trouvé</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/405.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>405 Method Not Allowed</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>405 Method Not Allowed</h1>
|
||||
<img src="/errors/cat/405.jpg"/>
|
||||
<p>Cette équipe n'a pas le droit d'utiliser cet endpoint.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/418.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>418 I’m a teapot</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>418 I’m a teapot</h1>
|
||||
<img src="/errors/cat/418.jpg"/>
|
||||
<p>Il y a quelque-chose ici, mais je montrerai rien.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/498.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>498 Token expired/invalid</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>498 Token expired/invalid</h1>
|
||||
<img src="/errors/cat/498.jpg"/>
|
||||
<p>Le token d'authentification est invalide.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/500.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>500 Internal Server Error</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>500 Internal Server Error</h1>
|
||||
<img src="/errors/cat/500.jpg"/>
|
||||
<p>Erreur Interne</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/501.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>501 Not Implemented</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>501 Not Implemented</h1>
|
||||
<img src="/errors/cat/501.jpg"/>
|
||||
<p>Une erreur inconnue a été rencontré.</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
19
static/errors/503.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>503 Service Unavailable</title>
|
||||
</head>
|
||||
<body align="center">
|
||||
<div role="main" align="center">
|
||||
<h1>503 Service Unavailable</h1>
|
||||
<img src="/errors/cat/503.jpg"/>
|
||||
<p>La traque n'est pas encore prête, on arrive bientôt...</p>
|
||||
<hr />
|
||||
</div>
|
||||
<div role="contentinfo" align="center">
|
||||
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
static/errors/cat/400.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
static/errors/cat/401.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
static/errors/cat/402.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
static/errors/cat/404.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
static/errors/cat/405.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
static/errors/cat/418.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
static/errors/cat/498.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
static/errors/cat/500.jpg
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
static/errors/cat/501.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
static/errors/cat/503.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
|
@ -45,30 +45,30 @@
|
|||
<body>
|
||||
<div id="map"></div>
|
||||
|
||||
<div id="right">
|
||||
<div class="tableFixHead">
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th>Nom</th>
|
||||
<th>Mallette</th>
|
||||
<th>Tracker</th>
|
||||
<th>Invisible</th>
|
||||
<th>Brouillé</th>
|
||||
<th>Code Invisibilité</th>
|
||||
<th>Code Brouillage</th>
|
||||
<th>Couleur</th>
|
||||
<!-- <th>Last Update</th> -->
|
||||
</tr></thead>
|
||||
<tbody id="teamInfos">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="right">
|
||||
<div class="tableFixHead">
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th>Nom</th>
|
||||
<th>Mallette</th>
|
||||
<th>Tracker</th>
|
||||
<th>Invisible</th>
|
||||
<th>Brouillé</th>
|
||||
<th>Code Invisibilité</th>
|
||||
<th>Code Brouillage</th>
|
||||
<th>Couleur</th>
|
||||
<!-- <th>Last Update</th> -->
|
||||
</tr></thead>
|
||||
<tbody id="teamInfos">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<input id="popup"/><button id="sendPopup">Send popup to all clients</button><br/>
|
||||
<br/>
|
||||
<a href="https://dgnum.eu"><img src="/dgnum-logo.png" height=50px /></a><br/>
|
||||
<span style="font-size: 0.8em">Merci à la <a href="https://dgnum.eu">Délégation Générale NUMérique de l'ENS</a>, qui héberge ce site.</span>
|
||||
</div>
|
||||
<input id="popup"/><button id="sendPopup">Send popup to all clients</button><br/>
|
||||
<br/>
|
||||
<a href="https://dgnum.eu"><img src="/dgnum-logo.png" height=50px /></a><br/>
|
||||
<span style="font-size: 0.8em">Merci à la <a href="https://dgnum.eu">Délégation Générale NUMérique de l'ENS</a>, qui héberge ce site.</span>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup_map();
|
||||
|
|