Browse Source

[Telegram] input_category_from_tg() now is called appropriately

Signed-off-by: Slava Barinov <rayslava@gmail.com>
Slava Barinov 4 năm trước cách đây
mục cha
commit
a38e2f3c4f
4 tập tin đã thay đổi với 53 bổ sung19 xóa
  1. 23 5
      src/categories.rs
  2. 13 6
      src/convert.rs
  3. 5 1
      src/main.rs
  4. 12 7
      src/telegram.rs

+ 23 - 5
src/categories.rs

@@ -5,6 +5,10 @@ use libc::isatty;
 use radix_trie::Trie;
 use serde::{Deserialize, Serialize};
 use std::cmp::Ordering;
+#[cfg(feature = "telegram")]
+use teloxide::prelude::*;
+#[cfg(feature = "telegram")]
+use tokio::runtime::Handle;
 
 /// Category statistics for single item
 #[derive(Serialize, Deserialize, Debug)]
@@ -75,13 +79,27 @@ pub fn get_top_category<'a>(item: &str, storage: &'a CatStats) -> Option<&'a str
     storage.get(item).map(|s| -> &'a str { &s[0].category })
 }
 
-/// Choose proper category or ask user
-pub fn get_category(item: &str, storage: &mut CatStats) -> String {
-    #[cfg(feature = "telegram")]
+/// Request category from user via telegram interface
+#[cfg(feature = "telegram")]
+pub fn get_category_from_tg(
+    item: &str,
+    storage: &mut CatStats,
+    ctx: &UpdateWithCx<AutoSend<Bot>, Message>,
+) -> String {
     if bot_is_running() {
-        return input_category_from_tg(item, &storage);
-    };
+        let future = async move { input_category_from_tg(item, &storage, &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) -> String {
     let istty = unsafe { isatty(libc::STDOUT_FILENO as i32) } != 0;
     if istty {
         let topcat = match get_top_category(item, storage) {

+ 13 - 6
src/convert.rs

@@ -1,5 +1,5 @@
+use crate::categories::get_top_category;
 use crate::categories::CatStats;
-use crate::categories::{get_category, get_top_category};
 use crate::receipt;
 use crate::user::User;
 use chrono::{Date, Utc};
@@ -30,13 +30,16 @@ mod tests {
 }
 
 /// Generate set of QIF Splits from a Purchase items
-pub fn gen_splits(items: &[receipt::Item], cs: &mut CatStats) -> Vec<Split> {
+pub fn gen_splits<F>(items: &[receipt::Item], cs: &mut CatStats, categorizer: F) -> Vec<Split>
+where
+    F: Fn(&str, &mut CatStats) -> String,
+{
     let mut result: Vec<Split> = Vec::new();
     for i in items.iter() {
         let t = Split::new()
             .memo(i.name.as_str())
             .amount(-i.sum)
-            .category(&get_category(i.name.as_str(), cs))
+            .category(&categorizer(i.name.as_str(), cs))
             .build();
 
         result.push(t);
@@ -88,13 +91,17 @@ pub fn non_cat_items(filename: &str, user: &User) -> Vec<String> {
 }
 
 /// Convert `filename` into a QIF transaction
-pub fn convert<'a>(
+pub fn convert<'a, F>(
     filename: &'a str,
     memo: &str,
     user: &'a mut User,
     acc: &'a Account,
-) -> Result<Transaction<'a>, String> {
+    categorizer: F,
+) -> Result<Transaction<'a>, String>
+where
+    F: Fn(&str, &mut CatStats) -> String,
+{
     let purchase = read_file(filename);
-    let splits = gen_splits(&purchase.items, &mut user.catmap);
+    let splits = gen_splits(&purchase.items, &mut user.catmap, categorizer);
     gen_trans(&acc, purchase.date(), purchase.total_sum(), memo, splits)
 }

+ 5 - 1
src/main.rs

@@ -57,10 +57,14 @@ fn main() {
         .build();
 
     if let Some(filename) = &args.filename {
-        let t = convert::convert(filename, &args.memo, &mut user, &acc).unwrap();
+        let cat = &|item: &str, stats: &mut categories::CatStats| -> String {
+            categories::get_category(&item, stats)
+        };
+        let t = convert::convert(filename, &args.memo, &mut user, &acc, &cat).unwrap();
         print!("{}", acc.to_string());
         println!("{}", t.to_string());
     }
+
     #[cfg(feature = "tv")]
     {
         ui::run_tv();

+ 12 - 7
src/telegram.rs

@@ -1,6 +1,6 @@
 // This bot throws a dice on each incoming message.
 
-use crate::categories::{assign_category, CatStats};
+use crate::categories::{get_category_from_tg, CatStats};
 use crate::convert::{convert, non_cat_items};
 use crate::user::User;
 use derive_more::From;
@@ -83,16 +83,19 @@ async fn convert_file(
     log::info!("Got file");
     for i in non_cat_items(&jsonfile, &user) {
         log::info!("Message about {}", i);
-        let newcat = input_category_from_tg(&i, &user.catmap);
-        ctx.answer(format!("{} is set to {}", i, newcat)).await;
+        let newcat = input_category_from_tg(&i, &user.catmap, &ctx).await;
+        ctx.answer(format!("{} is set to {}", i, newcat))
+            .await
+            .unwrap();
     }
     let acc = Account::new()
         .name("Wallet")
         .account_type(AccountType::Cash)
         .build();
-    log::info!("Account is ready");
-    let t = convert(jsonfile, "Test", user, &acc)?;
-    log::info!("Conversion performed");
+
+    let cat =
+        &|item: &str, stats: &mut CatStats| -> String { get_category_from_tg(&item, stats, &ctx) };
+    let t = convert(jsonfile, "Test", user, &acc, cat)?;
     file.write(acc.to_string().as_bytes()).await?;
     file.write(t.to_string().as_bytes()).await?;
     Ok(filepath)
@@ -109,7 +112,9 @@ pub async fn input_category_from_tg(
     categories: &CatStats,
     ctx: &UpdateWithCx<AutoSend<Bot>, Message>,
 ) -> String {
-    ctx.answer(format!("Input category for {}", item)).await;
+    ctx.answer(format!("Input category for {}", item))
+        .await
+        .unwrap();
     String::new()
 }