-
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
"""List all steam games and start them when selected""" | ||
import os | ||
import glob | ||
import struct | ||
import binascii | ||
import logging | ||
from lnxlink.modules.scripts.helpers import import_install_package, syscommand | ||
|
||
logger = logging.getLogger("lnxlink") | ||
|
||
|
||
class Addon: | ||
"""Addon module""" | ||
|
||
def __init__(self, lnxlink): | ||
"""Setup addon""" | ||
self.name = "Steam" | ||
self.lnxlink = lnxlink | ||
self._requirements() | ||
self.steam_config = self._find_libary_config() | ||
if self.steam_config is None: | ||
raise SystemError("Steam not found") | ||
self.games = {} | ||
self.games = self._get_games() | ||
|
||
def _requirements(self): | ||
self.vdf = import_install_package("vdf", ">=3.4") | ||
|
||
def exposed_controls(self): | ||
"""Exposes to home assistant""" | ||
mygames = list(self.games.values()) | ||
mygames.sort() | ||
discovery_info = { | ||
"Game Select": { | ||
"type": "select", | ||
"icon": "mdi:steam", | ||
"options": mygames, | ||
}, | ||
} | ||
return discovery_info | ||
|
||
def get_info(self): | ||
"""Gather information from the system""" | ||
games = self._get_games() | ||
if self.games != games: | ||
self.lnxlink.setup_discovery() | ||
self.games = games | ||
return self.games | ||
|
||
def start_control(self, topic, data): | ||
"""Control system""" | ||
try: | ||
position = list(self.games.values()).index(data) | ||
game_id = list(self.games.keys())[position] | ||
logger.info("running command: steam steam://rungameid/%s", game_id) | ||
syscommand(f"steam steam://rungameid/{game_id}") | ||
except ValueError: | ||
logger.error("Can't find selected game: %s", data) | ||
|
||
def _find_libary_config(self, level=4): | ||
"""Finds the library folders configuration from home directory | ||
with a max depth level""" | ||
home_dir = os.path.expanduser("~") | ||
num_sep = home_dir.count("/") | ||
name = "libraryfolders.vdf" | ||
for root, dirs, files in os.walk(home_dir): | ||
num_sep_this = root.count("/") | ||
if num_sep + level <= num_sep_this: | ||
del dirs[:] | ||
if name in files: | ||
return os.path.join(root, name) | ||
return None | ||
|
||
def _get_games(self): | ||
"""Gets a dictionary of the game_ids and their names""" | ||
with open(self.steam_config, encoding="UTF-8") as file: | ||
libraries = self.vdf.load(file) | ||
|
||
# Steam Games | ||
games = {} | ||
for num in libraries["libraryfolders"].values(): | ||
for app_id in num["apps"].keys(): | ||
if app_id not in self.games: | ||
acf_path = os.path.join( | ||
num["path"], f"steamapps/appmanifest_{app_id}.acf" | ||
) | ||
with open(acf_path, encoding="UTF-8") as file: | ||
game_properties = self.vdf.load(file) | ||
games[app_id] = game_properties["AppState"]["name"] | ||
else: | ||
games[app_id] = self.games[app_id] | ||
|
||
# Non-Steam Games | ||
shortcut_dirs = os.path.abspath( | ||
f"{self.steam_config}/../../userdata/*/config/shortcuts.vdf" | ||
) | ||
for shortcut_dir in glob.glob(shortcut_dirs): | ||
with open(shortcut_dir, "rb") as file: | ||
shortcuts_dict = self.vdf.binary_loads(file.read()) | ||
for shortcut in shortcuts_dict["shortcuts"].values(): | ||
# Convert to HEX | ||
bin_appid = struct.Struct("<i").pack(shortcut["appid"]) | ||
hex_appid = binascii.hexlify(bin_appid).decode("UTF-8") | ||
|
||
# Convert to long_appid | ||
reversed_hex = bytes.fromhex(hex_appid)[::-1].hex() | ||
app_id = int(reversed_hex, 16) << 32 | 0x02000000 | ||
games[app_id] = shortcut["AppName"] | ||
|
||
return games |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,4 +26,5 @@ pulsectl>=23.5.2 | |
pyalsaaudio>=0.9.2 | ||
pyamdgpuinfo>=2.1.4 | ||
python-xlib>=0.33 | ||
vdf>=3.4 | ||
xlib-hotkeys>=2024.3.0 |