Skip to content

Commit 5624b49

Browse files
committed
Use Steam HTTP API for app info
1 parent fea3e26 commit 5624b49

File tree

3 files changed

+101
-41
lines changed

3 files changed

+101
-41
lines changed

core/library_steam.gd

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ extends Library
66
# ~/.steam/steam/userdata/<user_id>/config/localconfig.vdf
77

88
const SteamClient := preload("res://plugins/steam/core/steam_client.gd")
9+
const SteamAPIClient := preload("res://plugins/steam/core/steam_api_client.gd")
910
const _apps_cache_file: String = "apps.json"
1011

1112
var thread_pool := load("res://core/systems/threading/thread_pool.tres") as ThreadPool
13+
var steam_api_client := SteamAPIClient.new()
1214

1315
@onready var steam: SteamClient = get_tree().get_first_node_in_group("steam_client")
1416

1517

1618
# Called when the node enters the scene tree for the first time.
1719
func _ready() -> void:
1820
super()
21+
add_child(steam_api_client)
1922
logger = Log.get_logger("Steam", Log.LEVEL.DEBUG)
2023
logger.info("Steam Library loaded")
2124
steam.logged_in.connect(_on_logged_in)
@@ -131,7 +134,8 @@ func _on_logged_in(status: SteamClient.LOGIN_STATUS):
131134
if not LibraryManager.has_app(item.name):
132135
var msg := "App {0} was not loaded. Adding item".format([item.name])
133136
logger.info(msg)
134-
LibraryManager.add_library_launch_item(library_id, item)
137+
launch_item_added.emit(item)
138+
#LibraryManager.add_library_launch_item(library_id, item)
135139
# TODO: Update installed status
136140

