From 4f281ef7cc64b1d88163ce3a6785f292f8d352e6 Mon Sep 17 00:00:00 2001 From: Palapeli <26661008+mkwcat@users.noreply.github.com> Date: Wed, 1 Apr 2026 06:29:07 -0400 Subject: [PATCH] SAKE: Fix CreateRecord response --- database/sake.go | 13 ++++++++----- sake/storage.go | 50 +++++++++++++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/database/sake.go b/database/sake.go index b42ffaf..0efa096 100644 --- a/database/sake.go +++ b/database/sake.go @@ -47,6 +47,7 @@ const ( AND table_id = $2 AND (cardinality($4::integer[]) = 0 OR record_id = ANY($4::integer[])) AND (cardinality($3::integer[]) = 0 OR owner_id = ANY($3::integer[]))` + updateSakeRecordQuery = ` UPDATE sake_records SET @@ -56,9 +57,11 @@ const ( AND table_id = $2 AND record_id = $3 RETURNING owner_id` + insertSakeRecordQuery = ` INSERT INTO sake_records (game_id, table_id, owner_id, fields) - VALUES ($1, $2, $3, $4)` + VALUES ($1, $2, $3, $4) + RETURNING record_id` ) var ( @@ -152,14 +155,14 @@ func UpdateSakeRecord(pool *pgxpool.Pool, ctx context.Context, record SakeRecord return nil } -func InsertSakeRecord(pool *pgxpool.Pool, ctx context.Context, record SakeRecord) error { +func InsertSakeRecord(pool *pgxpool.Pool, ctx context.Context, record SakeRecord) (recordId int32, err error) { fieldsJson, err := json.Marshal(record.Fields) if err != nil { - return err + return 0, err } for i := 0; i < 10; i++ { - _, err = pool.Exec(ctx, insertSakeRecordQuery, record.GameId, record.TableId, record.OwnerId, fieldsJson) + err = pool.QueryRow(ctx, insertSakeRecordQuery, record.GameId, record.TableId, record.OwnerId, fieldsJson).Scan(&recordId) if err == nil { break } @@ -172,5 +175,5 @@ func InsertSakeRecord(pool *pgxpool.Pool, ctx context.Context, record SakeRecord } // Retry if unique violation occurred, as the record ID is generated randomly } - return nil + return recordId, err } diff --git a/sake/storage.go b/sake/storage.go index 9ee4099..37d3ffb 100644 --- a/sake/storage.go +++ b/sake/storage.go @@ -105,16 +105,12 @@ type StorageResponseEnvelope struct { } type StorageResponseBody struct { - GetMyRecordsResponse *StorageGetMyRecordsResponse `xml:"http://gamespy.net/sake GetMyRecordsResponse"` + CreateRecordResponse *StorageCreateRecordResponse `xml:"http://gamespy.net/sake CreateRecordResponse"` UpdateRecordResponse *StorageUpdateRecordResponse `xml:"http://gamespy.net/sake UpdateRecordResponse"` + GetMyRecordsResponse *StorageGetMyRecordsResponse `xml:"http://gamespy.net/sake GetMyRecordsResponse"` SearchForRecordsResponse *StorageSearchForRecordsResponse `xml:"http://gamespy.net/sake SearchForRecordsResponse"` } -type StorageGetMyRecordsResponse struct { - GetMyRecordsResult string - Values StorageResponseValues `xml:"values"` -} - type StorageResponseValues struct { ArrayOfRecordValue []StorageArrayOfRecordValue `xml:"ArrayOfRecordValue"` } @@ -123,10 +119,20 @@ type StorageArrayOfRecordValue struct { RecordValues []StorageRecordValue `xml:"RecordValue"` } +type StorageCreateRecordResponse struct { + CreateRecordResult string + RecordID int32 `xml:"recordid"` +} + type StorageUpdateRecordResponse struct { UpdateRecordResult string } +type StorageGetMyRecordsResponse struct { + GetMyRecordsResult string + Values StorageResponseValues `xml:"values"` +} + type StorageSearchForRecordsResponse struct { XMLName xml.Name SearchForRecordsResult string @@ -208,6 +214,8 @@ func handleStorageRequest(moduleName string, w http.ResponseWriter, r *http.Requ panic(err) } + logging.Info(moduleName, "Responding with body:", aurora.Cyan(string(out))) + payload := append([]byte(xml.Header), out...) w.Header().Set("Content-Type", "text/xml") @@ -250,7 +258,7 @@ func getInputFields(moduleName string, request StorageRequestData) (map[string]d logging.Error(moduleName, "Invalid field type tag:", aurora.Cyan(field.Value.Value.XMLName.Local)) return nil, ResultFieldTypeInvalid } - if field.Name == "ownerid" || field.Name == "recordid" { + if field.Name == "ownerid" || field.Name == "recordid" || field.Name == "gameid" || field.Name == "tableid" { logging.Error(moduleName, "Attempt to set reserved field:", aurora.Cyan(field.Name)) return nil, ResultNoPermission } @@ -262,15 +270,15 @@ func getInputFields(moduleName string, request StorageRequestData) (map[string]d func createRecord(moduleName string, profileId uint32, gameInfo common.GameInfo, request StorageRequestData) StorageResponseBody { if request.TableID == "" { logging.Error(moduleName, "No table ID provided") - return StorageResponseBody{UpdateRecordResponse: &StorageUpdateRecordResponse{ - UpdateRecordResult: ResultTableNotFound, + return StorageResponseBody{CreateRecordResponse: &StorageCreateRecordResponse{ + CreateRecordResult: ResultTableNotFound, }} } if gameInfo.Name == "mariokartwii" && (request.TableID == "GhostData" || request.TableID == "StoredGhostData") { // Reserved for special handler - return StorageResponseBody{UpdateRecordResponse: &StorageUpdateRecordResponse{ - UpdateRecordResult: ResultTableNotFound, + return StorageResponseBody{CreateRecordResponse: &StorageCreateRecordResponse{ + CreateRecordResult: ResultTableNotFound, }} } @@ -278,8 +286,8 @@ func createRecord(moduleName string, profileId uint32, gameInfo common.GameInfo, var result string record.Fields, result = getInputFields(moduleName, request) if result != ResultSuccess { - return StorageResponseBody{UpdateRecordResponse: &StorageUpdateRecordResponse{ - UpdateRecordResult: result, + return StorageResponseBody{CreateRecordResponse: &StorageCreateRecordResponse{ + CreateRecordResult: result, }} } @@ -289,17 +297,19 @@ func createRecord(moduleName string, profileId uint32, gameInfo common.GameInfo, record.OwnerId = int32(profileId) // TODO: Limit number of records or fields a user can have - err := database.InsertSakeRecord(pool, ctx, record) + recordId, err := database.InsertSakeRecord(pool, ctx, record) if err != nil { - return StorageResponseBody{UpdateRecordResponse: &StorageUpdateRecordResponse{ - UpdateRecordResult: ResultDatabaseUnavailable, + return StorageResponseBody{CreateRecordResponse: &StorageCreateRecordResponse{ + CreateRecordResult: ResultDatabaseUnavailable, }} } - return StorageResponseBody{UpdateRecordResponse: &StorageUpdateRecordResponse{ - UpdateRecordResult: ResultSuccess, - }} + logging.Info(moduleName, "Created record in table", aurora.Cyan(record.TableId), "with ID", aurora.Cyan(recordId), "for profile", aurora.Cyan(profileId)) + return StorageResponseBody{CreateRecordResponse: &StorageCreateRecordResponse{ + CreateRecordResult: ResultSuccess, + RecordID: recordId, + }} } func getMyRecords(moduleName string, profileId uint32, gameInfo common.GameInfo, request StorageRequestData) StorageResponseBody { @@ -474,7 +484,7 @@ func searchForRecords(moduleName string, profileId uint32, gameInfo common.GameI SearchForRecordsResult: "Success", Values: fillResponseValues(records, request), } - logging.Info(moduleName, "Searched for records in table", aurora.Cyan(request.TableID), "for profile", aurora.Cyan(profileId), "with filter", aurora.Cyan(request.Filter), "and got", aurora.Cyan(len(records)), "records") + logging.Info(moduleName, "Found", aurora.Cyan(len(records)), "records in table", aurora.Cyan(request.TableID), "for profile", aurora.Cyan(profileId), "with filter", aurora.Cyan(request.Filter)) return StorageResponseBody{SearchForRecordsResponse: &response} }