295 lines
8.7 KiB
Go
295 lines
8.7 KiB
Go
package veli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func (s *Service) AddProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) {
|
|
|
|
logger := s.mongoLogger.With(zap.String("service", "AddProviders"), zap.Any("ProviderRequest", req))
|
|
|
|
// 0. Remove all existing providers first
|
|
if err := s.repo.DeleteAllVirtualGameProviders(ctx); err != nil {
|
|
logger.Error("failed to delete all virtual game providers", zap.Error(err))
|
|
return nil, fmt.Errorf("failed to clear existing providers: %w", err)
|
|
}
|
|
|
|
// 1. Prepare signature parameters
|
|
sigParams := map[string]any{
|
|
"brandId": req.BrandID,
|
|
}
|
|
|
|
// Optional fields
|
|
sigParams["extraData"] = fmt.Sprintf("%t", req.ExtraData) // false is still included
|
|
if req.Size > 0 {
|
|
sigParams["size"] = fmt.Sprintf("%d", req.Size)
|
|
} else {
|
|
sigParams["size"] = ""
|
|
}
|
|
|
|
if req.Page > 0 {
|
|
sigParams["page"] = fmt.Sprintf("%d", req.Page)
|
|
} else {
|
|
sigParams["page"] = ""
|
|
}
|
|
|
|
// 2. Call external API
|
|
var res domain.ProviderResponse
|
|
if err := s.client.post(ctx, "/game-lists/public/providers", req, sigParams, &res); err != nil {
|
|
return nil, fmt.Errorf("failed to fetch providers: %w", err)
|
|
}
|
|
|
|
// 3. Loop through fetched providers and insert into DB
|
|
for _, p := range res.Items {
|
|
createParams := dbgen.CreateVirtualGameProviderParams{
|
|
ProviderID: p.ProviderID,
|
|
ProviderName: p.ProviderName,
|
|
LogoDark: pgtype.Text{String: p.LogoForDark, Valid: p.LogoForDark != ""},
|
|
LogoLight: pgtype.Text{String: p.LogoForLight, Valid: p.LogoForLight != ""},
|
|
Enabled: true,
|
|
}
|
|
|
|
if _, err := s.repo.CreateVirtualGameProvider(ctx, createParams); err != nil {
|
|
logger.Error("failed to add provider", zap.Error(err))
|
|
return nil, fmt.Errorf("failed to add provider %s: %w", p.ProviderID, err)
|
|
}
|
|
}
|
|
|
|
// 4. Always add "popok" provider manually
|
|
popokParams := dbgen.CreateVirtualGameProviderParams{
|
|
ProviderID: "popok",
|
|
ProviderName: "Popok Gaming",
|
|
LogoDark: pgtype.Text{String: fmt.Sprintf("%v/static/logos/popok-dark.png", s.cfg.PopOK.CallbackURL), Valid: true}, // adjust as needed
|
|
LogoLight: pgtype.Text{String: fmt.Sprintf("%v/static/logos/popok-light.png", s.cfg.PopOK.CallbackURL), Valid: true}, // adjust as needed
|
|
Enabled: true,
|
|
}
|
|
|
|
atlasParams := dbgen.CreateVirtualGameProviderParams{
|
|
ProviderID: "atlas",
|
|
ProviderName: "Atlas Gaming",
|
|
LogoDark: pgtype.Text{String: "/static/logos/atlas-dark.png", Valid: true}, // adjust as needed
|
|
LogoLight: pgtype.Text{String: "/static/logos/atlas-light.png", Valid: true}, // adjust as needed
|
|
Enabled: true,
|
|
}
|
|
|
|
if _, err := s.repo.CreateVirtualGameProvider(ctx, popokParams); err != nil {
|
|
logger.Error("failed to add popok provider", zap.Any("popokParams", popokParams), zap.Error(err))
|
|
return nil, fmt.Errorf("failed to add popok provider: %w", err)
|
|
}
|
|
|
|
if _, err := s.repo.CreateVirtualGameProvider(ctx, atlasParams); err != nil {
|
|
return nil, fmt.Errorf("failed to add atlas provider: %w", err)
|
|
}
|
|
|
|
// Optionally also append it to the response for consistency
|
|
// res.Items = append(res.Items, domain.VirtualGameProvider{
|
|
// ProviderID: uuid.New().String(),
|
|
// ProviderName: "Popok Gaming",
|
|
// LogoForDark: "/static/logos/popok-dark.png",
|
|
// LogoForLight: "/static/logos/popok-light.png",
|
|
// })
|
|
|
|
return &res, nil
|
|
}
|
|
|
|
func (s *Service) GetAllVirtualGames(ctx context.Context, params dbgen.GetAllVirtualGamesParams) ([]domain.UnifiedGame, error) {
|
|
// Build params for repo call
|
|
logger := s.mongoLogger.With(zap.String("service", "GetAllVirtualGames"), zap.Any("params", params))
|
|
rows, err := s.repo.ListAllVirtualGames(ctx, params)
|
|
if err != nil {
|
|
logger.Error("[GetAllVirtualGames] Failed to fetch virtual games", zap.Error(err))
|
|
return nil, fmt.Errorf("failed to fetch virtual games: %w", err)
|
|
}
|
|
|
|
var allGames []domain.UnifiedGame
|
|
for _, r := range rows {
|
|
// --- Convert nullable Rtp to *float64 ---
|
|
var rtpPtr *float64
|
|
if r.Rtp.Valid {
|
|
rtpFloat, err := r.Rtp.Float64Value()
|
|
if err == nil {
|
|
rtpPtr = new(float64)
|
|
*rtpPtr = rtpFloat.Float64
|
|
}
|
|
}
|
|
var betsFloat64 []float64
|
|
for _, bet := range r.Bets {
|
|
if bet.Valid {
|
|
betFloat, err := bet.Float64Value()
|
|
if err == nil {
|
|
betsFloat64 = append(betsFloat64, betFloat.Float64)
|
|
}
|
|
}
|
|
}
|
|
|
|
allGames = append(allGames, domain.UnifiedGame{
|
|
GameID: r.GameID,
|
|
ProviderID: r.ProviderID,
|
|
Provider: r.ProviderName,
|
|
Name: r.Name,
|
|
Category: r.Category.String,
|
|
DeviceType: r.DeviceType.String,
|
|
Volatility: r.Volatility.String,
|
|
RTP: rtpPtr,
|
|
HasDemo: r.HasDemo.Bool,
|
|
HasFreeBets: r.HasFreeBets.Bool,
|
|
Bets: betsFloat64,
|
|
Thumbnail: r.Thumbnail.String,
|
|
Status: int(r.Status.Int32), // nullable status
|
|
})
|
|
}
|
|
|
|
return allGames, nil
|
|
}
|
|
|
|
func (s *Service) FetchAndStoreAllVirtualGames(ctx context.Context, req domain.ProviderRequest, currency string) ([]domain.UnifiedGame, error) {
|
|
|
|
logger := s.mongoLogger.With(
|
|
zap.String("service", "FetchAndStoreAllVirtualGames"),
|
|
zap.Any("ProviderRequest", req),
|
|
)
|
|
|
|
// This is necessary, since the provider is a foreign key
|
|
_, err := s.AddProviders(ctx, req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to add providers to database: %w", err)
|
|
}
|
|
|
|
var allGames []domain.UnifiedGame
|
|
// --- 1. Get providers from external API ---
|
|
providersRes, err := s.GetProviders(ctx, req)
|
|
if err != nil {
|
|
logger.Error("Failed to fetch provider", zap.Error(err))
|
|
return nil, fmt.Errorf("failed to fetch providers: %w", err)
|
|
}
|
|
|
|
// --- 2. Fetch games for each provider ---
|
|
for _, p := range providersRes.Items {
|
|
// Violates foreign key if the provider isn't added
|
|
games, err := s.GetGames(ctx, domain.GameListRequest{
|
|
BrandID: s.cfg.VeliGames.BrandID,
|
|
ProviderID: p.ProviderID,
|
|
Page: req.Page,
|
|
Size: req.Size,
|
|
})
|
|
if err != nil {
|
|
logger.Error("failed to get veli games", zap.String("ProviderID", p.ProviderID), zap.Error(err))
|
|
continue // skip failing provider but continue others
|
|
}
|
|
|
|
for _, g := range games {
|
|
unified := domain.UnifiedGame{
|
|
GameID: g.GameID,
|
|
ProviderID: g.ProviderID,
|
|
Provider: p.ProviderName,
|
|
Name: g.Name,
|
|
Category: g.Category,
|
|
DeviceType: g.DeviceType,
|
|
// Volatility: g.Volatility,
|
|
// RTP: g.RTP,
|
|
HasDemo: g.HasDemoMode,
|
|
HasFreeBets: g.HasFreeBets,
|
|
}
|
|
allGames = append(allGames, unified)
|
|
|
|
// --- Save to DB ---
|
|
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
|
GameID: g.GameID,
|
|
ProviderID: g.ProviderID,
|
|
Name: g.Name,
|
|
Category: pgtype.Text{
|
|
String: g.Category,
|
|
Valid: g.Category != "",
|
|
},
|
|
DeviceType: pgtype.Text{
|
|
String: g.DeviceType,
|
|
Valid: g.DeviceType != "",
|
|
},
|
|
// Volatility: g.Volatility,
|
|
// RTP: g.RTP,
|
|
HasDemo: pgtype.Bool{
|
|
Bool: g.HasDemoMode,
|
|
Valid: true,
|
|
},
|
|
HasFreeBets: pgtype.Bool{
|
|
Bool: g.HasFreeBets,
|
|
Valid: true,
|
|
},
|
|
// Bets: g.Bets,
|
|
// Thumbnail: g.Thumbnail,
|
|
// Status: g.Status,
|
|
})
|
|
|
|
if err != nil {
|
|
logger.Error("failed to create virtual game", zap.Error(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- 3. Handle PopOK separately ---
|
|
popokGames, err := s.virtualGameSvc.ListGames(ctx, currency)
|
|
if err != nil {
|
|
logger.Error("failed to fetch PopOk games", zap.Error(err))
|
|
return nil, fmt.Errorf("failed to fetch PopOK games: %w", err)
|
|
}
|
|
|
|
for _, g := range popokGames {
|
|
unified := domain.UnifiedGame{
|
|
GameID: fmt.Sprintf("%d", g.ID),
|
|
ProviderID: "popok",
|
|
Provider: "PopOK",
|
|
Name: g.GameName,
|
|
Category: "Crash",
|
|
Bets: g.Bets,
|
|
Thumbnail: g.Thumbnail,
|
|
Status: g.Status,
|
|
}
|
|
allGames = append(allGames, unified)
|
|
|
|
// --- Convert []float64 to []pgtype.Numeric ---
|
|
var betsNumeric []pgtype.Numeric
|
|
for _, bet := range g.Bets {
|
|
var num pgtype.Numeric
|
|
_ = num.Scan(bet)
|
|
betsNumeric = append(betsNumeric, num)
|
|
}
|
|
|
|
// --- Save to DB ---
|
|
_, err = s.repo.CreateVirtualGame(ctx, dbgen.CreateVirtualGameParams{
|
|
GameID: fmt.Sprintf("%d", g.ID), //The id here needs to be clean for me to access
|
|
ProviderID: "popok",
|
|
Name: g.GameName,
|
|
Bets: betsNumeric,
|
|
Thumbnail: pgtype.Text{
|
|
String: g.Thumbnail,
|
|
Valid: g.Thumbnail != "",
|
|
},
|
|
Status: pgtype.Int4{
|
|
Int32: int32(g.Status),
|
|
Valid: true,
|
|
},
|
|
HasDemo: pgtype.Bool{
|
|
Bool: true,
|
|
Valid: true,
|
|
},
|
|
Category: pgtype.Text{
|
|
String: "Crash",
|
|
Valid: true,
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
logger.Error("failed to create virtual game", zap.Error(err))
|
|
}
|
|
}
|
|
|
|
return allGames, nil
|
|
}
|