Skip to content

Commit

Permalink
♻️ Refactoring code
Browse files Browse the repository at this point in the history
  • Loading branch information
cristiancolosimo committed Oct 15, 2023
1 parent 67ecf95 commit e548323
Showing 1 changed file with 105 additions and 101 deletions.
206 changes: 105 additions & 101 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,83 @@ use serde::Deserialize;
use sqlx::{sqlite::SqlitePool, Pool, Sqlite};
use teloxide::prelude::*;

type DbConnectionType = Sqlite;
type DbPool = SqlitePool;
#[derive(Debug, Deserialize, sqlx::FromRow)]
struct User {
id: i32,
telegram_id: i32,
}

impl User {
async fn insert_user_db(
telegram_user_id: i32,
pool: &Pool<DbConnectionType>,
) -> Result<(), ()> {
let query_result =
sqlx::query::<DbConnectionType>("INSERT INTO users (telegram_id) VALUES (?)")
.bind(telegram_user_id)
.execute(pool)
.await;
if query_result.is_err() {
log::error!("Error inserting user in DB {:?}", query_result);
return Err(());
}
return Ok(());
}
async fn select_all_user_db(pool: &Pool<DbConnectionType>) -> Result<Vec<User>, sqlx::Error> {
return sqlx::query_as::<DbConnectionType, User>("SELECT * FROM users")
.fetch_all(pool)
.await;
}
}

#[derive(Debug, Deserialize, sqlx::FromRow)]
struct Log {
id: i32,
status: bool,
timestamp: String,
}

