199 lines
6.2 KiB
Rust
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(())
|
|
}
|
|
}
|