Merge pull request #20 from Bananaman/launch_rework
Improved game executable launcher, and added argument validation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
/subprojects/blueprint-compiler
|
||||
/.flatpak
|
||||
/.flatpak-builder
|
||||
/.vscode
|
||||
@@ -95,7 +95,6 @@ def bottles_parser(parent_widget, action):
|
||||
|
||||
with open(os.path.join(bottles_dir, "library.yml"), "r") as open_file:
|
||||
data = open_file.read()
|
||||
open_file.close()
|
||||
|
||||
library = yaml.load(data, Loader=yaml.Loader)
|
||||
|
||||
@@ -112,9 +111,10 @@ def bottles_parser(parent_widget, action):
|
||||
continue
|
||||
|
||||
values["name"] = game["name"]
|
||||
values["executable"] = "xdg-open " + shlex.quote(
|
||||
values["executable"] = [
|
||||
"xdg-open",
|
||||
f'bottles:run/{game["bottle"]["name"]}/{game["name"]}'
|
||||
)
|
||||
]
|
||||
values["hidden"] = False
|
||||
values["source"] = "bottles"
|
||||
values["added"] = current_time
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import shlex
|
||||
import time
|
||||
|
||||
from gi.repository import Adw, GdkPixbuf, Gio, GLib, GObject, Gtk
|
||||
@@ -52,7 +53,7 @@ def create_details_window(parent_widget, game_id=None):
|
||||
)
|
||||
name = Gtk.Entry.new_with_buffer(Gtk.EntryBuffer.new(games[game_id].name, -1))
|
||||
executable = Gtk.Entry.new_with_buffer(
|
||||
Gtk.EntryBuffer.new((games[game_id].executable), -1)
|
||||
Gtk.EntryBuffer.new(shlex.join(games[game_id].executable), -1)
|
||||
)
|
||||
apply_button = Gtk.Button.new_with_label(_("Apply"))
|
||||
|
||||
@@ -201,6 +202,21 @@ def create_details_window(parent_widget, game_id=None):
|
||||
final_developer = developer.get_buffer().get_text()
|
||||
final_executable = executable.get_buffer().get_text()
|
||||
|
||||
try:
|
||||
# Attempt to parse using shell parsing rules (doesn't verify executable existence).
|
||||
final_executable_split = shlex.split(
|
||||
final_executable, comments=False, posix=True
|
||||
)
|
||||
except Exception as e:
|
||||
create_dialog(
|
||||
window,
|
||||
_("Couldn't Add Game")
|
||||
if game_id is None
|
||||
else _("Couldn't Apply Preferences"),
|
||||
f'{_("Executable")}: {e}.', # e = Shell parsing error message. Not translatable.
|
||||
)
|
||||
return
|
||||
|
||||
if game_id is None:
|
||||
if final_name == "":
|
||||
create_dialog(
|
||||
@@ -252,7 +268,7 @@ def create_details_window(parent_widget, game_id=None):
|
||||
|
||||
values["name"] = final_name
|
||||
values["developer"] = final_developer or None
|
||||
values["executable"] = final_executable
|
||||
values["executable"] = final_executable_split
|
||||
|
||||
path = os.path.join(
|
||||
os.path.join(
|
||||
@@ -267,7 +283,6 @@ def create_details_window(parent_widget, game_id=None):
|
||||
if os.path.exists(path):
|
||||
with open(path, "r") as open_file:
|
||||
data = json.loads(open_file.read())
|
||||
open_file.close()
|
||||
data.update(values)
|
||||
save_games({game_id: data})
|
||||
else:
|
||||
|
||||
@@ -41,6 +41,6 @@ def get_games(game_ids=None):
|
||||
for game in game_files:
|
||||
with open(os.path.join(games_dir, game), "r") as open_file:
|
||||
data = json.loads(open_file.read())
|
||||
open_file.close()
|
||||
games[data["game_id"]] = data
|
||||
games[data["game_id"]] = data
|
||||
|
||||
return games
|
||||
|
||||
@@ -107,7 +107,6 @@ def heroic_parser(parent_widget, action):
|
||||
os.path.join(heroic_dir, "lib-cache", "library.json"), "r"
|
||||
) as open_file:
|
||||
data = open_file.read()
|
||||
open_file.close()
|
||||
library = json.loads(data)
|
||||
|
||||
try:
|
||||
@@ -129,9 +128,9 @@ def heroic_parser(parent_widget, action):
|
||||
values["name"] = game["title"]
|
||||
values["developer"] = game["developer"]
|
||||
values["executable"] = (
|
||||
f"start heroic://launch/{app_name}"
|
||||
["start", f"heroic://launch/{app_name}"]
|
||||
if os.name == "nt"
|
||||
else f"xdg-open heroic://launch/{app_name}"
|
||||
else ["xdg-open", f"heroic://launch/{app_name}"]
|
||||
)
|
||||
values["hidden"] = False
|
||||
values["source"] = "heroic_epic"
|
||||
@@ -160,7 +159,6 @@ def heroic_parser(parent_widget, action):
|
||||
os.path.join(heroic_dir, "gog_store", "installed.json"), "r"
|
||||
) as open_file:
|
||||
data = open_file.read()
|
||||
open_file.close()
|
||||
installed = json.loads(data)
|
||||
for item in installed["installed"]:
|
||||
values = {}
|
||||
@@ -179,7 +177,6 @@ def heroic_parser(parent_widget, action):
|
||||
os.path.join(heroic_dir, "gog_store", "library.json"), "r"
|
||||
) as open_file:
|
||||
data = open_file.read()
|
||||
open_file.close()
|
||||
library = json.loads(data)
|
||||
for game in library["games"]:
|
||||
if game["app_name"] == app_name:
|
||||
@@ -195,9 +192,9 @@ def heroic_parser(parent_widget, action):
|
||||
break
|
||||
|
||||
values["executable"] = (
|
||||
f"start heroic://launch/{app_name}"
|
||||
["start", f"heroic://launch/{app_name}"]
|
||||
if os.name == "nt"
|
||||
else f"xdg-open heroic://launch/{app_name}"
|
||||
else ["xdg-open", f"heroic://launch/{app_name}"]
|
||||
)
|
||||
values["hidden"] = False
|
||||
values["source"] = "heroic_gog"
|
||||
@@ -214,7 +211,6 @@ def heroic_parser(parent_widget, action):
|
||||
os.path.join(heroic_dir, "sideload_apps", "library.json"), "r"
|
||||
) as open_file:
|
||||
data = open_file.read()
|
||||
open_file.close()
|
||||
library = json.loads(data)
|
||||
for item in library["games"]:
|
||||
values = {}
|
||||
@@ -230,9 +226,9 @@ def heroic_parser(parent_widget, action):
|
||||
|
||||
values["name"] = item["title"]
|
||||
values["executable"] = (
|
||||
f"start heroic://launch/{app_name}"
|
||||
["start", f"heroic://launch/{app_name}"]
|
||||
if os.name == "nt"
|
||||
else f"xdg-open heroic://launch/{app_name}"
|
||||
else ["xdg-open", f"heroic://launch/{app_name}"]
|
||||
)
|
||||
values["hidden"] = False
|
||||
values["source"] = "heroic_sideload"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -25,13 +26,14 @@ from gi.repository import Gio
|
||||
|
||||
|
||||
def run_command(executable):
|
||||
# The host environment vars are automatically passed through by Popen.
|
||||
subprocess.Popen(
|
||||
[f"flatpak-spawn --host {executable}"]
|
||||
["flatpak-spawn", "--host", *executable] # Flatpak
|
||||
if os.getenv("FLATPAK_ID") == "hu.kramo.Cartridges"
|
||||
else executable.split()
|
||||
else executable # Windows
|
||||
if os.name == "nt"
|
||||
else [executable],
|
||||
shell=True,
|
||||
else executable, # Linux/Others
|
||||
shell=False, # If true, the extra arguments would incorrectly be given to the shell instead.
|
||||
start_new_session=True,
|
||||
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0,
|
||||
)
|
||||
|
||||
@@ -35,4 +35,3 @@ def save_games(games):
|
||||
for game in games:
|
||||
with open(os.path.join(games_dir, f"{game}.json"), "w") as open_file:
|
||||
open_file.write(json.dumps(games[game], indent=4, sort_keys=True))
|
||||
open_file.close()
|
||||
|
||||
@@ -49,7 +49,6 @@ def get_game(task, datatypes, current_time, parent_widget, appmanifest, steam_di
|
||||
|
||||
with open(appmanifest, "r") as open_file:
|
||||
data = open_file.read()
|
||||
open_file.close()
|
||||
for datatype in datatypes:
|
||||
value = re.findall(f'"{datatype}"\t\t"(.*)"\n', data)
|
||||
values[datatype] = value[0]
|
||||
@@ -64,9 +63,9 @@ def get_game(task, datatypes, current_time, parent_widget, appmanifest, steam_di
|
||||
return
|
||||
|
||||
values["executable"] = (
|
||||
f'start steam://rungameid/{values["appid"]}'
|
||||
["start", f'steam://rungameid/{values["appid"]}']
|
||||
if os.name == "nt"
|
||||
else f'xdg-open steam://rungameid/{values["appid"]}'
|
||||
else ["xdg-open", f'steam://rungameid/{values["appid"]}']
|
||||
)
|
||||
values["hidden"] = False
|
||||
values["source"] = "steam"
|
||||
|
||||
@@ -36,7 +36,6 @@ def toggle_hidden(game):
|
||||
|
||||
with open(os.path.join(games_dir, f"{game}.json"), "r") as open_file:
|
||||
data = json.loads(open_file.read())
|
||||
open_file.close()
|
||||
|
||||
data["hidden"] = not data["hidden"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user