Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
MBetterc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Mbetter
MBetterc
Commits
6e4ccd92
Commit
6e4ccd92
authored
Feb 01, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update new bet pages to manage cross data
parent
4e7a7dde
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
112 additions
and
6 deletions
+112
-6
client.py
mbetterclient/api_client/client.py
+63
-6
games_thread.py
mbetterclient/core/games_thread.py
+32
-0
message_bus.py
mbetterclient/core/message_bus.py
+1
-0
admin_new_bet.html
...ient/web_dashboard/templates/dashboard/admin_new_bet.html
+8
-0
new_bet.html
mbetterclient/web_dashboard/templates/dashboard/new_bet.html
+8
-0
No files found.
mbetterclient/api_client/client.py
View file @
6e4ccd92
...
@@ -980,6 +980,7 @@ class APIClient(ThreadedComponent):
...
@@ -980,6 +980,7 @@ class APIClient(ThreadedComponent):
# Subscribe to messages
# Subscribe to messages
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
CONFIG_UPDATE
,
self
.
_handle_config_update
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
CONFIG_UPDATE
,
self
.
_handle_config_update
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
API_REQUEST
,
self
.
_handle_api_request
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
API_REQUEST
,
self
.
_handle_api_request
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
FORCE_API_UPDATE
,
self
.
_handle_force_api_update
)
# Validate existing fixtures on startup
# Validate existing fixtures on startup
updates_handler
=
self
.
response_handlers
.
get
(
'updates'
)
updates_handler
=
self
.
response_handlers
.
get
(
'updates'
)
...
@@ -1256,6 +1257,14 @@ class APIClient(ThreadedComponent):
...
@@ -1256,6 +1257,14 @@ class APIClient(ThreadedComponent):
# For FastAPI /api/updates endpoint, add 'from' parameter and rustdesk_id if provided
# For FastAPI /api/updates endpoint, add 'from' parameter and rustdesk_id if provided
if
endpoint
.
name
==
'fastapi_main'
and
'updates'
in
endpoint
.
url
.
lower
():
if
endpoint
.
name
==
'fastapi_main'
and
'updates'
in
endpoint
.
url
.
lower
():
# Check if forced timestamp is requested (for empty templates table scenario)
force_timestamp
=
getattr
(
endpoint
,
'force_timestamp'
,
False
)
if
force_timestamp
:
# Force timestamp to 0 to download latest fixture from server
request_data
[
'from'
]
=
'0'
logger
.
debug
(
"Forcing timestamp to 0 to download latest fixture from server"
)
else
:
last_timestamp
=
self
.
_get_last_fixture_timestamp
()
last_timestamp
=
self
.
_get_last_fixture_timestamp
()
if
last_timestamp
:
if
last_timestamp
:
request_data
[
'from'
]
=
last_timestamp
request_data
[
'from'
]
=
last_timestamp
...
@@ -1528,6 +1537,8 @@ class APIClient(ThreadedComponent):
...
@@ -1528,6 +1537,8 @@ class APIClient(ThreadedComponent):
self
.
_handle_config_update
(
message
)
self
.
_handle_config_update
(
message
)
elif
message
.
type
==
MessageType
.
API_REQUEST
:
elif
message
.
type
==
MessageType
.
API_REQUEST
:
self
.
_handle_api_request
(
message
)
self
.
_handle_api_request
(
message
)
elif
message
.
type
==
MessageType
.
FORCE_API_UPDATE
:
self
.
_handle_force_api_update
(
message
)
# Add other message types as needed
# Add other message types as needed
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Failed to process message: {e}"
)
logger
.
error
(
f
"Failed to process message: {e}"
)
...
@@ -1766,6 +1777,52 @@ class APIClient(ThreadedComponent):
...
@@ -1766,6 +1777,52 @@ class APIClient(ThreadedComponent):
except
Exception
as
e
:
except
Exception
as
e
:
logger
.
error
(
f
"Failed to handle API request: {e}"
)
logger
.
error
(
f
"Failed to handle API request: {e}"
)
def
_handle_force_api_update
(
self
,
message
:
Message
):
"""Handle forced API update request from games thread"""
try
:
logger
.
info
(
"Received forced API update request: {}"
.
format
(
message
.
data
))
force_timestamp
=
message
.
data
.
get
(
"force_timestamp"
,
False
)
reason
=
message
.
data
.
get
(
"reason"
,
"unknown"
)
logger
.
info
(
"Forced API update triggered - reason: {}, force_timestamp: {}"
.
format
(
reason
,
force_timestamp
))
# Get fastapi_main endpoint
fastapi_endpoint
=
self
.
endpoints
.
get
(
'fastapi_main'
)
if
fastapi_endpoint
:
# Reset last_request to trigger immediate execution
fastapi_endpoint
.
last_request
=
None
# Store force_timestamp flag for use in request
fastapi_endpoint
.
force_timestamp
=
force_timestamp
# Execute immediate request
logger
.
info
(
"Executing immediate forced API update to synchronize match templates"
)
self
.
_execute_endpoint_request
(
fastapi_endpoint
)
# Clear the force_timestamp flag after execution
if
hasattr
(
fastapi_endpoint
,
'force_timestamp'
):
delattr
(
fastapi_endpoint
,
'force_timestamp'
)
logger
.
info
(
"Forced API update completed successfully"
)
# Send response back to games thread
response_message
=
Message
(
type
=
MessageType
.
FORCE_API_UPDATE
,
sender
=
self
.
name
,
recipient
=
message
.
sender
,
data
=
{
"status"
:
"completed"
,
"reason"
:
reason
,
"timestamp"
:
datetime
.
utcnow
()
.
isoformat
()
}
)
self
.
message_bus
.
publish
(
response_message
)
else
:
logger
.
error
(
"fastapi_main endpoint not found - cannot execute forced API update"
)
except
Exception
as
e
:
logger
.
error
(
"Failed to handle forced API update: {}"
.
format
(
e
))
def
get_endpoint_status
(
self
,
endpoint_name
:
str
)
->
Optional
[
Dict
[
str
,
Any
]]:
def
get_endpoint_status
(
self
,
endpoint_name
:
str
)
->
Optional
[
Dict
[
str
,
Any
]]:
"""Get status of a specific endpoint"""
"""Get status of a specific endpoint"""
endpoint
=
self
.
endpoints
.
get
(
endpoint_name
)
endpoint
=
self
.
endpoints
.
get
(
endpoint_name
)
...
...
mbetterclient/core/games_thread.py
View file @
6e4ccd92
...
@@ -349,6 +349,7 @@ class GamesThread(ThreadedComponent):
...
@@ -349,6 +349,7 @@ class GamesThread(ThreadedComponent):
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
MATCH_DONE
,
self
.
_handle_match_done
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
MATCH_DONE
,
self
.
_handle_match_done
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
GAME_STATUS
,
self
.
_handle_game_status_request
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
GAME_STATUS
,
self
.
_handle_game_status_request
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
SYSTEM_STATUS
,
self
.
_handle_system_status
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
SYSTEM_STATUS
,
self
.
_handle_system_status
)
self
.
message_bus
.
subscribe
(
self
.
name
,
MessageType
.
FORCE_API_UPDATE
,
self
.
_handle_force_api_update
)
# Send ready status
# Send ready status
ready_message
=
MessageBuilder
.
system_status
(
ready_message
=
MessageBuilder
.
system_status
(
...
@@ -4313,6 +4314,12 @@ class GamesThread(ThreadedComponent):
...
@@ -4313,6 +4314,12 @@ class GamesThread(ThreadedComponent):
if
len
(
match_templates
)
<
count
:
if
len
(
match_templates
)
<
count
:
logger
.
warning
(
f
"Only {len(match_templates)} validated match templates found, requested {count}"
)
logger
.
warning
(
f
"Only {len(match_templates)} validated match templates found, requested {count}"
)
# If templates table is completely empty, trigger forced API update
if
len
(
match_templates
)
==
0
:
logger
.
warning
(
"Match templates table is empty - triggering forced API update to synchronize with server"
)
self
.
_trigger_forced_api_update
()
return
match_templates
return
match_templates
# Select random templates
# Select random templates
...
@@ -4325,6 +4332,31 @@ class GamesThread(ThreadedComponent):
...
@@ -4325,6 +4332,31 @@ class GamesThread(ThreadedComponent):
logger
.
error
(
f
"Failed to select random match templates: {e}"
)
logger
.
error
(
f
"Failed to select random match templates: {e}"
)
return
[]
return
[]
def
_trigger_forced_api_update
(
self
):
"""Trigger forced API update to synchronize templates with server"""
try
:
logger
.
info
(
"Triggering forced API update to synchronize match templates"
)
force_update_message
=
Message
(
type
=
MessageType
.
FORCE_API_UPDATE
,
sender
=
self
.
name
,
recipient
=
"api_client"
,
data
=
{
"force_timestamp"
:
True
,
# Force timestamp to ensure latest fixture
"reason"
:
"empty_templates_table"
}
)
self
.
message_bus
.
publish
(
force_update_message
)
except
Exception
as
e
:
logger
.
error
(
f
"Failed to trigger forced API update: {e}"
)
def
_handle_force_api_update
(
self
,
message
:
Message
):
"""Handle FORCE_API_UPDATE response from API client"""
try
:
logger
.
info
(
f
"Received FORCE_API_UPDATE response: {message.data}"
)
# Could trigger retry of START_GAME if needed
except
Exception
as
e
:
logger
.
error
(
f
"Failed to handle FORCE_API_UPDATE response: {e}"
)
def
_get_available_matches_excluding_recent
(
self
,
fixture_id
:
Optional
[
str
],
exclude_last_n
:
int
,
fighters_only
:
bool
,
session
)
->
List
[
MatchModel
]:
def
_get_available_matches_excluding_recent
(
self
,
fixture_id
:
Optional
[
str
],
exclude_last_n
:
int
,
fighters_only
:
bool
,
session
)
->
List
[
MatchModel
]:
"""Get available matches excluding the last N recent matches in the fixture"""
"""Get available matches excluding the last N recent matches in the fixture"""
try
:
try
:
...
...
mbetterclient/core/message_bus.py
View file @
6e4ccd92
...
@@ -75,6 +75,7 @@ class MessageType(Enum):
...
@@ -75,6 +75,7 @@ class MessageType(Enum):
NEXT_MATCH
=
"NEXT_MATCH"
NEXT_MATCH
=
"NEXT_MATCH"
GAME_STATUS
=
"GAME_STATUS"
GAME_STATUS
=
"GAME_STATUS"
GAME_UPDATE
=
"GAME_UPDATE"
GAME_UPDATE
=
"GAME_UPDATE"
FORCE_API_UPDATE
=
"FORCE_API_UPDATE"
# Custom messages (for future extensions)
# Custom messages (for future extensions)
CUSTOM
=
"CUSTOM"
CUSTOM
=
"CUSTOM"
...
...
mbetterclient/web_dashboard/templates/dashboard/admin_new_bet.html
View file @
6e4ccd92
...
@@ -713,6 +713,14 @@ function updateAvailableMatchesDisplay(data, container) {
...
@@ -713,6 +713,14 @@ function updateAvailableMatchesDisplay(data, container) {
// Add event listeners for amount inputs only
// Add event listeners for amount inputs only
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
input
=>
{
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
input
=>
{
input
.
addEventListener
(
'input'
,
function
()
{
input
.
addEventListener
(
'input'
,
function
()
{
// Clear ALL other outcomes from ALL matches when entering an amount
// This ensures only ONE match and ONE outcome per bet
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
otherInput
=>
{
if
(
otherInput
!==
this
)
{
otherInput
.
value
=
''
;
}
});
updateBetSummary
();
updateBetSummary
();
});
});
});
});
...
...
mbetterclient/web_dashboard/templates/dashboard/new_bet.html
View file @
6e4ccd92
...
@@ -716,6 +716,14 @@ function updateAvailableMatchesDisplay(data, container) {
...
@@ -716,6 +716,14 @@ function updateAvailableMatchesDisplay(data, container) {
// Add event listeners for amount inputs only
// Add event listeners for amount inputs only
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
input
=>
{
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
input
=>
{
input
.
addEventListener
(
'input'
,
function
()
{
input
.
addEventListener
(
'input'
,
function
()
{
// Clear ALL other outcomes from ALL matches when entering an amount
// This ensures only ONE match and ONE outcome per bet
container
.
querySelectorAll
(
'.amount-input'
).
forEach
(
otherInput
=>
{
if
(
otherInput
!==
this
)
{
otherInput
.
value
=
''
;
}
});
updateBetSummary
();
updateBetSummary
();
});
});
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment