feat(api): Add compatibility layer for API v1
This commit is contained in:
+102
-2
@@ -26,8 +26,9 @@ type httpError struct {
|
||||
}
|
||||
|
||||
type Services struct {
|
||||
PrayerProvider PrayerProvider
|
||||
LocationProvider LocationProvider
|
||||
PrayerProvider PrayerProvider
|
||||
LocationProvider LocationProvider
|
||||
LegacyLocationProvider LegacyLocationProvider
|
||||
}
|
||||
|
||||
type PrayerProvider interface {
|
||||
@@ -40,6 +41,11 @@ type LocationProvider interface {
|
||||
SearchLocationsByCoords(ctx context.Context, coords prayer.Coordinates) ([]prayer.Location, error)
|
||||
}
|
||||
|
||||
type LegacyLocationProvider interface {
|
||||
SearchLocations(ctx context.Context, query string) ([]prayer.LegacyLocation, error)
|
||||
GetLocationByID(ctx context.Context, id int) (prayer.LegacyLocation, error)
|
||||
}
|
||||
|
||||
func New(services Services) *fiber.App {
|
||||
app := fiber.New(fiber.Config{
|
||||
Immutable: true,
|
||||
@@ -192,6 +198,74 @@ func New(services Services) *fiber.App {
|
||||
})
|
||||
})
|
||||
|
||||
app.Get("/api/diyanet/search", func(ctx fiber.Ctx) error {
|
||||
q := strings.TrimSpace(ctx.Query("q"))
|
||||
if q == "" {
|
||||
return fmt.Errorf("missing query parameter q: %w", fiber.ErrBadRequest)
|
||||
}
|
||||
|
||||
locations, err := services.LegacyLocationProvider.SearchLocations(ctx.Context(), q)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to search legacy diyanet locations: %w", err)
|
||||
}
|
||||
|
||||
resp := make([]fiber.Map, 0, len(locations))
|
||||
for _, location := range locations {
|
||||
resp = append(resp, fiber.Map{
|
||||
"id": location.ID,
|
||||
"country": location.Country,
|
||||
"city": location.City,
|
||||
"region": location.Region,
|
||||
})
|
||||
}
|
||||
|
||||
ctx.Response().Header.Set(fiber.HeaderCacheControl, "max-age=86400")
|
||||
return ctx.JSON(resp)
|
||||
})
|
||||
|
||||
app.Get("/api/diyanet/prayertimes", func(ctx fiber.Ctx) error {
|
||||
if services.LegacyLocationProvider == nil {
|
||||
return fmt.Errorf("legacy location provider is not configured: %w", fiber.ErrNotFound)
|
||||
}
|
||||
|
||||
locationIDText := strings.TrimSpace(ctx.Query("location_id"))
|
||||
if locationIDText == "" {
|
||||
return fmt.Errorf("missing query parameter location_id: %w", fiber.ErrBadRequest)
|
||||
}
|
||||
|
||||
locationID, err := strconv.Atoi(locationIDText)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse location_id query parameter: %w", errors.Join(fiber.ErrBadRequest, err))
|
||||
}
|
||||
|
||||
legacyLocation, err := services.LegacyLocationProvider.GetLocationByID(ctx.Context(), locationID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to resolve location by location_id: %w", errors.Join(fiber.ErrNotFound, err))
|
||||
}
|
||||
|
||||
result, err := services.PrayerProvider.GetByCoords(ctx.Context(), prayer.Coordinates{
|
||||
Latitude: legacyLocation.Latitude,
|
||||
Longitude: legacyLocation.Longitude,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch prayer times for location_id: %w", err)
|
||||
}
|
||||
|
||||
location := result.Location
|
||||
location.ID = legacyLocation.ID
|
||||
if strings.TrimSpace(legacyLocation.Timezone) != "" {
|
||||
location.Timezone = legacyLocation.Timezone
|
||||
}
|
||||
|
||||
mapped, err := mapPrayerTimesForLegacyResponse(result.Times, location)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to map legacy prayer times response: %w", err)
|
||||
}
|
||||
|
||||
ctx.Response().Header.Set(fiber.HeaderCacheControl, "max-age=86400")
|
||||
return ctx.JSON(mapped)
|
||||
})
|
||||
|
||||
app.Use("/", static.New("", static.Config{FS: templates.FS()}))
|
||||
|
||||
return app
|
||||
@@ -293,3 +367,29 @@ func loadTimezone(name string) (*time.Location, error) {
|
||||
|
||||
return loc, nil
|
||||
}
|
||||
|
||||
func mapPrayerTimesForLegacyResponse(times []prayer.Times, location prayer.Location) ([]fiber.Map, error) {
|
||||
tz := time.UTC
|
||||
if strings.TrimSpace(location.Timezone) != "" {
|
||||
loadedTZ, err := loadTimezone(location.Timezone)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load location timezone: %w", err)
|
||||
}
|
||||
tz = loadedTZ
|
||||
}
|
||||
|
||||
out := make([]fiber.Map, 0, len(times))
|
||||
for _, item := range times {
|
||||
out = append(out, fiber.Map{
|
||||
"date": item.Date.In(tz).Format(time.RFC3339),
|
||||
"fajr": formatHHMM(item.Fajr, tz),
|
||||
"sun": formatHHMM(item.Sunrise, tz),
|
||||
"dhuhr": formatHHMM(item.Dhuhr, tz),
|
||||
"asr": formatHHMM(item.Asr, tz),
|
||||
"maghrib": formatHHMM(item.Maghrib, tz),
|
||||
"isha": formatHHMM(item.Isha, tz),
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user