2017-11-09 00:17:42 +04:00
|
|
|
#![recursion_limit = "128"]
|
2017-01-29 22:03:35 +04:00
|
|
|
extern crate brotli2;
|
2016-11-26 13:31:21 +03:00
|
|
|
extern crate chrono;
|
2017-11-09 00:17:42 +04:00
|
|
|
extern crate clap;
|
2016-11-20 23:33:16 +03:00
|
|
|
#[macro_use]
|
|
|
|
extern crate diesel;
|
2017-09-02 02:05:44 +04:00
|
|
|
#[macro_use]
|
|
|
|
extern crate diesel_codegen;
|
2016-11-21 10:45:54 +03:00
|
|
|
extern crate djangohashers;
|
2016-11-20 23:33:16 +03:00
|
|
|
extern crate dotenv;
|
|
|
|
extern crate env_logger;
|
2017-01-29 22:03:35 +04:00
|
|
|
extern crate flate2;
|
2017-09-02 01:14:17 +04:00
|
|
|
extern crate hyper;
|
2017-11-09 00:17:42 +04:00
|
|
|
extern crate image;
|
2017-09-02 01:14:17 +04:00
|
|
|
extern crate libc;
|
2017-11-09 00:17:42 +04:00
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
2017-09-02 01:14:17 +04:00
|
|
|
extern crate memcached;
|
|
|
|
#[macro_use]
|
|
|
|
extern crate nickel;
|
|
|
|
extern crate nickel_jwt_session;
|
|
|
|
extern crate plugin;
|
|
|
|
extern crate r2d2;
|
|
|
|
extern crate r2d2_diesel;
|
2016-11-21 10:45:54 +03:00
|
|
|
extern crate rand;
|
2017-09-02 01:14:17 +04:00
|
|
|
extern crate regex;
|
2016-11-26 13:31:21 +03:00
|
|
|
extern crate rexif;
|
2017-11-06 02:03:55 +04:00
|
|
|
extern crate rustc_serialize;
|
2017-11-27 00:40:28 +04:00
|
|
|
extern crate slug;
|
2017-09-02 01:14:17 +04:00
|
|
|
extern crate time;
|
|
|
|
extern crate typemap;
|
2016-11-20 23:33:16 +03:00
|
|
|
|
|
|
|
mod adm;
|
|
|
|
mod env;
|
2017-09-02 01:14:17 +04:00
|
|
|
mod memcachemiddleware;
|
2017-09-02 02:05:44 +04:00
|
|
|
mod models;
|
2017-09-02 01:14:17 +04:00
|
|
|
mod nickel_diesel;
|
2016-11-25 00:42:57 +03:00
|
|
|
mod photosdir;
|
2017-09-02 01:14:17 +04:00
|
|
|
mod photosdirmiddleware;
|
|
|
|
mod pidfiles;
|
|
|
|
mod requestloggermiddleware;
|
2017-09-02 02:05:44 +04:00
|
|
|
mod schema;
|
2017-09-02 01:14:17 +04:00
|
|
|
mod server;
|
2016-11-20 23:33:16 +03:00
|
|
|
|
2017-11-09 00:17:42 +04:00
|
|
|
use adm::{findphotos, makepublic, precache, storestatics, users};
|
2016-11-21 10:45:54 +03:00
|
|
|
use adm::result::Error;
|
2016-11-20 23:33:16 +03:00
|
|
|
use adm::stats::show_stats;
|
2016-11-21 10:45:54 +03:00
|
|
|
use clap::{App, Arg, ArgMatches, SubCommand};
|
2016-11-20 23:33:16 +03:00
|
|
|
use diesel::pg::PgConnection;
|
|
|
|
use diesel::prelude::*;
|
|
|
|
use dotenv::dotenv;
|
2016-11-25 00:42:57 +03:00
|
|
|
use env::{dburl, photos_dir};
|
|
|
|
use photosdir::PhotosDir;
|
2017-11-09 00:17:42 +04:00
|
|
|
pub use server::{Coord, Group, Link};
|
2016-11-25 00:42:57 +03:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::{self, BufReader};
|
2016-11-26 13:31:21 +03:00
|
|
|
use std::path::Path;
|
2016-11-20 23:33:16 +03:00
|
|
|
use std::process::exit;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
dotenv().ok();
|
|
|
|
env_logger::init().unwrap();
|
2017-11-09 03:06:12 +04:00
|
|
|
let args = App::new("rphotos")
|
2017-08-01 03:40:42 +04:00
|
|
|
.version(env!("CARGO_PKG_VERSION"))
|
2016-11-20 23:33:16 +03:00
|
|
|
.about("Command line interface for rphotos")
|
2017-11-09 00:17:42 +04:00
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("findphotos")
|
|
|
|
.about("Find new photos in the photo directory")
|
|
|
|
.arg(Arg::with_name("BASE").multiple(true).help(
|
|
|
|
"Base directory to search in (relative to the \
|
|
|
|
image root).",
|
|
|
|
)),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("stats")
|
|
|
|
.about("Show some statistics from the database"),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("userlist").about("List existing users"),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("userpass")
|
|
|
|
.about("Set password for a (new or existing) user")
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("USER")
|
|
|
|
.required(true)
|
|
|
|
.help("Username to set password for"),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("makepublic")
|
|
|
|
.about("make specific image(s) public")
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("LIST")
|
|
|
|
.long("list")
|
|
|
|
.short("l")
|
|
|
|
.takes_value(true)
|
|
|
|
.help("File listing image paths to make public"),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("IMAGE")
|
|
|
|
.required_unless("LIST")
|
|
|
|
.help("Image path to make public"),
|
|
|
|
)
|
|
|
|
.after_help(
|
2017-11-09 03:06:12 +04:00
|
|
|
"The image path(s) are relative to the image root.",
|
2017-11-09 00:17:42 +04:00
|
|
|
),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("precache")
|
|
|
|
.about("Make sure the photos has thumbnails stored in cache."),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("storestatics")
|
|
|
|
.about("Store statics as files for a web server")
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("DIR")
|
|
|
|
.required(true)
|
|
|
|
.help("Directory to store the files in"),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.subcommand(
|
|
|
|
SubCommand::with_name("runserver")
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("PIDFILE")
|
|
|
|
.long("pidfile")
|
|
|
|
.takes_value(true)
|
|
|
|
.help(
|
2017-11-09 03:06:12 +04:00
|
|
|
"Write (and read, if --replace) a pid file with \
|
|
|
|
the name given as <PIDFILE>.",
|
2017-11-09 00:17:42 +04:00
|
|
|
),
|
|
|
|
)
|
|
|
|
.arg(Arg::with_name("REPLACE").long("replace").help(
|
2017-11-09 03:06:12 +04:00
|
|
|
"Kill old server (identified by pid file) before running",
|
2017-11-09 00:17:42 +04:00
|
|
|
)),
|
|
|
|
)
|
2016-11-20 23:33:16 +03:00
|
|
|
.get_matches();
|
|
|
|
|
2017-09-27 02:19:03 +04:00
|
|
|
match run(&args) {
|
2016-11-20 23:33:16 +03:00
|
|
|
Ok(()) => (),
|
|
|
|
Err(err) => {
|
|
|
|
println!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-27 02:19:03 +04:00
|
|
|
fn run(args: &ArgMatches) -> Result<(), Error> {
|
2016-11-20 23:33:16 +03:00
|
|
|
match args.subcommand() {
|
2016-11-26 13:31:21 +03:00
|
|
|
("findphotos", Some(args)) => {
|
|
|
|
let pd = PhotosDir::new(photos_dir());
|
2017-05-09 00:01:59 +04:00
|
|
|
let db = get_db()?;
|
2016-11-26 13:31:21 +03:00
|
|
|
if let Some(bases) = args.values_of("BASE") {
|
|
|
|
for base in bases {
|
2017-11-09 00:17:42 +04:00
|
|
|
findphotos::crawl(&db, &pd, Path::new(&base)).map_err(
|
|
|
|
|e| {
|
|
|
|
Error::Other(
|
|
|
|
format!("Failed to crawl {}: {}", base, e),
|
|
|
|
)
|
|
|
|
},
|
|
|
|
)?;
|
2016-11-26 13:31:21 +03:00
|
|
|
}
|
|
|
|
} else {
|
2017-11-09 00:17:42 +04:00
|
|
|
findphotos::crawl(&db, &pd, Path::new("")).map_err(
|
|
|
|
|e| Error::Other(format!("Failed to crawl: {}", e)),
|
|
|
|
)?;
|
2016-11-26 13:31:21 +03:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2016-11-25 00:42:57 +03:00
|
|
|
("makepublic", Some(args)) => {
|
|
|
|
let pd = PhotosDir::new(photos_dir());
|
2017-05-09 00:01:59 +04:00
|
|
|
let db = get_db()?;
|
2016-11-26 14:32:16 +03:00
|
|
|
match args.value_of("LIST") {
|
|
|
|
Some("-") => {
|
2016-11-25 00:42:57 +03:00
|
|
|
let list = io::stdin();
|
2017-05-09 00:01:59 +04:00
|
|
|
makepublic::by_file_list(&db, &pd, list.lock())?;
|
2016-11-26 14:32:16 +03:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
Some(f) => {
|
2017-05-09 00:01:59 +04:00
|
|
|
let list = File::open(f)?;
|
2016-11-25 00:42:57 +03:00
|
|
|
let list = BufReader::new(list);
|
2016-11-26 14:32:16 +03:00
|
|
|
makepublic::by_file_list(&db, &pd, list)
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
makepublic::one(&db, &pd, args.value_of("IMAGE").unwrap())
|
2016-11-25 00:42:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-09 00:01:59 +04:00
|
|
|
("stats", Some(_args)) => show_stats(&get_db()?),
|
|
|
|
("userlist", Some(_args)) => users::list(&get_db()?),
|
2016-11-26 13:31:21 +03:00
|
|
|
("userpass", Some(args)) => {
|
2017-05-09 00:01:59 +04:00
|
|
|
users::passwd(&get_db()?, args.value_of("USER").unwrap())
|
2016-11-26 13:31:21 +03:00
|
|
|
}
|
2017-09-21 01:47:27 +04:00
|
|
|
("precache", _) => {
|
|
|
|
precache::precache(&get_db()?, &PhotosDir::new(photos_dir()))
|
|
|
|
}
|
2017-01-29 22:03:35 +04:00
|
|
|
("storestatics", Some(args)) => {
|
|
|
|
storestatics::to_dir(args.value_of("DIR").unwrap())
|
|
|
|
}
|
2017-11-09 00:17:42 +04:00
|
|
|
("runserver", Some(args)) => server::run(args),
|
2016-11-20 23:33:16 +03:00
|
|
|
_ => Ok(println!("No subcommand given.\n\n{}", args.usage())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_db() -> Result<PgConnection, ConnectionError> {
|
|
|
|
PgConnection::establish(&dburl())
|
|
|
|
}
|
2017-09-02 01:14:17 +04:00
|
|
|
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
|