gitdataai/libs/room/src/draft_and_history.rs
2026-04-15 09:08:09 +08:00

199 lines
6.2 KiB
Rust

use crate::error::RoomError;
use crate::service::RoomService;
use crate::ws_context::WsUserContext;
use chrono::Utc;
use models::rooms::NotificationType;
use models::rooms::room_message_edit_history;
use models::users::user as user_model;
use sea_orm::*;
use uuid::Uuid;
#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
pub struct MessageEditHistoryEntry {
pub old_content: String,
pub new_content: String,
pub edited_at: chrono::DateTime<Utc>,
}
#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
pub struct MessageEditHistoryResponse {
pub message_id: Uuid,
pub history: Vec<MessageEditHistoryEntry>,
pub total_edits: i64,
}
#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
pub struct MentionNotificationResponse {
pub message_id: Uuid,
pub mentioned_by: Uuid,
pub mentioned_by_name: String,
pub content_preview: String,
pub room_id: Uuid,
pub room_name: String,
pub created_at: chrono::DateTime<Utc>,
}
#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
pub struct DraftResponse {
pub room_id: Uuid,
pub content: String,
pub saved_at: chrono::DateTime<Utc>,
}
#[derive(Debug, Clone, serde::Deserialize)]
pub struct DraftSaveRequest {
pub content: String,
}
impl RoomService {
pub async fn save_message_edit_history(
&self,
message_id: Uuid,
user_id: Uuid,
old_content: String,
new_content: String,
) -> Result<(), RoomError> {
let history = room_message_edit_history::ActiveModel {
id: Set(Uuid::now_v7()),
message: Set(message_id),
user: Set(user_id),
old_content: Set(old_content),
new_content: Set(new_content),
edited_at: Set(Utc::now()),
};
history.insert(&self.db).await?;
Ok(())
}
pub async fn get_message_edit_history(
&self,
message_id: Uuid,
ctx: &WsUserContext,
) -> Result<MessageEditHistoryResponse, RoomError> {
let user_id = ctx.user_id;
let message = models::rooms::room_message::Entity::find_by_id(message_id)
.one(&self.db)
.await?
.ok_or_else(|| RoomError::NotFound("Message not found".to_string()))?;
self.require_room_member(message.room, user_id).await?;
let history = room_message_edit_history::Entity::find()
.filter(room_message_edit_history::Column::Message.eq(message_id))
.order_by_asc(room_message_edit_history::Column::EditedAt)
.all(&self.db)
.await?;
let total_edits = history.len() as i64;
let history_entries = history
.into_iter()
.map(|h| MessageEditHistoryEntry {
old_content: h.old_content,
new_content: h.new_content,
edited_at: h.edited_at,
})
.collect();
Ok(MessageEditHistoryResponse {
message_id,
history: history_entries,
total_edits,
})
}
pub async fn get_mention_notifications(
&self,
limit: Option<u64>,
ctx: &WsUserContext,
) -> Result<Vec<MentionNotificationResponse>, RoomError> {
let user_id = ctx.user_id;
let limit = limit.unwrap_or(50);
let notifications = models::rooms::room_notifications::Entity::find()
.filter(models::rooms::room_notifications::Column::UserId.eq(user_id))
.filter(
models::rooms::room_notifications::Column::NotificationType
.eq(NotificationType::Mention),
)
.order_by_desc(models::rooms::room_notifications::Column::CreatedAt)
.limit(limit)
.all(&self.db)
.await?;
let mut result = Vec::new();
for notification in notifications {
let mentioned_by =
user_model::Entity::find_by_id(notification.related_user_id.unwrap_or_default())
.one(&self.db)
.await?;
let room_name = if let Some(room_id) = notification.room {
models::rooms::room::Entity::find_by_id(room_id)
.one(&self.db)
.await?
.map(|r| r.room_name)
.unwrap_or_else(|| "Unknown Room".to_string())
} else {
"Unknown Room".to_string()
};
let mentioned_by_name = mentioned_by
.map(|u| u.display_name.unwrap_or(u.username))
.unwrap_or_else(|| "Unknown User".to_string());
let content_preview = notification
.content
.unwrap_or_default()
.chars()
.take(100)
.collect();
result.push(MentionNotificationResponse {
message_id: notification.related_message_id.unwrap_or_default(),
mentioned_by: notification.related_user_id.unwrap_or_default(),
mentioned_by_name,
content_preview,
room_id: notification.room.unwrap_or_default(),
room_name,
created_at: notification.created_at,
});
}
Ok(result)
}
pub async fn mark_mention_notifications_read(
&self,
ctx: &WsUserContext,
) -> Result<(), RoomError> {
let user_id = ctx.user_id;
use sea_orm::sea_query::Expr;
let now = Utc::now();
models::rooms::room_notifications::Entity::update_many()
.col_expr(
models::rooms::room_notifications::Column::IsRead,
Expr::value(true),
)
.col_expr(
models::rooms::room_notifications::Column::ReadAt,
Expr::value(Some(now)),
)
.filter(models::rooms::room_notifications::Column::UserId.eq(user_id))
.filter(
models::rooms::room_notifications::Column::NotificationType
.eq(NotificationType::Mention),
)
.filter(models::rooms::room_notifications::Column::IsRead.eq(false))
.exec(&self.db)
.await?;
Ok(())
}
}