137141
# TODO: Remove library items that have been deleted
@@ -168,9 +172,10 @@ func _load_library(
168172
return []
169173

170174
logger.info("Fetching Steam library...")
175+
171176
# Get all available apps
172-
var app_ids: PackedInt64Array = await _get_available_apps()
173-
var app_info: Dictionary = await _get_games_from_app_info(app_ids)
177+
var app_ids: PackedInt64Array = await get_available_apps()
178+
var app_info: Dictionary = await get_apps_info(app_ids)
174179
var apps_installed: Array = await steam.get_installed_apps()
175180
var app_ids_installed := PackedStringArray()
176181
for app in apps_installed:
@@ -179,13 +184,11 @@ func _load_library(
179184
# Generate launch items for each game
180185
var items := [] as Array[LibraryLaunchItem]
181186
for app_id in app_info.keys():
182-
var item: LibraryLaunchItem = LibraryLaunchItem.new()
183-
item.provider_app_id = "{0}".format([app_id])
184-
item.name = app_info[app_id]
185-
item.command = "steam"
186-
item.args = ["-gamepadui", "-steamos3", "-steampal", "-steamdeck", "-silent", "steam://rungameid/" + item.provider_app_id]
187-
item.tags = ["steam"]
188-
item.installed = app_id in app_ids_installed
187+
var info := app_info[app_id] as Dictionary
188+
var item := _app_info_to_launch_item(info, app_id in app_ids_installed)
189+
if not item:
190+
logger.debug("Unable to create launch item for: " + app_id)
191+
continue
189192
items.append(item)
190193

191194
# Cache the discovered apps
@@ -202,65 +205,89 @@ func _load_library(
202205

203206

204207
# Returns an array of available steamAppIds
205-
func _get_available_apps() -> Array:
208+
func get_available_apps() -> Array:
206209
var app_ids = await steam.get_available_apps()
207210
return app_ids
208211

209212

210-
# Returns the app status for the given app ids
211-
func _get_app_status(app_ids: Array) -> Dictionary:
212-
var app_status := {}
213-
for app_id in app_ids:
214-
var id := str(app_id)
215-
var status := await steam.get_app_status(app_id)
216-
app_status[app_id] = status
217-
return app_status
218-
219-
220-
# Returns the app information for the given app ids
221-
func _get_games_from_app_info(app_ids: Array, caching_flags: int = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE) -> Dictionary:
213+
## Returns the app information for the given app ids. This is returned as a
214+
## dictionary where the key is the app ID, and the value is the app info.
215+
func get_apps_info(app_ids: Array, caching_flags: int = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE) -> Dictionary:
222216
var app_info := {}
223217
for app_id in app_ids:
224218
var id := str(app_id)
225-
var info := await _get_app_info(id, caching_flags)
219+
var info := await get_app_info(id, caching_flags)
226220

227221
if not id in info:
228222
continue
229-
if not "common" in info[id]:
230-
continue
231-
if not "type" in info[id]["common"]:
232-
continue
233-
if info[id]["common"]["type"] != "Game": # Skip non-games
234-
continue
235-
if not "name" in info[id]["common"]:
236-
continue
237-
app_info[id] = info[id]["common"]["name"]
223+
224+
app_info[id] = info
238225

239226
return app_info
240227

241228

242229
## Returns the app info dictionary parsed from the VDF
243-
func _get_app_info(app_id: String, caching_flags: int = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE) -> Dictionary:
230+
func get_app_info(app_id: String, caching_flags: int = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE) -> Dictionary:
244231
# Load the app info from cache if requested
245232
var cache_key := app_id + ".app_info"
246233
if caching_flags & Cache.FLAGS.LOAD and Cache.is_cached(_cache_dir, cache_key):
247234
return Cache.get_json(_cache_dir, cache_key)
248235
else:
249-
var info := await steam.get_app_info(app_id)
236+
var info = await steam_api_client.get_app_details(app_id)
237+
logger.debug("Found app info for " + app_id + ": " + str(info))
238+
if info == null:
239+
return {}
250240
if caching_flags & Cache.FLAGS.SAVE:
251241
Cache.save_json(_cache_dir, cache_key, info)
252242
return info
253243

254244

245+
## Builds a library launch item from the given Steam app information from the store API.
246+
func _app_info_to_launch_item(info: Dictionary, is_installed: bool) -> LibraryLaunchItem:
247+
if info.size() == 0:
248+
return null
249+
250+
var app_id := info.keys()[0] as String
251+
var details := info[app_id] as Dictionary
252+
if not "data" in details:
253+
return null
254+
var data := details["data"] as Dictionary
255+
if not "type" in data:
256+
return null
257+
if not data["type"] == "game":
258+
return null
259+
var categories := PackedStringArray()
260+
if "categories" in data:
261+
for category in data["categories"]:
262+
categories.append(category["description"])
263+
var tags := PackedStringArray()
264+
if "genres" in data:
265+
for genre in data["genres"]:
266+
tags.append((genre["description"] as String).to_lower())
267+
268+
var item := LibraryLaunchItem.new()
269+
item.provider_app_id = app_id
270+
item.name = data["name"]
271+
item.command = "steam"
272+
item.args = ["-gamepadui", "-steamos3", "-steampal", "-steamdeck", "-silent", "steam://rungameid/" + app_id]
273+
item.categories = categories
274+
item.tags = ["steam"]
275+
item.tags.append_array(tags)
276+
item.installed = is_installed
277+
278+
return item
279+
280+
255281
# Returns whether or not the given app id has a Linux binary
256282
func _app_supports_linux(app_id: String) -> bool:
257-
var info := await _get_app_info(app_id)
283+
var info = await steam_api_client.get_app_details(app_id)
258284
if not app_id in info:
259285
return false
260-
if not "common" in info[app_id]:
286+
if not "data" in info[app_id]:
287+
return false
288+
if not "platform" in info[app_id]["data"]:
261289
return false
262-
if not "oslist" in info[app_id]["common"]:
290+
if not "linux" in info[app_id]["data"]["platform"]:
263291
return false
264-
var os_list := info[app_id]["common"]["oslist"].split(",") as Array
265292

266-
return "linux" in os_list
293+
return info[app_id]["data"]["platform"]["linux"]

core/steam_api_client.gd

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
extends HTTPAPIClient
2+
3+
## Steam HTTP API Client
4+
##
5+
## HTTP API client for interacting with the Steam API.
6+
## Reference: https://wiki.teamfortress.com/wiki/User:RJackson/StorefrontAPI
7+
8+
9+
func _init() -> void:
10+
logger = Log.get_logger("SteamAPIClient")
11+
12+
13+
# Called when the node enters the scene tree for the first time.
14+
func _ready() -> void:
15+
base_url = "https://store.steampowered.com"
16+
17+
18+
## Returns the app details as a Dictionary with the given app id.
19+
## E.g.
20+
## {
21+
## "367520": {
22+
## "success": true,
23+
## "data": {
24+
## "type": "game",
25+
## "name": "Hollow Knight",
26+
## "steam_appid": 367520,
27+
## ...
28+
func get_app_details(app_id: String) -> Variant:
29+
var url := "/api/appdetails?appids={0}".format([app_id])
30+
var response := await request(url)
31+
if response.code != 200:
32+
return null
33+
return response.get_json()

plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"plugin.id": "steam",
33
"plugin.name": "Steam",
4-
"plugin.version": "1.0.6",
4+
"plugin.version": "1.0.8",
55
"plugin.min-api-version": "1.0.0",
66
"plugin.link": "https://github.com/ShadowBlip/OpenGamepadUI-steam",
77
"plugin.source": "https://github.com/ShadowBlip/OpenGamepadUI-steam",

0 commit comments

Comments
 (0)