use crate::util::{db::DbConnPool, operators::Operator}; use serenity::async_trait; use sqlx::Error; use std::str::FromStr; #[async_trait] pub(super) trait OpCommandQueries { async fn get_roll_count(&self, id: String) -> Result; async fn reset_roll_count(&self, id: String) -> Result<(), Error>; async fn add_roll_count(&self, id: String, amount: u32) -> Result<(), Error>; async fn get_operators(&self, id: String) -> Result, Error>; async fn add_operator(&self, id: String, op: Operator) -> Result<(), Error>; async fn remove_operator(&self, id: String, op: Operator) -> Result<(), Error>; } #[async_trait] impl OpCommandQueries for DbConnPool { async fn get_roll_count(&self, id: String) -> Result { let resp = sqlx::query!("SELECT count FROM RollCount WHERE user_id = ?", id) .fetch_one(&self.pool) .await?; Ok(resp.count) } async fn reset_roll_count(&self, id: String) -> Result<(), Error> { sqlx::query!( "INSERT INTO RollCount (user_id, count) VALUES (?, 0) ON CONFLICT(user_id) DO UPDATE SET count = 0", id ) .execute(&self.pool) .await?; Ok(()) } async fn add_roll_count(&self, id: String, amount: u32) -> Result<(), Error> { sqlx::query!( "INSERT INTO RollCount (user_id, count) VALUES (?, 0) ON CONFLICT(user_id) DO UPDATE SET count = MIN(99, count + ?)", id, amount as i32 ) .execute(&self.pool) .await?; Ok(()) } async fn get_operators(&self, id: String) -> Result, Error> { Ok(sqlx::query!( "SELECT operator, count FROM OperatorCount WHERE user_id = ?", id ) .fetch_all(&self.pool) .await? .iter() .map(|record| { ( Operator::from_str(record.operator.as_ref()).unwrap(), record.count as u32, ) }) .collect()) } async fn add_operator(&self, id: String, op: Operator) -> Result<(), Error> { sqlx::query!( "INSERT INTO OperatorCount (user_id, operator, count) VALUES (?, ?, 1) ON CONFLICT(user_id, operator) DO UPDATE SET count = count + 1", id, op ) .execute(&self.pool) .await?; Ok(()) } async fn remove_operator(&self, id: String, op: Operator) -> Result<(), Error> { sqlx::query!( "UPDATE OperatorCount SET count = MAX(count - 1, 0) WHERE user_id = ? AND operator = ?", id, op ) .execute(&self.pool) .await?; sqlx::query!("DELETE FROM OperatorCount WHERE count = 0") .execute(&self.pool) .await?; Ok(()) } }