#[macro_use] extern crate nickel; #[macro_use] extern crate log; extern crate env_logger; extern crate rustorm; extern crate rustc_serialize; extern crate typemap; extern crate plugin; extern crate image; extern crate hyper; extern crate time; mod models; use hyper::header::{Expires, HttpDate}; use image::open as image_open; use image::{FilterType, ImageFormat, GenericImage}; use models::{Photo, Tag, Person, Place, query_for}; use nickel::{MediaType, Nickel, StaticFilesHandler}; use plugin::{Pluggable}; use rustc_serialize::Encodable; use time::Duration; mod env; use env::dburl; mod rustormmiddleware; use rustormmiddleware::{RustormMiddleware, RustormRequestExtensions}; mod requestloggermiddleware; use requestloggermiddleware::RequestLoggerMiddleware; fn get_scaled_image(photo: Photo, width: u32, height: u32) -> Vec { let path = format!("/home/kaj/Bilder/foto/{}", photo.path); info!("Should open {}", path); let img = image_open(path).unwrap(); let img = if width < img.width() || height < img.height() { img.resize(width, height, FilterType::Nearest) } else { img }; let img = match photo.rotation { _x @ 0...44 => img, _x @ 45...134 => img.rotate90(), _x @ 135...224 => img.rotate180(), _x @ 225...314 => img.rotate270(), _x @ 315...360 => img, x => { warn!("Should rotate photo {} deg, which is unsupported", x); img } }; // TODO Put the icon in some kind of cache! let mut buf : Vec = Vec::new(); img.save(&mut buf, ImageFormat::JPEG).unwrap(); buf } macro_rules! render { ($res:expr, $template:expr, { $($param:ident : $ptype:ty = $value:expr),* }) => { { #[derive(Debug, Clone, RustcEncodable)] struct ParamData { $( $param: $ptype, )* } $res.render($template, &ParamData { $( $param: $value, )* }) } } } fn main() { env_logger::init().unwrap(); info!("Initalized logger"); let mut server = Nickel::new(); server.utilize(RequestLoggerMiddleware); server.utilize(StaticFilesHandler::new("static/")); server.utilize(RustormMiddleware::new(&dburl())); server.utilize(router! { get "/" => |req, res| { return render!(res, "templates/index.tpl", { photos: Vec = query_for::() .filter_gte("grade", &4_i16) .limit(24) .collect(req.db_conn()).unwrap() }); } get "/details/:id" => |req, res| { if let Ok(id) = req.param("id").unwrap().parse::() { if let Ok(photo) = req.orm_get::("id", &id) { return render!(res, "templates/details.tpl", { people: Vec = req.orm_get_related(&photo, "photo_person").unwrap(), places: Vec = req.orm_get_related(&photo, "photo_place").unwrap(), tags: Vec = req.orm_get_related(&photo, "photo_tag").unwrap(), photo: Photo = photo }); } } } get "/tag/" => |req, res| { return render!(res, "templates/tags.tpl", { tags: Vec = query_for::().asc("tag") .collect(req.db_conn()).unwrap() }); } get "/tag/:tag" => |req, res| { let slug = req.param("tag").unwrap(); if let Ok(tag) = req.orm_get::("slug", &slug) { return render!(res, "templates/tag.tpl", { photos: Vec = req.orm_get_related(&tag, "photo_tag").unwrap(), tag: Tag = tag }); } } get "/person/" => |req, res| { return render!(res, "templates/people.tpl", { people: Vec = query_for::().asc("name") .collect(req.db_conn()).unwrap() }); } get "/person/:slug" => |req, res| { let slug = req.param("slug").unwrap(); if let Ok(person) = req.orm_get::("slug", &slug) { return render!(res, "templates/person.tpl", { photos: Vec = req.orm_get_related(&person, "photo_person").unwrap(), person: Person = person }); } } get "/place/" => |req, res| { return render!(res, "templates/places.tpl", { places: Vec = query_for::().asc("place") .collect(req.db_conn()).unwrap() }); } get "/place/:slug" => |req, res| { let slug = req.param("slug").unwrap(); if let Ok(place) = req.orm_get::("slug", &slug) { return render!(res, "templates/place.tpl", { photos: Vec = req.orm_get_related(&place, "photo_place").unwrap(), place: Place = place }); } } get "/img/:id/:size" => |req, mut res| { if let Ok(id) = req.param("id").unwrap().parse::() { if let Ok(photo) = req.orm_get::("id", &id) { if let Some(size) = match req.param("size").unwrap() { "s" => Some(200), "m" => Some(800), "l" => Some(1200), _ => None } { let buf = get_scaled_image(photo, size, size); res.set(MediaType::Jpeg); res.set(Expires(HttpDate(time::now() + Duration::days(14)))); return res.send(buf); } } } } }); server.listen("127.0.0.1:6767"); }