initial commit
This commit is contained in:
commit
433ea1c76b
5 changed files with 1156 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/target
|
||||||
|
/files
|
||||||
|
/temp
|
||||||
|
.env
|
||||||
|
git_output_*
|
1018
Cargo.lock
generated
Normal file
1018
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "phone"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
axum = "0.7.2"
|
||||||
|
chrono = "0.4.31"
|
||||||
|
thiserror = "1.0.51"
|
||||||
|
tokio = { version = "1.35.1", features = ["macros", "rt-multi-thread"] }
|
||||||
|
tower = { version = "0.4.13", features = ["limit"] }
|
||||||
|
tracing = "0.1.40"
|
||||||
|
tracing-subscriber = "0.3.18"
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# phone
|
||||||
|
|
||||||
|
webhooks and stuff for my phone
|
115
src/main.rs
Normal file
115
src/main.rs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#![feature(let_chains)]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
fs::OpenOptions,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
time::SystemTime,
|
||||||
|
};
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::State,
|
||||||
|
http::{HeaderMap, StatusCode},
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use thiserror::Error;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tower::limit::ConcurrencyLimitLayer;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
macro_rules! silly {
|
||||||
|
($code:ident) => {
|
||||||
|
(StatusCode::$code, StatusCode::$code.to_string())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Config {
|
||||||
|
pub host: String,
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
enum AppError {
|
||||||
|
#[error("Command failed to execute (exit code {0})")]
|
||||||
|
CommandFailed(i32),
|
||||||
|
#[error(transparent)]
|
||||||
|
IoError(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for AppError {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
error!("{}", self);
|
||||||
|
silly!(INTERNAL_SERVER_ERROR).into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_website(
|
||||||
|
State(secret): State<String>,
|
||||||
|
headers: HeaderMap,
|
||||||
|
) -> Result<StatusCode, AppError> {
|
||||||
|
if let Some(secret_header) = headers.get("x-gitlab-token")
|
||||||
|
&& *secret_header == secret
|
||||||
|
{
|
||||||
|
let now = SystemTime::now();
|
||||||
|
let date: DateTime<Utc> = now.into();
|
||||||
|
|
||||||
|
let file_name = format!("git_output_{}", date);
|
||||||
|
|
||||||
|
let stdout_file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.write(true)
|
||||||
|
.open(&file_name)
|
||||||
|
.unwrap();
|
||||||
|
let stderr_file = OpenOptions::new().write(true).open(&file_name).unwrap();
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
let result = Command::new("git")
|
||||||
|
.current_dir(env::home_dir().unwrap().join("slonksite"))
|
||||||
|
.arg("pull")
|
||||||
|
.stdin(Stdio::null())
|
||||||
|
.stdout(stdout_file)
|
||||||
|
.stderr(stderr_file)
|
||||||
|
.spawn()?
|
||||||
|
.wait()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if result.success() {
|
||||||
|
Ok(StatusCode::OK)
|
||||||
|
} else {
|
||||||
|
Err(AppError::CommandFailed(result.code().unwrap_or(1)))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(StatusCode::UNAUTHORIZED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
host: env::var("HOST").unwrap_or("0.0.0.0".to_string()),
|
||||||
|
port: env::var("PORT")
|
||||||
|
.and_then(|port| Ok(port.parse::<u16>().unwrap()))
|
||||||
|
.unwrap_or(5000),
|
||||||
|
};
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/update_website", get(update_website))
|
||||||
|
.layer(ConcurrencyLimitLayer::new(8))
|
||||||
|
.with_state(env::var("SECRET").unwrap());
|
||||||
|
|
||||||
|
let address = (config.host, config.port);
|
||||||
|
let listener = TcpListener::bind(address).await.unwrap();
|
||||||
|
let local_addr = listener.local_addr().unwrap();
|
||||||
|
tracing::info!(
|
||||||
|
"listening on http://{}:{}",
|
||||||
|
local_addr.ip(),
|
||||||
|
local_addr.port()
|
||||||
|
);
|
||||||
|
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
|
}
|
Loading…
Reference in a new issue