- Implement full MessageHandler dispatch with all 18 incoming message types - Add handler_messages.go: SendMessage, EditMessage, DeleteMessage with ownership checks - Add handler_rooms.go: JoinConversation, LeaveConversation - Add handler_history.go: FetchHistory (cursor-based), SearchMessages (ILIKE), SyncMessages - Add handler_realtime.go: Typing, MarkAsRead, Delivered, AddReaction, RemoveReaction - Add handler_calls.go: WebRTC signaling relay (CallOffer/Answer/ICE/Hangup/Reject) - Add PermissionService: CanRead/CanSend/CanJoin/CanModerate based on room_members - Add RateLimiter: per-user per-action sliding window (in-memory) - Wire all dependencies in router.go setupChatWebSocket
80 lines
2.6 KiB
Go
80 lines
2.6 KiB
Go
package chat
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func (h *MessageHandler) HandleCallOffer(ctx context.Context, client *Client, msg *IncomingMessage) {
|
|
if msg.ConversationID == nil || msg.TargetUserID == nil {
|
|
client.SendJSON(NewErrorResponse("conversation_id and target_user_id are required"))
|
|
return
|
|
}
|
|
if msg.SDP == "" {
|
|
client.SendJSON(NewErrorResponse("sdp is required"))
|
|
return
|
|
}
|
|
|
|
outgoing := NewCallOfferResponse(*msg.ConversationID, client.UserID, msg.SDP, msg.CallType)
|
|
data, _ := json.Marshal(outgoing)
|
|
h.hub.SendToUser(*msg.TargetUserID, data)
|
|
|
|
h.logger.Info("Call offer relayed",
|
|
zap.String("from", client.UserID.String()),
|
|
zap.String("to", msg.TargetUserID.String()),
|
|
zap.String("type", msg.CallType))
|
|
}
|
|
|
|
func (h *MessageHandler) HandleCallAnswer(ctx context.Context, client *Client, msg *IncomingMessage) {
|
|
if msg.ConversationID == nil || msg.CallerUserID == nil {
|
|
client.SendJSON(NewErrorResponse("conversation_id and caller_user_id are required"))
|
|
return
|
|
}
|
|
if msg.SDP == "" {
|
|
client.SendJSON(NewErrorResponse("sdp is required"))
|
|
return
|
|
}
|
|
|
|
outgoing := NewCallAnswerResponse(*msg.ConversationID, *msg.CallerUserID, client.UserID, msg.SDP)
|
|
data, _ := json.Marshal(outgoing)
|
|
h.hub.SendToUser(*msg.CallerUserID, data)
|
|
}
|
|
|
|
func (h *MessageHandler) HandleICECandidate(ctx context.Context, client *Client, msg *IncomingMessage) {
|
|
if msg.ConversationID == nil || msg.TargetUserID == nil {
|
|
client.SendJSON(NewErrorResponse("conversation_id and target_user_id are required"))
|
|
return
|
|
}
|
|
if msg.Candidate == "" {
|
|
client.SendJSON(NewErrorResponse("candidate is required"))
|
|
return
|
|
}
|
|
|
|
outgoing := NewICECandidateResponse(*msg.ConversationID, client.UserID, msg.Candidate)
|
|
data, _ := json.Marshal(outgoing)
|
|
h.hub.SendToUser(*msg.TargetUserID, data)
|
|
}
|
|
|
|
func (h *MessageHandler) HandleCallHangup(ctx context.Context, client *Client, msg *IncomingMessage) {
|
|
if msg.ConversationID == nil || msg.TargetUserID == nil {
|
|
client.SendJSON(NewErrorResponse("conversation_id and target_user_id are required"))
|
|
return
|
|
}
|
|
|
|
outgoing := NewCallHangupResponse(*msg.ConversationID, client.UserID)
|
|
data, _ := json.Marshal(outgoing)
|
|
h.hub.SendToUser(*msg.TargetUserID, data)
|
|
}
|
|
|
|
func (h *MessageHandler) HandleCallReject(ctx context.Context, client *Client, msg *IncomingMessage) {
|
|
if msg.ConversationID == nil || msg.CallerUserID == nil {
|
|
client.SendJSON(NewErrorResponse("conversation_id and caller_user_id are required"))
|
|
return
|
|
}
|
|
|
|
outgoing := NewCallRejectedResponse(*msg.ConversationID, client.UserID)
|
|
data, _ := json.Marshal(outgoing)
|
|
h.hub.SendToUser(*msg.CallerUserID, data)
|
|
}
|