Add comments
This commit is contained in:
parent
024e51e60d
commit
55b6cc1a10
51
src/main.rs
51
src/main.rs
|
@ -6,21 +6,24 @@ use std::path::{PathBuf, Path};
|
|||
use std::{io, fs};
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
/// Simple program to greet a person
|
||||
/// Struct representing CLI arguments
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about)]
|
||||
struct CliArgs {
|
||||
/// Name of the person to greet
|
||||
//#[arg(short, long)]
|
||||
/// Paths to search for images in.
|
||||
paths: Vec<PathBuf>,
|
||||
|
||||
/// Port to serve the http server on.
|
||||
#[arg(short, long, default_value_t = 8080)]
|
||||
port: u16,
|
||||
|
||||
/// Wether or not to recursively search for images in supplied paths
|
||||
#[arg(short, long, default_value_t = true)]
|
||||
recursive: bool
|
||||
}
|
||||
|
||||
/// A Struct representing an image that was indexed.
|
||||
/// Currently this just stores a path, but it might be expanded on later.
|
||||
#[derive(Clone)]
|
||||
struct IndexedImage {
|
||||
path: PathBuf
|
||||
|
@ -34,6 +37,7 @@ impl IndexedImage {
|
|||
}
|
||||
}
|
||||
|
||||
/// Actix-web AppState. This is used to share the indexed pictures to routes.
|
||||
struct AppState {
|
||||
pub pictures: Vec<IndexedImage>,
|
||||
}
|
||||
|
@ -53,26 +57,36 @@ async fn chose_picture(data: web::Data<AppState>, path: web::Path<String>) -> im
|
|||
if tail.is_empty() {
|
||||
let pictures = &data.pictures;
|
||||
|
||||
// Randomly chose a image
|
||||
if let Some(chosen) = pictures.choose(&mut rand::thread_rng()) {
|
||||
// Convert the image's path to a &str and handle the option.
|
||||
let path = match chosen.path.to_str() {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
return HttpResponse::InternalServerError().body("Failed to convert path PathBuf to &str (The path is not valid unicode)!");
|
||||
return HttpResponse::InternalServerError()
|
||||
.body("Failed to convert path PathBuf to &str (The path is not valid unicode)!");
|
||||
}
|
||||
};
|
||||
|
||||
HttpResponse::TemporaryRedirect().insert_header((actix_web::http::header::LOCATION, format!("/{}", path))).finish()
|
||||
// Redirect client
|
||||
HttpResponse::TemporaryRedirect()
|
||||
.insert_header((actix_web::http::header::LOCATION, format!("/{}", path)))
|
||||
.finish()
|
||||
} else {
|
||||
HttpResponse::NotFound().body("No images were discovered")
|
||||
}
|
||||
} else {
|
||||
println!("Chose \"{}\"", tail);
|
||||
|
||||
|
||||
// Find the dimensions of the image.
|
||||
let (width, height) = match imagesize::size(tail.clone()) {
|
||||
Ok(dim) => (dim.width, dim.height),
|
||||
Err(err) => panic!("Error: {}", err),
|
||||
Err(err) => {
|
||||
return HttpResponse::InternalServerError().body(format!("Failure to get dimensions of image ({})!", err));
|
||||
}
|
||||
};
|
||||
|
||||
// Construct the html body
|
||||
let body = format!("
|
||||
<html lang=\"en\">
|
||||
<head>
|
||||
|
@ -88,12 +102,13 @@ async fn chose_picture(data: web::Data<AppState>, path: web::Path<String>) -> im
|
|||
<img src=\"/img/{}\" width=\"{0}\" height=\"{1}\" alt=\"Roulette selected: {}\">
|
||||
</a>
|
||||
</body>
|
||||
</html>", width, height, tail.clone(), tail);
|
||||
</html>", width, height, tail.clone(), tail); // TODO: Give filename instead of path
|
||||
|
||||
HttpResponse::Ok().body(body)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the image mime for responding
|
||||
fn get_image_mime(path: &String) -> std::io::Result<Option<String>> {
|
||||
if let Some(kind) = infer::get_from_path(path)? {
|
||||
if kind.matcher_type() == MatcherType::Image {
|
||||
|
@ -111,19 +126,22 @@ async fn serve_picture(path: web::Path<String>) -> impl Responder {
|
|||
if !tail.is_empty() {
|
||||
println!("Serving file \"{}\"", tail);
|
||||
|
||||
// Read byes of image
|
||||
let mut file = tokio::fs::File::open(&tail).await.unwrap(); // TODO: Don't unwrap
|
||||
|
||||
let mut contents = vec![];
|
||||
file.read_to_end(&mut contents).await.unwrap(); // TODO: Don't unwrap
|
||||
|
||||
let content_type = get_image_mime(&tail).unwrap(); // TODO: Don't unwrap
|
||||
|
||||
HttpResponse::Ok().content_type(content_type.unwrap_or_default()).body(contents)
|
||||
HttpResponse::Ok()
|
||||
.content_type(content_type.unwrap_or_default())
|
||||
.body(contents)
|
||||
} else {
|
||||
HttpResponse::NotFound().body("No path given")
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for images in `dir`
|
||||
fn image_discovery(dir: &Path, recursive: bool) -> io::Result<Vec<IndexedImage>> {
|
||||
let mut files = vec![];
|
||||
|
||||
|
@ -132,6 +150,7 @@ fn image_discovery(dir: &Path, recursive: bool) -> io::Result<Vec<IndexedImage>>
|
|||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
// If we're discovering recursively, append the indexed images.
|
||||
if recursive {
|
||||
let mut explored = image_discovery(&path, recursive)?;
|
||||
files.append(&mut explored);
|
||||
|
@ -147,9 +166,9 @@ fn image_discovery(dir: &Path, recursive: bool) -> io::Result<Vec<IndexedImage>>
|
|||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let args: CliArgs = CliArgs::parse();
|
||||
let args: CliArgs = CliArgs::parse(); // Parse CLI arguments
|
||||
|
||||
// Read all the images from the supplied paths
|
||||
// Index all the images from the supplied paths
|
||||
let mut images = vec![];
|
||||
for path in args.paths {
|
||||
println!("Exploring path: {:?}", path);
|
||||
|
@ -159,13 +178,13 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
println!("Discovered {} images!", images.len());
|
||||
|
||||
// Construct HTTP Actix server
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(AppState::new(images.clone())))
|
||||
.service(serve_picture)
|
||||
.service(chose_picture)
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}).bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}
|
Loading…
Reference in New Issue