Quellcode durchsuchen

bin/tau: notify tasks addition and modification to named pipe

Dastan-glitch vor 3 Jahren
Ursprung
Commit
1e76299bfb
4 geänderte Dateien mit 68 neuen und 9 gelöschten Zeilen
  1. 42 3
      bin/tau/taud/src/main.rs
  2. 3 0
      bin/tau/taud/src/settings.rs
  3. 6 6
      bin/tau/taud/src/task_info.rs
  4. 17 0
      bin/tau/taud/src/util.rs

+ 42 - 3
bin/tau/taud/src/main.rs

@@ -16,15 +16,17 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use async_std::sync::{Arc, Mutex};
+use libc::mkfifo;
 use std::{
     collections::HashMap,
     env,
+    ffi::CString,
     fs::{create_dir_all, remove_dir_all},
-    io::stdin,
+    io::{stdin, Write},
     path::Path,
 };
 
-use async_std::sync::{Arc, Mutex};
 use crypto_box::{
     aead::{Aead, AeadCore},
     rand_core::OsRng,
@@ -63,6 +65,7 @@ use crate::{
     jsonrpc::JsonRpcInterface,
     settings::{Args, CONFIG_FILE, CONFIG_FILE_CONTENTS},
     task_info::TaskInfo,
+    util::pipe_write,
 };
 
 fn get_workspaces(settings: &Args) -> Result<HashMap<String, SalsaBox>> {
@@ -146,6 +149,7 @@ async fn start_sync_loop(
     workspaces: HashMap<String, SalsaBox>,
     datastore_path: std::path::PathBuf,
     missed_events: Arc<Mutex<Vec<Event<EncryptedTask>>>>,
+    piped: bool,
     p2p: P2pPtr,
 ) -> TaudResult<()> {
     loop {
@@ -176,7 +180,7 @@ async fn start_sync_loop(
 
                 missed_events.lock().await.push(event.clone());
 
-                on_receive_task(&event.action, &datastore_path, &workspaces)
+                on_receive_task(&event.action, &datastore_path, &workspaces, piped)
                     .await?;
             }
         }
@@ -187,6 +191,7 @@ async fn on_receive_task(
     task: &EncryptedTask,
     datastore_path: &Path,
     workspaces: &HashMap<String, SalsaBox>,
+    piped: bool,
 ) -> TaudResult<()> {
     for (workspace, salsa_box) in workspaces.iter() {
         let task = decrypt_task(task, salsa_box);
@@ -198,6 +203,33 @@ async fn on_receive_task(
         let mut task = task.unwrap();
         info!(target: "tau", "Save the task: ref: {}", task.ref_id);
         task.workspace = workspace.clone();
+        if piped {
+            // if we can't load tha task then it's a new task.
+            // otherwise it's a modification.
+            if TaskInfo::load(&task.ref_id, datastore_path).is_err() {
+                let file = "/tmp/tau_pipe";
+                let mut pipe_write = pipe_write(file).unwrap();
+                let buf = format!(
+                    "{{ \"action\": \"add_task\", \"owner\": \"{}\", \"content\": \"{}\" }}",
+                    task.owner.clone(),
+                    task.title.clone()
+                );
+                pipe_write.write_all(buf.as_bytes()).unwrap();
+            } else {
+                match task.events.0.last() {
+                    Some(ev) => {
+                        let file = "/tmp/tau_pipe";
+                        let mut pipe_write = pipe_write(file).unwrap();
+                        let buf = format!(
+                            "{{ \"action\": \"{}\", \"author\": \"{}\", \"content\": \"{}\" }}",
+                            ev.action, ev.author, ev.content
+                        );
+                        pipe_write.write_all(buf.as_bytes()).unwrap();
+                    }
+                    None => todo!(),
+                }
+            }
+        }
         task.save(datastore_path)?;
     }
     Ok(())
@@ -233,6 +265,12 @@ async fn realmain(settings: Args, executor: Arc<smol::Executor<'_>>) -> Result<(
         return Ok(())
     }
 
+    if settings.piped {
+        let file = "/tmp/tau_pipe";
+        let path = CString::new(file).unwrap();
+        unsafe { mkfifo(path.as_ptr(), 0o644) };
+    }
+
     // mkdir datastore_path if not exists
     create_dir_all(datastore_path.clone())?;
     create_dir_all(datastore_path.join("month"))?;
@@ -330,6 +368,7 @@ async fn realmain(settings: Args, executor: Arc<smol::Executor<'_>>) -> Result<(
             workspaces.clone(),
             datastore_path.clone(),
             missed_events,
+            settings.piped,
             p2p.clone(),
         ))
         .detach();

+ 3 - 0
bin/tau/taud/src/settings.rs

@@ -58,4 +58,7 @@ pub struct Args {
     /// Current display name    
     #[structopt(long)]
     pub nickname: Option<String>,
+    // Whether to pipe notifications or not
+    #[structopt(long)]
+    pub piped: bool,
 }

+ 6 - 6
bin/tau/taud/src/task_info.rs

@@ -38,10 +38,10 @@ use crate::{
 
 #[derive(Clone, Debug, Serialize, Deserialize, SerialEncodable, SerialDecodable, PartialEq, Eq)]
 pub struct TaskEvent {
-    action: String,
-    author: String,
-    content: String,
-    timestamp: Timestamp,
+    pub action: String,
+    pub author: String,
+    pub content: String,
+    pub timestamp: Timestamp,
 }
 
 impl TaskEvent {
@@ -83,10 +83,10 @@ pub struct TaskInfo {
     pub(crate) ref_id: String,
     pub(crate) workspace: String,
     pub(crate) id: u32,
-    title: String,
+    pub(crate) title: String,
     tags: TaskTags,
     desc: String,
-    owner: String,
+    pub(crate) owner: String,
     assign: TaskAssigns,
     project: TaskProjects,
     due: Option<Timestamp>,

+ 17 - 0
bin/tau/taud/src/util.rs

@@ -16,8 +16,16 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use std::{
+    fs::{File, OpenOptions},
+    os::unix::prelude::OpenOptionsExt,
+    path::Path,
+};
+
 use log::debug;
 
+use darkfi::{Error, Result};
+
 use crate::task_info::{TaskEvent, TaskInfo};
 
 pub fn find_free_id(task_ids: &[u32]) -> u32 {
@@ -36,6 +44,15 @@ pub fn set_event(task_info: &mut TaskInfo, action: &str, author: &str, content:
     }
 }
 
+pub fn pipe_write<P: AsRef<Path>>(path: P) -> Result<File> {
+    OpenOptions::new()
+        .write(true)
+        .append(true)
+        .custom_flags(libc::O_NONBLOCK)
+        .open(path)
+        .map_err(Error::from)
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;