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 mlua::{
|
||||
Lua, Table,
|
||||
FromLua, Lua, Number, Table,
|
||||
Value::{self as LuaValue},
|
||||
};
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
@@ -17,6 +17,7 @@ use axum::{
|
||||
routing::get,
|
||||
};
|
||||
use base64::prelude::*;
|
||||
use reqwest::Method;
|
||||
use serde::Serialize;
|
||||
use tera::{to_value, Context, Result as TeraResult, Tera, Value};
|
||||
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());
|
||||
|
||||
#[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(|| {
|
||||
let mut tera = Tera::default();
|
||||
tera.add_raw_template(
|
||||
@@ -172,6 +201,48 @@ struct FileInfo {
|
||||
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]
|
||||
async fn main() -> AResult<()> {
|
||||
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};
|
||||
|
||||
let fetch_json = lua
|
||||
.create_function(|lua, uri: String| {
|
||||
let resp = reqwest::blocking::get(&uri)
|
||||
let fetch = lua
|
||||
.create_function(|lua, params: (String, Option<FetchOptions>)| {
|
||||
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())
|
||||
.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)
|
||||
})
|
||||
.map_err(|e| {
|
||||
@@ -229,14 +363,10 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
||||
render_lua_error(e)
|
||||
})?;
|
||||
|
||||
let fetch_b64 = lua
|
||||
.create_function(|lua, uri: String| {
|
||||
let resp = reqwest::blocking::get(&uri)
|
||||
.and_then(|resp| resp.error_for_status())
|
||||
.into_lua_err()?;
|
||||
let bytes = resp.bytes().into_lua_err()?;
|
||||
let b64 = BASE64_STANDARD.encode(bytes);
|
||||
lua.to_value(&b64)
|
||||
let to_string = lua
|
||||
.create_function(|lua, data: ArrayBuffer| {
|
||||
let data = String::from_utf8_lossy(&data.0);
|
||||
lua.to_value(&data)
|
||||
})
|
||||
.map_err(|e| {
|
||||
eprintln!("Lua Error: {:?}", e);
|
||||
@@ -253,21 +383,41 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
||||
render_lua_error(e)
|
||||
})?;
|
||||
|
||||
globals.set("fetch", fetch_json).map_err(|e| {
|
||||
globals.set("fetch", fetch).map_err(|e| {
|
||||
eprintln!("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);
|
||||
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| {
|
||||
eprintln!("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| {
|
||||
eprintln!("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();
|
||||
|
||||
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") {
|
||||
let pairs = headers.pairs::<String, String>();
|
||||
|
||||
@@ -425,11 +581,11 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
||||
})?;
|
||||
response.headers_mut().insert(
|
||||
HeaderName::from_str(&k).map_err(|e| {
|
||||
eprintln!("Lua Error: {:?}", e);
|
||||
eprintln!("Response Error: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||
})?,
|
||||
HeaderValue::from_str(&v).map_err(|e| {
|
||||
eprintln!("Lua Error: {:?}", e);
|
||||
eprintln!("Response Error: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
|
||||
})?,
|
||||
);
|
||||
@@ -439,18 +595,95 @@ async fn file_handler(request: Request) -> impl IntoResponse {
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn render_lua_error(e: mlua::Error) -> (StatusCode, String) {
|
||||
let e = e
|
||||
.to_string()
|
||||
.split(':')
|
||||
.skip(4)
|
||||
.collect::<Vec<&str>>()
|
||||
.join(":");
|
||||
match e {
|
||||
mlua::Error::SyntaxError {
|
||||
message,
|
||||
incomplete_input,
|
||||
} => {
|
||||
let mut message = message.split("]:");
|
||||
message.next();
|
||||
(
|
||||
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)> {
|
||||
let start = Instant::now();
|
||||
|
Reference in New Issue
Block a user