backend-service/internal/services/jitsi_service.go
ats-tech25 b8dd31b449 feat(services): Implement comprehensive booking service with Jitsi integration
- Add BookingService with core booking management functionality
- Implement mock repositories for testing booking service interactions
- Create booking integration test with Jitsi room generation
- Add methods for creating, retrieving, and managing bookings
- Integrate Jitsi service for generating meeting room URLs
- Implement schedule management within booking service
- Add support for booking creation with user and schedule context
- Enhance database layer to support repository retrieval
Closes #TICKET_NUMBER (if applicable)
2025-11-05 15:42:59 +00:00

93 lines
2.6 KiB
Go

package services
import (
"crypto/rand"
"encoding/hex"
"fmt"
"log"
"time"
"attune-heart-therapy/internal/config"
)
// jitsiService implements the JitsiService interface
type jitsiService struct {
config *config.JitsiConfig
}
// NewJitsiService creates a new instance of JitsiService
func NewJitsiService(cfg *config.JitsiConfig) JitsiService {
return &jitsiService{
config: cfg,
}
}
// CreateMeeting creates a new Jitsi meeting room for a booking
func (j *jitsiService) CreateMeeting(bookingID uint, scheduledAt time.Time) (*JitsiMeeting, error) {
// Generate a unique room ID
roomID, err := j.generateRoomID(bookingID)
if err != nil {
log.Printf("Failed to generate room ID for booking %d: %v", bookingID, err)
return nil, fmt.Errorf("failed to generate room ID: %w", err)
}
// Generate the meeting URL
roomURL := j.GetMeetingURL(roomID)
meeting := &JitsiMeeting{
RoomID: roomID,
RoomURL: roomURL,
}
log.Printf("Created Jitsi meeting for booking %d: Room ID %s", bookingID, roomID)
return meeting, nil
}
// GetMeetingURL generates the full Jitsi meeting URL for a given room ID
func (j *jitsiService) GetMeetingURL(roomID string) string {
baseURL := j.config.BaseURL
if baseURL == "" {
// Default to meet.jit.si if no base URL is configured
baseURL = "https://meet.jit.si"
}
// Ensure the base URL doesn't end with a slash
if baseURL[len(baseURL)-1] == '/' {
baseURL = baseURL[:len(baseURL)-1]
}
return fmt.Sprintf("%s/%s", baseURL, roomID)
}
// DeleteMeeting handles cleanup of a Jitsi meeting room
// Note: Jitsi Meet doesn't require explicit room deletion as rooms are ephemeral
// This method is implemented for interface compliance and future extensibility
func (j *jitsiService) DeleteMeeting(roomID string) error {
// Jitsi Meet rooms are ephemeral and don't require explicit deletion
// However, we can log the deletion for audit purposes
log.Printf("Meeting room %s marked for cleanup", roomID)
// In the future, if using Jitsi as a Service (JaaS) or custom deployment,
// this method could make API calls to clean up resources
return nil
}
// generateRoomID creates a unique room identifier for the meeting
func (j *jitsiService) generateRoomID(bookingID uint) (string, error) {
// Generate a random component for uniqueness
randomBytes := make([]byte, 8)
_, err := rand.Read(randomBytes)
if err != nil {
return "", fmt.Errorf("failed to generate random bytes: %w", err)
}
randomHex := hex.EncodeToString(randomBytes)
// Create a room ID that includes the booking ID and timestamp for uniqueness
timestamp := time.Now().Unix()
roomID := fmt.Sprintf("booking-%d-%d-%s", bookingID, timestamp, randomHex)
return roomID, nil
}