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.

126 lines
2.8 KiB
Go

package diyanetcitydb
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
"github.com/doug-martin/goqu/v9"
"prayertimes/pkg/prayer"
)
var ErrLocationNotFound = errors.New("location not found")
type Provider struct {
db *goqu.Database
}
func New(conn *sql.DB) Provider {
return Provider{db: goqu.New("sqlite3", conn)}
}
type locationRow struct {
ID int `db:"id"`
Country string `db:"country"`
City string `db:"city"`
Region string `db:"region"`
Latitude float64 `db:"latitude"`
Longitude float64 `db:"longitude"`
Timezone string `db:"timezone"`
}
func (p Provider) SearchLocations(ctx context.Context, query string) ([]prayer.LegacyLocation, error) {
query = strings.TrimSpace(query)
if query == "" {
return nil, nil
}
pattern := "%" + query + "%"
q := p.db.
From("diyanet_cities").
Select(
goqu.I("id"),
goqu.I("country"),
goqu.I("city"),
goqu.COALESCE(goqu.I("region"), "").As("region"),
goqu.I("latitude"),
goqu.I("longitude"),
goqu.COALESCE(goqu.I("timezone"), "").As("timezone"),
).
Where(
goqu.Or(
goqu.L("country LIKE ? COLLATE NOCASE", pattern),
goqu.L("city LIKE ? COLLATE NOCASE", pattern),
goqu.L("COALESCE(region, '') LIKE ? COLLATE NOCASE", pattern),
),
).
Order(
goqu.I("country").Asc(),
goqu.I("city").Asc(),
goqu.I("region").Asc(),
goqu.I("id").Asc(),
).
Limit(100)
rows := make([]locationRow, 0)
if err := q.ScanStructsContext(ctx, &rows); err != nil {
return nil, fmt.Errorf("failed to query diyanet locations: %w", err)
}
locations := make([]prayer.LegacyLocation, 0, len(rows))
for _, row := range rows {
locations = append(locations, prayer.LegacyLocation{
ID: row.ID,
Country: row.Country,
City: row.City,
Region: row.Region,
Latitude: row.Latitude,
Longitude: row.Longitude,
Timezone: row.Timezone,
})
}
return locations, nil
}
func (p Provider) GetLocationByID(ctx context.Context, id int) (prayer.LegacyLocation, error) {
q := p.db.
From("diyanet_cities").
Select(
goqu.I("id"),
goqu.I("country"),
goqu.I("city"),
goqu.COALESCE(goqu.I("region"), "").As("region"),
goqu.I("latitude"),
goqu.I("longitude"),
goqu.COALESCE(goqu.I("timezone"), "").As("timezone"),
).
Where(goqu.I("id").Eq(id)).
Limit(1)
var rows []locationRow
if err := q.ScanStructsContext(ctx, &rows); err != nil {
return prayer.LegacyLocation{}, fmt.Errorf("failed to query location by id: %w", err)
}
if len(rows) == 0 {
return prayer.LegacyLocation{}, ErrLocationNotFound
}
row := rows[0]
location := prayer.LegacyLocation{
ID: row.ID,
Country: row.Country,
City: row.City,
Region: row.Region,
Latitude: row.Latitude,
Longitude: row.Longitude,
Timezone: row.Timezone,
}
return location, nil
}