add QR Tracking, and czb page

main
Volkor 2023-02-24 02:49:41 +11:00
parent 8aff815ec8
commit 64cea76b50
Signed by: Volkor
GPG Key ID: BAD7CA8A81CC2DA5
3 changed files with 115 additions and 3 deletions

View File

@ -240,6 +240,31 @@ pub async fn get_old_files(sqlconn: &Pool<Sqlite>) -> Vec<String> {
files
}
// This function adds a new QR code scan to the database
// This uses the current time.
// Version is the 'iteration' of the QR Code, since in the future there wil be different QR Codes.
pub async fn add_qrscan(sqlconn: &Pool<Sqlite>, ip: String, useragent: String, version: String) -> Result<SqliteQueryResult, sqlx::Error>{
let time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as i32;
let result = sqlx::query!(
"INSERT INTO qrscan (
time,
IP,
useragent,
version)
VALUES ( ?,?,?,? )",
time,
ip,
useragent,
version
)
.execute(sqlconn)
.await;
result
}
// Updating the expiry_override of a file.
fn update_expiry_override() {
todo!()

View File

@ -1,7 +1,7 @@
use once_cell::sync::OnceCell;
use ramhorns::{Content, Ramhorns};
use salvo::fs::NamedFile;
use salvo::hyper::header::HOST;
use salvo::hyper::header::{HOST, USER_AGENT};
use salvo::prelude::*;
use salvo::serve_static::{StaticDir, StaticFile};
use sqlx::SqlitePool;
@ -424,8 +424,11 @@ async fn upload(req: &mut Request, res: &mut Response) {
#[handler]
async fn serve_static(req: &mut Request, res: &mut Response) {
let headers = req.headers();
let headers = &req.headers().clone();
let host = headers[HOST].to_str().unwrap_or("None");
let ip = engine::guess_ip(req);
let useragent = headers[USER_AGENT].to_str().unwrap();
match req.uri().path() {
"/services" => {
tracing::info!("New Request: /services");
@ -502,8 +505,48 @@ async fn serve_static(req: &mut Request, res: &mut Response) {
res.set_status_code(StatusCode::OK);
res.render(Text::Html(rendered));
}
"/czb" => {
tracing::info!("New Request: /czb");
let template_with_host = "./templates/".to_owned() + headers[HOST].to_str().unwrap();
let tpls: Ramhorns = Ramhorns::from_folder(template_with_host).unwrap();
let template = TemplateStruct {
domain: String::from(headers[HOST].to_str().unwrap()),
fileurl: String::from(""),
adminurl: String::from(""),
message1: rand::thread_rng().gen_range(0..1).to_string(),
message2: String::from(""),
};
let rendered = tpls.get("czb.html").unwrap().render(&template);
res.set_status_code(StatusCode::OK);
res.render(Text::Html(rendered));
}
"/qr" => {
tracing::info!("New Request: /qr");
// Setup the Sqlite pool stuff for later
let sqlconn = SQLITE.get().unwrap();
// Get the headers (for Host header stuff thats needed later)
let headers = req.headers().clone();
let host = headers[HOST].to_str().unwrap();
if db::add_qrscan(sqlconn, ip, useragent.to_string(), "1".to_string()).await.is_err() {
tracing::error!("Failed to add QR Scan to the database.");
}
let template_with_host = "./templates/".to_owned() + headers[HOST].to_str().unwrap();
let tpls: Ramhorns = Ramhorns::from_folder(template_with_host).unwrap();
let template = TemplateStruct {
domain: String::from(headers[HOST].to_str().unwrap()),
fileurl: String::from(""),
adminurl: String::from(""),
message1: rand::thread_rng().gen_range(0..1).to_string(),
message2: String::from(""),
};
let rendered = tpls.get("qr.html").unwrap().render(&template);
res.set_status_code(StatusCode::OK);
res.render(Text::Html(rendered));
}
_ => {
tracing::info!("Bad Request");
tracing::info!("Bad Request Received");
}
}
}
@ -710,6 +753,8 @@ async fn main() {
// Static Pages
.push(Router::with_path("/services").get(serve_static))
.push(Router::with_path("/about").get(serve_static))
.push(Router::with_path("/czb").get(serve_static))
.push(Router::with_path("/qr").get(serve_static))
.push(Router::with_path("/faq").get(serve_static))
.push(Router::with_path("/dmca").get(serve_static))
.push(Router::with_path("/welcome").get(serve_static))

View File

@ -0,0 +1,42 @@
{{>regular.html}}
<title>QR - {{domain}}</title>
<p>How did you even find this page????</p>
<p>⢾⣷⣷⣾⣷⣿⣾⣷⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣾⣿⣷⣿⣷⣿⣷⣿⣿⣾⣷⣿⣾⣷⣿⣾⣷⣿⣾⣿⣿⣿⣿⣿⣿⣿⣾⣾⣷⣿⣷⣿⣷⣿⣾⣶⣷⣾⣶⣿⣾⣷⣾⣶⣷⣶⢶⡶⣶⢶⠶⡶⡓⠞⠶⡀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣯⡿⣽⢾⡭⣟⡵⣫⢎⡳⢥⠙⡌⠱⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣳⣭⡛⠿⣿⣿⣿⣿⣿⣯⣷⢿⣯⢿⡽⣺⢵⡫⢼⡑⠎⡔⢢⠡⢀⠃⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⠲⠈⠙⢿⣿⣷⢿⣯⣟⡾⢧⣻⢱⢣⠝⣢⠙⡌⠘⠄⡁⠂⠁⠀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣛⢦⡱⢂⠞⣌⠳⡍⢯⣙⢯⣛⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠛⢷⣄⠀⠸⢿⣿⣟⡾⣝⢾⡹⢆⠯⡘⡜⢠⠡⢀⠁⠂⠀⠀⠀⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢍⡳⣍⠶⣩⠏⡞⣬⠳⣜⠣⡝⠮⣝⡾⢯⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⡯⢀⠀⠹⣦⠀⠸⣿⡿⣽⢮⣳⠹⣌⠖⡡⢘⡀⢂⠀⠄⠀⠀⠀⠀⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢇⡻⡱⢍⡚⡔⢫⠱⢪⡕⣊⠳⣍⠳⣌⠿⣭⢳⣏⢾⡽⣿⣿⣿⣿⣿⣿⣿⣿⣆⠉⠀⠀⣿⣧⠀⠈⢿⣗⡏⢶⡙⡔⢊⠱⠠⠐⡀⠀⠀⠀⠀⠀⠀⠀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣡⢣⠙⢢⠱⢌⢣⡙⠦⣙⡔⢣⠎⡵⢌⠻⡔⢯⡞⣭⢟⣷⣻⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⢸⣾⣷⡀⠀⢻⣞⡱⢞⢨⠁⠎⡁⠂⠄⠀⠁⠀⠀⠀⠀⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠜⡄⢣⠉⠆⡑⢈⠰⢈⠒⡅⢮⣑⢪⡱⣎⢳⡘⢧⡻⣜⢯⡶⣯⣟⣿⣿⣿⣿⣿⣿⣿⠁⠀⢸⣿⣿⣷⡀⠀⠹⣏⢆⠣⡘⢠⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀
⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢣⠘⣤⠉⠂⡔⢠⠃⡎⠘⢱⠂⠓⣦⠑⣮⢣⡜⢣⢻⣬⣷⢹⣷⣿⣯⣿⣿⣿⣿⣿⣿⣧⠀⠀⣿⢻⠈⢱⠀⠀⣿⡌⡆⢱⠀⡌⠀⠂⠀⠀⠀⠀⠀⠀⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣏⢆⠁⡐⢂⠐⢌⡐⢠⡙⢬⣉⠳⣄⠳⣘⢎⡱⢍⠮⣝⣷⣻⢿⣿⣿⣯⣿⣿⣿⣿⣿⣿⡄⠀⢸⡘⢧⠀⠁⠀⢻⡇⡜⢠⠒⠀⡁⠀⠀⠀⠀⠀⠀⠀⠀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⢛⠿⡻⢎⡐⠡⠂⠌⠠⢀⠡⢘⠤⢌⡳⢾⠱⡌⢆⡳⢌⠳⣎⢼⣻⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠆⠀⠘⡇⠀⢳⡀⠀⢸⡗⢌⠢⠈⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡻⣌⠳⣡⢣⢀⠑⡈⠄⢁⠂⢀⡀⠊⡐⢣⢏⣶⠩⢦⡁⢎⡕⢪⠖⣽⣿⡽⣿⣿⣻⣿⣿⣿⣿⡿⠀⠀⠈⣿⡀⠀⠃⢀⣼⡏⡐⢂⠉⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⢧⣍⢳⣤⣣⣼⣦⣤⣤⣀⡌⢀⠠⠁⡐⢀⣾⡀⡙⣿⡀⠌⣎⢣⢛⣼⣷⣿⣿⣿⣽⣿⣿⣿⡿⢤⡀⠀⠀⢿⠀⠀⠀⢸⣿⠡⢘⠠⢈⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣧⢻⣾⣿⣿⠿⡿⣿⢿⣿⣿⣿⣷⣾⣯⣽⣿⠀⢹⣿⣷⣈⣷⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡈⠁⠀⢸⠀⢀⠀⣾⡟⢄⠣⢐⠀⢂⠈⠀⠀⠀⠀⠀⠀⠀⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡯⣷⣿⣟⢿⡁⣄⣀⣩⣭⣾⣿⣿⣿⣿⣿⠟⠋⠀⠂⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣶⣶⣧⣿⣾⣿⣝⣿⣦⠀⢸⡆⠘⣶⣿⡴⣈⠦⢁⠊⠄⠠⠁⠀⠀⠀⠀⠀⠀⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡳⣍⠮⣱⣾⣿⠿⠿⣿⣿⣿⣿⣿⣿⡿⢙⡶⢁⠠⢑⣾⣿⣿⣿⣿⣿⣿⣿⡻⠿⣿⢿⣿⣿⣿⣿⣿⣿⣷⠀⠀⣇⠀⢷⣸⡗⡰⢌⠢⠁⠌⡀⠄⠀⠀⠀⠀⠀⠀⠀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣵⣉⠖⡩⠅⠠⠈⠓⠠⠞⠛⢛⣻⣿⡿⠃⡔⠀⠆⢼⣯⣿⣿⣿⣿⣿⣿⣿⣽⢷⣎⡿⣿⡿⣿⣯⣿⣻⣿⡃⠀⣿⡀⠈⢿⣏⠴⡈⢆⡉⠐⠠⡀⠀⠀⠀⠀⠀⠀⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡞⣜⠸⠠⠙⡄⠂⠄⡀⠀⠤⢾⠿⠋⠀⣁⠠⠑⡌⢰⢻⣿⣿⣿⣿⣿⣿⣿⣿⣟⡾⣷⢯⡿⣽⣳⣟⣿⣿⠁⢀⣿⢱⣿⠸⣿⡒⡍⢆⡌⢡⠡⠐⡀⠀⠀⠀⠀⠀⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣌⠳⡑⢆⠀⠁⠄⡀⢈⠐⠁⠀⠀⠌⡁⢂⠡⠘⢠⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⡷⣿⢯⣿⣿⣿⣿⠀⢸⡟⣰⠿⣟⣿⡕⣎⢣⠜⣢⢁⠣⣀⠡⠀⠀⠀⠀⠀
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢳⡉⢆⠣⢀⠠⠐⠀⢂⠠⠀⠀⢐⠰⢈⣌⠁⠆⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⣿⣿⣾⣿⣿⠀⠈⠀⣿⣿⢱⣿⡽⣬⢓⡞⢤⢋⠴⡀⠆⠡⠀⠀⠀⠀
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⢣⡝⣌⠒⡄⠀⠄⡁⠀⠀⣄⣾⠃⢌⣰⢾⣀⣠⠋⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⠀⠀⠀⣿⣷⣟⣯⣳⡝⡾⣜⣣⢏⠶⣉⢎⡡⢌⠠⠁⠀
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡧⣘⠤⡋⢄⠃⡀⠀⢂⠿⢋⠡⢘⠸⠟⡻⡅⢦⣙⣶⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣯⣻⣿⣏⠀⠀⠀⣿⡿⣽⣞⣷⣻⡵⣏⣞⢮⡳⣍⢦⠓⣌⠢⡑⠠
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡱⢊⡕⢊⡔⠡⣀⡍⡐⢦⠞⣃⠦⣉⠱⢈⣿⡿⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣹⣿⠻⣆⠀⢸⣿⣿⢷⣻⣞⣷⣻⡽⣮⢷⣻⣜⢮⣛⡴⣃⢇⠣
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣕⢣⡜⢢⠐⣡⢩⣵⡎⢆⠭⣐⠢⡑⢊⠼⣿⡷⣇⢞⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⡿⢴⣿⣿⣿⣿⣿⣿⣟⣿⡷⣿⣽⢯⣟⡷⣞⣯⡞⡶⣭⢎⡳
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡲⣌⠡⢃⢼⡟⣤⣽⣴⣦⣥⣶⣤⣧⣬⣽⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣟⣾⣿⣿⣿⣿⣿⣿⣻⣯⣿⣟⣯⣿⣯⣿⡽⣾⣽⣻⣼⣣⢟
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣗⣮⢓⠆⡌⣿⣍⠲⡐⢆⡒⡌⢦⣩⣜⣩⣝⣭⣟⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣷⣿⣟⣾⢷⣳⣟⣾
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣼⡭⣞⠜⡫⠔⡭⡙⢦⡑⣎⢧⣷⣿⢿⡻⣟⡾⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⡿⣯⣿⣾
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣞⡬⣫⠵⣉⠦⡙⢢⠱⣌⠒⡌⣌⢢⡙⣬⣙⡷⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿
⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⢇⣿⣻⢤⠛⣄⠣⡘⢧⠘⡠⢇⡸⣄⡻⣼⢧⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣼⣻⣯⣟⡬⢷⢿⣦⣧⣷⣾⣿⣯⣿⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⢈⣿⣷⡈⢿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⡿⣿⣽⣿⣿⠿⡿⣿⣷⣾⣷⣿⣾⣿⣾⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣂⣸⣿⣿⣷⢀⢿⣿⣿⣿⣿⣿⣟⣻⠿⢿⣿⣿⣿⣿⣿⣿
⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⡷⣭⣛⣷⣯⣻⢱⢏⡟⢿⣿⣾⣽⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣚⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣭⣙⡛⠿⢿
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣽⡲⣝⠦⣍⠻⢿⣮⣜⡣⢞⡽⣏⡿⣹⢛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦
⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣳⡝⣮⠽⣘⢳⠢⡜⡙⢻⣷⣮⣹⢼⡱⣮⢳⣳⣯⣿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣽⢎⡷⣙⢎⡱⠌⣅⠣⣀⠚⡝⠿⣿⣾⣿⣿⡟⣫⣵⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⡾⣱⣋⠞⡴⣉⠔⢢⠠⠑⣨⣿⠿⠛⣛⣻⣽⣷⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣥⢫⣝⢲⡡⠞⡠⣥⣾⣿⣏⣼⣧⣬⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣭⣷⣮⣧⣇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿</p>