package live import ( "context" "errors" "strings" "time" ) const ( MaxStreams = 20 StatusWaiting = "waiting" StatusLive = "live" ) var ( ErrInvalidStreamID = errors.New("invalid stream id") ErrMaxStreams = errors.New("maximum live streams reached") ErrPublisherExists = errors.New("publisher already exists") ErrPublisherNotFound = errors.New("publisher not found") ErrSubscriberExists = errors.New("subscriber already exists") ErrSubscriberNotFound = errors.New("subscriber not found") ) type Stream struct { StreamID string PublisherID uint PublisherOnline bool SubscriberCount int LikeCount int StartedAt time.Time UpdatedAt time.Time } type StreamRepo interface { Get(context.Context, string) (*Stream, error) List(context.Context) ([]*Stream, error) RegisterPublisher(context.Context, string, uint) (*Stream, error) UnregisterPublisher(context.Context, string, uint) error RegisterSubscriber(context.Context, string, uint) (*Stream, error) UnregisterSubscriber(context.Context, string, uint) error Like(context.Context, string) (int, error) } type StreamUsecase struct{ repo StreamRepo } func NewStreamUsecase(repo StreamRepo) *StreamUsecase { return &StreamUsecase{repo: repo} } func (uc *StreamUsecase) List(ctx context.Context) ([]*Stream, error) { return uc.repo.List(ctx) } func (uc *StreamUsecase) Get(ctx context.Context, streamID string) (*Stream, error) { streamID = normalizeStreamID(streamID) if streamID == "" { return nil, ErrInvalidStreamID } return uc.repo.Get(ctx, streamID) } func (uc *StreamUsecase) RegisterPublisher(ctx context.Context, streamID string, userID uint) (*Stream, error) { streamID = normalizeStreamID(streamID) if streamID == "" || userID == 0 { return nil, ErrInvalidStreamID } return uc.repo.RegisterPublisher(ctx, streamID, userID) } func (uc *StreamUsecase) UnregisterPublisher(ctx context.Context, streamID string, userID uint) error { return uc.repo.UnregisterPublisher(ctx, normalizeStreamID(streamID), userID) } func (uc *StreamUsecase) RegisterSubscriber(ctx context.Context, streamID string, userID uint) (*Stream, error) { streamID = normalizeStreamID(streamID) if streamID == "" || userID == 0 { return nil, ErrInvalidStreamID } return uc.repo.RegisterSubscriber(ctx, streamID, userID) } func (uc *StreamUsecase) UnregisterSubscriber(ctx context.Context, streamID string, userID uint) error { return uc.repo.UnregisterSubscriber(ctx, normalizeStreamID(streamID), userID) } func (uc *StreamUsecase) Like(ctx context.Context, streamID string) (int, error) { streamID = normalizeStreamID(streamID) if streamID == "" { return 0, ErrInvalidStreamID } return uc.repo.Like(ctx, streamID) } func normalizeStreamID(value string) string { return strings.TrimSpace(value) }