This commit is contained in:
Rasmus Kaj 2018-07-05 23:28:57 +02:00
parent 96a5a07ce7
commit 20c72d5ef3
18 changed files with 97 additions and 201 deletions

View File

@ -17,4 +17,4 @@ matrix:
before_script:
- rustup component add rustfmt-preview
script:
- cargo fmt -- --unstable-features --write-mode=diff
- cargo fmt -- --check

View File

@ -1,6 +1,4 @@
max_width = 79
reorder_imported_names = true
reorder_imports = true
report_fixme = "Always"
write_mode = "Diff"

View File

@ -12,16 +12,12 @@ pub fn crawl(
photos: &PhotosDir,
only_in: &Path,
) -> Result<(), Error> {
Ok(
photos.find_files(only_in, &|path, exif| match save_photo(
db,
path,
exif,
) {
Ok(()) => debug!("Saved photo {}", path),
Err(e) => warn!("Failed to save photo {}: {:?}", path, e),
})?,
)
Ok(photos.find_files(only_in, &|path, exif| match save_photo(
db, path, exif,
) {
Ok(()) => debug!("Saved photo {}", path),
Err(e) => warn!("Failed to save photo {}: {:?}", path, e),
})?)
}
fn save_photo(
@ -29,14 +25,12 @@ fn save_photo(
file_path: &str,
exif: &ExifData,
) -> Result<(), Error> {
let width = exif.width.ok_or(Error::Other(format!(
"Image {} missing width",
file_path,
)))?;
let height = exif.height.ok_or(Error::Other(format!(
"Image {} missing height",
file_path,
)))?;
let width = exif
.width
.ok_or(Error::Other(format!("Image {} missing width", file_path,)))?;
let height = exif
.height
.ok_or(Error::Other(format!("Image {} missing height", file_path,)))?;
let photo = match Photo::create_or_set_basics(
db,
file_path,

View File

@ -16,10 +16,9 @@ pub fn one(db: &PgConnection, tpath: &str) -> Result<(), Error> {
println!("Made {} public: {:?}", tpath, photo);
Ok(())
}
Err(DieselError::NotFound) => Err(Error::Other(format!(
"File {} is not known",
tpath,
))),
Err(DieselError::NotFound) => {
Err(Error::Other(format!("File {} is not known", tpath,)))
}
Err(error) => Err(error.into()),
}
}

View File

@ -1,8 +1,8 @@
use adm::result::Error;
use diesel::pg::PgConnection;
use diesel::prelude::*;
use memcached::Client;
use memcached::proto::{Operation, ProtoType};
use memcached::Client;
use models::Photo;
use photosdir::PhotosDir;
use schema::photos::dsl::{date, is_public};
@ -15,10 +15,8 @@ use server::SizeTag;
/// The images are handled in public first, new first order, to have
/// the probably most requested images precached as soon as possible.
pub fn precache(db: &PgConnection, pd: &PhotosDir) -> Result<(), Error> {
let mut cache = Client::connect(
&[("tcp://127.0.0.1:11211", 1)],
ProtoType::Binary,
)?;
let mut cache =
Client::connect(&[("tcp://127.0.0.1:11211", 1)], ProtoType::Binary)?;
let size = SizeTag::Small;
let (mut n, mut n_stored) = (0, 0);
let photos = Photo::query(true)
@ -32,21 +30,17 @@ pub fn precache(db: &PgConnection, pd: &PhotosDir) -> Result<(), Error> {
debug!("Cache: {} found for {}", key, photo.path);
} else {
let size = size.px();
let data = pd.scale_image(&photo, size, size)
.map_err(|e| {
Error::Other(format!(
"Failed to scale #{} ({}): {}",
photo.id, photo.path, e,
))
})?;
let data = pd.scale_image(&photo, size, size).map_err(|e| {
Error::Other(format!(
"Failed to scale #{} ({}): {}",
photo.id, photo.path, e,
))
})?;
cache.set(key.as_bytes(), &data, 0, no_expire)?;
debug!("Cache: stored {} for {}", key, photo.path);
n_stored += 1;
if n_stored % 64 == 0 {
info!(
"{} images of {} updated in cache ...",
n_stored, n
);
info!("{} images of {} updated in cache ...", n_stored, n);
}
}
}

View File

@ -3,8 +3,8 @@ use diesel::pg::PgConnection;
use diesel::prelude::*;
use diesel::{insert_into, update};
use djangohashers::make_password;
use rand::distributions::IndependentSample;
use rand::distributions::range::Range;
use rand::distributions::IndependentSample;
use rand::os::OsRng;
use std::iter::Iterator;
@ -26,19 +26,13 @@ pub fn passwd(db: &PgConnection, uname: &str) -> Result<(), Error> {
.execute(db)?
{
1 => {
println!(
"Updated password for {:?} to {:?}",
uname, pword
);
println!("Updated password for {:?} to {:?}", uname, pword);
}
0 => {
insert_into(users)
.values((username.eq(uname), password.eq(&hashword)))
.execute(db)?;
println!(
"Created user {:?} with password {:?}",
uname, pword
);
println!("Created user {:?} with password {:?}", uname, pword);
}
n => {
println!(

View File

@ -9,12 +9,8 @@ fn main() {
let base_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let mut statics = StaticFiles::new(&out_dir).unwrap();
let s_dir = base_dir.join("res");
statics
.add_sass_file(&s_dir.join("photos.scss"))
.unwrap();
statics
.add_file(&s_dir.join("admin.js"))
.unwrap();
statics.add_sass_file(&s_dir.join("photos.scss")).unwrap();
statics.add_file(&s_dir.join("admin.js")).unwrap();
statics.add_file(&s_dir.join("ux.js")).unwrap();
statics
.add_files_as(&s_dir.join("leaflet-1.3.1"), "l131")

View File

@ -196,10 +196,7 @@ fn run(args: &ArgMatches) -> Result<(), Error> {
storestatics::to_dir(args.value_of("DIR").unwrap())
}
("runserver", Some(args)) => server::run(args),
_ => Ok(println!(
"No subcommand given.\n\n{}",
args.usage()
)),
_ => Ok(println!("No subcommand given.\n\n{}", args.usage())),
}
}

View File

@ -1,5 +1,5 @@
use memcached::Client;
use memcached::proto::{Error as MprotError, Operation, ProtoType};
use memcached::Client;
use nickel::{Continue, Middleware, MiddlewareResult, Request, Response};
use plugin::Extensible;
use std::convert::From;

View File

@ -116,12 +116,7 @@ impl Photo {
use diesel::prelude::*;
use schema::photos::dsl::*;
if let Some(result) = Self::update_by_path(
db,
file_path,
newwidth,
newheight,
exifdate,
&camera,
db, file_path, newwidth, newheight, exifdate, &camera,
)? {
Ok(result)
} else {
@ -146,13 +141,9 @@ impl Photo {
use schema::people::dsl::{id, people};
use schema::photo_people::dsl::{person_id, photo_id, photo_people};
people
.filter(
id.eq_any(
photo_people
.select(person_id)
.filter(photo_id.eq(self.id)),
),
)
.filter(id.eq_any(
photo_people.select(person_id).filter(photo_id.eq(self.id)),
))
.load(db)
}
@ -163,13 +154,9 @@ impl Photo {
use schema::photo_places::dsl::{photo_id, photo_places, place_id};
use schema::places::dsl::{id, places};
places
.filter(
id.eq_any(
photo_places
.select(place_id)
.filter(photo_id.eq(self.id)),
),
)
.filter(id.eq_any(
photo_places.select(place_id).filter(photo_id.eq(self.id)),
))
.load(db)
}
pub fn load_tags(
@ -179,11 +166,7 @@ impl Photo {
use schema::photo_tags::dsl::{photo_id, photo_tags, tag_id};
use schema::tags::dsl::{id, tags};
tags.filter(
id.eq_any(
photo_tags
.select(tag_id)
.filter(photo_id.eq(self.id)),
),
id.eq_any(photo_tags.select(tag_id).filter(photo_id.eq(self.id))),
).load(db)
}
@ -212,8 +195,7 @@ impl Photo {
}
pub fn load_camera(&self, db: &PgConnection) -> Option<Camera> {
use schema::cameras::dsl::cameras;
self.camera_id
.and_then(|i| cameras.find(i).first(db).ok())
self.camera_id.and_then(|i| cameras.find(i).first(db).ok())
}
pub fn get_size(&self, max_size: u32) -> Option<(u32, u32)> {
if let (Some(width), Some(height)) = (self.width, self.height) {

View File

@ -82,13 +82,11 @@ impl ExifData {
// possibly utc, instead.
if let (&Some(date), &Some((h, m, s))) = (&self.gpsdate, &self.gpstime)
{
let naive = date.and_hms(h as u32, m as u32, s as u32)
let naive = date
.and_hms(h as u32, m as u32, s as u32)
.with_timezone(&Local)
.naive_local();
debug!(
"GPS Date {}, {}:{}:{} => {}",
date, h, m, s, naive
);
debug!("GPS Date {}, {}:{}:{} => {}", date, h, m, s, naive);
Some(naive)
} else if let Some(date) = self.dateval {
Some(date)
@ -175,10 +173,7 @@ fn is_datetime(f: &Field, tag: &Tag) -> Option<NaiveDateTime> {
match single_datetime(&f.value) {
Ok(date) => Some(date),
Err(err) => {
println!(
"ERROR: Expected datetime for {}: {:?}",
tag, err
);
println!("ERROR: Expected datetime for {}: {:?}", tag, err);
None
}
}
@ -205,7 +200,9 @@ fn is_time(f: &Field, tag: &Tag) -> Option<(u8, u8, u8)> {
if f.tag == *tag {
match &f.value {
&Value::Rational(ref v)
if v.len() == 3 && v[0].denom == 1 && v[1].denom == 1
if v.len() == 3
&& v[0].denom == 1
&& v[1].denom == 1
&& v[2].denom == 1 =>
{
Some((v[0].num as u8, v[1].num as u8, v[2].num as u8))

View File

@ -37,10 +37,7 @@ impl PhotosDir {
_x @ 135...224 => img.rotate180(),
_x @ 225...314 => img.rotate270(),
x => {
warn!(
"Should rotate photo {} deg, which is unsupported",
x
);
warn!("Should rotate photo {} deg, which is unsupported", x);
img
}
};

View File

@ -36,8 +36,6 @@ pub trait PhotosDirRequestExtensions {
impl<'a, 'b, D> PhotosDirRequestExtensions for Request<'a, 'b, D> {
fn photos(&self) -> &PhotosDir {
self.extensions()
.get::<PhotosDirMiddleware>()
.unwrap()
self.extensions().get::<PhotosDirMiddleware>().unwrap()
}
}

View File

@ -65,11 +65,9 @@ impl<D> Middleware<D> for RequestLoggerMiddleware {
) -> MiddlewareResult<'mw, D> {
let mu = format!("{} {}", req.origin.method, req.origin.uri);
let status = Arc::new(Mutex::new(StatusCode::Continue));
req.extensions_mut()
.insert::<RequestLoggerMiddleware>(RequestLogger::new(
mu,
Arc::clone(&status),
));
req.extensions_mut().insert::<RequestLoggerMiddleware>(
RequestLogger::new(mu, Arc::clone(&status)),
);
res.on_send(move |r| {
if let Ok(mut sw) = status.lock() {
*sw = r.status();

View File

@ -24,10 +24,7 @@ pub fn rotate<'mw>(
let c: &PgConnection = &req.db_conn();
if let Ok(mut image) = photos.find(image).first::<Photo>(c) {
let newvalue = (360 + image.rotation + angle) % 360;
info!(
"Rotation was {}, setting to {}",
image.rotation, newvalue
);
info!("Rotation was {}, setting to {}", image.rotation, newvalue);
image.rotation = newvalue;
match image.save_changes::<Photo>(c) {
Ok(image) => {
@ -177,23 +174,14 @@ pub fn set_grade<'mw>(
}
Ok(0) => (),
Ok(n) => {
warn!(
"Strange, updated {} images with id {}",
n, image
);
warn!("Strange, updated {} images with id {}", n, image);
}
Err(error) => {
warn!(
"Failed set grade of image #{}: {}",
image, error
);
warn!("Failed set grade of image #{}: {}", image, error);
}
}
} else {
info!(
"Grade {} is out of range for image #{}",
newgrade, image
);
info!("Grade {} is out of range for image #{}", newgrade, image);
}
}
info!("Missing image and/or angle to rotate or image not found");

View File

@ -20,12 +20,14 @@ use memcachemiddleware::{MemcacheMiddleware, MemcacheRequestExtensions};
use models::{Person, Photo, Place, Tag};
use nickel::extensions::response::Redirect;
use nickel::status::StatusCode;
use nickel::{Action, Continue, FormBody, Halt, HttpRouter, MediaType,
MiddlewareResult, Nickel, NickelError, QueryString, Request,
Response};
use nickel::{
Action, Continue, FormBody, Halt, HttpRouter, MediaType, MiddlewareResult,
Nickel, NickelError, QueryString, Request, Response,
};
use nickel_diesel::{DieselMiddleware, DieselRequestExtensions};
use nickel_jwt_session::{SessionMiddleware, SessionRequestExtensions,
SessionResponseExtensions};
use nickel_jwt_session::{
SessionMiddleware, SessionRequestExtensions, SessionResponseExtensions,
};
use photosdirmiddleware::{PhotosDirMiddleware, PhotosDirRequestExtensions};
use pidfiles::handle_pid_file;
use r2d2::NopErrorHandler;
@ -48,7 +50,8 @@ impl PhotoLink {
PhotoLink::from(&g[0])
} else {
fn imgscore(p: &Photo) -> i16 {
p.grade.unwrap_or(27) + if p.is_public { 38 } else { 0 }
// Only score below 19 is worse than ungraded.
p.grade.unwrap_or(19) * if p.is_public { 5 } else { 4 }
}
let photo = g.iter().max_by_key(|p| imgscore(p)).unwrap();
PhotoLink {
@ -116,9 +119,10 @@ pub fn run(args: &ArgMatches) -> Result<(), Error> {
let mut server = Nickel::new();
server.utilize(RequestLoggerMiddleware);
wrap3!(server.get "/static/",.. static_file);
server.utilize(MemcacheMiddleware::new(vec![
("tcp://127.0.0.1:11211".into(), 1),
]));
server.utilize(MemcacheMiddleware::new(vec![(
"tcp://127.0.0.1:11211".into(),
1,
)]));
server.utilize(SessionMiddleware::new(&jwt_key()));
let dm: DieselMiddleware<PgConnection> =
DieselMiddleware::new(&dburl(), 5, Box::new(NopErrorHandler)).unwrap();
@ -255,10 +259,7 @@ fn test_sanitize_good_1() {
}
#[test]
fn test_sanitize_good_2() {
assert_eq!(
Some("/2017/7/15"),
sanitize_next(Some("/2017/7/15"))
)
assert_eq!(Some("/2017/7/15"), sanitize_next(Some("/2017/7/15")))
}
fn logout<'mw>(
@ -346,23 +347,15 @@ fn tag_all<'mw>(
} else {
use schema::photo_tags::dsl as tp;
use schema::photos::dsl as p;
query.filter(
id.eq_any(
tp::photo_tags.select(tp::tag_id).filter(
tp::photo_id
.eq_any(p::photos.select(p::id).filter(p::is_public)),
),
),
)
query.filter(id.eq_any(tp::photo_tags.select(tp::tag_id).filter(
tp::photo_id.eq_any(p::photos.select(p::id).filter(p::is_public)),
)))
};
res.ok(|o| {
templates::tags(
o,
req,
&query
.order(tag_name)
.load(c)
.expect("List tags"),
&query.order(tag_name).load(c).expect("List tags"),
)
})
}
@ -378,11 +371,7 @@ fn tag_one<'mw>(
use schema::photo_tags::dsl::{photo_id, photo_tags, tag_id};
use schema::photos::dsl::id;
let photos = Photo::query(req.authorized_user().is_some()).filter(
id.eq_any(
photo_tags
.select(photo_id)
.filter(tag_id.eq(tag.id)),
),
id.eq_any(photo_tags.select(photo_id).filter(tag_id.eq(tag.id))),
);
let (links, coords) = links_by_time(req, photos);
return res.ok(|o| templates::tag(o, req, &links, &coords, &tag));
@ -401,24 +390,16 @@ fn place_all<'mw>(
} else {
use schema::photo_places::dsl as pp;
use schema::photos::dsl as p;
query.filter(
id.eq_any(
pp::photo_places.select(pp::place_id).filter(
pp::photo_id
.eq_any(p::photos.select(p::id).filter(p::is_public)),
),
),
)
query.filter(id.eq_any(pp::photo_places.select(pp::place_id).filter(
pp::photo_id.eq_any(p::photos.select(p::id).filter(p::is_public)),
)))
};
let c: &PgConnection = &req.db_conn();
res.ok(|o| {
templates::places(
o,
req,
&query
.order(place_name)
.load(c)
.expect("List places"),
&query.order(place_name).load(c).expect("List places"),
)
})
}
@ -446,13 +427,10 @@ fn place_one<'mw>(
if let Ok(place) = places.filter(slug.eq(tslug)).first::<Place>(c) {
use schema::photo_places::dsl::{photo_id, photo_places, place_id};
use schema::photos::dsl::id;
let photos = Photo::query(req.authorized_user().is_some()).filter(
id.eq_any(
photo_places
.select(photo_id)
.filter(place_id.eq(place.id)),
),
);
let photos =
Photo::query(req.authorized_user().is_some()).filter(id.eq_any(
photo_places.select(photo_id).filter(place_id.eq(place.id)),
));
let (links, coord) = links_by_time(req, photos);
return res.ok(|o| templates::place(o, req, &links, &coord, &place));
}
@ -470,24 +448,16 @@ fn person_all<'mw>(
} else {
use schema::photo_people::dsl as pp;
use schema::photos::dsl as p;
query.filter(
id.eq_any(
pp::photo_people.select(pp::person_id).filter(
pp::photo_id
.eq_any(p::photos.select(p::id).filter(p::is_public)),
),
),
)
query.filter(id.eq_any(pp::photo_people.select(pp::person_id).filter(
pp::photo_id.eq_any(p::photos.select(p::id).filter(p::is_public)),
)))
};
let c: &PgConnection = &req.db_conn();
res.ok(|o| {
templates::people(
o,
req,
&query
.order(person_name)
.load(c)
.expect("list people"),
&query.order(person_name).load(c).expect("list people"),
)
})
}
@ -623,7 +593,8 @@ fn auto_complete_tag<'mw>(
if let Some(q) = req.query().get("q").map(String::from) {
use schema::tags::dsl::{tag_name, tags};
let c: &PgConnection = &req.db_conn();
let q = tags.select(tag_name)
let q = tags
.select(tag_name)
.filter(tag_name.ilike(q + "%"))
.order(tag_name)
.limit(10);

View File

@ -1,5 +1,5 @@
use super::PhotoLink;
use super::views_by_date::query_date;
use super::PhotoLink;
use diesel::pg::{Pg, PgConnection};
use diesel::prelude::*;
use models::{Coord, Photo};

View File

@ -1,7 +1,7 @@
use super::splitlist::links_by_time;
use super::{Link, PhotoLink, SizeTag};
use chrono::Duration as ChDuration;
use chrono::naive::{NaiveDate, NaiveDateTime};
use chrono::Duration as ChDuration;
use diesel::expression::sql_literal::SqlLiteral;
use diesel::pg::PgConnection;
use diesel::prelude::*;
@ -222,12 +222,7 @@ pub fn all_for_day<'mw>(
templates::index(
o,
req,
&format!(
"Photos from {} {} {}",
day,
monthname(month),
year
),
&format!("Photos from {} {} {}", day, monthname(month), year),
&[Link::year(year), Link::month(year, month)],
&links,
&coords,
@ -269,11 +264,9 @@ pub fn on_this_day<'mw>(
.iter()
.map(|&(year, count)| {
let year = year.map(|y| y as i32).unwrap_or(0);
let fromdate = NaiveDate::from_ymd(
year,
month as u32,
day,
).and_hms(0, 0, 0);
let fromdate =
NaiveDate::from_ymd(year, month as u32, day)
.and_hms(0, 0, 0);
let photo = Photo::query(req.authorized_user().is_some())
.filter(date.ge(fromdate))
.filter(date.lt(fromdate + ChDuration::days(1)))