use super::accounts::DEFAULT_ACCOUNT_ID;
use super::DbPool;
use crate::error::StorageError;
pub async fn increment_author_interaction_for(
pool: &DbPool,
account_id: &str,
author_id: &str,
author_username: &str,
) -> Result<(), StorageError> {
sqlx::query(
"INSERT INTO author_interactions (account_id, author_id, author_username, interaction_date, reply_count) \
VALUES (?, ?, ?, date('now'), 1) \
ON CONFLICT(author_id, interaction_date) \
DO UPDATE SET reply_count = reply_count + 1, author_username = excluded.author_username",
)
.bind(account_id)
.bind(author_id)
.bind(author_username)
.execute(pool)
.await
.map_err(|e| StorageError::Query { source: e })?;
Ok(())
}
pub async fn increment_author_interaction(
pool: &DbPool,
author_id: &str,
author_username: &str,
) -> Result<(), StorageError> {
increment_author_interaction_for(pool, DEFAULT_ACCOUNT_ID, author_id, author_username).await
}
pub async fn get_author_reply_count_today_for(
pool: &DbPool,
account_id: &str,
author_id: &str,
) -> Result<i64, StorageError> {
let row: (i64,) = sqlx::query_as(
"SELECT COALESCE( \
(SELECT reply_count FROM author_interactions \
WHERE author_id = ? AND interaction_date = date('now') AND account_id = ?), \
0)",
)
.bind(author_id)
.bind(account_id)
.fetch_one(pool)
.await
.map_err(|e| StorageError::Query { source: e })?;
Ok(row.0)
}
pub async fn get_author_reply_count_today(
pool: &DbPool,
author_id: &str,
) -> Result<i64, StorageError> {
get_author_reply_count_today_for(pool, DEFAULT_ACCOUNT_ID, author_id).await
}
#[cfg(test)]
mod tests {
use super::*;
use crate::storage::init_test_db;
#[tokio::test]
async fn increment_and_get_author_count() {
let pool = init_test_db().await.expect("init db");
let count = get_author_reply_count_today(&pool, "author_1")
.await
.expect("get");
assert_eq!(count, 0);
increment_author_interaction(&pool, "author_1", "alice")
.await
.expect("inc");
let count = get_author_reply_count_today(&pool, "author_1")
.await
.expect("get");
assert_eq!(count, 1);
increment_author_interaction(&pool, "author_1", "alice")
.await
.expect("inc");
let count = get_author_reply_count_today(&pool, "author_1")
.await
.expect("get");
assert_eq!(count, 2);
}
#[tokio::test]
async fn different_authors_tracked_separately() {
let pool = init_test_db().await.expect("init db");
increment_author_interaction(&pool, "author_1", "alice")
.await
.expect("inc");
increment_author_interaction(&pool, "author_2", "bob")
.await
.expect("inc");
let count1 = get_author_reply_count_today(&pool, "author_1")
.await
.expect("get");
let count2 = get_author_reply_count_today(&pool, "author_2")
.await
.expect("get");
assert_eq!(count1, 1);
assert_eq!(count2, 1);
}
}