Compare commits
2 commits
515e5ed199
...
9c3002a8d0
Author | SHA1 | Date | |
---|---|---|---|
9c3002a8d0 | |||
8581bc5f65 |
11 changed files with 1048 additions and 91 deletions
822
Cargo.lock
generated
822
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
13
Cargo.toml
13
Cargo.toml
|
@ -5,5 +5,14 @@ edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies.rocket]
|
||||||
rocket = { version = "=0.5.0-rc.3", features = ["json"] }
|
version = "=0.5.0-rc.3"
|
||||||
|
features = ["json"]
|
||||||
|
|
||||||
|
[dependencies.rocket_dyn_templates]
|
||||||
|
version = "=0.1.0-rc.3"
|
||||||
|
features = ["tera"]
|
||||||
|
|
||||||
|
[dependencies.rust-embed]
|
||||||
|
version = "6.7.0"
|
||||||
|
features = ["debug-embed"]
|
||||||
|
|
BIN
public/atkinson-hyperlegible-all-400-normal.woff
Normal file
BIN
public/atkinson-hyperlegible-all-400-normal.woff
Normal file
Binary file not shown.
BIN
public/atkinson-hyperlegible-latin-400-normal.woff2
Normal file
BIN
public/atkinson-hyperlegible-latin-400-normal.woff2
Normal file
Binary file not shown.
BIN
public/atkinson-hyperlegible-latin-ext-400-normal.woff2
Normal file
BIN
public/atkinson-hyperlegible-latin-ext-400-normal.woff2
Normal file
Binary file not shown.
72
public/style.css
Normal file
72
public/style.css
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--background-color: #f6f5f4;
|
||||||
|
--text-color: black;
|
||||||
|
--link-color: darkblue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--background-color: #191919;
|
||||||
|
--text-color: #E9E9E9;
|
||||||
|
--link-color: cyan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Atkinson Hyperlegible", sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: auto;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
color: var(--text-color)
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Atkinson Hyperlegible;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(/public/woff2/atkinson-hyperlegible-latin-ext-400-normal.woff2) format("woff2"),
|
||||||
|
url(/public/woff/atkinson-hyperlegible-all-400-normal.woff) format("woff");
|
||||||
|
unicode-range: U+0100-024F,
|
||||||
|
U+0259,
|
||||||
|
U+1E00-1EFF,
|
||||||
|
U+2020,
|
||||||
|
U+20A0-20AB,
|
||||||
|
U+20AD-20CF,
|
||||||
|
U+2113,
|
||||||
|
U+2C60-2C7F,
|
||||||
|
U+A720-A7FF
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Atkinson Hyperlegible;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(/public/woff2/atkinson-hyperlegible-latin-400-normal.woff2) format("woff2"),
|
||||||
|
url(/public/woff/atkinson-hyperlegible-all-400-normal.woff) format("woff");
|
||||||
|
unicode-range: U+0000-00FF,
|
||||||
|
U+0131,
|
||||||
|
U+0152-0153,
|
||||||
|
U+02BB-02BC,
|
||||||
|
U+02C6,
|
||||||
|
U+02DA,
|
||||||
|
U+02DC,
|
||||||
|
U+2000-206F,
|
||||||
|
U+2074,
|
||||||
|
U+20AC,
|
||||||
|
U+2122,
|
||||||
|
U+2191,
|
||||||
|
U+2193,
|
||||||
|
U+2212,
|
||||||
|
U+2215,
|
||||||
|
U+FEFF,
|
||||||
|
U+FFFD
|
||||||
|
}
|
50
src/assets.rs
Normal file
50
src/assets.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use rocket::http::Status;
|
||||||
|
use rust_embed::RustEmbed;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "public/"]
|
||||||
|
pub struct PublicAssets;
|
||||||
|
|
||||||
|
#[derive(Responder)]
|
||||||
|
#[response(status = 200, content_type = "font/woff2")]
|
||||||
|
pub struct RawWoff2Font(pub Cow<'static, [u8]>);
|
||||||
|
|
||||||
|
#[derive(Responder)]
|
||||||
|
#[response(status = 200, content_type = "font/woff")]
|
||||||
|
pub struct RawWoffFont(pub Cow<'static, [u8]>);
|
||||||
|
|
||||||
|
#[get("/style.css")]
|
||||||
|
pub fn style() -> Result<rocket::response::content::RawCss<String>, Status> {
|
||||||
|
let style = PublicAssets::get("style.css").unwrap();
|
||||||
|
match std::str::from_utf8(&style.data) {
|
||||||
|
Ok(style) => Ok(rocket::response::content::RawCss::<String>(style.to_string())),
|
||||||
|
Err(_) => Err(Status::InternalServerError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/woff2/<font>")]
|
||||||
|
pub fn woff2_font(font: &str) -> Result<RawWoff2Font, Status> {
|
||||||
|
let latin = "atkinson-hyperlegible-latin-400-normal.woff2";
|
||||||
|
let latin_ext = "atkinson-hyperlegible-latin-ext-400-normal.woff2";
|
||||||
|
|
||||||
|
if font == latin {
|
||||||
|
Ok(RawWoff2Font(PublicAssets::get(latin).unwrap().data))
|
||||||
|
} else if font == latin_ext {
|
||||||
|
Ok(RawWoff2Font(PublicAssets::get(latin_ext).unwrap().data))
|
||||||
|
} else {
|
||||||
|
Err(Status::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/woff/<font>")]
|
||||||
|
pub fn woff_font(font: &str) -> Result<RawWoffFont, Status> {
|
||||||
|
let all = "atkinson-hyperlegible-all-400-normal.woff";
|
||||||
|
|
||||||
|
if font == all {
|
||||||
|
Ok(RawWoffFont(PublicAssets::get(all).unwrap().data))
|
||||||
|
} else {
|
||||||
|
Err(Status::NotFound)
|
||||||
|
}
|
||||||
|
}
|
18
src/links.rs
Normal file
18
src/links.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
static NAMES: [&str; 3] = ["mossfet.xyz", "fries.gay", "ta-kev.digital"];
|
||||||
|
|
||||||
|
pub fn previous_url(source_url: &String) -> Option<String> {
|
||||||
|
match NAMES.iter().position(|&r| r == source_url) {
|
||||||
|
Some(index) if index == 0 => Some(NAMES[NAMES.len() - 1].to_string()),
|
||||||
|
Some(index) => Some(NAMES[index - 1].to_string()),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_url(source_url: &String) -> Option<String> {
|
||||||
|
// this is gay
|
||||||
|
match NAMES.iter().position(|&r| r == source_url) {
|
||||||
|
Some(index) if index == NAMES.len() - 1 => Some(NAMES[0].to_string()),
|
||||||
|
Some(index) => Some(NAMES[index + 1].to_string()),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
82
src/main.rs
82
src/main.rs
|
@ -1,74 +1,22 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
use rocket::response::Redirect;
|
use rocket_dyn_templates::Template;
|
||||||
use rocket::serde::{json::Json, Serialize};
|
|
||||||
|
|
||||||
static NAMES: [&str; 3] = ["mossfet.xyz", "fries.gay", "ta-kev.digital"];
|
mod assets;
|
||||||
|
mod links;
|
||||||
#[derive(Serialize)]
|
mod routes;
|
||||||
#[serde(crate = "rocket::serde")]
|
|
||||||
struct JsonResponse {
|
|
||||||
previous_site_name: Option<String>,
|
|
||||||
next_site_name: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/")]
|
|
||||||
fn index() -> &'static str {
|
|
||||||
"Like, this is a webring, meow!"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn previous_url(source_url: &String, overflow: bool) -> Option<String> {
|
|
||||||
match NAMES.iter().position(|&r| r == source_url) {
|
|
||||||
Some(index) if index == 0 => {
|
|
||||||
if !overflow {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(NAMES[NAMES.len() - 1].to_string())
|
|
||||||
},
|
|
||||||
Some(index) => Some(NAMES[index - 1].to_string()),
|
|
||||||
None => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_url(source_url: &String, overflow: bool) -> Option<String> {
|
|
||||||
// this is gay
|
|
||||||
match NAMES.iter().position(|&r| r == source_url) {
|
|
||||||
Some(index) if index == NAMES.len() - 1 => {
|
|
||||||
if !overflow {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(NAMES[0].to_string())
|
|
||||||
}
|
|
||||||
Some(index) => Some(NAMES[index + 1].to_string()),
|
|
||||||
None => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/previous?<source_url>")]
|
|
||||||
fn previous(source_url: String) -> Redirect {
|
|
||||||
match previous_url(&source_url, true) {
|
|
||||||
Some(url) => Redirect::to(format!("https://{}", url)),
|
|
||||||
None => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/next?<source_url>")]
|
|
||||||
fn next(source_url: String) -> Redirect {
|
|
||||||
match next_url(&source_url, true) {
|
|
||||||
Some(url) => Redirect::to(format!("https://{}", url)),
|
|
||||||
None => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/name?<source_url>")]
|
|
||||||
fn name(source_url: String) -> Json<JsonResponse> {
|
|
||||||
Json(JsonResponse {
|
|
||||||
previous_site_name: previous_url(&source_url, false),
|
|
||||||
next_site_name: next_url(&source_url, false),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[launch]
|
#[launch]
|
||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
rocket::build().mount("/", routes![index, previous, next, name])
|
rocket::build()
|
||||||
|
.attach(Template::fairing())
|
||||||
|
.mount(
|
||||||
|
"/",
|
||||||
|
routes![routes::index, routes::previous, routes::next, routes::name],
|
||||||
|
)
|
||||||
|
.register("/", catchers![routes::not_found])
|
||||||
|
.mount(
|
||||||
|
"/public",
|
||||||
|
routes![assets::style, assets::woff2_font, assets::woff_font],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
67
src/routes.rs
Normal file
67
src/routes.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use crate::links::{next_url, previous_url};
|
||||||
|
use rocket::{
|
||||||
|
http::Status,
|
||||||
|
response::Redirect,
|
||||||
|
serde::{json::Json, Serialize},
|
||||||
|
};
|
||||||
|
use rocket_dyn_templates::Template;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
struct ErrorTemplate<'a> {
|
||||||
|
error: &'a str,
|
||||||
|
error_description: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
const NOT_FOUND_ERROR: ErrorTemplate = ErrorTemplate {
|
||||||
|
error: "Not Found",
|
||||||
|
error_description: "this URL could not be found on the webring.",
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
pub struct JsonResponse {
|
||||||
|
previous_site_name: Option<String>,
|
||||||
|
next_site_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
pub fn index() -> &'static str {
|
||||||
|
"Like, this is a webring, meow!"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/previous?<source_url>")]
|
||||||
|
pub fn previous(source_url: String) -> Result<Redirect, Status> {
|
||||||
|
match previous_url(&source_url) {
|
||||||
|
Some(url) => Ok(Redirect::to(format!("https://{}", url))),
|
||||||
|
None => Err(Status::NotFound),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/next?<source_url>")]
|
||||||
|
pub fn next(source_url: String) -> Result<Redirect, Status> {
|
||||||
|
match next_url(&source_url) {
|
||||||
|
Some(url) => Ok(Redirect::to(format!("https://{}", url))),
|
||||||
|
None => Err(Status::NotFound),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/name?<source_url>")]
|
||||||
|
pub fn name(source_url: String) -> Result<Json<JsonResponse>, Status> {
|
||||||
|
let previous_site_name = previous_url(&source_url);
|
||||||
|
let next_site_name = next_url(&source_url);
|
||||||
|
|
||||||
|
if previous_site_name.is_none() && next_site_name.is_none() {
|
||||||
|
return Err(Status::NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Json(JsonResponse {
|
||||||
|
previous_site_name,
|
||||||
|
next_site_name,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[catch(404)]
|
||||||
|
pub fn not_found() -> Template {
|
||||||
|
Template::render("error", NOT_FOUND_ERROR)
|
||||||
|
}
|
15
templates/error.html.tera
Normal file
15
templates/error.html.tera
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<title>Meowy Webring - {{ error }}</title>
|
||||||
|
<link rel="stylesheet" href="/public/style.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>{{ error }}</h1>
|
||||||
|
<p>{{ error_description }}</p>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue