Switch to relative time, path parsing, SVG templating

This commit is contained in:
2023-06-17 02:36:28 -05:00
parent 3b5fc36744
commit f7dcfffd07
4 changed files with 144 additions and 35 deletions

View File

@@ -1,16 +1,18 @@
mod config;
use std::net::SocketAddr;
use std::time::SystemTime;
use axum::{http::StatusCode, response::IntoResponse, Router, routing::{get}};
use axum::body::{Full};
use axum::extract::ConnectInfo;
use axum::extract::{ConnectInfo, Path};
use axum::http::{header, HeaderMap};
use axum::response::Response;
use dotenvy::dotenv;
use lazy_static::lazy_static;
use config::Configuration;
use tera::{Tera, Context};
use timeago::Formatter;
mod svg;
@@ -46,7 +48,7 @@ async fn main() {
.with_max_level(config.log_level())
.init();
let app = Router::new().route("/", get(root_handler));
let app = Router::new().route("/:path", get(root_handler));
let addr = SocketAddr::from((config.socket_addr(), config.port));
axum::Server::bind(&addr)
.serve(app.into_make_service_with_connect_info::<SocketAddr>())
@@ -54,21 +56,51 @@ async fn main() {
.unwrap();
}
// basic handler that responds with a static string
async fn root_handler(connect_info: ConnectInfo<SocketAddr>, headers: HeaderMap) -> impl IntoResponse {
let renderer = svg::Renderer::new();
fn convert_epoch(epoch: u64) -> SystemTime {
SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(epoch)
}
let mut context = Context::new();
fn parse_path(path: String) -> Result<(SystemTime, String), String> {
if path.contains(".") {
let split_path = path.split_once(".").unwrap();
let epoch_int = split_path.0.parse::<u64>();
if epoch_int.is_err() {
return Err("Epoch is not a valid integer.".to_string());
}
let mut ip_repr: Option<String> = headers.get("X-Forwarded-For").and_then(|hv| Some(String::from(hv.to_str().unwrap())));
if ip_repr.is_none() {
let connect_ip = connect_info.ip().to_string();
ip_repr = Some(connect_ip.to_string());
return Ok((convert_epoch(epoch_int.unwrap()), split_path.1.parse().unwrap()));
}
context.insert("text", &ip_repr.unwrap());
let data = TEMPLATES.render("basic.svg", &context);
let epoch_int = path.parse::<u64>();
if epoch_int.is_err() {
return Err("Epoch is not a valid integer.".to_string());
}
Ok(
(convert_epoch(epoch_int.unwrap()), String::from("svg"))
)
}
// basic handler that responds with a static string
async fn root_handler(Path(path): Path<String>) -> impl IntoResponse {
let renderer = svg::Renderer::new();
let mut context = Context::new();
let f = Formatter::new();
let parse_result = parse_path(path);
if parse_result.is_err() {
return Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Full::from(parse_result.err().unwrap()))
.unwrap();
}
let (epoch, extension) = parse_result.unwrap();
context.insert("text", &f.convert(epoch.elapsed().ok().unwrap()));
context.insert("width", "512");
context.insert("height", "34");
let data = TEMPLATES.render("basic.svg", &context);
if data.is_err() {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
@@ -78,20 +110,35 @@ async fn root_handler(connect_info: ConnectInfo<SocketAddr>, headers: HeaderMap)
.unwrap();
}
let raw_image = renderer.render(data.unwrap().into_bytes());
match extension.as_str() {
"svg" => {
Response::builder()
.header(header::CONTENT_TYPE, "image/svg+xml")
.body(Full::from(data.unwrap()))
.unwrap()
}
"png" => {
let raw_image = renderer.render(data.unwrap().into_bytes());
if raw_image.is_err() {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Full::from(
format!("Internal Server Error :: {}", raw_image.err().unwrap())
))
.unwrap();
}
if raw_image.is_err() {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Full::from(
format!("Internal Server Error :: {}", raw_image.err().unwrap())
))
.unwrap();
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "image/x-png")
.body(Full::from(raw_image.unwrap()))
.unwrap()
}
_ => {
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Full::from("Unsupported extension."))
.unwrap()
}
}
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "image/x-png")
.body(Full::from(raw_image.unwrap()))
.unwrap()
}

View File

@@ -1,3 +1,6 @@
<svg width="256" height="32" xmlns="http://www.w3.org/2000/svg" font-family="Arial" font-size="28">
<text x="10" y="28">{{ text }}</text>
<svg width="{{ width }}" height="{{ height }}" xmlns="http://www.w3.org/2000/svg" font-family="Roboto Mono" font-size="27">
<text x="8" y="27">{{ text }}</text>
<style>
text
</style>
</svg>

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 209 B