Fix butlerd RPC -32700: normalize integral JSON floats to ints
Godot JSON.parse decodes every JSON number as a float, so integer ids (7670) round-trip through JSON.stringify as 7670.0, which Go's int64 fields reject with RPC error -32700. Normalize at the parse boundary so profile/game/upload ids serialize correctly. Also drop the nonexistent 'fresh' parameter from Fetch.ProfileOwnedKeys.
This commit is contained in:
parent
5d686a5b02
commit
408991a693
2 changed files with 33 additions and 7 deletions
|
|
@ -184,7 +184,7 @@ func _thread_process(_delta: float) -> void:
|
|||
var line: String = lines[i].strip_edges()
|
||||
if line == "":
|
||||
continue
|
||||
var parsed: Variant = JSON.parse_string(line)
|
||||
var parsed: Variant = _normalize_json(JSON.parse_string(line))
|
||||
if typeof(parsed) != TYPE_DICTIONARY:
|
||||
continue
|
||||
var msg: Dictionary = parsed
|
||||
|
|
@ -210,7 +210,7 @@ func _thread_process(_delta: float) -> void:
|
|||
_recv_buffer = _recv_buffer.substr(idx + 1)
|
||||
if line.strip_edges() == "":
|
||||
continue
|
||||
var parsed: Variant = JSON.parse_string(line)
|
||||
var parsed: Variant = _normalize_json(JSON.parse_string(line))
|
||||
if typeof(parsed) != TYPE_DICTIONARY:
|
||||
continue
|
||||
var msg: Dictionary = parsed
|
||||
|
|
@ -261,6 +261,33 @@ func _send_line(text: String) -> void:
|
|||
socket.put_data((text + "\n").to_utf8_buffer())
|
||||
|
||||
|
||||
## Godot's JSON.parse decodes every JSON number as a float (so 7670 becomes
|
||||
## 7670.0), and JSON.stringify then re-serializes it as "7670.0". butlerd's Go
|
||||
## structs use int64 for ids, and Go's encoding/json rejects "7670.0" for an
|
||||
## int64 field (RPC error -32700). Normalizing integral floats back to ints at
|
||||
## the parse boundary keeps every id (profileId, game.id, upload.id, ...)
|
||||
## typed correctly so downstream RPC params serialize without the trailing
|
||||
## ".0".
|
||||
func _normalize_json(value: Variant) -> Variant:
|
||||
match typeof(value):
|
||||
TYPE_DICTIONARY:
|
||||
var out := {}
|
||||
for key in value:
|
||||
out[key] = _normalize_json(value[key])
|
||||
return out
|
||||
TYPE_ARRAY:
|
||||
var out := []
|
||||
for item in value:
|
||||
out.append(_normalize_json(item))
|
||||
return out
|
||||
TYPE_FLOAT:
|
||||
if is_finite(value) and value == floor(value):
|
||||
return int(value)
|
||||
return value
|
||||
_:
|
||||
return value
|
||||
|
||||
|
||||
## Sends a JSON-RPC request and waits (via signal await, not a busy loop, so
|
||||
## [method _thread_process] keeps ticking and can deliver the response) for
|
||||
## the matching response. Mirrors the `_wait_for_command` pattern used by the
|
||||
|
|
@ -306,16 +333,15 @@ func _login_with_api_key(api_key: String) -> void:
|
|||
|
||||
## Returns every game the logged-in profile owns a download key for.
|
||||
## Each item looks like: {"downloadKey": {...}, "game": {...}}
|
||||
func get_owned_games(fresh: bool = false) -> Array:
|
||||
return await thread_group.exec(_get_owned_games.bind(fresh))
|
||||
func get_owned_games() -> Array:
|
||||
return await thread_group.exec(_get_owned_games)
|
||||
|
||||
|
||||
func _get_owned_games(fresh: bool) -> Array:
|
||||
func _get_owned_games() -> Array:
|
||||
if not is_logged_in:
|
||||
return []
|
||||
var res := await _rpc_call("Fetch.ProfileOwnedKeys", {
|
||||
"profileId": profile.get("user", {}).get("id", profile.get("id", 0)),
|
||||
"fresh": fresh,
|
||||
})
|
||||
if "error" in res:
|
||||
logger.warn("Fetch.ProfileOwnedKeys failed: " + str(res["error"]))
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ func _load_library(caching_flags: int = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE) ->
|
|||
return []
|
||||
|
||||
logger.info("Fetching itch.io library...")
|
||||
var owned: Array = await itch.get_owned_games(false)
|
||||
var owned: Array = await itch.get_owned_games()
|
||||
var caves: Array = await itch.get_caves()
|
||||
|
||||
var caves_by_game_id := {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue