GIT THIS
This commit is contained in:
commit
cf24968725
4 changed files with 134 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
Cargo.lock
|
||||
tmp/*
|
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "hit-counter-rs"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4"
|
||||
actix-files = "0.6.5"
|
||||
env_logger = "0.11.3"
|
||||
log = "0.4"
|
||||
async-stream = "0.3.5"
|
1
asset
Symbolic link
1
asset
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../perl/hit-counter/asset/
|
117
src/main.rs
Normal file
117
src/main.rs
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Due to the slowness of imagemagick (and calling system commands and w/e else)
|
||||
// the image that the user will see on the page will be -1 behind the actual count
|
||||
use actix_web::{
|
||||
get,
|
||||
App,
|
||||
HttpServer,
|
||||
HttpResponse,
|
||||
HttpRequest,
|
||||
};
|
||||
use actix_files::NamedFile;
|
||||
use std::{
|
||||
fs,
|
||||
path::Path,
|
||||
process::Command,
|
||||
};
|
||||
|
||||
const MONTAGE_PATH: &str = "/bin/montage";
|
||||
// this kinda dates ImageMagick, oh well (6.9)
|
||||
//const MONTAGE_ARGS: &str = "-tile 6x1 -geometry +0+0 -background none -scale 50";
|
||||
const ASSET_DIR: &str = "asset/";
|
||||
const TMP_OUTPUT: &str = "tmp/counter.png";
|
||||
|
||||
|
||||
const BIND_IP: &str = "127.0.0.1";
|
||||
const BIND_PORT: u16 = 8080;
|
||||
|
||||
static mut COUNTER: u16 = 0;
|
||||
const NUMBER_LENGTH: u8 = 6;
|
||||
const COUNTER_FILE : &str = "counter.numb";
|
||||
|
||||
#[get("/")]
|
||||
async fn counter_route(req: HttpRequest ) -> HttpResponse {
|
||||
|
||||
let count: String;
|
||||
unsafe {
|
||||
COUNTER = &COUNTER + 1;
|
||||
count = number_to_length(&COUNTER, NUMBER_LENGTH);
|
||||
write_counter();
|
||||
}
|
||||
|
||||
create_image(count);
|
||||
|
||||
let file = NamedFile::open_async(TMP_OUTPUT).await.unwrap(); // streams the file
|
||||
let res = file.into_response(&req); // NamedFile to HttpResponse
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn create_image (count: String) {
|
||||
let mut command = Command::new(MONTAGE_PATH);
|
||||
|
||||
for i in 0..NUMBER_LENGTH {
|
||||
let mut file_name: String = String::new();
|
||||
|
||||
file_name.push_str( ASSET_DIR );
|
||||
file_name.push_str( &(count.as_str()[i as usize..i as usize + 1]) );
|
||||
file_name.push_str( ".png" );
|
||||
|
||||
command.arg(file_name);
|
||||
}
|
||||
command.arg("-tile").arg("6x1").arg("-geometry").arg("+0+0").arg("-background").arg("none").arg("-scale").arg("50");
|
||||
command.arg(TMP_OUTPUT);
|
||||
// user will refresh the page faster than imagemagick does stuff
|
||||
// possible dos I guess, idc
|
||||
command.spawn().expect("`/bin/montage` has an error! (probably, idk)");
|
||||
}
|
||||
|
||||
fn number_to_length(counter: &u16, length: u8) -> String {
|
||||
let mut string : String = String::from("");
|
||||
|
||||
let mut counter_len = (counter.checked_ilog10().unwrap_or(0) + 1) as u8; // like length() in perl
|
||||
while counter_len < length {
|
||||
string.push('0');
|
||||
counter_len = counter_len + 1;
|
||||
}
|
||||
|
||||
string.push_str( counter.to_string().as_str() );
|
||||
|
||||
string
|
||||
}
|
||||
|
||||
unsafe fn read_counter() {
|
||||
match fs::read_to_string(COUNTER_FILE) {
|
||||
Ok(n) => COUNTER = n.as_str().parse().unwrap(),
|
||||
Err(e) => log::info!("{e}"),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn write_counter() {
|
||||
let count = COUNTER.to_string();
|
||||
fs::write(COUNTER_FILE, &count).expect("I can't write to file");
|
||||
}
|
||||
|
||||
|
||||
#[actix_web::main] // or #[tokio::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
if ! Path::new(COUNTER_FILE).exists() {
|
||||
unsafe {
|
||||
write_counter();
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
read_counter();
|
||||
}
|
||||
|
||||
log::info!("starting HTTP server at http://{BIND_IP}:{BIND_PORT}");
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.service(counter_route)
|
||||
})
|
||||
.bind((BIND_IP, BIND_PORT))?
|
||||
.run()
|
||||
.await
|
||||
}
|
Loading…
Reference in a new issue