use std::convert::Infallible;
use std::collections::HashMap;
use warp::http::StatusCode;
use log::*;
use crate::db::{self, DbConn};
use crate::models::comment::{self, Comment};
use crate::models::reply::{self, Reply};
use crate::models::upvote::{self, Upvote};
use crate::models::downvote::{self, Downvote};
use crate::models::status::Status;
pub async fn list_comments(
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
let mut results: Vec<Comment> = Vec::new();
match db::get_all_comments(db_conn).await {
Ok(data) => results = data,
Err(message) => error!("{:?} occurred in handlers::list_comments()", message),
};
let filtered: Vec<Comment> = results.into_iter().filter(|each|
each.status == Status::Pending
|| each.status == Status::Approved
|| each.status == Status:: Disabled
).collect();
Ok( warp::reply::json( &filtered ) )
}
pub async fn more_comments(
count: usize,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
let mut results: Vec<Comment> = Vec::new();
match db::get_more_comments(count, db_conn).await {
Ok(data) => results = data,
Err(message) => error!("{:?} occurred in handlers::more_comments()", message),
};
let filtered: Vec<Comment> = results.into_iter().filter(|each|
each.status == Status::Pending
|| each.status == Status::Approved
|| each.status == Status:: Disabled
).collect();
Ok( warp::reply::json( &filtered ) )
}
pub async fn add_comment(
new_comment: Comment,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("add comment: {:?}", new_comment);
let mut comment_clone = new_comment.clone();
comment::assign_uid(&mut comment_clone);
comment::assign_created_date(&mut comment_clone);
let result = db::add_comment(&comment_clone, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
fn process_db_result(result: Result<usize, rusqlite::Error>) -> warp::http::StatusCode {
match result {
Ok(count) => {
match count {
1 => StatusCode::NO_CONTENT,
_ => StatusCode::NOT_FOUND
}
},
Err(error) => {
error!("Error: {} occurred in process_db_result...........", &error);
StatusCode::NOT_FOUND
}
}
}
pub async fn update_comment(
uid: String,
mut comment: Comment,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("update comment: uid = {}, comment = {:?}", uid, comment);
comment.unique_id = uid;
comment.remarks = String::from("several fields are updated");
comment::assign_updated_date(&mut comment);
let result = db::update_comment(&comment, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn update_comment_status(
stat: String,
uid: String,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("update comment status: stat = {}, uid = {}", &stat, uid);
let now: String = comment::timestamp_now();
let status: Status = Status::from_string(stat);
let result = db::update_comment_status(status, uid, now, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn update_comment_message(
uid: String,
map: HashMap<String, String>,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("update comment message: uid = {}, new-message: {:?}+++++++++++++++++++++++++++", &uid, &map);
let now: String = comment::timestamp_now();
let msg = map.get("message").unwrap();
let result = db::update_comment_message(msg.to_string(), uid, now, db_conn).await;
let code = process_db_result(result);
Ok(code)
}
pub async fn delete_comment(
uid: String,
db_conn: DbConn
) -> Result<impl warp::Reply, Infallible> {
debug!("delete comment: uid = {}", uid);
let now: String = comment::timestamp_now();
let result = db::delete_comment(&uid, now, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn get_comment(
uid: String,
db_conn: DbConn
) -> Result<impl warp::Reply, Infallible> {
debug!("get comment: uid = {}", uid);
match db::get_comment(&uid, db_conn).await {
Ok(data) => Ok( warp::reply::json( &data ) ),
Err(message) => {
error!("{} occurred in handlers::get_comment()", message);
Ok( warp::reply::json( &"No Data Found" ) )
},
}
}
pub async fn comments_total(
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
let total: u32 = match db::get_comments_total(db_conn).await {
Ok(data) => data,
Err(message) => {
error!("{:?} occurred in handlers::comments_total()", message);
0u32
}
};
Ok( warp::reply::json( &total ) )
}
pub async fn add_reply(
new_reply: Reply,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("add reply: {:?}", new_reply);
let mut reply_clone = new_reply.clone();
reply::assign_uid(&mut reply_clone);
reply::assign_created_date(&mut reply_clone);
let result = db::add_reply(&reply_clone, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn list_replies(
comment_id: String,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
let mut results: Vec<Reply> = Vec::new();
match db::get_replies(comment_id, &Status::Pending.to_string(), db_conn).await {
Ok(data) => results = data,
Err(message) => error!("{:?} occurred in handlers::list_replies()", message),
};
Ok( warp::reply::json( &results ) )
}
pub async fn update_reply(
uid: String,
mut reply: Reply,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("update reply: uid = {}, reply = {:?}", uid, reply);
reply.unique_id = uid;
reply.status = Status::Approved;
reply.remarks = String::from("updated");
reply::assign_updated_date(&mut reply);
let result = db::update_reply(&reply, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn update_reply_message(
uid: String,
map: HashMap<String, String>,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("update reply message: uid = {}, new-message: {:?}+++++++++++++++++++++++++++", &uid, &map);
let now: String = comment::timestamp_now();
let msg = map.get("message").unwrap();
let result = db::update_reply_message(msg.to_string(), uid, now, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn delete_reply(
uid: String,
db_conn: DbConn
) -> Result<impl warp::Reply, Infallible> {
debug!("delete reply: uid = {}", uid);
let now: String = comment::timestamp_now();
let result = db::delete_reply(&uid, now, db_conn).await;
let code = process_db_result( result );
Ok(code)
}
pub async fn get_reply(
uid: String,
db_conn: DbConn
) -> Result<impl warp::Reply, Infallible> {
debug!("get reply: uid = {}", uid);
match db::get_reply(&uid, db_conn).await {
Ok(data) => Ok( warp::reply::json( &data ) ),
Err(message) => {
error!("{} occurred in handlers::get_reply()", message);
Ok( warp::reply::json( &"No Data Found" ) )
},
}
}
pub async fn add_upvote(
new_upvote: Upvote,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("add upvote: {:?}", new_upvote);
let mut upvote_clone = new_upvote.clone();
upvote::assign_created_date(&mut upvote_clone);
match db::add_upvote(&upvote_clone, db_conn.clone()).await {
Ok(count) => {
match count {
1 => Ok(StatusCode::CREATED),
_ => Ok(StatusCode::BAD_REQUEST)
}
},
Err(rusqlite::Error::SqliteFailure(error, _options)) => {
let mut code = StatusCode::BAD_REQUEST;
let is_constraint_error = error.code == rusqlite::ErrorCode::ConstraintViolation
&& error.extended_code == "2067".parse::<i32>().unwrap();
if is_constraint_error {
code = revoke_upvote(&upvote_clone, db_conn.clone()).await;
}
Ok(code)
},
Err(error) => {
error!("{:?} occurred in handlers::add_upvote()", &error);
Ok(StatusCode::BAD_REQUEST)
},
}
}
async fn revoke_upvote(upvote: &Upvote, db_conn: DbConn) -> warp::http::StatusCode {
let now: String = upvote::timestamp_now();
let result = db::delete_upvote(&upvote.comment_id, &upvote.user_id, now, db_conn).await;
process_db_result(result)
}
pub async fn delete_upvote(
comment_id: String,
user_id: String,
db_conn: DbConn
) -> Result<impl warp::Reply, Infallible> {
debug!("delete upvote: comment_id = {}, user_id = {}", &comment_id, &user_id);
let now: String = upvote::timestamp_now();
let result = db::delete_upvote(&comment_id, &user_id, now, db_conn).await;
let code = process_db_result(result);
Ok(code)
}
pub async fn upvotes_total(
comment_id: String,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
let total: u32 = match db::get_upvotes_total(&comment_id, db_conn).await {
Ok(data) => data,
Err(message) => {
error!("{:?} occurred in handlers::upvotes_total()", message);
0u32
}
};
Ok( warp::reply::json( &total ) )
}
pub async fn add_downvote(
new_downvote: Downvote,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
debug!("add downvote: {:?}", new_downvote);
let mut downvote_clone = new_downvote.clone();
downvote::assign_created_date(&mut downvote_clone);
match db::add_downvote(&downvote_clone, db_conn.clone()).await {
Ok(count) => {
match count {
1 => Ok(StatusCode::CREATED),
_ => Ok(StatusCode::BAD_REQUEST)
}
},
Err(rusqlite::Error::SqliteFailure(error, _options)) => {
let mut code = StatusCode::BAD_REQUEST;
let is_constraint_error = error.code == rusqlite::ErrorCode::ConstraintViolation
&& error.extended_code == "2067".parse::<i32>().unwrap();
if is_constraint_error {
code = revoke_downvote(&downvote_clone, db_conn.clone()).await;
}
Ok(code)
},
Err(error) => {
error!("{:?} occurred in handlers::add_downvote()", &error);
Ok(StatusCode::BAD_REQUEST)
},
}
}
async fn revoke_downvote(downvote: &Downvote, db_conn: DbConn) -> warp::http::StatusCode {
let now: String = downvote::timestamp_now();
let result = db::delete_downvote(&downvote.comment_id, &downvote.user_id, now, db_conn).await;
process_db_result(result)
}
pub async fn delete_downvote(
comment_id: String,
user_id: String,
db_conn: DbConn
) -> Result<impl warp::Reply, Infallible> {
debug!("delete downvote: comment_id = {}, user_id = {}", &comment_id, &user_id);
let now: String = downvote::timestamp_now();
let result = db::delete_downvote(&comment_id, &user_id, now, db_conn).await;
let code = process_db_result(result);
Ok(code)
}
pub async fn downvotes_total(
comment_id: String,
db_conn: DbConn,
) -> Result<impl warp::Reply, Infallible> {
let total: u32 = match db::get_downvotes_total(&comment_id, db_conn).await {
Ok(data) => data,
Err(message) => {
error!("{:?} occurred in handlers::downvotes_total()", message);
0u32
}
};
Ok( warp::reply::json( &total ) )
}