Commit 30816d3c authored by Stavros Korokithakis's avatar Stavros Korokithakis

Accept an Eternum API key and notify on hash change

parent a827a230
......@@ -8,6 +8,7 @@ clap = "^2.30"
lazy_static = "^0.2"
log = "^0.4"
notify = "^4.0"
reqwest = "^0.8"
rouille = "^1.0"
rustc-serialize = "^0.3"
simple_logger = "^0.5"
......
......@@ -7,6 +7,7 @@ extern crate notify;
#[macro_use]
extern crate rouille;
extern crate rustc_serialize;
extern crate reqwest;
extern crate simple_logger;
extern crate xdg;
......@@ -26,16 +27,19 @@ use std::process::Command;
use std::sync::mpsc::channel;
use std::sync::Mutex;
use std::thread;
use std::time::{Duration, SystemTime, Instant};
use std::time::{Duration, Instant, SystemTime};
use views::start_api;
/// The time of the last filesystem event in the Hearth folder, or None if the files were already
/// added to IPFS.
lazy_static! {
static ref LAST_EVENT_TIME: Mutex<Option<Instant>> = Mutex::new(None);
}
lazy_static! {
static ref ETERNUM_KEY: Mutex<String> = Mutex::new(String::from(""));
}
lazy_static! {
static ref IPFS_PID: Mutex<u32> = Mutex::new(0);
}
......@@ -109,6 +113,40 @@ fn add_files_to_ipfs() {
}));
}
/// Send the latest root hash to Eternum.
fn notify_eternum() {
let hash = {
let hashes = IPFS_HASHES.lock().unwrap();
hashes.get("").unwrap_or(&String::from("")).clone()
};
let eternum_key = {
let eternum_key = ETERNUM_KEY.lock().unwrap();
eternum_key.clone()
};
if hash == "" || eternum_key == "" {
debug!(
"No key ({}) or hash ({}) found, will not notify Eternum...",
eternum_key, hash
);
return;
}
debug!("Notifying Eternum with hash {}...", hash);
let mut payload = HashMap::new();
payload.insert("site_hash", hash);
let eternum_url = format!("https://www.eternum.io/api/site/?key={}", eternum_key);
let client = reqwest::Client::new();
let _ = client.put(eternum_url.as_str())
.json(&payload)
.send();
debug!("Successfully notified Eterunm.");
}
/// Receive a filesystem event and act on it.
///
/// This does the proper debouncing (on top of the inotify debouncer) to emit the necessary
......@@ -135,7 +173,11 @@ fn notify_ipfs(fs_event: bool) {
return;
} else {
// This is a timer event, so we should check when the last timer event was.
if last_event_time.is_none() || Instant::now().duration_since(last_event_time.unwrap()).as_secs() < 5 {
if last_event_time.is_none()
|| Instant::now()
.duration_since(last_event_time.unwrap())
.as_secs() < 5
{
// It there was no event, or there hasn't been long enough since the last one, return.
return;
}
......@@ -145,22 +187,9 @@ fn notify_ipfs(fs_event: bool) {
// We added files to IPFS, so we'll set the last_event_time to None.
*last_event_time = None;
}
}
/// This function gets triggered when inotify notices files having changed.
///
/// add_to_ipfs will be true when we actually need to add the files to IPFS (ie when enough time
/// has passed after debouncing).
fn files_changed(op: notify::Op, path: std::path::PathBuf) {
debug!("Got new event: {:?}, {:?}", op, path);
if op.contains(notify::op::CREATE) ||
op.contains(notify::op::REMOVE) ||
op.contains(notify::op::RENAME) ||
op.contains(notify::op::WRITE) ||
op.contains(notify::op::RESCAN) ||
op.contains(notify::op::CLOSE_WRITE) {
notify_ipfs(true);
// Send the updated hash to Eternum.
thread::spawn(notify_eternum);
}
}
......@@ -238,7 +267,6 @@ fn start_ipfs() {
process::exit(1)
}
/// Run notify_ipfs every second, for debouncing.
///
/// notify_ipfs stores the last time an event occurred, and only adds files to IPFS if there's no
......@@ -252,6 +280,17 @@ fn cron_thread() {
}
}
/// Handle the inotify events in the Hearth directory.
fn files_changed(op: notify::Op, path: std::path::PathBuf) {
debug!("Got new event: {:?}, {:?}", op, path);
if op.contains(notify::op::CREATE) || op.contains(notify::op::REMOVE)
|| op.contains(notify::op::RENAME) || op.contains(notify::op::WRITE)
|| op.contains(notify::op::RESCAN) || op.contains(notify::op::CLOSE_WRITE)
{
notify_ipfs(true);
}
}
fn create_watcher() {
let (tx, rx) = channel();
let mut watcher: RecommendedWatcher = Watcher::new_raw(tx).unwrap();
......@@ -265,7 +304,7 @@ fn create_watcher() {
Ok(notify::RawEvent {
path: Some(path),
op: Ok(op),
cookie: _cookie
cookie: _cookie,
}) => files_changed(op, path),
Ok(event) => debug!("Broken event: {:?}", event),
Err(event) => debug!("Watch error: {:?}", event),
......@@ -274,9 +313,17 @@ fn create_watcher() {
}
fn main() {
let matches = App::new("hearth")
.author("Stavros and Stelios")
let matches = App::new("Hearth")
.author("by Stavros and Stelios")
.about("A personal website publisher")
.arg(
Arg::with_name("eternum_key")
.short("k")
.long("api_key")
.value_name("APIKEY")
.help("Your Eternum API key, to automatically update your personal site hash")
.takes_value(true),
)
.arg(
Arg::with_name("debug")
.short("d")
......@@ -291,6 +338,11 @@ fn main() {
simple_logger::init_with_level(Level::Info).unwrap();
}
{
let mut eternum_key = ETERNUM_KEY.lock().unwrap();
*eternum_key = String::from(matches.value_of("eternum_key").unwrap_or(""));
}
info!("Starting hearth...");
thread::spawn(start_ipfs);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment