Connect db_activity to notification system

This commit is contained in:
kpcyrd
2020-06-11 01:51:59 +02:00
parent 484a426834
commit 51e76b4c89
5 changed files with 121 additions and 32 deletions

View File

@@ -0,0 +1,26 @@
-- Description: Log some dummy activity
-- Version: 0.1.0
-- License: GPL-3.0
function run()
local uniq = getopt('uniq')
local topic = getopt('topic') or 'harness/activity-ping:dummy'
if getopt('gps') then
lat=1.23
lon=4.56
radius=100
end
db_activity({
topic=topic,
time=sn0int_time(),
uniq=uniq,
latitude=lat,
longitude=lon,
radius=radius,
content={
msg='ohai',
},
})
end

View File

@@ -65,9 +65,7 @@ fn print_summary(module: &Module, sent: usize, errors: usize) {
}
fn send(args: SendArgs, rl: &mut Shell) -> Result<()> {
let config = rl.config().notifications.clone();
let workspace = rl.workspace().to_string();
notify::run_router(rl, args.dry_run, &config, &workspace, &args.topic, &args.notification)?;
notify::run_router(rl, &mut term::Term, args.dry_run, &args.topic, &args.notification)?;
Ok(())
}

View File

@@ -4,7 +4,7 @@ use crate::cmd::run_cmd::Params;
use crate::engine::Module;
use crate::options;
use crate::shell::Shell;
use crate::term;
use crate::term::SpinLogger;
use crate::worker;
use serde::de::{self, Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
@@ -111,6 +111,10 @@ impl NotificationConfig {
}
}
pub fn trigger_notify_event<T: SpinLogger>(rl: &mut Shell, spinner: &mut T, topic: &str, notification: &Notification) -> Result<()> {
run_router(rl, spinner, false, topic, notification)
}
fn prepare_arg(notification: &Notification) -> Result<(serde_json::Value, Option<String>, Vec<Blob>)> {
let arg = serde_json::to_value(notification)?;
Ok((arg, None, vec![]))
@@ -141,25 +145,27 @@ pub fn exec(rl: &mut Shell, module: &Module, options: HashMap<String, String>, n
Ok(errors)
}
pub fn run_router(rl: &mut Shell, dry_run: bool, configs: &HashMap<String, NotificationConfig>, workspace: &str, topic: &str, notification: &Notification) -> Result<()> {
pub fn run_router<T: SpinLogger>(rl: &mut Shell, spinner: &mut T, dry_run: bool, topic: &str, notification: &Notification) -> Result<()> {
let configs = rl.config().notifications.clone();
for (name, config) in configs {
if config.matches(workspace, topic) {
if config.matches(rl.workspace(), topic) {
let module = rl.library().get(&config.script)?.clone();
if dry_run {
term::info(&format!("Executed {} {:?} (dry-run)", module.canonical(), name));
spinner.success(&format!("Executed {} {:?} (dry-run)", module.canonical(), name));
} else {
let options = options::Opt::collect(&config.options);
match exec(rl, &module, options, notification) {
Ok(0) => {
let msg = format!("Executed {} {:?}", module.canonical(), name);
term::info(&msg);
spinner.success(&msg);
},
Ok(errors) => {
let msg = format!("Executed {} {:?} ({} errors)", module.canonical(), name, errors);
term::error(&msg);
spinner.error(&msg);
},
Err(err) => {
term::error(&format!("Fatal {} {:?}: {}", module.canonical(), name, err));
spinner.error(&format!("Fatal {} {:?}: {}", module.canonical(), name, err));
},
}
}
@@ -168,7 +174,6 @@ pub fn run_router(rl: &mut Shell, dry_run: bool, configs: &HashMap<String, Notif
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -221,6 +221,44 @@ pub fn error(line: &str) {
eprintln!("\x1b[1m[\x1b[31m{}\x1b[0;1m]\x1b[0m {}", '-', line);
}
pub struct Term;
impl SpinLogger for Term {
fn log(&mut self, line: &str) {
success(line)
}
fn debug(&mut self, line: &str) {
debug(line)
}
fn success(&mut self, line: &str) {
info(line)
}
fn error(&mut self, line: &str) {
error(line)
}
fn warn(&mut self, line: &str) {
warn(line)
}
fn warn_once(&mut self, _line: &str) {
unimplemented!()
}
#[inline]
fn status(&mut self, _status: String) {
unimplemented!()
}
#[inline]
fn stacked_status(&mut self, _name: &String, _status: String) {
unimplemented!()
}
}
pub struct Prompt {
pub workspace: String,
pub module: Option<Module>,

View File

@@ -9,6 +9,7 @@ use crate::engine::Module;
use crate::ipc;
use crate::ipc::parent::IpcParent;
use crate::models::*;
use crate::notify::{self, Notification};
use serde_json;
use crate::ratelimits::{Ratelimiter, RatelimitResponse};
use crate::shell::Shell;
@@ -231,32 +232,52 @@ impl DatabaseEvent {
tx.send(result).expect("Failed to send db result to channel");
}
pub fn activity<T: SpinLogger>(object: NewActivity, tx: DbSender, spinner: &mut T, db: &Database, verbose: u64) {
fn spinner_log_new_activity<T: SpinLogger>(object: &NewActivity, spinner: &mut T, verbose: u64) {
let mut log = format!("{:?} ", object.topic);
if let Some(uniq) = &object.uniq {
log.push_str(&format!("({:?}) ", uniq));
}
log.push_str(&format!("@ {}", object.time));
if let (Some(ref lat), Some(ref lon)) = (object.latitude, object.longitude) {
log.push_str(&format!(" ({}, {}", lat, lon));
if let Some(radius) = &object.radius {
log.push_str(&format!(" | {}m", radius));
}
log.push_str(")");
}
if verbose > 0 {
log.push_str(&format!(": {}", object.content));
}
spinner.log(&log);
}
pub fn activity<T: SpinLogger>(rl: &mut Shell, object: NewActivity, tx: DbSender, spinner: &mut T, verbose: u64) {
let db = rl.db();
let result = db.insert_activity(object.clone());
debug!("{:?} => {:?}", object, result);
let result = match result {
Ok(true) => {
let mut log = format!("{:?} ", object.topic);
Self::spinner_log_new_activity(&object, spinner, verbose);
// TODO: we don't want to copy the match arms everywhere
let topic = format!("activity:{}", object.topic);
let mut subject = format!("New activity: {:?}", object.topic);
if let Some(uniq) = &object.uniq {
log.push_str(&format!("({:?}) ", uniq));
subject += &format!(" ({:?})", uniq);
}
log.push_str(&format!("@ {}", object.time));
if let (Some(ref lat), Some(ref lon)) = (object.latitude, object.longitude) {
log.push_str(&format!(" ({}, {}", lat, lon));
if let Some(radius) = &object.radius {
log.push_str(&format!(" | {}m", radius));
}
log.push_str(")");
if let Err(err) = notify::trigger_notify_event(rl, spinner, &topic, &Notification {
subject,
body: None,
}) {
let err = err.to_string();
spinner.error(&format!("Failed to send notifications: {}", err));
Err(err)
} else {
Ok(DatabaseResponse::Inserted(0))
}
if verbose > 0 {
log.push_str(&format!(": {}", object.content));
}
spinner.log(&log);
Ok(DatabaseResponse::Inserted(0))
},
Ok(false) => Ok(DatabaseResponse::NoChange(0)),
Err(err) => {
@@ -269,11 +290,12 @@ impl DatabaseEvent {
tx.send(result).expect("Failed to send db result to channel");
}
pub fn apply<T: SpinLogger>(self, tx: DbSender, spinner: &mut T, db: &Database, verbose: u64) {
pub fn apply<T: SpinLogger>(self, rl: &mut Shell, tx: DbSender, spinner: &mut T, verbose: u64) {
let db = rl.db();
match self {
DatabaseEvent::Insert(object) => Self::insert(object, None, tx, spinner, db, verbose),
DatabaseEvent::InsertTtl((object, ttl)) => Self::insert(object, Some(ttl), tx, spinner, db, verbose),
DatabaseEvent::Activity(object) => Self::activity(object, tx, spinner, db, verbose),
DatabaseEvent::Activity(object) => Self::activity(rl, object, tx, spinner, verbose),
DatabaseEvent::Select((family, value)) => {
let result = match db.get_opt(&family, &value) {
Ok(Some(id)) => Ok(DatabaseResponse::Found(id)),
@@ -443,7 +465,7 @@ pub fn spawn(rl: &mut Shell, module: &Module, args: Vec<(serde_json::Value, Opti
stack.add(name, label);
},
Event2::Log(log) => log.apply(&mut stack.prefixed(name)),
Event2::Database((db, tx)) => db.apply(tx, &mut stack.prefixed(name), rl.db(), verbose),
Event2::Database((db, tx)) => db.apply(rl, tx, &mut stack.prefixed(name), verbose),
Event2::Ratelimit((req, tx)) => ratelimit.pass(tx, &req.key, req.passes, req.time),
Event2::Blob((blob, tx)) => rl.store_blob(tx, &blob),
Event2::Exit(event) => {