You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
2.3 KiB
Go

package diyanetprovider
import (
"context"
"errors"
"fmt"
"time"
"prayertimes/pkg/prayer"
)
type APIProvider interface {
Get(ctx context.Context, locationID string) ([]prayer.Times, error)
GetByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Times, error)
SearchLocations(ctx context.Context, query string) ([]prayer.Location, error)
}
type FallbackProvider interface {
GetByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Times, error)
}
type Provider struct {
api APIProvider
fallback FallbackProvider
timeout time.Duration
}
func New(api APIProvider, fallback FallbackProvider) Provider {
return Provider{
api: api,
fallback: fallback,
timeout: time.Second,
}
}
func (p Provider) SearchLocations(ctx context.Context, query string) ([]prayer.Location, error) {
locations, err := p.api.SearchLocations(ctx, query)
if err != nil {
return nil, fmt.Errorf("failed to search locations from api provider: %w", err)
}
return locations, nil
}
func (p Provider) Get(ctx context.Context, locationID string) ([]prayer.Times, error) {
ctxWithTimeout, cancel := context.WithTimeout(ctx, p.timeout)
defer cancel()
times, err := p.api.Get(ctxWithTimeout, locationID)
if err != nil {
return nil, fmt.Errorf("failed to get prayer times from api provider: %w", err)
}
if len(times) == 0 {
return nil, fmt.Errorf("failed to get prayer times from api provider: %w", errors.New("empty prayer times result"))
}
return times, nil
}
func (p Provider) GetByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Times, error) {
ctxWithTimeout, cancel := context.WithTimeout(ctx, p.timeout)
defer cancel()
times, err := p.api.GetByCoords(ctxWithTimeout, coords)
if err == nil && len(times) > 0 {
return times, nil
}
fallbackTimes, fallbackErr := p.fallback.GetByCoords(ctx, coords)
if fallbackErr != nil {
if err != nil {
return nil, fmt.Errorf("failed to get prayer times from fallback provider: %w", errors.Join(err, fallbackErr))
}
return nil, fmt.Errorf("failed to get prayer times from fallback provider: %w", fallbackErr)
}
if len(fallbackTimes) == 0 {
return nil, fmt.Errorf("failed to get prayer times from fallback provider: %w", errors.New("empty prayer times result"))
}
return fallbackTimes, nil
}