106 lines
3.1 KiB
Rust
106 lines
3.1 KiB
Rust
use chrono::Utc;
|
|
use uuid::Uuid;
|
|
|
|
use crate::event::{RoomInfo, UserInfo, reaction};
|
|
use crate::{ChannelBus, ChannelError, ChannelResult};
|
|
|
|
use super::WsHandler;
|
|
use super::WsOutEvent;
|
|
|
|
impl WsHandler {
|
|
pub(super) async fn reaction_add(
|
|
bus: &ChannelBus,
|
|
user_id: Uuid,
|
|
room: Uuid,
|
|
message: Uuid,
|
|
emoji: String,
|
|
) -> ChannelResult<Option<WsOutEvent>> {
|
|
Self::ensure_room_access(bus, user_id, room).await?;
|
|
Self::ensure_message_in_room(bus, room, message).await?;
|
|
if emoji.is_empty() || emoji.len() > 100 {
|
|
return Err(ChannelError::Validation("invalid emoji".into()));
|
|
}
|
|
let seq = bus.inner.seq.seq(room).await?;
|
|
let result = db::sqlx::query(
|
|
"INSERT INTO room_reaction (message, \"user\", seq, reaction, created_at) \
|
|
VALUES ($1, $2, $3, $4, now()) \
|
|
ON CONFLICT DO NOTHING",
|
|
)
|
|
.bind(message)
|
|
.bind(user_id)
|
|
.bind(seq)
|
|
.bind(&emoji)
|
|
.execute(bus.inner.db.writer())
|
|
.await?;
|
|
if result.rows_affected() == 0 {
|
|
return Ok(None);
|
|
}
|
|
let user = bus
|
|
.lookup_user(user_id)
|
|
.await
|
|
.unwrap_or_else(|_| UserInfo::unknown(user_id));
|
|
let rct_room = bus
|
|
.lookup_room(room)
|
|
.await
|
|
.unwrap_or_else(|_| RoomInfo::unknown(room));
|
|
let data = reaction::ReactionAddedService {
|
|
id: Uuid::now_v7(),
|
|
room: rct_room,
|
|
message,
|
|
user,
|
|
emoji,
|
|
created_at: Utc::now(),
|
|
};
|
|
bus.publish_room_event(room, "reaction.added", &data)
|
|
.await?;
|
|
Ok(Some(WsOutEvent::ReactionAdded {
|
|
room: data.room.clone(),
|
|
data,
|
|
}))
|
|
}
|
|
|
|
pub(super) async fn reaction_remove(
|
|
bus: &ChannelBus,
|
|
user_id: Uuid,
|
|
room: Uuid,
|
|
message: Uuid,
|
|
emoji: String,
|
|
) -> ChannelResult<Option<WsOutEvent>> {
|
|
Self::ensure_room_access(bus, user_id, room).await?;
|
|
Self::ensure_message_in_room(bus, room, message).await?;
|
|
let result = db::sqlx::query(
|
|
"DELETE FROM room_reaction WHERE message = $1 AND \"user\" = $2 AND reaction = $3",
|
|
)
|
|
.bind(message)
|
|
.bind(user_id)
|
|
.bind(&emoji)
|
|
.execute(bus.inner.db.writer())
|
|
.await?;
|
|
if result.rows_affected() == 0 {
|
|
return Ok(None);
|
|
}
|
|
let user = bus
|
|
.lookup_user(user_id)
|
|
.await
|
|
.unwrap_or_else(|_| UserInfo::unknown(user_id));
|
|
let rct_room = bus
|
|
.lookup_room(room)
|
|
.await
|
|
.unwrap_or_else(|_| RoomInfo::unknown(room));
|
|
let data = reaction::ReactionRemovedService {
|
|
id: Uuid::now_v7(),
|
|
room: rct_room,
|
|
message,
|
|
user,
|
|
emoji,
|
|
removed_at: Utc::now(),
|
|
};
|
|
bus.publish_room_event(room, "reaction.removed", &data)
|
|
.await?;
|
|
Ok(Some(WsOutEvent::ReactionRemoved {
|
|
room: data.room.clone(),
|
|
data,
|
|
}))
|
|
}
|
|
}
|