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