Selaa lähdekoodia

[Telegram] Fixed mixed json processing (cat/uncat)

Slava Barinov 2 vuotta sitten
vanhempi
commit
f7f8f87639
4 muutettua tiedostoa jossa 66 lisäystä ja 75 poistoa
  1. 0 21
      src/categories.rs
  2. 6 19
      src/convert.rs
  3. 53 33
      src/telegram.rs
  4. 7 2
      src/user.rs

+ 0 - 21
src/categories.rs

@@ -74,27 +74,6 @@ pub fn get_top_category<'a>(item: &str, storage: &'a CatStats) -> Option<&'a str
     storage.get(item).map(|s| -> &'a str { &s[0].category })
 }
 
-/// Request category from user via telegram interface
-/*
-#[cfg(feature = "telegram")]
-pub fn get_category_from_tg(
-    item: &str,
-    storage: &mut CatStats,
-    accounts: &[String],
-    ctx: &UpdateWithCx<AutoSend<Bot>, Message>,
-) -> String {
-    if bot_is_running() {
-        let future = async move { input_category_from_tg(item, storage, accounts, ctx).await };
-        if let Ok(handle) = Handle::try_current() {
-            tokio::task::block_in_place(move || handle.block_on(future))
-        } else {
-            String::new()
-        }
-    } else {
-        String::new()
-    }
-}
-*/
 /// Choose proper category or ask user
 pub fn get_category(item: &str, storage: &mut CatStats, accounts: &[String]) -> String {
     let istty = unsafe { isatty(libc::STDOUT_FILENO) } != 0;

+ 6 - 19
src/convert.rs

@@ -69,33 +69,20 @@ pub fn gen_trans<'a>(
     }
 }
 
-/// Check if all items in `filename` do have a category assigned by `user`
-#[cfg(feature = "telegram")]
-pub fn non_cat_items(filename: &str, user: &User) -> Vec<String> {
-    let file = read_file(filename);
-    let mut result: Vec<String> = Vec::new();
-    for i in file.items {
-        match get_top_category(i.name.as_str(), &user.catmap) {
-            Some(_) => (),
-            None => result.push(String::from(i.name.as_str())),
-        }
-    }
-    result
-}
-
 /// Build a fully automatically categorized list
 #[cfg(feature = "telegram")]
