fix market fetching
This commit is contained in:
parent
35b846bcc8
commit
d5be4803ae
|
|
@ -1,43 +1,52 @@
|
||||||
-- name: InsertNonLiveOdd :exec
|
-- name: InsertNonLiveOdd :exec
|
||||||
INSERT INTO odds (
|
INSERT INTO odds (
|
||||||
event_id,
|
event_id,
|
||||||
fi,
|
fi,
|
||||||
market_type,
|
market_type,
|
||||||
market_name,
|
market_name,
|
||||||
market_category,
|
market_category,
|
||||||
market_id,
|
market_id,
|
||||||
name,
|
name,
|
||||||
handicap,
|
handicap,
|
||||||
odds_value,
|
odds_value,
|
||||||
section,
|
section,
|
||||||
category,
|
category,
|
||||||
raw_odds,
|
raw_odds,
|
||||||
is_active,
|
is_active,
|
||||||
source,
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
) VALUES (
|
)
|
||||||
$1, $2, $3, $4, $5, $6, $7,
|
VALUES (
|
||||||
$8, $9, $10, $11, $12, $13, $14, $15
|
$1,
|
||||||
)
|
$2,
|
||||||
ON CONFLICT (event_id, market_id) DO UPDATE SET
|
$3,
|
||||||
odds_value = EXCLUDED.odds_value,
|
$4,
|
||||||
raw_odds = EXCLUDED.raw_odds,
|
$5,
|
||||||
market_type = EXCLUDED.market_type,
|
$6,
|
||||||
market_name = EXCLUDED.market_name,
|
$7,
|
||||||
|
$8,
|
||||||
|
$9,
|
||||||
|
$10,
|
||||||
|
$11,
|
||||||
|
$12,
|
||||||
|
$13,
|
||||||
|
$14,
|
||||||
|
$15
|
||||||
|
) ON CONFLICT (event_id, market_id) DO
|
||||||
|
UPDATE
|
||||||
|
SET odds_value = EXCLUDED.odds_value,
|
||||||
|
raw_odds = EXCLUDED.raw_odds,
|
||||||
|
market_type = EXCLUDED.market_type,
|
||||||
|
market_name = EXCLUDED.market_name,
|
||||||
market_category = EXCLUDED.market_category,
|
market_category = EXCLUDED.market_category,
|
||||||
name = EXCLUDED.name,
|
name = EXCLUDED.name,
|
||||||
handicap = EXCLUDED.handicap,
|
handicap = EXCLUDED.handicap,
|
||||||
fetched_at = EXCLUDED.fetched_at,
|
fetched_at = EXCLUDED.fetched_at,
|
||||||
is_active = EXCLUDED.is_active,
|
is_active = EXCLUDED.is_active,
|
||||||
source = EXCLUDED.source,
|
source = EXCLUDED.source,
|
||||||
fi = EXCLUDED.fi;
|
fi = EXCLUDED.fi;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- name: GetPrematchOdds :many
|
-- name: GetPrematchOdds :many
|
||||||
SELECT
|
SELECT event_id,
|
||||||
event_id,
|
|
||||||
fi,
|
fi,
|
||||||
market_type,
|
market_type,
|
||||||
market_name,
|
market_name,
|
||||||
|
|
@ -53,11 +62,10 @@ SELECT
|
||||||
source,
|
source,
|
||||||
is_active
|
is_active
|
||||||
FROM odds
|
FROM odds
|
||||||
WHERE is_active = true AND source = 'b365api';
|
WHERE is_active = true
|
||||||
|
AND source = 'b365api';
|
||||||
-- name: GetALLPrematchOdds :many
|
-- name: GetALLPrematchOdds :many
|
||||||
SELECT
|
SELECT event_id,
|
||||||
event_id,
|
|
||||||
fi,
|
fi,
|
||||||
market_type,
|
market_type,
|
||||||
market_name,
|
market_name,
|
||||||
|
|
@ -73,23 +81,20 @@ SELECT
|
||||||
source,
|
source,
|
||||||
is_active
|
is_active
|
||||||
FROM odds
|
FROM odds
|
||||||
WHERE is_active = true AND source = 'b365api';
|
WHERE is_active = true
|
||||||
|
AND source = 'b365api';
|
||||||
-- name: GetRawOddsByMarketID :many
|
-- name: GetRawOddsByMarketID :many
|
||||||
SELECT
|
SELECT id,
|
||||||
id,
|
raw_odds,
|
||||||
raw_odds,
|
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM odds
|
FROM odds
|
||||||
WHERE
|
WHERE market_id = $1
|
||||||
market_id = $1 AND
|
AND fi = $2
|
||||||
is_active = true AND
|
AND is_active = true
|
||||||
source = 'b365api'
|
AND source = 'b365api'
|
||||||
LIMIT $2 OFFSET $3;
|
LIMIT $3 OFFSET $4;
|
||||||
|
|
||||||
-- name: GetPrematchOddsByUpcomingID :many
|
-- name: GetPrematchOddsByUpcomingID :many
|
||||||
SELECT
|
SELECT o.event_id,
|
||||||
o.event_id,
|
|
||||||
o.fi,
|
o.fi,
|
||||||
o.market_type,
|
o.market_type,
|
||||||
o.market_name,
|
o.market_name,
|
||||||
|
|
@ -105,10 +110,10 @@ SELECT
|
||||||
o.source,
|
o.source,
|
||||||
o.is_active
|
o.is_active
|
||||||
FROM odds o
|
FROM odds o
|
||||||
JOIN events e ON o.fi = e.id
|
JOIN events e ON o.fi = e.id
|
||||||
WHERE e.id = $1
|
WHERE e.id = $1
|
||||||
AND e.is_live = false
|
AND e.is_live = false
|
||||||
AND e.status = 'upcoming'
|
AND e.status = 'upcoming'
|
||||||
AND o.is_active = true
|
AND o.is_active = true
|
||||||
AND o.source = 'b365api'
|
AND o.source = 'b365api'
|
||||||
LIMIT $2 OFFSET $3;
|
LIMIT $2 OFFSET $3;
|
||||||
101
docs/docs.go
101
docs/docs.go
|
|
@ -1354,53 +1354,6 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/prematch/odds/raw/{market_id}": {
|
|
||||||
"get": {
|
|
||||||
"description": "Retrieve raw odds records using a Market ID",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"prematch"
|
|
||||||
],
|
|
||||||
"summary": "Retrieve raw odds by Market ID",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "Market ID",
|
|
||||||
"name": "market_id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/domain.RawOddsByMarketID"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.APIResponse"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.APIResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/prematch/odds/upcoming/{upcoming_id}": {
|
"/prematch/odds/upcoming/{upcoming_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination",
|
"description": "Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination",
|
||||||
|
|
@ -1460,6 +1413,60 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/prematch/odds/upcoming/{upcoming_id}/market/{market_id}": {
|
||||||
|
"get": {
|
||||||
|
"description": "Retrieve raw odds records using a Market ID",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"prematch"
|
||||||
|
],
|
||||||
|
"summary": "Retrieve raw odds by Market ID",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Upcoming ID",
|
||||||
|
"name": "upcoming_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Market ID",
|
||||||
|
"name": "market_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/domain.RawOddsByMarketID"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/prematch/odds/{event_id}": {
|
"/prematch/odds/{event_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Retrieve prematch odds for a specific event by event ID",
|
"description": "Retrieve prematch odds for a specific event by event ID",
|
||||||
|
|
|
||||||
|
|
@ -1346,53 +1346,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/prematch/odds/raw/{market_id}": {
|
|
||||||
"get": {
|
|
||||||
"description": "Retrieve raw odds records using a Market ID",
|
|
||||||
"consumes": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"prematch"
|
|
||||||
],
|
|
||||||
"summary": "Retrieve raw odds by Market ID",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "Market ID",
|
|
||||||
"name": "market_id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/domain.RawOddsByMarketID"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Bad Request",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.APIResponse"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Internal Server Error",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/response.APIResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/prematch/odds/upcoming/{upcoming_id}": {
|
"/prematch/odds/upcoming/{upcoming_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination",
|
"description": "Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination",
|
||||||
|
|
@ -1452,6 +1405,60 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/prematch/odds/upcoming/{upcoming_id}/market/{market_id}": {
|
||||||
|
"get": {
|
||||||
|
"description": "Retrieve raw odds records using a Market ID",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"prematch"
|
||||||
|
],
|
||||||
|
"summary": "Retrieve raw odds by Market ID",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Upcoming ID",
|
||||||
|
"name": "upcoming_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Market ID",
|
||||||
|
"name": "market_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/domain.RawOddsByMarketID"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.APIResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/prematch/odds/{event_id}": {
|
"/prematch/odds/{event_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Retrieve prematch odds for a specific event by event ID",
|
"description": "Retrieve prematch odds for a specific event by event ID",
|
||||||
|
|
|
||||||
|
|
@ -1704,37 +1704,6 @@ paths:
|
||||||
summary: Retrieve prematch odds for an event
|
summary: Retrieve prematch odds for an event
|
||||||
tags:
|
tags:
|
||||||
- prematch
|
- prematch
|
||||||
/prematch/odds/raw/{market_id}:
|
|
||||||
get:
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
description: Retrieve raw odds records using a Market ID
|
|
||||||
parameters:
|
|
||||||
- description: Market ID
|
|
||||||
in: path
|
|
||||||
name: market_id
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
items:
|
|
||||||
$ref: '#/definitions/domain.RawOddsByMarketID'
|
|
||||||
type: array
|
|
||||||
"400":
|
|
||||||
description: Bad Request
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.APIResponse'
|
|
||||||
"500":
|
|
||||||
description: Internal Server Error
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/response.APIResponse'
|
|
||||||
summary: Retrieve raw odds by Market ID
|
|
||||||
tags:
|
|
||||||
- prematch
|
|
||||||
/prematch/odds/upcoming/{upcoming_id}:
|
/prematch/odds/upcoming/{upcoming_id}:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|
@ -1775,6 +1744,42 @@ paths:
|
||||||
summary: Retrieve prematch odds by upcoming ID (FI)
|
summary: Retrieve prematch odds by upcoming ID (FI)
|
||||||
tags:
|
tags:
|
||||||
- prematch
|
- prematch
|
||||||
|
/prematch/odds/upcoming/{upcoming_id}/market/{market_id}:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: Retrieve raw odds records using a Market ID
|
||||||
|
parameters:
|
||||||
|
- description: Upcoming ID
|
||||||
|
in: path
|
||||||
|
name: upcoming_id
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: Market ID
|
||||||
|
in: path
|
||||||
|
name: market_id
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/domain.RawOddsByMarketID'
|
||||||
|
type: array
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.APIResponse'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/response.APIResponse'
|
||||||
|
summary: Retrieve raw odds by Market ID
|
||||||
|
tags:
|
||||||
|
- prematch
|
||||||
/search/branch:
|
/search/branch:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,6 @@ type Odd struct {
|
||||||
MarketCategory pgtype.Text `json:"market_category"`
|
MarketCategory pgtype.Text `json:"market_category"`
|
||||||
MarketID pgtype.Text `json:"market_id"`
|
MarketID pgtype.Text `json:"market_id"`
|
||||||
Name pgtype.Text `json:"name"`
|
Name pgtype.Text `json:"name"`
|
||||||
Header pgtype.Text `json:"header"`
|
|
||||||
Handicap pgtype.Text `json:"handicap"`
|
Handicap pgtype.Text `json:"handicap"`
|
||||||
OddsValue pgtype.Float8 `json:"odds_value"`
|
OddsValue pgtype.Float8 `json:"odds_value"`
|
||||||
Section string `json:"section"`
|
Section string `json:"section"`
|
||||||
|
|
|
||||||
|
|
@ -253,15 +253,17 @@ SELECT id,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM odds
|
FROM odds
|
||||||
WHERE market_id = $1
|
WHERE market_id = $1
|
||||||
|
AND fi = $2
|
||||||
AND is_active = true
|
AND is_active = true
|
||||||
AND source = 'b365api'
|
AND source = 'b365api'
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $3 OFFSET $4
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetRawOddsByMarketIDParams struct {
|
type GetRawOddsByMarketIDParams struct {
|
||||||
MarketID pgtype.Text
|
MarketID pgtype.Text `json:"market_id"`
|
||||||
Limit int32
|
Fi pgtype.Text `json:"fi"`
|
||||||
Offset int32
|
Limit int32 `json:"limit"`
|
||||||
|
Offset int32 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetRawOddsByMarketIDRow struct {
|
type GetRawOddsByMarketIDRow struct {
|
||||||
|
|
@ -271,7 +273,12 @@ type GetRawOddsByMarketIDRow struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetRawOddsByMarketID(ctx context.Context, arg GetRawOddsByMarketIDParams) ([]GetRawOddsByMarketIDRow, error) {
|
func (q *Queries) GetRawOddsByMarketID(ctx context.Context, arg GetRawOddsByMarketIDParams) ([]GetRawOddsByMarketIDRow, error) {
|
||||||
rows, err := q.db.Query(ctx, GetRawOddsByMarketID, arg.MarketID, arg.Limit, arg.Offset)
|
rows, err := q.db.Query(ctx, GetRawOddsByMarketID,
|
||||||
|
arg.MarketID,
|
||||||
|
arg.Fi,
|
||||||
|
arg.Limit,
|
||||||
|
arg.Offset,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -324,37 +331,15 @@ VALUES (
|
||||||
$13,
|
$13,
|
||||||
$14,
|
$14,
|
||||||
$15
|
$15
|
||||||
) ON CONFLICT (market_id, name, handicap) DO
|
) ON CONFLICT (event_id, market_id) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
SET odds_value = EXCLUDED.odds_value,
|
SET odds_value = EXCLUDED.odds_value,
|
||||||
raw_odds = EXCLUDED.raw_odds,
|
raw_odds = EXCLUDED.raw_odds,
|
||||||
market_type = EXCLUDED.market_type,
|
market_type = EXCLUDED.market_type,
|
||||||
market_name = EXCLUDED.market_name,
|
market_name = EXCLUDED.market_name,
|
||||||
event_id,
|
|
||||||
fi,
|
|
||||||
market_type,
|
|
||||||
market_name,
|
|
||||||
market_category,
|
|
||||||
market_id,
|
|
||||||
name,
|
|
||||||
handicap,
|
|
||||||
odds_value,
|
|
||||||
section,
|
|
||||||
category,
|
|
||||||
raw_odds,
|
|
||||||
is_active,
|
|
||||||
source,
|
|
||||||
fetched_at
|
|
||||||
) VALUES (
|
|
||||||
$1, $2, $3, $4, $5, $6, $7,
|
|
||||||
$8, $9, $10, $11, $12, $13, $14, $15
|
|
||||||
)
|
|
||||||
ON CONFLICT (event_id, market_id) DO UPDATE SET
|
|
||||||
odds_value = EXCLUDED.odds_value,
|
|
||||||
raw_odds = EXCLUDED.raw_odds,
|
|
||||||
market_type = EXCLUDED.market_type,
|
|
||||||
market_name = EXCLUDED.market_name,
|
|
||||||
market_category = EXCLUDED.market_category,
|
market_category = EXCLUDED.market_category,
|
||||||
|
name = EXCLUDED.name,
|
||||||
|
handicap = EXCLUDED.handicap,
|
||||||
fetched_at = EXCLUDED.fetched_at,
|
fetched_at = EXCLUDED.fetched_at,
|
||||||
is_active = EXCLUDED.is_active,
|
is_active = EXCLUDED.is_active,
|
||||||
source = EXCLUDED.source,
|
source = EXCLUDED.source,
|
||||||
|
|
|
||||||
|
|
@ -14,242 +14,243 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Store) SaveNonLiveMarket(ctx context.Context, m domain.Market) error {
|
func (s *Store) SaveNonLiveMarket(ctx context.Context, m domain.Market) error {
|
||||||
if len(m.Odds) == 0 {
|
if len(m.Odds) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, raw := range m.Odds {
|
for _, raw := range m.Odds {
|
||||||
var item map[string]interface{}
|
var item map[string]interface{}
|
||||||
if err := json.Unmarshal(raw, &item); err != nil {
|
if err := json.Unmarshal(raw, &item); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
name := getString(item["name"])
|
name := getString(item["name"])
|
||||||
handicap := getString(item["handicap"])
|
handicap := getString(item["handicap"])
|
||||||
oddsVal := getFloat(item["odds"])
|
oddsVal := getFloat(item["odds"])
|
||||||
|
|
||||||
rawOddsBytes, _ := json.Marshal(m.Odds)
|
rawOddsBytes, _ := json.Marshal(m.Odds)
|
||||||
|
|
||||||
params := dbgen.InsertNonLiveOddParams{
|
params := dbgen.InsertNonLiveOddParams{
|
||||||
EventID: pgtype.Text{String: m.EventID, Valid: m.EventID != ""},
|
EventID: pgtype.Text{String: m.EventID, Valid: m.EventID != ""},
|
||||||
Fi: pgtype.Text{String: m.FI, Valid: m.FI != ""},
|
Fi: pgtype.Text{String: m.FI, Valid: m.FI != ""},
|
||||||
MarketType: m.MarketType,
|
MarketType: m.MarketType,
|
||||||
MarketName: pgtype.Text{String: m.MarketName, Valid: m.MarketName != ""},
|
MarketName: pgtype.Text{String: m.MarketName, Valid: m.MarketName != ""},
|
||||||
MarketCategory: pgtype.Text{String: m.MarketCategory, Valid: m.MarketCategory != ""},
|
MarketCategory: pgtype.Text{String: m.MarketCategory, Valid: m.MarketCategory != ""},
|
||||||
MarketID: pgtype.Text{String: m.MarketID, Valid: m.MarketID != ""},
|
MarketID: pgtype.Text{String: m.MarketID, Valid: m.MarketID != ""},
|
||||||
Name: pgtype.Text{String: name, Valid: name != ""},
|
Name: pgtype.Text{String: name, Valid: name != ""},
|
||||||
Handicap: pgtype.Text{String: handicap, Valid: handicap != ""},
|
Handicap: pgtype.Text{String: handicap, Valid: handicap != ""},
|
||||||
OddsValue: pgtype.Float8{Float64: oddsVal, Valid: oddsVal != 0},
|
OddsValue: pgtype.Float8{Float64: oddsVal, Valid: oddsVal != 0},
|
||||||
Section: m.MarketCategory,
|
Section: m.MarketCategory,
|
||||||
Category: pgtype.Text{Valid: false},
|
Category: pgtype.Text{Valid: false},
|
||||||
RawOdds: rawOddsBytes,
|
RawOdds: rawOddsBytes,
|
||||||
IsActive: pgtype.Bool{Bool: true, Valid: true},
|
IsActive: pgtype.Bool{Bool: true, Valid: true},
|
||||||
Source: pgtype.Text{String: "b365api", Valid: true},
|
Source: pgtype.Text{String: "b365api", Valid: true},
|
||||||
FetchedAt: pgtype.Timestamp{Time: time.Now(), Valid: true},
|
FetchedAt: pgtype.Timestamp{Time: time.Now(), Valid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.queries.InsertNonLiveOdd(ctx, params)
|
err := s.queries.InsertNonLiveOdd(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = writeFailedMarketLog(m, err)
|
_ = writeFailedMarketLog(m, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFailedMarketLog(m domain.Market, err error) error {
|
func writeFailedMarketLog(m domain.Market, err error) error {
|
||||||
logDir := "logs"
|
logDir := "logs"
|
||||||
logFile := logDir + "/failed_markets.log"
|
logFile := logDir + "/failed_markets.log"
|
||||||
|
|
||||||
if mkErr := os.MkdirAll(logDir, 0755); mkErr != nil {
|
if mkErr := os.MkdirAll(logDir, 0755); mkErr != nil {
|
||||||
return mkErr
|
return mkErr
|
||||||
}
|
}
|
||||||
|
|
||||||
f, fileErr := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
f, fileErr := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if fileErr != nil {
|
if fileErr != nil {
|
||||||
return fileErr
|
return fileErr
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
entry := struct {
|
entry := struct {
|
||||||
Time string `json:"time"`
|
Time string `json:"time"`
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
Record domain.Market `json:"record"`
|
Record domain.Market `json:"record"`
|
||||||
}{
|
}{
|
||||||
Time: time.Now().Format(time.RFC3339),
|
Time: time.Now().Format(time.RFC3339),
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
Record: m,
|
Record: m,
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonData, _ := json.MarshalIndent(entry, "", " ")
|
jsonData, _ := json.MarshalIndent(entry, "", " ")
|
||||||
_, writeErr := f.WriteString(string(jsonData) + "\n\n")
|
_, writeErr := f.WriteString(string(jsonData) + "\n\n")
|
||||||
return writeErr
|
return writeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func getString(v interface{}) string {
|
func getString(v interface{}) string {
|
||||||
if s, ok := v.(string); ok {
|
if s, ok := v.(string); ok {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFloat(v interface{}) float64 {
|
func getFloat(v interface{}) float64 {
|
||||||
if s, ok := v.(string); ok {
|
if s, ok := v.(string); ok {
|
||||||
f, err := strconv.ParseFloat(s, 64)
|
f, err := strconv.ParseFloat(s, 64)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error) {
|
func (s *Store) GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error) {
|
||||||
odds, err := s.queries.GetPrematchOdds(ctx)
|
odds, err := s.queries.GetPrematchOdds(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
domainOdds := make([]domain.Odd, len(odds))
|
domainOdds := make([]domain.Odd, len(odds))
|
||||||
for i, odd := range odds {
|
for i, odd := range odds {
|
||||||
domainOdds[i] = domain.Odd{
|
domainOdds[i] = domain.Odd{
|
||||||
EventID: odd.EventID.String,
|
EventID: odd.EventID.String,
|
||||||
Fi: odd.Fi.String,
|
Fi: odd.Fi.String,
|
||||||
MarketType: odd.MarketType,
|
MarketType: odd.MarketType,
|
||||||
MarketName: odd.MarketName.String,
|
MarketName: odd.MarketName.String,
|
||||||
MarketCategory: odd.MarketCategory.String,
|
MarketCategory: odd.MarketCategory.String,
|
||||||
MarketID: odd.MarketID.String,
|
MarketID: odd.MarketID.String,
|
||||||
Name: odd.Name.String,
|
Name: odd.Name.String,
|
||||||
Handicap: odd.Handicap.String,
|
Handicap: odd.Handicap.String,
|
||||||
OddsValue: odd.OddsValue.Float64,
|
OddsValue: odd.OddsValue.Float64,
|
||||||
Section: odd.Section,
|
Section: odd.Section,
|
||||||
Category: odd.Category.String,
|
Category: odd.Category.String,
|
||||||
RawOdds: func() []domain.RawMessage {
|
RawOdds: func() []domain.RawMessage {
|
||||||
var rawOdds []domain.RawMessage
|
var rawOdds []domain.RawMessage
|
||||||
if err := json.Unmarshal(odd.RawOdds, &rawOdds); err != nil {
|
if err := json.Unmarshal(odd.RawOdds, &rawOdds); err != nil {
|
||||||
rawOdds = nil
|
rawOdds = nil
|
||||||
}
|
}
|
||||||
return rawOdds
|
return rawOdds
|
||||||
}(),
|
}(),
|
||||||
FetchedAt: odd.FetchedAt.Time,
|
FetchedAt: odd.FetchedAt.Time,
|
||||||
Source: odd.Source.String,
|
Source: odd.Source.String,
|
||||||
IsActive: odd.IsActive.Bool,
|
IsActive: odd.IsActive.Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return domainOdds, nil
|
return domainOdds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetALLPrematchOdds(ctx context.Context) ([]domain.Odd, error) {
|
func (s *Store) GetALLPrematchOdds(ctx context.Context) ([]domain.Odd, error) {
|
||||||
rows, err := s.queries.GetALLPrematchOdds(ctx)
|
rows, err := s.queries.GetALLPrematchOdds(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
domainOdds := make([]domain.Odd, len(rows))
|
domainOdds := make([]domain.Odd, len(rows))
|
||||||
for i, row := range rows {
|
for i, row := range rows {
|
||||||
domainOdds[i] = domain.Odd{
|
domainOdds[i] = domain.Odd{
|
||||||
// ID: int64(row.ID),
|
// ID: int64(row.ID),
|
||||||
EventID: row.EventID.String,
|
EventID: row.EventID.String,
|
||||||
Fi: row.Fi.String,
|
Fi: row.Fi.String,
|
||||||
MarketType: row.MarketType,
|
MarketType: row.MarketType,
|
||||||
MarketName: row.MarketName.String,
|
MarketName: row.MarketName.String,
|
||||||
MarketCategory: row.MarketCategory.String,
|
MarketCategory: row.MarketCategory.String,
|
||||||
MarketID: row.MarketID.String,
|
MarketID: row.MarketID.String,
|
||||||
Name: row.Name.String,
|
Name: row.Name.String,
|
||||||
Handicap: row.Handicap.String,
|
Handicap: row.Handicap.String,
|
||||||
OddsValue: row.OddsValue.Float64,
|
OddsValue: row.OddsValue.Float64,
|
||||||
Section: row.Section,
|
Section: row.Section,
|
||||||
Category: row.Category.String,
|
Category: row.Category.String,
|
||||||
RawOdds: func() []domain.RawMessage {
|
RawOdds: func() []domain.RawMessage {
|
||||||
var rawOdds []domain.RawMessage
|
var rawOdds []domain.RawMessage
|
||||||
if err := json.Unmarshal(row.RawOdds, &rawOdds); err != nil {
|
if err := json.Unmarshal(row.RawOdds, &rawOdds); err != nil {
|
||||||
rawOdds = nil
|
rawOdds = nil
|
||||||
}
|
}
|
||||||
return rawOdds
|
return rawOdds
|
||||||
}(),
|
}(),
|
||||||
FetchedAt: row.FetchedAt.Time,
|
FetchedAt: row.FetchedAt.Time,
|
||||||
Source: row.Source.String,
|
Source: row.Source.String,
|
||||||
IsActive: row.IsActive.Bool,
|
IsActive: row.IsActive.Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return domainOdds, nil
|
return domainOdds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetRawOddsByMarketID(ctx context.Context, rawOddsID string) (domain.RawOddsByMarketID, error) {
|
func (s *Store) GetRawOddsByMarketID(ctx context.Context, rawOddsID string, upcomingID string) (domain.RawOddsByMarketID, error) {
|
||||||
params := dbgen.GetRawOddsByMarketIDParams{
|
params := dbgen.GetRawOddsByMarketIDParams{
|
||||||
MarketID: pgtype.Text{String: rawOddsID, Valid: true},
|
MarketID: pgtype.Text{String: rawOddsID, Valid: true},
|
||||||
Limit: 1,
|
Fi: pgtype.Text{String: upcomingID, Valid: true},
|
||||||
Offset: 0,
|
Limit: 1,
|
||||||
}
|
Offset: 0,
|
||||||
|
}
|
||||||
|
|
||||||
rows, err := s.queries.GetRawOddsByMarketID(ctx, params)
|
rows, err := s.queries.GetRawOddsByMarketID(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.RawOddsByMarketID{}, err
|
return domain.RawOddsByMarketID{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rows) == 0 {
|
if len(rows) == 0 {
|
||||||
return domain.RawOddsByMarketID{}, fmt.Errorf("no raw odds found for market_id: %s", rawOddsID)
|
return domain.RawOddsByMarketID{}, fmt.Errorf("no raw odds found for market_id: %s", rawOddsID)
|
||||||
}
|
}
|
||||||
|
|
||||||
row := rows[0]
|
row := rows[0]
|
||||||
|
|
||||||
var rawOdds []json.RawMessage
|
var rawOdds []json.RawMessage
|
||||||
if err := json.Unmarshal(row.RawOdds, &rawOdds); err != nil {
|
if err := json.Unmarshal(row.RawOdds, &rawOdds); err != nil {
|
||||||
return domain.RawOddsByMarketID{}, err
|
return domain.RawOddsByMarketID{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.RawOddsByMarketID{
|
return domain.RawOddsByMarketID{
|
||||||
ID: int64(row.ID),
|
ID: int64(row.ID),
|
||||||
RawOdds: func() []domain.RawMessage {
|
RawOdds: func() []domain.RawMessage {
|
||||||
converted := make([]domain.RawMessage, len(rawOdds))
|
converted := make([]domain.RawMessage, len(rawOdds))
|
||||||
for i, r := range rawOdds {
|
for i, r := range rawOdds {
|
||||||
converted[i] = domain.RawMessage(r)
|
converted[i] = domain.RawMessage(r)
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}(),
|
}(),
|
||||||
FetchedAt: row.FetchedAt.Time,
|
FetchedAt: row.FetchedAt.Time,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetPrematchOddsByUpcomingID(ctx context.Context, upcomingID string, limit, offset int32) ([]domain.Odd, error) {
|
func (s *Store) GetPrematchOddsByUpcomingID(ctx context.Context, upcomingID string, limit, offset int32) ([]domain.Odd, error) {
|
||||||
params := dbgen.GetPrematchOddsByUpcomingIDParams{
|
params := dbgen.GetPrematchOddsByUpcomingIDParams{
|
||||||
ID: upcomingID,
|
ID: upcomingID,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Offset: offset,
|
Offset: offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
odds, err := s.queries.GetPrematchOddsByUpcomingID(ctx, params)
|
odds, err := s.queries.GetPrematchOddsByUpcomingID(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map the results to domain.Odd
|
// Map the results to domain.Odd
|
||||||
domainOdds := make([]domain.Odd, len(odds))
|
domainOdds := make([]domain.Odd, len(odds))
|
||||||
for i, odd := range odds {
|
for i, odd := range odds {
|
||||||
var rawOdds []domain.RawMessage
|
var rawOdds []domain.RawMessage
|
||||||
if err := json.Unmarshal(odd.RawOdds, &rawOdds); err != nil {
|
if err := json.Unmarshal(odd.RawOdds, &rawOdds); err != nil {
|
||||||
rawOdds = nil
|
rawOdds = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
domainOdds[i] = domain.Odd{
|
domainOdds[i] = domain.Odd{
|
||||||
EventID: odd.EventID.String,
|
EventID: odd.EventID.String,
|
||||||
Fi: odd.Fi.String,
|
Fi: odd.Fi.String,
|
||||||
MarketType: odd.MarketType,
|
MarketType: odd.MarketType,
|
||||||
MarketName: odd.MarketName.String,
|
MarketName: odd.MarketName.String,
|
||||||
MarketCategory: odd.MarketCategory.String,
|
MarketCategory: odd.MarketCategory.String,
|
||||||
MarketID: odd.MarketID.String,
|
MarketID: odd.MarketID.String,
|
||||||
Name: odd.Name.String,
|
Name: odd.Name.String,
|
||||||
Handicap: odd.Handicap.String,
|
Handicap: odd.Handicap.String,
|
||||||
OddsValue: odd.OddsValue.Float64,
|
OddsValue: odd.OddsValue.Float64,
|
||||||
Section: odd.Section,
|
Section: odd.Section,
|
||||||
Category: odd.Category.String,
|
Category: odd.Category.String,
|
||||||
RawOdds: rawOdds,
|
RawOdds: rawOdds,
|
||||||
FetchedAt: odd.FetchedAt.Time,
|
FetchedAt: odd.FetchedAt.Time,
|
||||||
Source: odd.Source.String,
|
Source: odd.Source.String,
|
||||||
IsActive: odd.IsActive.Bool,
|
IsActive: odd.IsActive.Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return domainOdds, nil
|
return domainOdds, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,5 @@ type Service interface {
|
||||||
FetchNonLiveOdds(ctx context.Context) error
|
FetchNonLiveOdds(ctx context.Context) error
|
||||||
GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error)
|
GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error)
|
||||||
GetALLPrematchOdds(ctx context.Context) ([]domain.Odd, error)
|
GetALLPrematchOdds(ctx context.Context) ([]domain.Odd, error)
|
||||||
GetRawOddsByMarketID(ctx context.Context, marketID string) ([]domain.RawOddsByMarketID, error)
|
GetRawOddsByMarketID(ctx context.Context, marketID string, upcomingID string) ([]domain.RawOddsByMarketID, error)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ func New(token string, store *repository.Store) *ServiceImpl {
|
||||||
return &ServiceImpl{token: token, store: store}
|
return &ServiceImpl{token: token, store: store}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *ServiceImpl) FetchNonLiveOdds(ctx context.Context) error {
|
func (s *ServiceImpl) FetchNonLiveOdds(ctx context.Context) error {
|
||||||
eventIDs, err := s.store.GetAllUpcomingEvents(ctx)
|
eventIDs, err := s.store.GetAllUpcomingEvents(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -30,43 +29,43 @@ func (s *ServiceImpl) FetchNonLiveOdds(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, event := range eventIDs {
|
for _, event := range eventIDs {
|
||||||
eventID := event.ID
|
eventID := event.ID
|
||||||
prematchURL := "https://api.b365api.com/v3/bet365/prematch?token=" + s.token + "&FI=" + eventID
|
prematchURL := "https://api.b365api.com/v3/bet365/prematch?token=" + s.token + "&FI=" + eventID
|
||||||
log.Printf("📡 Fetching prematch odds for event ID: %s", eventID)
|
log.Printf("📡 Fetching prematch odds for event ID: %s", eventID)
|
||||||
resp, err := http.Get(prematchURL)
|
resp, err := http.Get(prematchURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ Failed to fetch prematch odds for event %s: %v", eventID, err)
|
log.Printf("❌ Failed to fetch prematch odds for event %s: %v", eventID, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
var oddsData struct {
|
var oddsData struct {
|
||||||
Success int `json:"success"`
|
Success int `json:"success"`
|
||||||
Results []struct {
|
Results []struct {
|
||||||
EventID string `json:"event_id"`
|
EventID string `json:"event_id"`
|
||||||
FI string `json:"FI"`
|
FI string `json:"FI"`
|
||||||
Main OddsSection `json:"main"`
|
Main OddsSection `json:"main"`
|
||||||
} `json:"results"`
|
} `json:"results"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(body, &oddsData); err != nil || oddsData.Success != 1 || len(oddsData.Results) == 0 {
|
if err := json.Unmarshal(body, &oddsData); err != nil || oddsData.Success != 1 || len(oddsData.Results) == 0 {
|
||||||
log.Printf("❌ Invalid prematch data for event %s", eventID)
|
log.Printf("❌ Invalid prematch data for event %s", eventID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
result := oddsData.Results[0]
|
result := oddsData.Results[0]
|
||||||
finalID := result.EventID
|
finalID := result.EventID
|
||||||
if finalID == "" {
|
if finalID == "" {
|
||||||
finalID = result.FI
|
finalID = result.FI
|
||||||
}
|
}
|
||||||
if finalID == "" {
|
if finalID == "" {
|
||||||
log.Printf("⚠️ Skipping event %s with no valid ID", eventID)
|
log.Printf("⚠️ Skipping event %s with no valid ID", eventID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.storeSection(ctx, finalID, result.FI, "main", result.Main)
|
s.storeSection(ctx, finalID, result.FI, "main", result.Main)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -108,12 +107,10 @@ type OddsMarket struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type OddsSection struct {
|
type OddsSection struct {
|
||||||
UpdatedAt string `json:"updated_at"`
|
UpdatedAt string `json:"updated_at"`
|
||||||
Sp map[string]OddsMarket `json:"sp"`
|
Sp map[string]OddsMarket `json:"sp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (s *ServiceImpl) GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error) {
|
func (s *ServiceImpl) GetPrematchOdds(ctx context.Context, eventID string) ([]domain.Odd, error) {
|
||||||
return s.store.GetPrematchOdds(ctx, eventID)
|
return s.store.GetPrematchOdds(ctx, eventID)
|
||||||
}
|
}
|
||||||
|
|
@ -122,8 +119,8 @@ func (s *ServiceImpl) GetALLPrematchOdds(ctx context.Context) ([]domain.Odd, err
|
||||||
return s.store.GetALLPrematchOdds(ctx)
|
return s.store.GetALLPrematchOdds(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServiceImpl) GetRawOddsByMarketID(ctx context.Context, marketID string) ([]domain.RawOddsByMarketID, error) {
|
func (s *ServiceImpl) GetRawOddsByMarketID(ctx context.Context, marketID string, upcomingID string) ([]domain.RawOddsByMarketID, error) {
|
||||||
rows, err := s.store.GetRawOddsByMarketID(ctx, marketID)
|
rows, err := s.store.GetRawOddsByMarketID(ctx, marketID, upcomingID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -132,5 +129,5 @@ func (s *ServiceImpl) GetRawOddsByMarketID(ctx context.Context, marketID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServiceImpl) GetPrematchOddsByUpcomingID(ctx context.Context, upcomingID string, limit, offset int32) ([]domain.Odd, error) {
|
func (s *ServiceImpl) GetPrematchOddsByUpcomingID(ctx context.Context, upcomingID string, limit, offset int32) ([]domain.Odd, error) {
|
||||||
return s.store.GetPrematchOddsByUpcomingID(ctx, upcomingID, limit, offset)
|
return s.store.GetPrematchOddsByUpcomingID(ctx, upcomingID, limit, offset)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,58 @@
|
||||||
package httpserver
|
package httpserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "context"
|
// "context"
|
||||||
"log"
|
|
||||||
|
|
||||||
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
"log"
|
||||||
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
|
||||||
"github.com/robfig/cron/v3"
|
eventsvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/event"
|
||||||
|
oddssvc "github.com/SamuelTariku/FortuneBet-Backend/internal/services/odds"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.Service) {
|
func StartDataFetchingCrons(eventService eventsvc.Service, oddsService oddssvc.Service) {
|
||||||
c := cron.New(cron.WithSeconds())
|
c := cron.New(cron.WithSeconds())
|
||||||
|
|
||||||
schedule := []struct {
|
schedule := []struct {
|
||||||
spec string
|
spec string
|
||||||
task func()
|
task func()
|
||||||
}{
|
}{
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// spec: "*/30 * * * * *", // Every 30 seconds
|
// spec: "*/30 * * * * *", // Every 30 seconds
|
||||||
// task: func() {
|
// task: func() {
|
||||||
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
// if err := eventService.FetchUpcomingEvents(context.Background()); err != nil {
|
||||||
// log.Printf("FetchUpcomingEvents error: %v", err)
|
// log.Printf("FetchUpcomingEvents error: %v", err)
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
|
||||||
// {
|
|
||||||
// spec: "*/5 * * * * *", // Every 5 seconds
|
|
||||||
// task: func() {
|
|
||||||
// if err := eventService.FetchLiveEvents(context.Background()); err != nil {
|
|
||||||
// log.Printf("FetchLiveEvents error: %v", err)
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// spec: "*/5 * * * * *", // Every 5 seconds
|
||||||
|
// task: func() {
|
||||||
|
// if err := eventService.FetchLiveEvents(context.Background()); err != nil {
|
||||||
|
// log.Printf("FetchLiveEvents error: %v", err)
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// spec: "*/5 * * * * *", // Every 5 seconds
|
// spec: "*/5 * * * * *", // Every 5 seconds
|
||||||
// task: func() {
|
// task: func() {
|
||||||
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
// if err := oddsService.FetchNonLiveOdds(context.Background()); err != nil {
|
||||||
// log.Printf("FetchNonLiveOdds error: %v", err)
|
// log.Printf("FetchNonLiveOdds error: %v", err)
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for _, job := range schedule {
|
||||||
for _, job := range schedule {
|
job.task()
|
||||||
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
if _, err := c.AddFunc(job.spec, job.task); err != nil {
|
||||||
log.Fatalf("Failed to schedule cron job: %v", err)
|
log.Fatalf("Failed to schedule cron job: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Start()
|
c.Start()
|
||||||
log.Println("Cron jobs started for event and odds services")
|
log.Println("Cron jobs started for event and odds services")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,21 +22,22 @@ import (
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /prematch/odds/{event_id} [get]
|
// @Router /prematch/odds/{event_id} [get]
|
||||||
func GetPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
func GetPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
eventID := c.Params("event_id")
|
eventID := c.Params("event_id")
|
||||||
if eventID == "" {
|
if eventID == "" {
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing event_id", nil, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing event_id", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
odds, err := prematchSvc.GetPrematchOdds(c.Context(), eventID)
|
odds, err := prematchSvc.GetPrematchOdds(c.Context(), eventID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve odds", nil, nil)
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve odds", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//GetALLPrematchOdds
|
|
||||||
|
// GetALLPrematchOdds
|
||||||
// @Summary Retrieve all prematch odds
|
// @Summary Retrieve all prematch odds
|
||||||
// @Description Retrieve all prematch odds from the database
|
// @Description Retrieve all prematch odds from the database
|
||||||
// @Tags prematch
|
// @Tags prematch
|
||||||
|
|
@ -46,41 +47,48 @@ func GetPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.H
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /prematch/odds [get]
|
// @Router /prematch/odds [get]
|
||||||
func GetALLPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
func GetALLPrematchOdds(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
odds, err := prematchSvc.GetALLPrematchOdds(c.Context())
|
odds, err := prematchSvc.GetALLPrematchOdds(c.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRawOddsByMarketID
|
// GetRawOddsByMarketID
|
||||||
// @Summary Retrieve raw odds by Market ID
|
// @Summary Retrieve raw odds by Market ID
|
||||||
// @Description Retrieve raw odds records using a Market ID
|
// @Description Retrieve raw odds records using a Market ID
|
||||||
// @Tags prematch
|
// @Tags prematch
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Param upcoming_id path string true "Upcoming ID"
|
||||||
// @Param market_id path string true "Market ID"
|
// @Param market_id path string true "Market ID"
|
||||||
// @Success 200 {array} domain.RawOddsByMarketID
|
// @Success 200 {array} domain.RawOddsByMarketID
|
||||||
// @Failure 400 {object} response.APIResponse
|
// @Failure 400 {object} response.APIResponse
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /prematch/odds/raw/{market_id} [get]
|
// @Router /prematch/odds/upcoming/{upcoming_id}/market/{market_id} [get]
|
||||||
func GetRawOddsByMarketID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
func GetRawOddsByMarketID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
marketID := c.Params("market_id")
|
marketID := c.Params("market_id")
|
||||||
if marketID == "" {
|
upcomingID := c.Params("upcoming_id")
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
|
if marketID == "" {
|
||||||
}
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
rawOdds, err := prematchSvc.GetRawOddsByMarketID(c.Context(), marketID)
|
if upcomingID == "" {
|
||||||
if err != nil {
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
||||||
logger.Error("failed to fetch raw odds", "error", err)
|
}
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
|
rawOdds, err := prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
|
||||||
}
|
if err != nil {
|
||||||
|
logger.Error("failed to fetch raw odds", "error", err)
|
||||||
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Retrieve all upcoming events
|
// @Summary Retrieve all upcoming events
|
||||||
|
|
@ -92,15 +100,16 @@ func GetRawOddsByMarketID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fi
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /prematch/events [get]
|
// @Router /prematch/events [get]
|
||||||
func GetAllUpcomingEvents(logger *slog.Logger, eventSvc event.Service) fiber.Handler {
|
func GetAllUpcomingEvents(logger *slog.Logger, eventSvc event.Service) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
events, err := eventSvc.GetAllUpcomingEvents(c.Context())
|
events, err := eventSvc.GetAllUpcomingEvents(c.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Retrieve an upcoming by ID
|
// @Summary Retrieve an upcoming by ID
|
||||||
// @Description Retrieve an upcoming event by ID
|
// @Description Retrieve an upcoming event by ID
|
||||||
// @Tags prematch
|
// @Tags prematch
|
||||||
|
|
@ -112,20 +121,21 @@ func GetAllUpcomingEvents(logger *slog.Logger, eventSvc event.Service) fiber.Han
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /prematch/events/{id} [get]
|
// @Router /prematch/events/{id} [get]
|
||||||
func GetUpcomingEventByID(logger *slog.Logger, eventSvc event.Service) fiber.Handler {
|
func GetUpcomingEventByID(logger *slog.Logger, eventSvc event.Service) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
id := c.Params("id")
|
id := c.Params("id")
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing id", nil, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing id", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
event, err := eventSvc.GetUpcomingEventByID(c.Context(), id)
|
event, err := eventSvc.GetUpcomingEventByID(c.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve upcoming event", nil, nil)
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve upcoming event", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Retrieve prematch odds by upcoming ID (FI)
|
// @Summary Retrieve prematch odds by upcoming ID (FI)
|
||||||
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
|
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
|
||||||
// @Tags prematch
|
// @Tags prematch
|
||||||
|
|
@ -139,28 +149,27 @@ func GetUpcomingEventByID(logger *slog.Logger, eventSvc event.Service) fiber.Han
|
||||||
// @Failure 500 {object} response.APIResponse
|
// @Failure 500 {object} response.APIResponse
|
||||||
// @Router /prematch/odds/upcoming/{upcoming_id} [get]
|
// @Router /prematch/odds/upcoming/{upcoming_id} [get]
|
||||||
func GetPrematchOddsByUpcomingID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
func GetPrematchOddsByUpcomingID(logger *slog.Logger, prematchSvc *odds.ServiceImpl) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
upcomingID := c.Params("upcoming_id")
|
upcomingID := c.Params("upcoming_id")
|
||||||
if upcomingID == "" {
|
if upcomingID == "" {
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
|
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
|
||||||
if err != nil || limit <= 0 {
|
if err != nil || limit <= 0 {
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
|
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
|
||||||
if err != nil || offset < 0 {
|
if err != nil || offset < 0 {
|
||||||
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
odds, err := prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID, int32(limit), int32(offset))
|
odds, err := prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID, int32(limit), int32(offset))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
|
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func (a *App) initAppRoutes() {
|
||||||
|
|
||||||
a.fiber.Get("/prematch/odds/:event_id", handlers.GetPrematchOdds(a.logger, a.prematchSvc))
|
a.fiber.Get("/prematch/odds/:event_id", handlers.GetPrematchOdds(a.logger, a.prematchSvc))
|
||||||
a.fiber.Get("/prematch/odds", handlers.GetALLPrematchOdds(a.logger, a.prematchSvc))
|
a.fiber.Get("/prematch/odds", handlers.GetALLPrematchOdds(a.logger, a.prematchSvc))
|
||||||
a.fiber.Get("/prematch/odds/raw/:market_id", handlers.GetRawOddsByMarketID(a.logger, a.prematchSvc))
|
a.fiber.Get("/prematch/odds/upcoming/:upcoming_id/market/:market_id", handlers.GetRawOddsByMarketID(a.logger, a.prematchSvc))
|
||||||
|
|
||||||
a.fiber.Get("/prematch/events/:id", handlers.GetUpcomingEventByID(a.logger, a.eventSvc))
|
a.fiber.Get("/prematch/events/:id", handlers.GetUpcomingEventByID(a.logger, a.eventSvc))
|
||||||
a.fiber.Get("/prematch/events", handlers.GetAllUpcomingEvents(a.logger, a.eventSvc))
|
a.fiber.Get("/prematch/events", handlers.GetAllUpcomingEvents(a.logger, a.eventSvc))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user