recommendation service
This commit is contained in:
parent
169e22e3a7
commit
5dcefa377f
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
|
|
@ -88,6 +89,7 @@ func main() {
|
|||
notificationRepo := repository.NewNotificationRepository(store)
|
||||
referalRepo := repository.NewReferralRepository(store)
|
||||
vitualGameRepo := repository.NewVirtualGameRepository(store)
|
||||
recommendationRepo := repository.NewRecommendationRepository(store)
|
||||
|
||||
notificationSvc := notificationservice.New(notificationRepo, logger, cfg)
|
||||
referalSvc := referralservice.New(referalRepo, *walletSvc, store, cfg, logger)
|
||||
|
|
@ -98,13 +100,13 @@ func main() {
|
|||
cfg,
|
||||
logger,
|
||||
)
|
||||
|
||||
veliService := veli.NewVeliPlayService(
|
||||
vitualGameRepo,
|
||||
*walletSvc,
|
||||
cfg,
|
||||
logger,
|
||||
)
|
||||
recommendationSvc := recommendation.NewService(recommendationRepo)
|
||||
|
||||
httpserver.StartDataFetchingCrons(eventSvc, oddsSvc, resultSvc)
|
||||
httpserver.StartTicketCrons(*ticketSvc)
|
||||
|
|
@ -113,7 +115,7 @@ func main() {
|
|||
JwtAccessKey: cfg.JwtKey,
|
||||
JwtAccessExpiry: cfg.AccessExpiry,
|
||||
}, userSvc,
|
||||
ticketSvc, betSvc, walletSvc, transactionSvc, branchSvc, companySvc, notificationSvc, oddsSvc, eventSvc, referalSvc, virtualGameSvc, aleaService, veliService, resultSvc, cfg)
|
||||
ticketSvc, betSvc, walletSvc, transactionSvc, branchSvc, companySvc, notificationSvc, oddsSvc, eventSvc, referalSvc, virtualGameSvc, aleaService, veliService, recommendationSvc, resultSvc, cfg)
|
||||
logger.Info("Starting server", "port", cfg.Port)
|
||||
|
||||
if err := app.Run(); err != nil {
|
||||
|
|
|
|||
15
db/migrations/000005_result_checker.up copy.sql
Normal file
15
db/migrations/000005_result_checker.up copy.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
CREATE TABLE IF NOT EXISTS results (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
bet_outcome_id BIGINT NOT NULL,
|
||||
event_id BIGINT NOT NULL,
|
||||
odd_id BIGINT NOT NULL,
|
||||
market_id BIGINT NOT NULL,
|
||||
status INT NOT NULL,
|
||||
score VARCHAR(255),
|
||||
full_time_score VARCHAR(255),
|
||||
half_time_score VARCHAR(255),
|
||||
ss VARCHAR(255),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (bet_outcome_id) REFERENCES bet_outcomes (id)
|
||||
);
|
||||
28
db/migrations/000006_recommendation.up.sql
Normal file
28
db/migrations/000006_recommendation.up.sql
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
CREATE TABLE virtual_games (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
provider VARCHAR(100) NOT NULL,
|
||||
category VARCHAR(100) NOT NULL,
|
||||
min_bet DECIMAL(15,2) NOT NULL,
|
||||
max_bet DECIMAL(15,2) NOT NULL,
|
||||
volatility VARCHAR(50) NOT NULL,
|
||||
rtp DECIMAL(5,2) NOT NULL,
|
||||
is_featured BOOLEAN DEFAULT false,
|
||||
popularity_score INTEGER DEFAULT 0,
|
||||
thumbnail_url TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE user_game_interactions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id),
|
||||
game_id BIGINT NOT NULL REFERENCES virtual_games(id),
|
||||
interaction_type VARCHAR(50) NOT NULL, -- 'view', 'play', 'bet', 'favorite'
|
||||
amount DECIMAL(15,2),
|
||||
duration_seconds INTEGER,
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_user_game_interactions_user ON user_game_interactions(user_id);
|
||||
CREATE INDEX idx_user_game_interactions_game ON user_game_interactions(game_id);
|
||||
47
docs/docs.go
47
docs/docs.go
|
|
@ -493,6 +493,45 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-games/recommendations/{userID}": {
|
||||
"get": {
|
||||
"description": "Returns a list of recommended virtual games for a specific user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Recommendations"
|
||||
],
|
||||
"summary": "Get virtual game recommendations",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User ID",
|
||||
"name": "userID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Recommended games fetched successfully",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Failed to fetch recommendations",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.RecommendationErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/webhooks/alea": {
|
||||
"post": {
|
||||
"description": "Handles webhook callbacks from Alea Play virtual games for bet settlement",
|
||||
|
|
@ -4678,6 +4717,14 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.RecommendationErrorResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.ReferralSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -485,6 +485,45 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/virtual-games/recommendations/{userID}": {
|
||||
"get": {
|
||||
"description": "Returns a list of recommended virtual games for a specific user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Recommendations"
|
||||
],
|
||||
"summary": "Get virtual game recommendations",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User ID",
|
||||
"name": "userID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Recommended games fetched successfully",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Failed to fetch recommendations",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.RecommendationErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/webhooks/alea": {
|
||||
"post": {
|
||||
"description": "Handles webhook callbacks from Alea Play virtual games for bet settlement",
|
||||
|
|
@ -4670,6 +4709,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.RecommendationErrorResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.ReferralSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -357,6 +357,11 @@ definitions:
|
|||
items: {}
|
||||
type: array
|
||||
type: object
|
||||
domain.RecommendationErrorResponse:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
domain.ReferralSettings:
|
||||
properties:
|
||||
betReferralBonusPercentage:
|
||||
|
|
@ -1761,6 +1766,32 @@ paths:
|
|||
summary: Verify a transfer
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/virtual-games/recommendations/{userID}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Returns a list of recommended virtual games for a specific user
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
name: userID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Recommended games fetched successfully
|
||||
schema:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
"500":
|
||||
description: Failed to fetch recommendations
|
||||
schema:
|
||||
$ref: '#/definitions/domain.RecommendationErrorResponse'
|
||||
summary: Get virtual game recommendations
|
||||
tags:
|
||||
- Recommendations
|
||||
/api/v1/webhooks/alea:
|
||||
post:
|
||||
consumes:
|
||||
|
|
|
|||
5
internal/domain/recommendation.go
Normal file
5
internal/domain/recommendation.go
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package domain
|
||||
|
||||
type RecommendationErrorResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ type BaseballResultResponse struct {
|
|||
EighthInning Score `json:"8"`
|
||||
NinthInning Score `json:"9"`
|
||||
ExtraInnings Score `json:"10"`
|
||||
TotalScore Score `json:"7"`
|
||||
TotalScore Score `json:"11"`
|
||||
} `json:"scores"`
|
||||
Stats struct {
|
||||
Hits []string `json:"hits"`
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
|
||||
func (s *Store) GetUserByEmailPhone(ctx context.Context, email, phone string) (domain.User, error) {
|
||||
user, err := s.queries.GetUserByEmailPhone(ctx, dbgen.GetUserByEmailPhoneParams{
|
||||
Email: pgtype.Text{
|
||||
|
|
|
|||
48
internal/repository/recommendation.go
Normal file
48
internal/repository/recommendation.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type RecommendationRepository interface {
|
||||
GetUserVirtualGameInteractions(ctx context.Context, userID string) ([]UserGameInteraction, error)
|
||||
}
|
||||
|
||||
type recommendationRepo struct {
|
||||
store *Store
|
||||
}
|
||||
|
||||
func NewRecommendationRepository(store *Store) RecommendationRepository {
|
||||
return &recommendationRepo{store: store}
|
||||
}
|
||||
|
||||
func (r *recommendationRepo) GetUserVirtualGameInteractions(ctx context.Context, userID string) ([]UserGameInteraction, error) {
|
||||
var interactions []UserGameInteraction
|
||||
query := `SELECT game_id, interaction_type, timestamp FROM virtual_game_interactions WHERE user_id = $1 ORDER BY timestamp DESC LIMIT 100`
|
||||
|
||||
rows, err := r.store.conn.Query(ctx, query, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var u UserGameInteraction
|
||||
if err := rows.Scan(&u.GameID, &u.InteractionType, &u.Timestamp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
interactions = append(interactions, u)
|
||||
}
|
||||
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return interactions, nil
|
||||
}
|
||||
|
||||
type UserGameInteraction struct {
|
||||
GameID string
|
||||
InteractionType string // e.g., "view", "bet", "like"
|
||||
Timestamp string
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ type VirtualGameRepository interface {
|
|||
CreateVirtualGameSession(ctx context.Context, session *domain.VirtualGameSession) error
|
||||
GetVirtualGameSessionByToken(ctx context.Context, token string) (*domain.VirtualGameSession, error)
|
||||
UpdateVirtualGameSessionStatus(ctx context.Context, id int64, status string) error
|
||||
// UpdateVirtualGameSessionStatus(ctx context.Context, id int64, status string) error
|
||||
CreateVirtualGameTransaction(ctx context.Context, tx *domain.VirtualGameTransaction) error
|
||||
GetVirtualGameTransactionByExternalID(ctx context.Context, externalID string) (*domain.VirtualGameTransaction, error)
|
||||
UpdateVirtualGameTransactionStatus(ctx context.Context, id int64, status string) error
|
||||
|
|
|
|||
7
internal/services/recommendation/port.go
Normal file
7
internal/services/recommendation/port.go
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package recommendation
|
||||
|
||||
import "context"
|
||||
|
||||
type RecommendationService interface {
|
||||
GetRecommendations(ctx context.Context, userID string) ([]string, error)
|
||||
}
|
||||
65
internal/services/recommendation/service.go
Normal file
65
internal/services/recommendation/service.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package recommendation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
|
||||
)
|
||||
|
||||
// type RecommendationService interface {
|
||||
// GetRecommendations(ctx context.Context, userID string) ([]string, error)
|
||||
// }
|
||||
|
||||
type service struct {
|
||||
repo repository.RecommendationRepository
|
||||
}
|
||||
|
||||
func NewService(repo repository.RecommendationRepository) RecommendationService {
|
||||
return &service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *service) GetRecommendations(ctx context.Context, userID string) ([]string, error) {
|
||||
interactions, err := s.repo.GetUserVirtualGameInteractions(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recommendationMap := map[string]int{}
|
||||
for _, interaction := range interactions {
|
||||
score := 1
|
||||
switch interaction.InteractionType {
|
||||
case "bet":
|
||||
score = 5
|
||||
case "view":
|
||||
score = 1
|
||||
}
|
||||
recommendationMap[interaction.GameID] += score
|
||||
}
|
||||
|
||||
// Example: return top 3 games based on score
|
||||
topGames := sortGamesByScore(recommendationMap)
|
||||
return topGames, nil
|
||||
}
|
||||
|
||||
func sortGamesByScore(scoreMap map[string]int) []string {
|
||||
type kv struct {
|
||||
Key string
|
||||
Value int
|
||||
}
|
||||
|
||||
var sorted []kv
|
||||
for k, v := range scoreMap {
|
||||
sorted = append(sorted, kv{k, v})
|
||||
}
|
||||
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
return sorted[i].Value > sorted[j].Value
|
||||
})
|
||||
|
||||
var result []string
|
||||
for i := 0; i < len(sorted) && i < 3; i++ {
|
||||
result = append(result, sorted[i].Key)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -38,7 +38,6 @@ func NewVeliPlayService(
|
|||
}
|
||||
}
|
||||
|
||||
// GenerateGameLaunchURL mirrors Alea's pattern but uses Veli's auth requirements
|
||||
func (s *VeliPlayService) GenerateGameLaunchURL(ctx context.Context, userID int64, gameID, currency, mode string) (string, error) {
|
||||
session := &domain.VirtualGameSession{
|
||||
UserID: userID,
|
||||
|
|
@ -71,7 +70,6 @@ func (s *VeliPlayService) GenerateGameLaunchURL(ctx context.Context, userID int6
|
|||
return fmt.Sprintf("%s/launch?%s", s.config.APIURL, params.Encode()), nil
|
||||
}
|
||||
|
||||
// HandleCallback processes Veli's webhooks (similar structure to Alea)
|
||||
func (s *VeliPlayService) HandleCallback(ctx context.Context, callback *domain.VeliCallback) error {
|
||||
if !s.verifyCallbackSignature(callback) {
|
||||
return errors.New("invalid callback signature")
|
||||
|
|
@ -114,7 +112,6 @@ func (s *VeliPlayService) HandleCallback(ctx context.Context, callback *domain.V
|
|||
return nil
|
||||
}
|
||||
|
||||
// Shared helper methods (same pattern as Alea)
|
||||
func (s *VeliPlayService) generateSignature(data string) string {
|
||||
h := hmac.New(sha256.New, []byte(s.config.SecretKey))
|
||||
h.Write([]byte(data))
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/company"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/result"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
|
|
@ -33,6 +34,7 @@ type App struct {
|
|||
fiber *fiber.App
|
||||
aleaVirtualGameService alea.AleaVirtualGameService
|
||||
veliVirtualGameService veli.VeliVirtualGameService
|
||||
recommendationSvc recommendation.RecommendationService
|
||||
cfg *config.Config
|
||||
logger *slog.Logger
|
||||
NotidicationStore *notificationservice.Service
|
||||
|
|
@ -74,6 +76,7 @@ func NewApp(
|
|||
virtualGameSvc virtualgameservice.VirtualGameService,
|
||||
aleaVirtualGameService alea.AleaVirtualGameService,
|
||||
veliVirtualGameService veli.VeliVirtualGameService,
|
||||
recommendationSvc recommendation.RecommendationService,
|
||||
resultSvc *result.Service,
|
||||
cfg *config.Config,
|
||||
) *App {
|
||||
|
|
@ -113,6 +116,7 @@ func NewApp(
|
|||
virtualGameSvc: virtualGameSvc,
|
||||
aleaVirtualGameService: aleaVirtualGameService,
|
||||
veliVirtualGameService: veliVirtualGameService,
|
||||
recommendationSvc: recommendationSvc,
|
||||
resultSvc: resultSvc,
|
||||
cfg: cfg,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||
notificationservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/notfication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/recommendation"
|
||||
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
|
||||
|
|
@ -39,6 +40,7 @@ type Handler struct {
|
|||
virtualGameSvc virtualgameservice.VirtualGameService
|
||||
aleaVirtualGameSvc alea.AleaVirtualGameService
|
||||
veliVirtualGameSvc veli.VeliVirtualGameService
|
||||
recommendationSvc recommendation.RecommendationService
|
||||
authSvc *authentication.Service
|
||||
jwtConfig jwtutil.JwtConfig
|
||||
validator *customvalidator.CustomValidator
|
||||
|
|
@ -54,6 +56,7 @@ func New(
|
|||
virtualGameSvc virtualgameservice.VirtualGameService,
|
||||
aleaVirtualGameSvc alea.AleaVirtualGameService,
|
||||
veliVirtualGameSvc veli.VeliVirtualGameService,
|
||||
recommendationSvc recommendation.RecommendationService,
|
||||
userSvc *user.Service,
|
||||
transactionSvc *transaction.Service,
|
||||
ticketSvc *ticket.Service,
|
||||
|
|
@ -83,6 +86,7 @@ func New(
|
|||
virtualGameSvc: virtualGameSvc,
|
||||
aleaVirtualGameSvc: aleaVirtualGameSvc,
|
||||
veliVirtualGameSvc: veliVirtualGameSvc,
|
||||
recommendationSvc: recommendationSvc,
|
||||
authSvc: authSvc,
|
||||
jwtConfig: jwtConfig,
|
||||
Cfg: cfg,
|
||||
|
|
|
|||
26
internal/web_server/handlers/recommendation.go
Normal file
26
internal/web_server/handlers/recommendation.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// @Summary Get virtual game recommendations
|
||||
// @Description Returns a list of recommended virtual games for a specific user
|
||||
// @Tags Recommendations
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID path string true "User ID"
|
||||
// @Success 200 {object} map[string]interface{} "Recommended games fetched successfully"
|
||||
// @Failure 500 {object} domain.RecommendationErrorResponse "Failed to fetch recommendations"
|
||||
// @Router /api/v1/virtual-games/recommendations/{userID} [get]
|
||||
func (h *Handler) GetRecommendations(c *fiber.Ctx) error {
|
||||
userID := c.Params("userID") // or from JWT
|
||||
recommendations, err := h.recommendationSvc.GetRecommendations(c.Context(), userID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch recommendations")
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Recommended games fetched successfully",
|
||||
"recommended_games": recommendations,
|
||||
})
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ func (a *App) initAppRoutes() {
|
|||
a.virtualGameSvc,
|
||||
a.aleaVirtualGameService,
|
||||
a.veliVirtualGameService,
|
||||
a.recommendationSvc,
|
||||
a.userSvc,
|
||||
a.transactionSvc,
|
||||
a.ticketSvc,
|
||||
|
|
@ -36,6 +37,8 @@ func (a *App) initAppRoutes() {
|
|||
a.cfg,
|
||||
)
|
||||
|
||||
group := a.fiber.Group("/api/v1")
|
||||
|
||||
a.fiber.Get("/", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Welcome to the FortuneBet API",
|
||||
|
|
@ -177,7 +180,6 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
||||
|
||||
//Chapa Routes
|
||||
group := a.fiber.Group("/api/v1")
|
||||
|
||||
group.Post("/chapa/payments/initialize", h.InitializePayment)
|
||||
group.Get("/chapa/payments/verify/:tx_ref", h.VerifyTransaction)
|
||||
|
|
@ -194,6 +196,9 @@ func (a *App) initAppRoutes() {
|
|||
group.Get("/veli-games/launch", a.authMiddleware, h.LaunchVeliGame)
|
||||
group.Post("/webhooks/veli-games", a.authMiddleware, h.HandleVeliCallback)
|
||||
|
||||
// Recommendation Routes
|
||||
group.Get("/virtual-games/recommendations/:userID", a.authMiddleware, h.GetRecommendations)
|
||||
|
||||
// Transactions /transactions
|
||||
a.fiber.Post("/transaction", a.authMiddleware, h.CreateTransaction)
|
||||
a.fiber.Get("/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user