Explorar o código

[Telegram] Conversion function call added

Signed-off-by: Slava Barinov <rayslava@gmail.com>
Slava Barinov %!s(int64=4) %!d(string=hai) anos
pai
achega
29e227e3e6
Modificáronse 3 ficheiros con 61 adicións e 1 borrados
  1. 7 0
      src/categories.rs
  2. 53 0
      src/telegram.rs
  3. 1 1
      src/user.rs

+ 7 - 0
src/categories.rs

@@ -1,3 +1,5 @@
+#[cfg(feature = "telegram")]
+use crate::telegram::{bot_is_running, input_category_from_tg};
 use crate::ui::input_category;
 use libc::isatty;
 use radix_trie::Trie;
@@ -75,6 +77,11 @@ pub fn get_top_category<'a>(item: &str, storage: &'a CatStats) -> Option<&'a str
 
 /// Choose proper category or ask user
 pub fn get_category(item: &str, storage: &mut CatStats) -> String {
+    #[cfg(feature = "telegram")]
+    if bot_is_running() {
+        input_category_from_tg(item, &storage);
+    };
+
     let istty = unsafe { isatty(libc::STDOUT_FILENO as i32) } != 0;
     if istty {
         let topcat = match get_top_category(item, storage) {

+ 53 - 0
src/telegram.rs

@@ -1,12 +1,18 @@
 // This bot throws a dice on each incoming message.
 
+use crate::categories::CatStats;
+use crate::convert::convert;
+use crate::user::User;
 use derive_more::From;
+use qif_generator::{account::Account, account::AccountType};
+use std::sync::atomic::{AtomicBool, Ordering};
 use teloxide::types::*;
 use teloxide::{net::Download, types::File as TgFile, Bot};
 use teloxide::{prelude::*, utils::command::BotCommand};
 use teloxide::{DownloadError, RequestError};
 use thiserror::Error;
 use tokio::fs::File;
+use tokio::io::AsyncWriteExt;
 
 #[cfg(feature = "telegram")]
 #[tokio::main]
@@ -29,6 +35,18 @@ enum FileReceiveError {
     Io(#[source] std::io::Error),
 }
 
+/// Possible error while receiving a file
+#[cfg(feature = "telegram")]
+#[derive(Debug, Error, From)]
+enum FileConvertError {
+    /// Telegram request error
+    #[error("JSON conversion error: {0}")]
+    Request(String),
+    /// Io error while writing file
+    #[error("An I/O error: {0}")]
+    Io(#[source] std::io::Error),
+}
+
 #[derive(BotCommand, Debug)]
 #[command(rename = "lowercase", description = "These commands are supported:")]
 enum Command {
@@ -38,6 +56,9 @@ enum Command {
     Start,
 }
 
+#[cfg(feature = "telegram")]
+static IS_RUNNING: AtomicBool = AtomicBool::new(false);
+
 #[cfg(feature = "telegram")]
 async fn download_file(downloader: &Bot, file_id: &str) -> Result<String, FileReceiveError> {
     let TgFile {
@@ -49,10 +70,37 @@ async fn download_file(downloader: &Bot, file_id: &str) -> Result<String, FileRe
     Ok(filepath)
 }
 
+#[cfg(feature = "telegram")]
+async fn convert_file(jsonfile: &str, user: &mut User) -> Result<String, FileConvertError> {
+    let filepath = format!("/tmp/{}.qif", jsonfile);
+    let mut file = File::create(&filepath).await?;
+
+    let acc = Account::new()
+        .name("Wallet")
+        .account_type(AccountType::Cash)
+        .build();
+
+    let t = convert(jsonfile, "Test", user, &acc)?;
+    file.write(acc.to_string().as_bytes()).await?;
+    file.write(t.to_string().as_bytes()).await?;
+    Ok(filepath)
+}
+
+#[cfg(feature = "telegram")]
+pub fn bot_is_running() -> bool {
+    IS_RUNNING.load(Ordering::SeqCst)
+}
+
+#[cfg(feature = "telegram")]
+pub fn input_category_from_tg(item: &str, categories: &CatStats) -> String {
+    String::new()
+}
+
 #[cfg(feature = "telegram")]
 async fn run() {
     teloxide::enable_logging!();
     log::info!("Starting dices_bot...");
+    IS_RUNNING.store(true, Ordering::SeqCst);
 
     let bot = Bot::from_env().auto_send();
 
@@ -66,6 +114,10 @@ async fn run() {
                     message
                         .answer(format!("File received: {:} ", newfile))
                         .await?;
+                    if let Some(tguser) = message.update.from() {
+                        let mut user = User::new(tguser.id, &None);
+                        let result = convert_file(&newfile, &mut user);
+                    }
                 }
 
                 message.answer_dice().await?;
@@ -92,4 +144,5 @@ async fn run() {
         respond(())
     })
     .await;
+    IS_RUNNING.store(false, Ordering::SeqCst);
 }

+ 1 - 1
src/user.rs

@@ -27,7 +27,7 @@ impl Drop for User {
 }
 
 impl User {
-    pub fn new(uid: i128, dbfile: &Option<String>) -> Self {
+    pub fn new(uid: i64, dbfile: &Option<String>) -> Self {
         let ten_sec = Duration::from_secs(10);
         let path: String = match dbfile {
             Some(path) => path.to_string(),