Fix race condition exception by checking badge key exists

Enabling disk_cache can lead to an exception (invalid_index)
when changing channel:

Invalid get index 'badge_sets' (on base 'Dictionary').
(gift_node.gd:525)

We short-circuit the get_badge_mapping (and also, as a side
effect, we lower the ciclomatic complexity of the method) so
that when there is a missing key the right thing happens.

This way we "return early" in the three cases: if it is cached
on memory, if it is cached on disk, or if we have to retrieve
it from Twitch/HTTPS.

Fixes #25
This commit is contained in:
Jaime Crespo 2023-08-19 13:31:19 +02:00
parent 7751bbf853
commit 554e32495e

View File

@ -519,32 +519,36 @@ func get_badge(badge_name : String, channel_id : String = "_global", scale : Str
return caches[RequestType.BADGE][channel_id][cachename] return caches[RequestType.BADGE][channel_id][cachename]
func get_badge_mapping(channel_id : String = "_global") -> Dictionary: func get_badge_mapping(channel_id : String = "_global") -> Dictionary:
if !caches[RequestType.BADGE_MAPPING].has(channel_id): if caches[RequestType.BADGE_MAPPING].has(channel_id):
var filename : String = disk_cache_path + "/" + RequestType.keys()[RequestType.BADGE_MAPPING] + "/" + channel_id + ".json" return caches[RequestType.BADGE_MAPPING][channel_id]
if (disk_cache && FileAccess.file_exists(filename)):
caches[RequestType.BADGE_MAPPING][channel_id] = JSON.parse_string(FileAccess.get_file_as_string(filename))["badge_sets"] var filename : String = disk_cache_path + "/" + RequestType.keys()[RequestType.BADGE_MAPPING] + "/" + channel_id + ".json"
else: if (disk_cache && FileAccess.file_exists(filename)):
var request : HTTPRequest = HTTPRequest.new() var cache = JSON.parse_string(FileAccess.get_file_as_string(filename))
add_child(request) if "badge_sets" in cache:
request.request("https://api.twitch.tv/helix/chat/badges" + ("/global" if channel_id == "_global" else "?broadcaster_id=" + channel_id), [USER_AGENT, "Authorization: Bearer " + token["access_token"], "Client-Id:" + client_id, "Content-Type: application/json"], HTTPClient.METHOD_GET) return cache["badge_sets"]
var reply : Array = await(request.request_completed)
var response : Dictionary = JSON.parse_string(reply[3].get_string_from_utf8()) var request : HTTPRequest = HTTPRequest.new()
var mappings : Dictionary = {} add_child(request)
for entry in response["data"]: request.request("https://api.twitch.tv/helix/chat/badges" + ("/global" if channel_id == "_global" else "?broadcaster_id=" + channel_id), [USER_AGENT, "Authorization: Bearer " + token["access_token"], "Client-Id:" + client_id, "Content-Type: application/json"], HTTPClient.METHOD_GET)
if (!mappings.has(entry["set_id"])): var reply : Array = await(request.request_completed)
mappings[entry["set_id"]] = {"versions": {}} var response : Dictionary = JSON.parse_string(reply[3].get_string_from_utf8())
for version in entry["versions"]: var mappings : Dictionary = {}
mappings[entry["set_id"]]["versions"][version["id"]] = version for entry in response["data"]:
request.queue_free() if (!mappings.has(entry["set_id"])):
if (reply[1] == HTTPClient.RESPONSE_OK): mappings[entry["set_id"]] = {"versions": {}}
caches[RequestType.BADGE_MAPPING][channel_id] = mappings for version in entry["versions"]:
if (disk_cache): mappings[entry["set_id"]]["versions"][version["id"]] = version
DirAccess.make_dir_recursive_absolute(filename.get_base_dir()) request.queue_free()
var file : FileAccess = FileAccess.open(filename, FileAccess.WRITE) if (reply[1] == HTTPClient.RESPONSE_OK):
file.store_string(JSON.stringify(mappings)) caches[RequestType.BADGE_MAPPING][channel_id] = mappings
else: if (disk_cache):
print("Could not retrieve badge mapping for channel_id " + channel_id + ".") DirAccess.make_dir_recursive_absolute(filename.get_base_dir())
return {} var file : FileAccess = FileAccess.open(filename, FileAccess.WRITE)
file.store_string(JSON.stringify(mappings))
else:
print("Could not retrieve badge mapping for channel_id " + channel_id + ".")
return {}
return caches[RequestType.BADGE_MAPPING][channel_id] return caches[RequestType.BADGE_MAPPING][channel_id]
func data_received(data : PackedByteArray) -> void: func data_received(data : PackedByteArray) -> void: