Explorar o código

get_thread endpoint added

Yurii Sokolovskyi hai 2 meses
pai
achega
083c5c8f68
Modificáronse 2 ficheiros con 90 adicións e 41 borrados
  1. 8 8
      src/indexes.rs
  2. 82 33
      src/server.rs

+ 8 - 8
src/indexes.rs

@@ -33,12 +33,12 @@ pub struct SerializableMessage {
 impl PartialEq for SerializableMessage {
     fn eq(&self, other: &Self) -> bool {
         self.name == other.name &&
-            self.from == other.from &&
-            self.hash == other.hash &&
-            self.subject == other.subject &&
-            self.date == other.date &&
-            self.uid == other.uid &&
-            self.list == other.list
+        self.from == other.from &&
+        self.hash == other.hash &&
+        self.subject == other.subject &&
+        self.date == other.date &&
+        self.uid == other.uid &&
+        self.list == other.list
         // TODO add more properties
     }
 }
@@ -356,7 +356,7 @@ impl Indexes {
         None
     }
     
-    fn get_messages() -> anyhow::Result<Vec<SerializableMessage>>{
+    pub fn get_messages() -> anyhow::Result<Vec<SerializableMessage>>{
         let path = Config::global().out_dir.clone().join("messages.json");
         let messages: Vec<SerializableMessage> = if path.exists() {
             let file = File::open(&path)?;
@@ -369,7 +369,7 @@ impl Indexes {
         Ok(messages)
     }
     
-    fn get_threads() -> anyhow::Result<Vec<SerializableThread>>{
+    pub fn get_threads() -> anyhow::Result<Vec<SerializableThread>>{
         let path = Config::global().out_dir.clone().join("threads.json");
 
         let mut threads: Vec<SerializableThread> = if path.exists() {

+ 82 - 33
src/server.rs

@@ -1,16 +1,27 @@
 use crate::config::Config;
-use crate::indexes::{SerializableMessage, SerializableThread};
+use crate::indexes::{Indexes, SerializableMessage, SerializableThread};
 use serde::{Deserialize, Serialize};
 use std::fs::File;
 use std::io::{BufReader};
 use std::net::{IpAddr, SocketAddr};
 use std::str::FromStr;
+use chrono::{DateTime, Utc};
 use warp::Filter;
 use warp::http::StatusCode;
 use crate::{create_folder_lar, delete_folder_lar, rename_folder_lar};
+use crate::models::MailAddress;
 use crate::sonic::SearchSonic;
 use crate::util::read_and_decompress_file;
 
+/// folders -> GET, returns list of all mailboxes
+/// sorted_threads_by_date -> GET, returns hashmap with date: list of thread ids sorted by date
+/// get_thread -> GET, returns all information about one thread
+/// get_thread_messages -> GET, returns a list of SerializableMessage in the thread
+/// email -> GET, returns html for the message
+/// search -> GET, returns a list of message ids where search found matches
+/// create_folder -> POST, creates a new mailbox
+/// rename_folder -> POST, renames a mailbox
+/// delete_folder -> POST, deletes a mailbox
 pub async fn run_api() {
     let cors = warp::cors()
         .allow_any_origin()
@@ -24,6 +35,10 @@ pub async fn run_api() {
             .and(warp::get())
             .and(warp::query::<GetSortedThreadsByDateQuery>())
             .and_then(sorted_threads_by_date_handle))
+        .or(warp::path("get_thread")
+            .and(warp::get())
+            .and(warp::query::<GetThreadQuery>())
+            .and_then(get_thread_handle))
         .or(warp::path("get_thread_messages")
             .and(warp::get())
             .and(warp::query::<GetThreadMessagesQuery>())
@@ -109,40 +124,10 @@ pub async fn get_email(id: String) -> String {
 }
 
 pub async fn get_thread_messages(id: u32) -> String {
-    let threads_path = Config::global()
-        .out_dir
-        .clone()
-        .join("threads.json");
-    let messages_path = Config::global()
-        .out_dir
-        .clone()
-        .join("messages.json");
-    
-    let threads_file = match File::open(threads_path) {
-        Ok(file) => file,
-        Err(_) => return serde_json::to_string(&Vec::<String>::new()).unwrap(),
-    };
-    let messages_file = match File::open(messages_path) {
-        Ok(file) => file,
-        Err(_) => return serde_json::to_string(&Vec::<SerializableMessage>::new()).unwrap(),
-    };
-    
-    let threads_reader = BufReader::new(threads_file);
-    let messages_reader = BufReader::new(messages_file);
-    
-    let threads: Vec<SerializableThread> = match serde_json::from_reader(threads_reader)
-    {
-        Ok(threads) => threads,
-        Err(_) => return serde_json::to_string(&Vec::<SerializableMessage>::new()).unwrap(),
-    };
+    let threads = Indexes::get_threads().unwrap();
+    let messages = Indexes::get_messages().unwrap();
 
     if let Some(thread) = threads.into_iter().find(|thread| thread.id == id) {
-        let messages: Vec<SerializableMessage> = match serde_json::from_reader(messages_reader)
-        {
-            Ok(messages) => messages,
-            Err(_) => return serde_json::to_string(&Vec::<SerializableMessage>::new()).unwrap(),
-        };
-
         let result_messages: Vec<SerializableMessage> = thread.messages.into_iter()
             .filter_map(|message_id| {
                 messages.iter().find(|message| message.id == message_id).cloned()
@@ -155,6 +140,36 @@ pub async fn get_thread_messages(id: u32) -> String {
     }
 }
 
+pub async fn get_thread(id: u32) -> String {
+    let threads = Indexes::get_threads().unwrap();
+    let messages = Indexes::get_messages().unwrap();
+
+    let mut get_thread_response: GetThreadResponse = GetThreadResponse::new();
+    
+    if let Some(thread) = threads.into_iter().find(|thread| thread.id == id) {
+        get_thread_response.id = thread.id.clone();
+        get_thread_response.messages = thread.messages.clone();
+
+        if let Some(first_message_id) = thread.messages.first(){
+            if let Some(first_message) = messages.clone().into_iter().find(|message| message.id == *first_message_id){
+                get_thread_response.subject = first_message.subject.clone();
+            }
+        }
+        if let Some(last_message_id) = thread.messages.last(){
+            if let Some(last_message) = messages.clone().into_iter().find(|message| message.id == *last_message_id){
+                get_thread_response.date = last_message.date.clone();
+                get_thread_response.from_name = last_message.name.clone();
+                get_thread_response.from_address = last_message.from.clone();
+                get_thread_response.to = last_message.to.clone();
+            }
+        }
+
+        serde_json::to_string(&get_thread_response).unwrap()
+    } else {
+        serde_json::to_string(&GetThreadResponse::new()).unwrap()
+    }
+}
+
 async fn get_threads(folder: String, file_name: String) -> String {
     let path = Config::global()
         .out_dir
@@ -211,6 +226,40 @@ async fn get_email_handle(query: GetEmailQuery) -> Result<impl warp::Reply, warp
     Ok(warp::reply::html(result))
 }
 
+#[derive(Deserialize)]
+struct GetThreadQuery {
+    id: u32,
+}
+
+#[derive(Serialize, Deserialize)]
+struct GetThreadResponse{
+    pub id: u32,
+    pub messages: Vec<String>,
+    pub subject: String,
+    pub date: DateTime<Utc>,
+    pub from_name: String,
+    pub from_address: String,
+    pub to: Vec<MailAddress>,
+}
+impl GetThreadResponse{
+    pub fn new() -> Self{
+        GetThreadResponse{
+            id: 0,
+            messages: vec![],
+            subject: "".to_string(),
+            date: Default::default(),
+            from_name: "".to_string(),
+            from_address: "".to_string(),
+            to: vec![],
+        }
+    }
+}
+
+async fn get_thread_handle(query: GetThreadQuery) -> Result<impl warp::Reply, warp::Rejection> {
+    let result: GetThreadResponse = serde_json::from_str(&*get_thread(query.id).await).unwrap();
+    Ok(warp::reply::json(&result))
+}
+
 #[derive(Deserialize)]
 struct GetThreadMessagesQuery {
     id: u32,