diff --git a/lib/games_info/itch_io_service.gd b/lib/games_info/itch_io_service.gd new file mode 100644 index 00000000..e5a1a1fb --- /dev/null +++ b/lib/games_info/itch_io_service.gd @@ -0,0 +1,86 @@ +@tool +@icon("res://UI/assets/font_awesome/itch-io.svg") +extends Node +class_name ItchIOService + +static var _log: TwitchLogger = TwitchLogger.new(&"ItchIOService") + +#region RegEx HTML Scrapping +static var _desc_re: RegEx = RegEx.create_from_string(r'(?s)
(.*?)<\/div>') +static var _div_re: RegEx = RegEx.create_from_string(r'(?s)
(.*?)<\/div>') +static var _ss_thumb_re: RegEx = RegEx.create_from_string(r']+src="([^"]+/\d+x\d+/[^"]+)"') +static var _ss_full_re: RegEx = RegEx.create_from_string(r']+href=\"([^"]+\/original\/[^"]+)"') +#endregion + +func get_itch_app_data(game_url: String) -> ItchIOAppData: + var http_request = HTTPRequest.new() + add_child(http_request) + + var base_url := game_url.strip_edges().rstrip("/") + var json_url := base_url + "/data.json" + + var err := http_request.request(json_url) + if err != OK: + _log.e("Error requesting Itch data: %s" % error_string(err)) + return null + + var json_result: Array = await http_request.request_completed + var _result: int = json_result[0] + var response_code: int = json_result[1] + var body: PackedByteArray = json_result[3] + + if response_code != HTTPClient.RESPONSE_OK: + _log.e("Failed to fetch Itch data.json. HTTP %s" % response_code) + return null + + var json = JSON.parse_string(body.get_string_from_utf8()) + if typeof(json) != TYPE_DICTIONARY: + _log.e("Invalid JSON from Itch") + return null + + err = http_request.request(base_url) + if err != OK: + _log.e("Error requesting Itch HTML: %s" % error_string(err)) + return ItchIOAppData.from_json(json) + + var html_result: Array = await http_request.request_completed + var html_code: int = html_result[1] + var html_body: PackedByteArray = html_result[3] + + if html_code == HTTPClient.RESPONSE_OK: + var html := html_body.get_string_from_utf8() + var extra_info: Dictionary = scrape_html(html) + json.merge(extra_info) + else: + _log.e("Could not retrieve HTML content. Skipping description/screenshot parsing.") + http_request.queue_free() + + return ItchIOAppData.from_json(json) + +func scrape_html(html: String) -> Dictionary: + var data := { + "description": "", + "screenshots_thumbnails": [], + "screenshots_full": [], + } + + var desc_match: RegExMatch = _desc_re.search(html) + if desc_match: + data["description"] = Util.convert_html_to_bbcode(desc_match.get_string(1)) + + var div_match := _div_re.search(html) + + if div_match: + var screenshot_block: String = div_match.get_string(1) + + var ss_thumb_matches: Array[RegExMatch] = _ss_thumb_re.search_all(screenshot_block) + + for s_match: RegExMatch in ss_thumb_matches: + data["screenshots_thumbnails"].append(s_match.get_string(1)) + + var ss_full_matches: Array[RegExMatch] = _ss_full_re.search_all(screenshot_block) + + for s_match: RegExMatch in ss_full_matches: + data["screenshots_full"].append(s_match.get_string(1)) + + return data diff --git a/lib/games_info/itch_io_service.gd.uid b/lib/games_info/itch_io_service.gd.uid new file mode 100644 index 00000000..5f50f2a7 --- /dev/null +++ b/lib/games_info/itch_io_service.gd.uid @@ -0,0 +1 @@ +uid://cyef5m8x5f7k6 diff --git a/lib/games_info/steam_service.gd b/lib/games_info/steam_service.gd new file mode 100644 index 00000000..5e4b7211 --- /dev/null +++ b/lib/games_info/steam_service.gd @@ -0,0 +1,44 @@ +@tool +@icon("res://UI/assets/font_awesome/steam.svg") +extends Node +class_name SteamService + +const STEAM_SERVICE_STORE_API_URL = "https://store.steampowered.com/api/" +const ENDPOINT_STORE_GET_APP_INFO = "appdetails?appids={appid}" + +static var _log: TwitchLogger = TwitchLogger.new(&"SteamService") + +func get_steam_app_data(app_id: int) -> SteamAppData: + var http_request = HTTPRequest.new() + add_child(http_request) + + var store_request_query: Dictionary = { + "appid": app_id, + } + var request_url: String = STEAM_SERVICE_STORE_API_URL + ENDPOINT_STORE_GET_APP_INFO + request_url = request_url.format(store_request_query) + var _err = http_request.request(request_url) + if _err != OK: + _log.e("Error: %s" % error_string(_err)) + return null + + var http_result: Array = await http_request.request_completed + var result: int = http_result[0] + var response_code: int = http_result[1] + var _headers: PackedStringArray = http_result[2] + var body: PackedByteArray = http_result[3] + _log.d("result: " + str(result)) + _log.d("response_code: " + str(response_code)) + + if response_code != HTTPClient.RESPONSE_OK: + _log.e("Request failed. Response code %s" % response_code) + return null + var response_json: Dictionary = JSON.parse_string(body.get_string_from_utf8()) + if not response_json.has(str(app_id)): + return null + if not response_json[str(app_id)].has("data"): + return null + var game_data: Dictionary = response_json[str(app_id)]["data"] + game_data["steam_app_id"] = game_data["steam_appid"] + http_request.queue_free() + return SteamAppData.from_json(game_data) diff --git a/lib/games_info/steam_service.gd.uid b/lib/games_info/steam_service.gd.uid new file mode 100644 index 00000000..868217e3 --- /dev/null +++ b/lib/games_info/steam_service.gd.uid @@ -0,0 +1 @@ +uid://chgufd1youdel