gitdataai/libs/room/src/reaction_write.rs
ZhenYi 14f6e1e500 feat(core): initialize project with access control and AI integration
- Add gitignore and prettier configuration files for project scaffolding
- Implement room access control service with project member verification
- Create user access key management with CRUD operations and activity logging
- Add accordion UI component for frontend expandable sections
- Implement room AI configuration with list, upsert, and delete operations
- Add AI event types for agent join/leave/status change tracking
- Create streaming AI processing services for mode and react patterns
- Build room AI service with model detection and idempotency handling
- Integrate chat service orchestration for AI message processing
- Add typing indicators and stream cancellation for AI interactions
- Implement mention parsing and context extraction for AI agents
2026-05-03 06:04:31 +08:00

105 lines
3.5 KiB
Rust

use crate::error::RoomError;
use crate::service::RoomService;
use crate::ws_context::WsUserContext;
use chrono::Utc;
use models::rooms::room_message_reaction;
use queue::ReactionGroup;
use sea_orm::*;
use uuid::Uuid;
impl RoomService {
pub async fn message_reaction_add(
&self,
message_id: Uuid,
emoji: String,
ctx: &WsUserContext,
) -> Result<super::reaction::MessageReactionsResponse, RoomError> {
let user_id = ctx.user_id;
let message = self.find_message_or_404(message_id).await?;
self.require_room_access(message.room, user_id).await?;
Self::validate_emoji(&emoji)?;
let txn = self.db.begin().await?;
let existing = room_message_reaction::Entity::find()
.filter(room_message_reaction::Column::Message.eq(message_id))
.filter(room_message_reaction::Column::User.eq(user_id))
.filter(room_message_reaction::Column::Emoji.eq(&emoji))
.one(&txn)
.await?;
if existing.is_some() {
txn.commit().await?;
return self.get_message_reactions(message_id, Some(user_id)).await;
}
let reaction = room_message_reaction::ActiveModel {
id: Set(Uuid::now_v7()),
room: Set(message.room),
message: Set(message_id),
user: Set(user_id),
emoji: Set(emoji.clone()),
created_at: Set(Utc::now()),
};
room_message_reaction::Entity::insert(reaction)
.exec(&txn)
.await?;
txn.commit().await?;
let reactions = self
.get_message_reactions(message_id, Some(user_id))
.await?;
let groups = reactions
.reactions
.iter()
.map(|g| ReactionGroup {
emoji: g.emoji.clone(),
count: g.count as i32,
reacted_by_me: g.reacted_by_me,
users: g.users.iter().filter_map(|u| u.parse().ok()).collect(),
})
.collect();
self.queue
.publish_reaction_event(message.room, message_id, groups)
.await;
self.get_message_reactions(message_id, Some(user_id)).await
}
pub async fn message_reaction_remove(
&self,
message_id: Uuid,
emoji: String,
ctx: &WsUserContext,
) -> Result<super::reaction::MessageReactionsResponse, RoomError> {
let user_id = ctx.user_id;
let message = self.find_message_or_404(message_id).await?;
self.require_room_access(message.room, user_id).await?;
room_message_reaction::Entity::delete_many()
.filter(room_message_reaction::Column::Message.eq(message_id))
.filter(room_message_reaction::Column::User.eq(user_id))
.filter(room_message_reaction::Column::Emoji.eq(&emoji))
.exec(&self.db)
.await?;
let reactions = self
.get_message_reactions(message_id, Some(user_id))
.await?;
let groups = reactions
.reactions
.iter()
.map(|g| ReactionGroup {
emoji: g.emoji.clone(),
count: g.count as i32,
reacted_by_me: g.reacted_by_me,
users: g.users.iter().filter_map(|u| u.parse().ok()).collect(),
})
.collect();
self.queue
.publish_reaction_event(message.room, message_id, groups)
.await;
self.get_message_reactions(message_id, Some(user_id)).await
}
}