-pub fn auto_cat_items(filename: &str, user: &User) -> Result<HashMap<String, String>, ()> {
+pub fn auto_cat_items(filename: &str, user: &User) -> (HashMap<String, String>, Vec<String>) {
     let file = read_file(filename);
-    let mut result: HashMap<String, String> = HashMap::new();
+    let mut categorized: HashMap<String, String> = HashMap::new();
+    let mut uncategorized: Vec<String> = Vec::new();
     for i in file.items {
         if let Some(category) = get_top_category(i.name.as_str(), &user.catmap) {
-            result.insert(i.name, category.to_string());
+            categorized.insert(i.name, category.to_string());
         } else {
-            return Err(());
+            uncategorized.push(i.name)
         }
     }
-    Ok(result)
+    (categorized, uncategorized)
 }
 
 /// Convert `filename` into a QIF transaction

+ 53 - 33
src/telegram.rs

@@ -1,5 +1,5 @@
 use crate::categories;
-use crate::convert::{auto_cat_items, convert, non_cat_items};
+use crate::convert::{auto_cat_items, convert};
 use qif_generator::account::{Account, AccountType};
 
 #[cfg(feature = "monitoring")]
@@ -238,8 +238,25 @@ async fn handle_json(
     if let Ok(newfile) = download_file(&bot, &file_id).await {
         log::info!("Active user: {:} File received: {:} ", msg.chat.id, newfile);
         let user = User::new(msg.chat.id.0, &None);
-        let mut i = non_cat_items(&newfile, &user);
-        if let Some(item) = i.pop() {
+        let (cat, mut uncat) = auto_cat_items(&newfile, &user);
+
+        log::debug!("Categorized item list: {:?}", cat);
+        log::debug!("Non-categorized item list: {:?}", uncat);
+
+        if uncat.is_empty() {
+            log::info!("Automatically categorized");
+            bot.send_message(
+                msg.chat.id,
+                "All the items were categorized automatically\nEnter the memo line".to_string(),
+            )
+            .await?;
+            dialogue
+                .update(State::Ready {
+                    filename: newfile,
+                    item_categories: cat,
+                })
+                .await?;
+        } else if let Some(item) = uncat.pop() {
             log::info!("No category for {}", &item);
             bot.send_message(
                 msg.chat.id,
@@ -250,36 +267,24 @@ async fn handle_json(
                 .update(State::CategorySelect {
                     filename: newfile,
                     item,
-                    items_left: i,
-                    items_processed: HashMap::new(),
+                    items_left: uncat,
+                    items_processed: cat,
                 })
                 .await?;
         } else {
-            log::info!("No items to pop");
-            if let Ok(items) = auto_cat_items(&newfile, &user) {
-                bot.send_message(
-                    msg.chat.id,
-                    "All the items were categorized automatically\nEnter the memo line".to_string(),
-                )
-                .await?;
-                dialogue
-                    .update(State::Ready {
-                        filename: newfile,
-                        item_categories: items,
-                    })
-                    .await?;
-            } else {
-                log::warn!("Malformed json or categorization problem");
-                bot.send_message(msg.chat.id, "Can't parse the provided file".to_string())
-                    .await?;
-                dialogue
-                    .update(State::NewJson {
-                        filename: String::new(),
-                    })
-                    .await?;
-            }
+            log::error!("Can't pop from non-empty list");
         }
+    } else {
+        log::warn!("Malformed json or categorization problem");
+        bot.send_message(msg.chat.id, "Can't parse the provided file".to_string())
+            .await?;
+        dialogue
+            .update(State::NewJson {
+                filename: String::new(),
+            })
+            .await?;
     }
+
     Ok(())
 }
 
@@ -398,7 +403,13 @@ async fn handle_subcategory(
                         })
                         .await?;
                 } else {
-                    bot.send_message(msg.chat.id, "Can't pop next item :(")
+                    log::error!("Can't pop next item :(");
+                    bot.send_message(msg.chat.id, "Internal error happened".to_string())
+                        .await?;
+                    dialogue
+                        .update(State::NewJson {
+                            filename: String::new(),
+                        })
                         .await?;
                 }
             }
@@ -430,6 +441,7 @@ async fn handle_qif_ready(
         .account_type(AccountType::Bank)
         .build();
 
+    // TODO: Check if we need to assign categories by default
     for (i, c) in &item_categories {
         if c.is_empty() {
             log::error!("QIF is ready with no category for item {:}", i);
@@ -442,6 +454,8 @@ async fn handle_qif_ready(
                 .await?;
             return Ok(());
         }
+
+        categories::assign_category(i, c, &mut user.catmap);
     }
 
     let cat = &|item: &str, _stats: &mut categories::CatStats, _acc: &[String]| -> String {
@@ -452,6 +466,7 @@ async fn handle_qif_ready(
     let qif = InputFile::memory(format!("{}{}", acc, t).into_bytes());
     bot.send_message(msg.chat.id, "QIF is ready.").await?;
     bot.send_document(msg.chat.id, qif).await?;
+
     dialogue
         .update(State::NewJson {
             filename: String::new(),
@@ -503,10 +518,15 @@ async fn callback_handler(q: CallbackQuery, bot: Bot, dialogue: QIFDialogue) ->
                         } else {
                             bot.send_message(chat.id, "This was the last item!".to_string())
                                 .await?;
-                            for (key, value) in &items_processed {
-                                bot.send_message(chat.id, format!("{}: {}", key, value))
-                                    .await?;
-                            }
+                            let listgen = || -> String {
+                                let mut res = String::new();
+                                for (item, category) in &items_processed {
+                                    res.push_str(format!("{}: {}\n", item, category).as_str());
+                                }
+                                res
+                            };
+                            bot.send_message(chat.id, listgen()).await?;
+
                             bot.send_message(chat.id, "Enter the memo line".to_string())
                                 .await?;
                             dialogue

+ 7 - 2
src/user.rs

@@ -25,8 +25,7 @@ pub const DEFAULT_DB_PATH: &str = "/etc/receqif/";
 
 impl Drop for User {
     fn drop(&mut self) {
-        self.db.set("catmap", &self.catmap).unwrap();
-        self.db.dump().unwrap();
+        self.save_data();
     }
 }
 
@@ -75,4 +74,10 @@ impl User {
     pub fn accounts(&mut self, acc: Vec<String>) {
         self.accounts = acc;
     }
+
+    pub fn save_data(&mut self) {
+        log::debug!("Saving user data");
+        self.db.set("catmap", &self.catmap).unwrap();
+        self.db.dump().unwrap();
+    }
 }