atlas orchestration + .env fixes
This commit is contained in:
parent
f5f2ab995f
commit
423ae69fb0
|
|
@ -380,6 +380,13 @@ func (c *Config) loadEnv() error {
|
||||||
c.ADRO_SMS_HOST_URL = "https://api.afrosms.com"
|
c.ADRO_SMS_HOST_URL = "https://api.afrosms.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Atlas
|
||||||
|
c.Atlas.BaseURL = os.Getenv("ATLAS_BASE_URL")
|
||||||
|
c.Atlas.CasinoID = os.Getenv("ATLAS_CASINO_ID")
|
||||||
|
c.Atlas.OperatorID = os.Getenv("ATLAS_OPERATOR_ID")
|
||||||
|
c.Atlas.PartnerID = os.Getenv("ATLAS_PARTNER_ID")
|
||||||
|
c.Atlas.SecretKey = os.Getenv("ATLAS_SECRET_KEY")
|
||||||
|
|
||||||
popOKClientID := os.Getenv("POPOK_CLIENT_ID")
|
popOKClientID := os.Getenv("POPOK_CLIENT_ID")
|
||||||
|
|
||||||
popOKPlatform := os.Getenv("POPOK_PLATFORM")
|
popOKPlatform := os.Getenv("POPOK_PLATFORM")
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,20 @@ type GameEntity struct {
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
HasDemoMode bool `json:"hasDemoMode"`
|
HasDemoMode bool `json:"hasDemoMode"`
|
||||||
HasFreeBets bool `json:"hasFreeBets"`
|
HasFreeBets bool `json:"hasFreeBets"`
|
||||||
|
// Thumbnail string `json:"thumbnail"` // ✅ new field
|
||||||
|
// DemoURL string `json:"demoUrl"` // ✅ new field
|
||||||
|
}
|
||||||
|
|
||||||
|
type AtlasGameEntity struct {
|
||||||
|
GameID string `json:"game_id"`
|
||||||
|
ProviderID string `json:"providerId"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
DeviceType string `json:"deviceType"`
|
||||||
|
Category string `json:"type"`
|
||||||
|
HasDemoMode bool `json:"has_demo"`
|
||||||
|
HasFreeBets bool `json:"hasFreeBets"`
|
||||||
|
Thumbnail string `json:"thumbnail_img_url"` // ✅ new field
|
||||||
|
DemoURL string `json:"demo_url"` // ✅ new field
|
||||||
}
|
}
|
||||||
|
|
||||||
type GameStartRequest struct {
|
type GameStartRequest struct {
|
||||||
|
|
|
||||||
|
|
@ -283,35 +283,36 @@ type PopokLaunchResponse struct {
|
||||||
|
|
||||||
type VirtualGameProvider struct {
|
type VirtualGameProvider struct {
|
||||||
// ID int64 `json:"id" db:"id"`
|
// ID int64 `json:"id" db:"id"`
|
||||||
ProviderID string `json:"provider_id" db:"provider_id"`
|
ProviderID string `json:"provider_id" db:"provider_id"`
|
||||||
ProviderName string `json:"provider_name" db:"provider_name"`
|
ProviderName string `json:"provider_name" db:"provider_name"`
|
||||||
LogoDark *string `json:"logo_dark,omitempty" db:"logo_dark"`
|
LogoDark *string `json:"logo_dark,omitempty" db:"logo_dark"`
|
||||||
LogoLight *string `json:"logo_light,omitempty" db:"logo_light"`
|
LogoLight *string `json:"logo_light,omitempty" db:"logo_light"`
|
||||||
Enabled bool `json:"enabled" db:"enabled"`
|
Enabled bool `json:"enabled" db:"enabled"`
|
||||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||||
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
UpdatedAt *time.Time `json:"updated_at,omitempty" db:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VirtualGameProviderPagination is used when returning paginated results
|
// VirtualGameProviderPagination is used when returning paginated results
|
||||||
type VirtualGameProviderPagination struct {
|
type VirtualGameProviderPagination struct {
|
||||||
Providers []VirtualGameProvider `json:"providers"`
|
Providers []VirtualGameProvider `json:"providers"`
|
||||||
TotalCount int64 `json:"total_count"`
|
TotalCount int64 `json:"total_count"`
|
||||||
Limit int32 `json:"limit"`
|
Limit int32 `json:"limit"`
|
||||||
Offset int32 `json:"offset"`
|
Offset int32 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UnifiedGame struct {
|
type UnifiedGame struct {
|
||||||
GameID string `json:"gameId"`
|
GameID string `json:"gameId"`
|
||||||
ProviderID string `json:"providerId"`
|
ProviderID string `json:"providerId"`
|
||||||
Provider string `json:"provider"`
|
Provider string `json:"provider"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Category string `json:"category,omitempty"`
|
Category string `json:"category,omitempty"`
|
||||||
DeviceType string `json:"deviceType,omitempty"`
|
DeviceType string `json:"deviceType,omitempty"`
|
||||||
Volatility string `json:"volatility,omitempty"`
|
Volatility string `json:"volatility,omitempty"`
|
||||||
RTP *float64 `json:"rtp,omitempty"`
|
RTP *float64 `json:"rtp,omitempty"`
|
||||||
HasDemo bool `json:"hasDemo"`
|
HasDemo bool `json:"hasDemo"`
|
||||||
HasFreeBets bool `json:"hasFreeBets"`
|
HasFreeBets bool `json:"hasFreeBets"`
|
||||||
Bets []float64 `json:"bets,omitempty"`
|
Bets []float64 `json:"bets,omitempty"`
|
||||||
Thumbnail string `json:"thumbnail,omitempty"`
|
Thumbnail string `json:"thumbnail,omitempty"`
|
||||||
Status int `json:"status,omitempty"`
|
Status int `json:"status,omitempty"`
|
||||||
|
DemoURL string `json:"demoUrl"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,29 +149,28 @@ func (s *Service) GetAllVirtualGames(ctx context.Context, params dbgen.GetAllVir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.ProviderRequest, currency string) ([]domain.UnifiedGame, error) {
|
func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.ProviderRequest, currency string) ([]domain.UnifiedGame, error) {
|
||||||
|
|
||||||
logger := s.mongoLogger.With(
|
logger := s.mongoLogger.With(
|
||||||
zap.String("service", "FetchAndStoreAllVirtualGames"),
|
zap.String("service", "FetchAndStoreAllVirtualGames"),
|
||||||
zap.Any("ProviderRequest", req),
|
zap.Any("ProviderRequest", req),
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is necessary, since the provider is a foreign key
|
// This is necessary since the provider is a foreign key
|
||||||
_, err := s.AddProviders(ctx, req)
|
_, err := s.AddProviders(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to add providers to database: %w", err)
|
return nil, fmt.Errorf("failed to add providers to database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var allGames []domain.UnifiedGame
|
var allGames []domain.UnifiedGame
|
||||||
// --- 1. Get providers from external API ---
|
|
||||||
|
// --- 1. Existing providers (Veli Games) ---
|
||||||
providersRes, err := s.GetProviders(ctx, req)
|
providersRes, err := s.GetProviders(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to fetch provider", zap.Error(err))
|
logger.Error("Failed to fetch provider", zap.Error(err))
|
||||||
return nil, fmt.Errorf("failed to fetch providers: %w", err)
|
return nil, fmt.Errorf("failed to fetch providers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 2. Fetch games for each provider ---
|
// --- 2. Fetch games for each provider (Veli Games) ---
|
||||||
for _, p := range providersRes.Items {
|
for _, p := range providersRes.Items {
|
||||||
// Violates foreign key if the provider isn't added
|
|
||||||
games, err := s.GetGames(ctx, domain.GameListRequest{
|
games, err := s.GetGames(ctx, domain.GameListRequest{
|
||||||
BrandID: s.cfg.VeliGames.BrandID,
|
BrandID: s.cfg.VeliGames.BrandID,
|
||||||
ProviderID: p.ProviderID,
|
ProviderID: p.ProviderID,
|
||||||
|
|
@ -185,20 +184,18 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
||||||
|
|
||||||
for _, g := range games {
|
for _, g := range games {
|
||||||
unified := domain.UnifiedGame{
|
unified := domain.UnifiedGame{
|
||||||
GameID: g.GameID,
|
GameID: g.GameID,
|
||||||
ProviderID: g.ProviderID,
|
ProviderID: g.ProviderID,
|
||||||
Provider: p.ProviderName,
|
Provider: p.ProviderName,
|
||||||
Name: g.Name,
|
Name: g.Name,
|
||||||
Category: g.Category,
|
Category: g.Category,
|
||||||
DeviceType: g.DeviceType,
|
DeviceType: g.DeviceType,
|
||||||
// Volatility: g.Volatility,
|
|
||||||
// RTP: g.RTP,
|
|
||||||
HasDemo: g.HasDemoMode,
|
HasDemo: g.HasDemoMode,
|
||||||
HasFreeBets: g.HasFreeBets,
|
HasFreeBets: g.HasFreeBets,
|
||||||
}
|
}
|
||||||
allGames = append(allGames, unified)
|
allGames = append(allGames, unified)
|
||||||
|
|
||||||
// --- Save to DB ---
|
// Save to DB
|
||||||
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
||||||
GameID: g.GameID,
|
GameID: g.GameID,
|
||||||
ProviderID: g.ProviderID,
|
ProviderID: g.ProviderID,
|
||||||
|
|
@ -211,8 +208,6 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
||||||
String: g.DeviceType,
|
String: g.DeviceType,
|
||||||
Valid: g.DeviceType != "",
|
Valid: g.DeviceType != "",
|
||||||
},
|
},
|
||||||
// Volatility: g.Volatility,
|
|
||||||
// RTP: g.RTP,
|
|
||||||
HasDemo: pgtype.Bool{
|
HasDemo: pgtype.Bool{
|
||||||
Bool: g.HasDemoMode,
|
Bool: g.HasDemoMode,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
|
|
@ -221,18 +216,56 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
||||||
Bool: g.HasFreeBets,
|
Bool: g.HasFreeBets,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
},
|
},
|
||||||
// Bets: g.Bets,
|
|
||||||
// Thumbnail: g.Thumbnail,
|
|
||||||
// Status: g.Status,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to create virtual game", zap.Error(err))
|
logger.Error("failed to create virtual game", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 3. Handle PopOK separately ---
|
// --- 3. Fetch Atlas-V games ---
|
||||||
|
atlasGames, err := s.GetAtlasVGames(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to fetch Atlas-V games", zap.Error(err))
|
||||||
|
} else {
|
||||||
|
for _, g := range atlasGames {
|
||||||
|
unified := domain.UnifiedGame{
|
||||||
|
GameID: g.GameID,
|
||||||
|
ProviderID: "atlasv",
|
||||||
|
Provider: "Atlas-V Gaming", // "Atlas-V"
|
||||||
|
Name: g.Name,
|
||||||
|
Category: g.Category, // using Type as Category
|
||||||
|
Thumbnail: g.Thumbnail,
|
||||||
|
HasDemo: true,
|
||||||
|
DemoURL: g.DemoURL,
|
||||||
|
}
|
||||||
|
allGames = append(allGames, unified)
|
||||||
|
|
||||||
|
// Save to DB
|
||||||
|
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
||||||
|
GameID: g.GameID,
|
||||||
|
ProviderID: "atlasv",
|
||||||
|
Name: g.Name,
|
||||||
|
Category: pgtype.Text{
|
||||||
|
String: g.Category,
|
||||||
|
Valid: g.Category != "",
|
||||||
|
},
|
||||||
|
Thumbnail: pgtype.Text{
|
||||||
|
String: g.Thumbnail,
|
||||||
|
Valid: g.Thumbnail != "",
|
||||||
|
},
|
||||||
|
HasDemo: pgtype.Bool{
|
||||||
|
Bool: g.HasDemoMode,
|
||||||
|
Valid: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to create Atlas-V virtual game", zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 4. Handle PopOK separately ---
|
||||||
popokGames, err := s.virtualGameSvc.ListGames(ctx, currency)
|
popokGames, err := s.virtualGameSvc.ListGames(ctx, currency)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to fetch PopOk games", zap.Error(err))
|
logger.Error("failed to fetch PopOk games", zap.Error(err))
|
||||||
|
|
@ -252,7 +285,7 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
||||||
}
|
}
|
||||||
allGames = append(allGames, unified)
|
allGames = append(allGames, unified)
|
||||||
|
|
||||||
// --- Convert []float64 to []pgtype.Numeric ---
|
// Convert []float64 to []pgtype.Numeric
|
||||||
var betsNumeric []pgtype.Numeric
|
var betsNumeric []pgtype.Numeric
|
||||||
for _, bet := range g.Bets {
|
for _, bet := range g.Bets {
|
||||||
var num pgtype.Numeric
|
var num pgtype.Numeric
|
||||||
|
|
@ -260,9 +293,9 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
||||||
betsNumeric = append(betsNumeric, num)
|
betsNumeric = append(betsNumeric, num)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Save to DB ---
|
// Save to DB
|
||||||
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
||||||
GameID: fmt.Sprintf("%d", g.ID), //The id here needs to be clean for me to access
|
GameID: fmt.Sprintf("%d", g.ID),
|
||||||
ProviderID: "popok",
|
ProviderID: "popok",
|
||||||
Name: g.GameName,
|
Name: g.GameName,
|
||||||
Bets: betsNumeric,
|
Bets: betsNumeric,
|
||||||
|
|
@ -275,9 +308,8 @@ func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.P
|
||||||
Valid: true,
|
Valid: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to create virtual game", zap.Error(err))
|
logger.Error("failed to create PopOK virtual game", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type VeliVirtualGameService interface {
|
type VeliVirtualGameService interface {
|
||||||
|
GetAtlasVGames(ctx context.Context) ([]domain.AtlasGameEntity, error)
|
||||||
FetchAndStoreAllVirtualGames(ctx context.Context, req domain.ProviderRequest, currency string) ([]domain.UnifiedGame, error)
|
FetchAndStoreAllVirtualGames(ctx context.Context, req domain.ProviderRequest, currency string) ([]domain.UnifiedGame, error)
|
||||||
GetAllVirtualGames(ctx context.Context, params dbgen.GetAllVirtualGamesParams) ([]domain.UnifiedGame, error)
|
GetAllVirtualGames(ctx context.Context, params dbgen.GetAllVirtualGamesParams) ([]domain.UnifiedGame, error)
|
||||||
AddProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error)
|
AddProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@ package veli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
|
|
@ -51,6 +55,42 @@ func New(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) GetAtlasVGames(ctx context.Context) ([]domain.AtlasGameEntity, error) {
|
||||||
|
// 1. Compose URL (could be configurable)
|
||||||
|
url := "https://atlas-v.com/partner/35fr5784dbgr4dfw234wsdsw" +
|
||||||
|
"?hash=b3596faa6185180e9b2ca01cb5a052d316511872×tamp=1700244963080"
|
||||||
|
|
||||||
|
// 2. Create a dedicated HTTP client with timeout
|
||||||
|
client := &http.Client{Timeout: 15 * time.Second}
|
||||||
|
|
||||||
|
// 3. Prepare request with context
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("creating request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Execute request
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("calling Atlas-V API: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 5. Check response status
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
return nil, fmt.Errorf("Atlas-V API error: status %d, body: %s", resp.StatusCode, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Decode response into slice of GameEntity
|
||||||
|
var games []domain.AtlasGameEntity
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&games); err != nil {
|
||||||
|
return nil, fmt.Errorf("decoding Atlas-V games: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return games, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) {
|
func (s *Service) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) {
|
||||||
// Always mirror request body fields into sigParams
|
// Always mirror request body fields into sigParams
|
||||||
sigParams := map[string]any{
|
sigParams := map[string]any{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user