mirror of
https://github.com/kemko/icecast-ripper.git
synced 2026-01-01 15:55:42 +03:00
* feat: integrate MP3 duration extraction and silence handling - Added a new dependency on github.com/tcolgate/mp3 for MP3 frame decoding. - Implemented actual MP3 duration retrieval in the scanRecordings function, falling back to an estimation if retrieval fails. - Introduced a silent frame asset for generating silence in audio streams. - Created a silence reader to provide a continuous stream of silent frames. - Added necessary documentation and licensing for the new MP3 package. - Updated .gitignore to exclude MP3 files except for the internal data directory. * feat: update README and improve application configuration and logging * refactor: remove unused GenerateFileHash function and improve resource cleanup in MP3 and recorder modules
84 lines
1.9 KiB
Go
84 lines
1.9 KiB
Go
package streamchecker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type Checker struct {
|
|
streamURL string
|
|
client *http.Client
|
|
userAgent string
|
|
}
|
|
|
|
// Option represents a functional option for configuring the Checker
|
|
type Option func(*Checker)
|
|
|
|
// WithUserAgent sets a custom User-Agent header
|
|
func WithUserAgent(userAgent string) Option {
|
|
return func(c *Checker) {
|
|
c.userAgent = userAgent
|
|
}
|
|
}
|
|
|
|
// New creates a new stream checker with sensible defaults
|
|
func New(streamURL string, opts ...Option) *Checker {
|
|
c := &Checker{
|
|
streamURL: streamURL,
|
|
client: &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
},
|
|
}
|
|
|
|
// Apply any provided options
|
|
for _, opt := range opts {
|
|
opt(c)
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
// IsLive checks if the stream is currently broadcasting
|
|
func (c *Checker) IsLive() (bool, error) {
|
|
return c.IsLiveWithContext(context.Background())
|
|
}
|
|
|
|
// IsLiveWithContext checks if the stream is live using the provided context
|
|
func (c *Checker) IsLiveWithContext(ctx context.Context) (bool, error) {
|
|
slog.Debug("Checking stream status", "url", c.streamURL)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.streamURL, nil)
|
|
if err != nil {
|
|
return false, fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
|
|
req.Header.Set("User-Agent", c.userAgent)
|
|
|
|
resp, err := c.client.Do(req)
|
|
if err != nil {
|
|
slog.Debug("Connection to stream failed, considering not live", "error", err)
|
|
return false, nil // Connection failures mean the stream is not available
|
|
}
|
|
defer func() {
|
|
if err := resp.Body.Close(); err != nil {
|
|
slog.Error("Failed to close response body", "error", err)
|
|
}
|
|
}()
|
|
|
|
if resp.StatusCode == http.StatusOK {
|
|
slog.Info("Stream is live", "status", resp.StatusCode)
|
|
return true, nil
|
|
}
|
|
|
|
slog.Debug("Stream is not live", "status", resp.StatusCode)
|
|
return false, nil
|
|
}
|
|
|
|
// GetStreamURL returns the URL being monitored
|
|
func (c *Checker) GetStreamURL() string {
|
|
return c.streamURL
|
|
}
|