omg so much better updates now doing good
This commit is contained in:
281
src/main.rs
281
src/main.rs
@@ -4,7 +4,7 @@ use std::{collections::HashMap, fs, io::ErrorKind, path::PathBuf, str::FromStr};
|
|||||||
|
|
||||||
use icon::extract_icon;
|
use icon::extract_icon;
|
||||||
use mlua::{
|
use mlua::{
|
||||||
Lua, Table,
|
FromLua, Lua, Number, Table,
|
||||||
Value::{self as LuaValue},
|
Value::{self as LuaValue},
|
||||||
};
|
};
|
||||||
use once_cell::sync::{Lazy, OnceCell};
|
use once_cell::sync::{Lazy, OnceCell};
|
||||||
@@ -17,6 +17,7 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
};
|
};
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
|
use reqwest::Method;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tera::{to_value, Context, Result as TeraResult, Tera, Value};
|
use tera::{to_value, Context, Result as TeraResult, Tera, Value};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
@@ -29,6 +30,34 @@ pub type AResult<T> = Result<T, AError>;
|
|||||||
|
|
||||||
pub static CWD: Lazy<PathBuf> = Lazy::new(|| std::env::current_dir().unwrap());
|
pub static CWD: Lazy<PathBuf> = Lazy::new(|| std::env::current_dir().unwrap());
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct ArrayBuffer(Vec<u8>);
|
||||||
|
|
||||||
|
impl mlua::FromLua for ArrayBuffer {
|
||||||
|
fn from_lua(value: LuaValue, _: &Lua) -> mlua::Result<Self> {
|
||||||
|
if let Some(data) = value.as_str() {
|
||||||
|
return Ok(Self(data.as_bytes().to_owned()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(data) = value.as_table() {
|
||||||
|
let mut out = vec![];
|
||||||
|
for pair in data.pairs::<mlua::Value, mlua::Value>() {
|
||||||
|
let (_, v) = pair?;
|
||||||
|
if let Some(value) = v.as_integer() {
|
||||||
|
out.push(value as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Self(out));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(mlua::Error::FromLuaConversionError {
|
||||||
|
from: value.type_name(),
|
||||||
|
to: "ArrayBuffer".to_string(),
|
||||||
|
message: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub static TERA: Lazy<Tera> = Lazy::new(|| {
|
pub static TERA: Lazy<Tera> = Lazy::new(|| {
|
||||||
let mut tera = Tera::default();
|
let mut tera = Tera::default();
|
||||||
tera.add_raw_template(
|
tera.add_raw_template(
|
||||||
@@ -172,6 +201,48 @@ struct FileInfo {
|
|||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct FetchOptions {
|
||||||
|
method: String,
|
||||||
|
headers: HashMap<String, String>,
|
||||||
|
body: Option<ArrayBuffer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FetchOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
method: "GET".to_string(),
|
||||||
|
headers: HashMap::new(),
|
||||||
|
body: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromLua for FetchOptions {
|
||||||
|
fn from_lua(value: LuaValue, _lua: &Lua) -> mlua::Result<Self> {
|
||||||
|
let Some(options) = value.as_table() else {
|
||||||
|
return Err(mlua::Error::FromLuaConversionError {
|
||||||
|
from: value.type_name(),
|
||||||
|
to: "FetchOptions".to_string(),
|
||||||
|
message: Some("options must be a table".to_string()),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = FetchOptions::default();
|
||||||
|
if let Ok(method) = options.get::<String>("method") {
|
||||||
|
result.method = method;
|
||||||
|
}
|
||||||
|
if let Ok(headers) = options.get::<HashMap<String, String>>("headers") {
|
||||||
|
result.headers = headers;
|
||||||
|
}
|
||||||
|
if let Ok(body) = options.get::<Option<ArrayBuffer>>("body") {
|
||||||
|
result.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> AResult<()> {
|
async fn main() -> AResult<()> {
|
||||||
let listener = tokio::net::TcpListener::bind("[::]:3000").await.unwrap();
|
let listener = tokio::net::TcpListener::bind("[::]:3000").await.unwrap();
|
||||||
@@ -216,12 +287,75 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
|||||||
|
|
||||||
use mlua::{ExternalResult, LuaSerdeExt};
|
use mlua::{ExternalResult, LuaSerdeExt};
|
||||||
|
|
||||||
let fetch_json = lua
|
let fetch = lua
|
||||||
.create_function(|lua, uri: String| {
|
.create_function(|lua, params: (String, Option<FetchOptions>)| {
|
||||||
let resp = reqwest::blocking::get(&uri)
|
let uri = params.0;
|
||||||
|
let options = params.1;
|
||||||
|
let options = options.unwrap_or_default();
|
||||||
|
|
||||||
|
let Ok(method) = Method::from_bytes(options.method.as_bytes()) else {
|
||||||
|
return Err(mlua::Error::RuntimeError("Invalid method".to_string()));
|
||||||
|
};
|
||||||
|
let Ok(uri) = reqwest::Url::parse(&uri) else {
|
||||||
|
return Err(mlua::Error::RuntimeError("Invalid uri".to_string()));
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut request = reqwest::blocking::Request::new(method, uri);
|
||||||
|
// let mut headers = ;
|
||||||
|
|
||||||
|
for (k, v) in &options.headers {
|
||||||
|
let Ok(k) = reqwest::header::HeaderName::from_str(k) else {
|
||||||
|
return Err(mlua::Error::RuntimeError("Invalid header name".to_string()));
|
||||||
|
};
|
||||||
|
let Ok(v) = reqwest::header::HeaderValue::from_str(v) else {
|
||||||
|
return Err(mlua::Error::RuntimeError(
|
||||||
|
"Invalid header value".to_string(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = request.headers_mut().try_append(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
*request.body_mut() = options.body.map(|f| f.0.into());
|
||||||
|
|
||||||
|
let client = reqwest::blocking::Client::new();
|
||||||
|
let resp = client
|
||||||
|
.execute(request)
|
||||||
.and_then(|resp| resp.error_for_status())
|
.and_then(|resp| resp.error_for_status())
|
||||||
.into_lua_err()?;
|
.into_lua_err()?;
|
||||||
let json = resp.json::<serde_json::Value>().into_lua_err()?;
|
|
||||||
|
let json = resp.bytes().into_lua_err()?;
|
||||||
|
lua.to_value(&json.to_vec())
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Lua Error: {:?}", e);
|
||||||
|
render_lua_error(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let base64_encode = lua
|
||||||
|
.create_function(|lua, bytes: ArrayBuffer| {
|
||||||
|
let b64 = BASE64_STANDARD.encode(&bytes.0);
|
||||||
|
lua.to_value(&b64)
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Lua Error: {:?}", e);
|
||||||
|
render_lua_error(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let base64_decode = lua
|
||||||
|
.create_function(|lua, data: ArrayBuffer| {
|
||||||
|
let b64 = BASE64_STANDARD.decode(&data.0).into_lua_err()?;
|
||||||
|
lua.to_value(&b64)
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Lua Error: {:?}", e);
|
||||||
|
render_lua_error(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let json_decode = lua
|
||||||
|
.create_function(|lua, data: ArrayBuffer| {
|
||||||
|
let data = String::from_utf8_lossy(&data.0);
|
||||||
|
let json = serde_json::from_str::<serde_json::Value>(&data).into_lua_err()?; //data.json::<serde_json::Value>().into_lua_err()?;
|
||||||
lua.to_value(&json)
|
lua.to_value(&json)
|
||||||
})
|
})
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -229,14 +363,10 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
|||||||
render_lua_error(e)
|
render_lua_error(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let fetch_b64 = lua
|
let to_string = lua
|
||||||
.create_function(|lua, uri: String| {
|
.create_function(|lua, data: ArrayBuffer| {
|
||||||
let resp = reqwest::blocking::get(&uri)
|
let data = String::from_utf8_lossy(&data.0);
|
||||||
.and_then(|resp| resp.error_for_status())
|
lua.to_value(&data)
|
||||||
.into_lua_err()?;
|
|
||||||
let bytes = resp.bytes().into_lua_err()?;
|
|
||||||
let b64 = BASE64_STANDARD.encode(bytes);
|
|
||||||
lua.to_value(&b64)
|
|
||||||
})
|
})
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Lua Error: {:?}", e);
|
||||||
@@ -253,21 +383,41 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
|||||||
render_lua_error(e)
|
render_lua_error(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
globals.set("fetch", fetch_json).map_err(|e| {
|
globals.set("fetch", fetch).map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Lua Error: {:?}", e);
|
||||||
render_lua_error(e)
|
render_lua_error(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
globals.set("fetch_b64", fetch_b64).map_err(|e| {
|
globals.set("base64_encode", base64_encode).map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Lua Error: {:?}", e);
|
||||||
render_lua_error(e)
|
render_lua_error(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
globals.set("base64_decode", base64_decode).map_err(|e| {
|
||||||
|
eprintln!("Lua Error: {:?}", e);
|
||||||
|
render_lua_error(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
globals.set("json_decode", json_decode).map_err(|e| {
|
||||||
|
eprintln!("Lua Error: {:?}", e);
|
||||||
|
render_lua_error(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// globals.set("fetch_b64", fetch_b64).map_err(|e| {
|
||||||
|
// eprintln!("Lua Error: {:?}", e);
|
||||||
|
// render_lua_error(e)
|
||||||
|
// })?;
|
||||||
|
|
||||||
globals.set("dbg", dbg).map_err(|e| {
|
globals.set("dbg", dbg).map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Lua Error: {:?}", e);
|
||||||
render_lua_error(e)
|
render_lua_error(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
globals.set("to_string", to_string).map_err(|e| {
|
||||||
|
eprintln!("Lua Error: {:?}", e);
|
||||||
|
render_lua_error(e)
|
||||||
|
})?;
|
||||||
|
|
||||||
let request_table = lua.create_table().map_err(|e| {
|
let request_table = lua.create_table().map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Lua Error: {:?}", e);
|
||||||
render_lua_error(e)
|
render_lua_error(e)
|
||||||
@@ -415,6 +565,12 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
|||||||
|
|
||||||
let mut response = Html(script).into_response();
|
let mut response = Html(script).into_response();
|
||||||
|
|
||||||
|
if let Ok(status_code) = result.get::<Number>("code") {
|
||||||
|
if let Ok(code) = StatusCode::from_u16(status_code as u16) {
|
||||||
|
*response.status_mut() = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(headers) = result.get::<Table>("headers") {
|
if let Ok(headers) = result.get::<Table>("headers") {
|
||||||
let pairs = headers.pairs::<String, String>();
|
let pairs = headers.pairs::<String, String>();
|
||||||
|
|
||||||
@@ -425,11 +581,11 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
|||||||
})?;
|
})?;
|
||||||
response.headers_mut().insert(
|
response.headers_mut().insert(
|
||||||
HeaderName::from_str(&k).map_err(|e| {
|
HeaderName::from_str(&k).map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Response Error: {:?}", e);
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||||
})?,
|
})?,
|
||||||
HeaderValue::from_str(&v).map_err(|e| {
|
HeaderValue::from_str(&v).map_err(|e| {
|
||||||
eprintln!("Lua Error: {:?}", e);
|
eprintln!("Response Error: {:?}", e);
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||||
})?,
|
})?,
|
||||||
);
|
);
|
||||||
@@ -439,18 +595,95 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
|||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn render_lua_error(e: mlua::Error) -> (StatusCode, String) {
|
fn render_lua_error(e: mlua::Error) -> (StatusCode, String) {
|
||||||
let e = e
|
match e {
|
||||||
.to_string()
|
mlua::Error::SyntaxError {
|
||||||
.split(':')
|
message,
|
||||||
.skip(4)
|
incomplete_input,
|
||||||
.collect::<Vec<&str>>()
|
} => {
|
||||||
.join(":");
|
let mut message = message.split("]:");
|
||||||
|
message.next();
|
||||||
(
|
(
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
format!("LuaError on line {}", e),
|
message.next().unwrap_or_default().to_string(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
mlua::Error::RuntimeError(message) => (StatusCode::INTERNAL_SERVER_ERROR, message),
|
||||||
|
mlua::Error::MemoryError(message) => (StatusCode::INTERNAL_SERVER_ERROR, message),
|
||||||
|
mlua::Error::SafetyError(message) => (StatusCode::INTERNAL_SERVER_ERROR, message),
|
||||||
|
mlua::Error::MemoryControlNotAvailable => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"MemoryControlNotAvailable".to_string(),
|
||||||
|
),
|
||||||
|
mlua::Error::RecursiveMutCallback => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"RecursiveMutCallback".to_string(),
|
||||||
|
),
|
||||||
|
mlua::Error::CallbackDestructed => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"CallbackDestructed".to_string(),
|
||||||
|
),
|
||||||
|
mlua::Error::StackError => (StatusCode::INTERNAL_SERVER_ERROR, "StackError".to_string()),
|
||||||
|
mlua::Error::BindError => (StatusCode::INTERNAL_SERVER_ERROR, "BindError".to_string()),
|
||||||
|
mlua::Error::BadArgument {
|
||||||
|
to,
|
||||||
|
pos,
|
||||||
|
name,
|
||||||
|
cause,
|
||||||
|
} => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!(
|
||||||
|
"Bad Argument:\n\tto: {}\n\tpos: {}\n\tname: {}\n\tcause: {:?}",
|
||||||
|
to.unwrap_or_default(),
|
||||||
|
pos,
|
||||||
|
name.unwrap_or_default(),
|
||||||
|
cause
|
||||||
|
),
|
||||||
|
),
|
||||||
|
mlua::Error::ToLuaConversionError { from, to, message } => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
message.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
mlua::Error::FromLuaConversionError { from, to, message } => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
message.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
mlua::Error::CoroutineUnresumable => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::UserDataTypeMismatch => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::UserDataDestructed => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::UserDataBorrowError => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::UserDataBorrowMutError => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::MetaMethodRestricted(message) => (StatusCode::INTERNAL_SERVER_ERROR, message),
|
||||||
|
mlua::Error::MetaMethodTypeError {
|
||||||
|
method,
|
||||||
|
type_name,
|
||||||
|
message,
|
||||||
|
} => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
message.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
mlua::Error::MismatchedRegistryKey => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::CallbackError { traceback, cause } => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("{}\n\n{:#?}", traceback, cause),
|
||||||
|
),
|
||||||
|
mlua::Error::PreviouslyResumedPanic => (StatusCode::INTERNAL_SERVER_ERROR, String::new()),
|
||||||
|
mlua::Error::SerializeError(message) => (StatusCode::INTERNAL_SERVER_ERROR, message),
|
||||||
|
mlua::Error::DeserializeError(message) => (StatusCode::INTERNAL_SERVER_ERROR, message),
|
||||||
|
mlua::Error::ExternalError(error) => {
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, format!("{:#?}", error))
|
||||||
|
}
|
||||||
|
mlua::Error::WithContext { context, cause } => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("{}\n\n{:#?}", context, cause),
|
||||||
|
),
|
||||||
|
_ => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
String::from("Unknown Error"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn handler(request: Request) -> Result<Html<String>, (StatusCode, String)> {
|
async fn handler(request: Request) -> Result<Html<String>, (StatusCode, String)> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
Reference in New Issue
Block a user