// Copyright © 2020 Jakob L. Kreuze // // This file is part of бирка-тян. // // бирка-тян is free software; you can redistribute it and/or modify it // under the terms of the GNU Affero General Public License as published // by the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // бирка-тян is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public // License along with бирка-тян. If not, see . #![feature(proc_macro_hygiene, decl_macro)] #[macro_use] extern crate anyhow; extern crate image; #[macro_use] extern crate rocket; #[macro_use] extern crate rocket_contrib; #[macro_use] extern crate serde_derive; mod database; use database::{Query, TagDatabase}; use image::{GenericImageView, ImageFormat}; use rocket::State; use rocket_contrib::json::{Json, JsonValue}; use std::env; use std::fs; use std::fs::File; use std::os::unix::fs::symlink; use std::path::Path; use std::sync::Mutex; #[get("/")] fn index(tb: State>) -> &'static str { "Hello, world!" } #[derive(Serialize)] struct ImageResult { filename: String, tags: Vec, } #[get("/posts?")] fn posts(tb: State>, tags: String) -> Json> { let tb = tb.inner().lock().unwrap(); let tags = tags.split(",").collect::>(); let results = tb .query(Query { tags: &tags[..], last_id: Some(0), limit: Some(50), }) .unwrap(); Json( results .iter() .map(|image| ImageResult { filename: image.filename.clone(), tags: tb.tags_for_image(image.id).unwrap(), }) .collect(), ) } /// Maybe initialize the directory for storing image symlinks and thumbnails. fn create_image_directory() -> TagDatabase { let bin = env::current_exe().unwrap(); let image_dir = bin.parent().unwrap().join("image/"); fs::create_dir(&image_dir).ok(); let tb_path = bin.parent().unwrap().join("birka.db"); let tb = TagDatabase::new(tb_path.to_str().unwrap()).unwrap(); for image in tb.images_by_tags(&vec![][..]).unwrap() { let src = format!("{}/{}", image.orig_dir, image.filename); let dst = format!("{}/{}", image_dir.to_str().unwrap(), image.filename); symlink(&src, &dst).ok(); let stem = Path::new(&dst).file_stem().unwrap().to_str().unwrap(); let thumb_path = format!("{}_thumb.png", stem); let thumb_path = Path::new(&thumb_path); if !thumb_path.exists() { let im = image::open(&Path::new(&src)).unwrap(); let fout = &mut File::create(&thumb_path).unwrap(); im.thumbnail(100, 100) .write_to(fout, ImageFormat::Png) .unwrap(); } } tb } fn main() { let tb = create_image_directory(); rocket::ignite() .manage(Mutex::new(tb)) .mount("/", routes![index, posts]) .launch(); }