Files
home 08bd41e75c feat: travel service with 2GIS routing, POI, hotels + finance providers + UI overhaul
- Add travel-svc microservice (Amadeus, TravelPayouts, 2GIS, OpenRouteService)
- Add travel orchestrator with parallel collectors (events, POI, hotels, flights)
- Add 2GIS road routing with transport cost calculation (car/bus/taxi)
- Add TravelMap (2GIS MapGL) and TravelWidgets components
- Add useTravelChat hook for streaming travel agent responses
- Add finance heatmap providers refactor
- Add SearXNG settings, API proxy routes, Docker compose updates
- Update Dockerfiles, config, types, and all UI pages for consistency

Made-with: Cursor
2026-03-01 21:58:32 +03:00

141 lines
3.8 KiB
Go

package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gooseek/backend/internal/finance"
)
func main() {
heatmapSvc := finance.NewHeatmapService(finance.HeatmapConfig{
DataProviderURL: os.Getenv("FINANCE_DATA_PROVIDER_URL"),
CacheTTL: 5 * time.Minute,
RefreshInterval: time.Minute,
})
app := fiber.New(fiber.Config{
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
})
app.Use(logger.New())
app.Use(cors.New())
app.Get("/health", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"status": "ok"})
})
app.Get("/api/v1/heatmap/:market", func(c *fiber.Ctx) error {
market := c.Params("market")
timeRange := c.Query("range", "1d")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
heatmap, err := heatmapSvc.GetMarketHeatmap(ctx, market, timeRange)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(heatmap)
})
app.Get("/api/v1/heatmap/:market/treemap", func(c *fiber.Ctx) error {
market := c.Params("market")
timeRange := c.Query("range", "1d")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
heatmap, err := heatmapSvc.GetMarketHeatmap(ctx, market, timeRange)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
treemapData := heatmapSvc.GenerateTreemapData(heatmap)
return c.JSON(treemapData)
})
app.Get("/api/v1/heatmap/:market/grid", func(c *fiber.Ctx) error {
market := c.Params("market")
timeRange := c.Query("range", "1d")
rows := c.QueryInt("rows", 5)
cols := c.QueryInt("cols", 10)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
heatmap, err := heatmapSvc.GetMarketHeatmap(ctx, market, timeRange)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
gridData := heatmapSvc.GenerateGridData(heatmap, rows, cols)
return c.JSON(fiber.Map{"grid": gridData, "rows": rows, "cols": cols})
})
app.Get("/api/v1/heatmap/:market/sector/:sector", func(c *fiber.Ctx) error {
market := c.Params("market")
sector := c.Params("sector")
timeRange := c.Query("range", "1d")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
heatmap, err := heatmapSvc.GetSectorHeatmap(ctx, market, sector, timeRange)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(heatmap)
})
app.Get("/api/v1/movers/:market", func(c *fiber.Ctx) error {
market := c.Params("market")
count := c.QueryInt("count", 10)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
movers, err := heatmapSvc.GetTopMovers(ctx, market, count)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(movers)
})
app.Get("/api/v1/markets", func(c *fiber.Ctx) error {
markets := []map[string]interface{}{
{"id": "sp500", "name": "S&P 500", "region": "us"},
{"id": "nasdaq", "name": "NASDAQ", "region": "us"},
{"id": "dow", "name": "Dow Jones", "region": "us"},
{"id": "moex", "name": "MOEX", "region": "ru"},
{"id": "crypto", "name": "Cryptocurrency", "region": "global"},
{"id": "forex", "name": "Forex", "region": "global"},
}
return c.JSON(fiber.Map{"markets": markets})
})
port := getEnvInt("PORT", 3033)
log.Printf("finance-heatmap-svc listening on :%d", port)
log.Fatal(app.Listen(fmt.Sprintf(":%d", port)))
}
func getEnvInt(key string, defaultValue int) int {
if val := os.Getenv(key); val != "" {
var result int
if _, err := fmt.Sscanf(val, "%d", &result); err == nil {
return result
}
}
return defaultValue
}