I am batman
This commit is contained in:
105
internal/chat_service/chat_service.go
Normal file
105
internal/chat_service/chat_service.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package chat_service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"OpsMastery.v5/internal/utils"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/websocket/v2"
|
||||
)
|
||||
|
||||
// Message struct definition
|
||||
// This struct represents a chat message sent/received via WebSocket.
|
||||
// It contains the message content and the sender's identifier (email).
|
||||
type Message struct {
|
||||
Content string `json:"content"` // The actual message text
|
||||
Sender string `json:"sender"` // The sender's email or username
|
||||
// Add more fields as needed (e.g., timestamp, chatId, etc.)
|
||||
}
|
||||
|
||||
// clients is a map of active WebSocket connections.
|
||||
// The key is the pointer to the websocket.Conn, the value is a boolean (always true).
|
||||
// This allows us to keep track of all connected clients for broadcasting messages.
|
||||
var clients = make(map[*websocket.Conn]bool)
|
||||
|
||||
// broadcastMessage sends a given Message to all connected clients.
|
||||
// If a client connection fails, it is removed from the clients map.
|
||||
func broadcastMessage(msg Message) {
|
||||
for client := range clients {
|
||||
// Send the message as JSON to the client
|
||||
err := client.WriteJSON(msg)
|
||||
if err != nil {
|
||||
// If sending fails, print error, close connection, and remove client
|
||||
fmt.Println("Error sending message:", err)
|
||||
client.Close()
|
||||
delete(clients, client)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start initializes and runs the chat WebSocket server.
|
||||
func Start() {
|
||||
// Create a new Fiber app instance
|
||||
app := fiber.New()
|
||||
|
||||
// Serve static files from the ./public directory at /public
|
||||
app.Static("/public", "./public")
|
||||
|
||||
// Middleware for /ws route to validate JWT token before allowing WebSocket upgrade
|
||||
app.Use("/ws", func(c *fiber.Ctx) error {
|
||||
// Extract token from query parameters
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
// If no token, reject the request
|
||||
return c.Status(fiber.StatusUnauthorized).SendString("Missing token")
|
||||
}
|
||||
// Validate the JWT token
|
||||
claims, err := utils.ValidateJWT(token, false)
|
||||
if err != nil {
|
||||
// If token is invalid, reject the request
|
||||
return c.Status(fiber.StatusUnauthorized).SendString("Invalid token")
|
||||
}
|
||||
// Store the user's email in Fiber's context locals for later use
|
||||
c.Locals("userEmail", claims["email"])
|
||||
// Proceed to the next handler (WebSocket upgrade)
|
||||
return c.Next()
|
||||
})
|
||||
|
||||
// WebSocket endpoint for chat communication
|
||||
app.Get("/ws", websocket.New(func(c *websocket.Conn) {
|
||||
// Retrieve the user's email from context locals
|
||||
userEmail, _ := c.Locals("userEmail").(string)
|
||||
// Register the new client connection
|
||||
clients[c] = true
|
||||
// Ensure client is removed and connection closed when handler exits
|
||||
defer func() {
|
||||
delete(clients, c)
|
||||
c.Close()
|
||||
}()
|
||||
// Main loop: read messages from this client and broadcast to all clients
|
||||
for {
|
||||
var msg Message
|
||||
// Try to read a JSON message from the client
|
||||
err := c.ReadJSON(&msg)
|
||||
if err != nil {
|
||||
// If JSON parsing fails, try to read a raw message (e.g., plain text)
|
||||
_, rawMsg, readErr := c.ReadMessage()
|
||||
if readErr != nil {
|
||||
// If reading fails, log and break the loop (disconnect client)
|
||||
fmt.Println("WebSocket closed:", readErr)
|
||||
break
|
||||
}
|
||||
// Construct a Message from the raw message and set sender
|
||||
msg = Message{Content: string(rawMsg), Sender: userEmail}
|
||||
} else {
|
||||
// If JSON was parsed, set the sender field
|
||||
msg.Sender = userEmail
|
||||
}
|
||||
// Broadcast the received message to all connected clients
|
||||
broadcastMessage(msg)
|
||||
}
|
||||
}))
|
||||
|
||||
// Start the Fiber server on port 5000
|
||||
app.Listen(":5000")
|
||||
}
|
||||
Reference in New Issue
Block a user