Features: - Allow to search for individual resources by their name - Add new resources and their handler: Universities, Restaurants - Added new parameter to reverse output order Reviewed-on: #4 Co-authored-by: bdoerfchen <git@bissendorf.co> Co-committed-by: bdoerfchen <git@bissendorf.co>
94 lines
3.2 KiB
Go
94 lines
3.2 KiB
Go
package universities
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
"sync"
|
|
|
|
"git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces"
|
|
"git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces/params"
|
|
"git.bissendorf.co/bissendorf/unifood/m/v2/model/external/stwbremen"
|
|
"git.bissendorf.co/bissendorf/unifood/m/v2/model/resources"
|
|
"git.bissendorf.co/bissendorf/unifood/m/v2/util"
|
|
)
|
|
|
|
type RestaurantHandler struct {
|
|
QueryClient interfaces.QueryClient[stwbremen.RestaurantList]
|
|
QueryClientRestaurant interfaces.QueryClient[stwbremen.Restaurant]
|
|
}
|
|
|
|
func (h *RestaurantHandler) Get(ctx context.Context, name string, params params.Container) (*interfaces.ResourceList, error) {
|
|
var list []string = []string{name}
|
|
|
|
// If no name provided, get list of all available restaurants
|
|
if name == "" {
|
|
fetchedNames, err := getRestaurantList(ctx, h.QueryClient)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
list = fetchedNames
|
|
}
|
|
|
|
// Get restaurant information in parallel
|
|
var wg sync.WaitGroup
|
|
var mutex sync.Mutex
|
|
restaurants := make([]resources.Restaurant, 0, len(list))
|
|
for _, name := range list {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
|
|
restaurant, err := h.getRestaurantInfo(ctx, name)
|
|
|
|
// Append restaurant in critical section
|
|
if err == nil {
|
|
mutex.Lock()
|
|
restaurants = append(restaurants, *restaurant)
|
|
mutex.Unlock()
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
// Sort by name
|
|
slices.SortFunc(restaurants, func(a, b resources.Restaurant) int { return strings.Compare(a.Name, b.Name) })
|
|
|
|
// Return
|
|
return &interfaces.ResourceList{
|
|
ItemKind: resources.ResourceRestaurant,
|
|
Items: util.Transform(restaurants, func(i *resources.Restaurant) interfaces.Resource { return i }),
|
|
}, nil
|
|
|
|
}
|
|
|
|
func (h *RestaurantHandler) getRestaurantInfo(ctx context.Context, name string) (*resources.Restaurant, error) {
|
|
r, err := h.QueryClientRestaurant.Get(ctx,
|
|
fmt.Sprintf("page('essen-und-trinken/%s')", name),
|
|
`{"title": "page.title","id": "page.content.mensalocationid","image": "page.files.first().url","address": "page.content.address","openingTimes": {"query": "page.openingTimes.toStructure()","select": {"weekday": "structureItem.day","openingTime": "structureItem.open","closingTime": "structureItem.close"}},"offseasonOpeningTimes": {"query": "page.offseasonOpeningTimes.toStructure()","select": {"weekday": "structureItem.day","openingTime": "structureItem.open","closingTime": "structureItem.close"}},"offseasonStart": true,"offseasonEnd": true,"changedTimes": {"query": "page.changedTimes.toStructure()","select": {"startDate": "structureItem.startChangedDate","endDate": "structureItem.endChangedDate","openingTime": "structureItem.openChangedTime","closingTime": "structureItem.closedChangedTime"}}}`,
|
|
false,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load restaurant %s: %w", name, err)
|
|
}
|
|
|
|
if r.Title == "" {
|
|
return nil, fmt.Errorf("restaurant not found: %s", name)
|
|
}
|
|
|
|
return &resources.Restaurant{
|
|
Name: name,
|
|
Title: r.Title,
|
|
ID: r.ID,
|
|
Address: r.Address,
|
|
Image: r.Image,
|
|
OpeningHours: r.OpeningHours,
|
|
}, nil
|
|
}
|
|
|
|
func (h *RestaurantHandler) GetParametersForVerb(verb interfaces.Verb) []params.Registration {
|
|
return []params.Registration{}
|
|
}
|