async fn get_db() -> Pool<Sqlite> {
impl Log {
async fn get_last_status_db(pool: &Pool<DbConnectionType>) -> Result<Log, sqlx::Error> {
let db_last_state: Result<Log, sqlx::Error> =
sqlx::query_as::<DbConnectionType, Log>("SELECT * FROM logs ORDER BY id DESC LIMIT 1")
.fetch_one(pool)
.await;
if db_last_state.is_err() {
log::error!("Error fetching last status in DB {:?}", db_last_state);
return Err(db_last_state.unwrap_err());
}
let db_last_state = db_last_state.unwrap();
return Ok(db_last_state);
}
async fn insert_status_db(
current_real_status: bool,
pool: &Pool<DbConnectionType>,
) -> Result<(), sqlx::Error> {
return match sqlx::query::<DbConnectionType>(
"INSERT INTO logs (status, timestamp) VALUES (?, ?)",
)
.bind(current_real_status)
.bind(chrono::Local::now().to_rfc3339())
.execute(pool)
.await
{
Ok(_) => Ok(()),
Err(err) => {
log::error!("Error insert status in DB {:?}", err);
Err(err)
}
};
}
}

async fn get_db() -> Pool<DbConnectionType> {
let current_dir = std::env::current_dir().unwrap();
let db_path = format!("{}/presencebot.db", current_dir.display());
let pool = SqlitePool::connect(&db_path).await.unwrap();
sqlx::query::<Sqlite>(
let pool = DbPool::connect(&db_path).await.unwrap();
sqlx::query::<DbConnectionType>(
r"
CREATE TABLE IF NOT EXISTS logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
Expand Down Expand Up @@ -96,12 +156,7 @@ async fn fetch_history() -> Option<String> {
}
let first_user = first_user.unwrap();
let env_time_offset = std::env::var("CHRONO_TIME_OFFSET");
let time_offset = if env_time_offset.is_ok() {
env_time_offset.unwrap()
} else {
//Italy offset //Offset Z for UTC
String::from("+02:00")
};
let time_offset = env_time_offset.unwrap_or(String::from("+02:00")); //Z = UTF, +02:00 italy,ecc
let time = format!("{}{}", first_user.time, time_offset);
let time_parsed = DateTime::parse_from_rfc3339(&time);
if time_parsed.is_err() {
Expand All @@ -119,87 +174,52 @@ async fn fetch_history() -> Option<String> {
return None;
}

async fn fetching_state_loop(pool: &Pool<Sqlite>) {
async fn fetching_state_loop(pool: &Pool<DbConnectionType>) {
let get_lab_state_endpoint = std::env::var("GET_LAB_STATE_ENDPOINT").unwrap();

let current_state_lab_raw = reqwest::get(get_lab_state_endpoint).await;
let mut current_state_lab_id: u8 = 0;
match current_state_lab_raw {
Ok(data) => {
let current_state_lab: LabState = data.json().await.unwrap();
log::info!("Current state 1: {:?}", current_state_lab);
current_state_lab_id = current_state_lab.id;
}
Err(_) => {
log::error!("Error fetching lab state ");
}
let mut current_state_lab_id: bool = false;
if let Ok(data) = current_state_lab_raw {
let current_state_lab: LabState = data.json().await.unwrap();
log::info!("Current state 1: {:?}", current_state_lab);
current_state_lab_id = current_state_lab.id == 1; //Casting int to bool
}
log::info!("Current state 2: {:?}", current_state_lab_id);
let current_state_lab_id: bool = current_state_lab_id == 1; // 1 = open, 0 = closed
let db_last_state = Log::get_last_status_db(pool).await;

let db_last_state: Result<Log, sqlx::Error> =
sqlx::query_as::<Sqlite, Log>("SELECT * FROM logs ORDER BY id DESC LIMIT 1")
.fetch_one(pool)
.await;
match db_last_state {
Ok(data) => {
let db_last_status = data.status;
if db_last_status == current_state_lab_id {
log::info!("Current state: equal to last state");
return;
}

sqlx::query::<Sqlite>("INSERT INTO logs (status,timestamp) VALUES (?,?)")
.bind(current_state_lab_id)
.bind(chrono::Local::now().to_rfc3339())
.execute(pool)
Log::insert_status_db(current_state_lab_id, pool)
.await
.unwrap();
let message: String;
if current_state_lab_id {
let history_user_name = fetch_history().await;
message = generate_response(current_state_lab_id, history_user_name);
} else {
message = generate_response(current_state_lab_id, None);
}

sqlx::query_as::<Sqlite, User>("SELECT * FROM users")
.fetch_all(pool)
.await
.unwrap()
.iter()
.for_each(|user| {
log::info!("Sending message to user: {:?}", user);
let history_user_name = fetch_history().await;
let message: String = generate_response(current_state_lab_id, history_user_name);

let users = User::select_all_user_db(pool).await.unwrap();
let bot = Bot::from_env();

let bot = Bot::from_env();
let user_id = user.telegram_id as i64;
let message = message.clone();
tokio::spawn(async move {
bot.send_message(ChatId(user_id), message)
.send()
.await
.unwrap();
});
});
data.status
for user in users.iter() {
log::info!("Sending message to user: {:?}", user);

let user_id = user.telegram_id as i64;
bot.send_message(ChatId(user_id), &message)
.send()
.await
.unwrap();
}
}
Err(error) => {
//Insert genesis status record
log::error!("Error genesis status record: {:?}", error);
Err(_) => {
log::info!("Current state: no last state, inserting genesis status in DB");
match sqlx::query::<Sqlite>("INSERT INTO logs (status) VALUES (?)")
.bind(current_state_lab_id)
.execute(pool)

Log::insert_status_db(current_state_lab_id, pool)
.await
{
Ok(_) => {
log::info!("Current state: genesis status inserted in DB");
}
Err(err) => {
log::error!("Error insert genesis status in DB {:?}", err);
}
}
false
.unwrap();
}
};
}
Expand All @@ -217,60 +237,44 @@ async fn main() {
let pool = get_db().await;
let pool_loop = pool.clone();
let pool_telegram = pool.clone();
//Loop fetch state
tokio::spawn(async move {
let mut interval = tokio::time::interval(std::time::Duration::from_secs(polling_interval));

loop {
interval.tick().await;
log::info!("Fetching state LAB...");
fetching_state_loop(&pool_loop).await;
}
});
//Loop telegram bot
teloxide::repl(bot, move |bot: Bot, msg: Message| {
loop_telegram(bot, msg, pool_telegram.clone())
})
.await;
}

async fn loop_telegram(bot: Bot, msg: Message, db: Pool<Sqlite>) -> ResponseResult<()> {
let query = sqlx::query::<Sqlite>("INSERT INTO users (telegram_id) VALUES (?)")
.bind(msg.chat.id.0)
.execute(&db)
.await;
let db_last_state: Result<Log, sqlx::Error> =
sqlx::query_as::<Sqlite, Log>("SELECT * FROM logs ORDER BY id DESC LIMIT 1")
.fetch_one(&db)
.await;
async fn loop_telegram(bot: Bot, msg: Message, db: Pool<DbConnectionType>) -> ResponseResult<()> {
let user_add_try = User::insert_user_db(msg.chat.id.0 as i32, &db).await;

let db_last_state = Log::get_last_status_db(&db).await;
let mut message_status: Option<String> = None;
if let Ok(db_last_state) = db_last_state {
if let Ok(db_last_state) = db_last_state {
if db_last_state.status {
message_status = Some(String::from("Il laboratorio è attualmente aperto"));
} else {
message_status = Some(String::from("Il laboratorio è attualmente chiuso"));
}
}

match query {
Ok(_) => {
log::info!("User added to db");
let message: &str =
"Ciao, sono il bot HLCS 🦀. Ti avviserò quando il laboratorio sarà aperto o chiuso";
bot.send_message(msg.chat.id, message).await?;
if message_status.is_some() {
bot.send_message(msg.chat.id, message_status.unwrap())
.await?;
}
}
Err(err) => {
log::info!("User already exists in db {:?}", err);
let message: &str = "Ciao, sono il bot HLCS 🦀. Ti avviserò quando il laboratorio sarà aperto o chiuso, ti avverto che eri già iscritto";
bot.send_message(msg.chat.id, message).await?;
let messaggio_benvenuto = match user_add_try {
Ok(()) => "Ciao, sono il bot HLCS 🦀. Ti avviserò quando il laboratorio sarà aperto o chiuso",
Err(()) => "Ciao, sono il bot HLCS 🦀. Ti avviserò quando il laboratorio sarà aperto o chiuso, ti avverto che eri già iscritto"
};
bot.send_message(msg.chat.id, messaggio_benvenuto).await?;

if message_status.is_some() {
bot.send_message(msg.chat.id, message_status.unwrap())
.await?;
}
}
if message_status.is_some() {
bot.send_message(msg.chat.id, message_status.unwrap())
.await?;
}
Ok(())
}

0 comments on commit e548323

Please sign in to comment.