Skip to content

Commit 49acdc3

Browse files
committed
feat(scan-shortcuts): fix gog shortcut flow (through to GalaxyClient.exe) and add folder scanning functionality
- Detects goggame-1423049311.info next to the exe - Reads the game name from the JSON - Sets launch_exe = GalaxyClient.exe, launch_dir = Program Files (x86)/GOG Galaxy, launch_args = /command=runGame /gameId=NNNNNNNNNN - Icon still extracts from the game dir (where goggame-*.ico lives)
1 parent 384db42 commit 49acdc3

2 files changed

Lines changed: 119 additions & 2 deletions

File tree

lib/shortcuts.sh

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,34 @@ create_external_shortcut() {
331331
[ -n "$extracted" ] && app_icon="$extracted"
332332
fi
333333

334+
# GOG: goggame-*.info marks a GOG game; prefer GalaxyClient for auth/DRM/overlay.
335+
local launch_exe="$exe_bin" launch_dir="$exe_dir" launch_args=""
336+
local gog_info
337+
gog_info=$(find "$exe_dir" -maxdepth 1 -name "goggame-*.info" 2>/dev/null | head -1)
338+
if [ -n "$gog_info" ]; then
339+
local gog_id; gog_id=$(basename "$gog_info" | sed 's/goggame-//;s/\.info//')
340+
if command -v python3 &>/dev/null && [ -z "${2:-}" ]; then
341+
local json_name
342+
json_name=$(python3 -c "
343+
import json,sys
344+
try:
345+
d=json.load(open(sys.argv[1]))
346+
print(d.get('name',''))
347+
except: pass
348+
" "$gog_info" 2>/dev/null)
349+
[ -n "$json_name" ] && display_name="$json_name"
350+
fi
351+
local galaxy_exe="$WINEPREFIX/pfx/drive_c/Program Files (x86)/GOG Galaxy/GalaxyClient.exe"
352+
if [ -f "$galaxy_exe" ]; then
353+
launch_exe="GalaxyClient.exe"
354+
launch_dir="$WINEPREFIX/pfx/drive_c/Program Files (x86)/GOG Galaxy"
355+
launch_args="/command=runGame /gameId=${gog_id}"
356+
print_info "GOG game ID ${gog_id} — launching via GalaxyClient"
357+
else
358+
print_warning "GOG Galaxy not found in prefix; launching game exe directly"
359+
fi
360+
fi
361+
334362
local launcher="$BIN_DIR/${app_key}"
335363
local desktop="$APPS_DIR/${app_key}.desktop"
336364

@@ -345,8 +373,8 @@ export WINEDLLOVERRIDES="winemenubuilder.exe=d"
345373
export WINEESYNC="\${WINEESYNC:-1}" WINEFSYNC="\${WINEFSYNC:-1}"
346374
347375
[ -d "\${_dd}" ] && rm -f "\${_dd}/z:" "\${_dd}/z::" 2>/dev/null || true
348-
cd "${exe_dir}" || exit 1
349-
"${PROTON_DIR}/proton" run "${exe_bin}" >"${WINE_DIR}/${app_key}.log" 2>&1 &
376+
cd "${launch_dir}" || exit 1
377+
"${PROTON_DIR}/proton" run "${launch_exe}" ${launch_args} >"${WINE_DIR}/${app_key}.log" 2>&1 &
350378
( _i=0; while [ \${_i} -lt 20 ]; do rm -f "\${_dd}/z:" "\${_dd}/z::" 2>/dev/null; sleep 0.5; _i=\$((\${_i}+1)); done ) &
351379
LAUNCHER_EOF
352380
chmod +x "$launcher"
@@ -369,3 +397,89 @@ DESKTOP_EOF
369397
print_success "Shortcut created: ${display_name}"
370398
print_info "Key: ${app_key} | Icon: $(basename "${app_icon}")"
371399
}
400+
401+
# Scan a path (or default prefix + common GOG locations) for GOG games and Windows .lnk
402+
# shortcuts, then create Proton-based .desktop entries for each discovered game.
403+
# Usage: scan_shortcuts [path]
404+
scan_shortcuts() {
405+
local scan_arg="${1:-}"
406+
local created=0 skipped=0
407+
408+
print_info "Scanning for GOG games and Windows shortcuts..."
409+
410+
# Build list of directories to search
411+
local -a roots=()
412+
if [ -n "$scan_arg" ]; then
413+
roots=("$scan_arg")
414+
else
415+
for d in \
416+
"$WINEPREFIX/pfx/drive_c/users/steamuser/Desktop" \
417+
"$WINEPREFIX/pfx/drive_c/ProgramData/Microsoft/Windows/Start Menu/Programs" \
418+
"${HOME}/Games" "${HOME}/GOG Games" "${HOME}/Games/GOG Galaxy"; do
419+
[ -d "$d" ] && roots+=("$d")
420+
done
421+
fi
422+
423+
if [ ${#roots[@]} -eq 0 ]; then
424+
print_warning "No directories to scan. Try: wig scan-shortcuts /path/to/games/"
425+
return 1
426+
fi
427+
428+
# Track processed dirs to avoid duplicate shortcuts from .lnk + goggame-*.info in same dir
429+
local -A _seen=()
430+
431+
# Pass 1: GOG game directories identified by goggame-*.info
432+
while IFS= read -r -d '' info_file; do
433+
local game_dir; game_dir=$(dirname "$info_file")
434+
[[ -n "${_seen[$game_dir]:-}" ]] && continue
435+
_seen[$game_dir]=1
436+
437+
# Parse primary play task exe from the info JSON
438+
local primary_exe=""
439+
if command -v python3 &>/dev/null; then
440+
primary_exe=$(python3 -c "
441+
import json, sys
442+
try:
443+
d = json.load(open(sys.argv[1]))
444+
for t in d.get('playTasks', []):
445+
if t.get('isPrimary') and t.get('type') == 'FileTask':
446+
print(t.get('path', '').replace('\\\\\\\\', '/').strip('/'))
447+
break
448+
except: pass
449+
" "$info_file" 2>/dev/null)
450+
fi
451+
452+
# Fallback: largest .exe in the game dir
453+
if [ -z "$primary_exe" ] || [ ! -f "$game_dir/$primary_exe" ]; then
454+
local _bf="" _bsz=0 _f _sz
455+
while IFS= read -r -d '' _f; do
456+
_sz=$(stat -c%s "$_f" 2>/dev/null || echo 0)
457+
(( _sz > _bsz )) && { _bsz=$_sz; _bf="$_f"; }
458+
done < <(find "$game_dir" -maxdepth 1 -name "*.exe" -print0 2>/dev/null)
459+
[ -n "$_bf" ] && primary_exe=$(basename "$_bf")
460+
fi
461+
462+
if [ -n "$primary_exe" ] && [ -f "$game_dir/$primary_exe" ]; then
463+
print_info "GOG game: $(basename "$game_dir")$primary_exe"
464+
create_external_shortcut "$game_dir/$primary_exe" && ((created++)) || ((skipped++))
465+
fi
466+
done < <(find "${roots[@]}" -name "goggame-*.info" -print0 2>/dev/null)
467+
468+
# Pass 2: Windows .lnk shortcuts not already covered by goggame detection
469+
while IFS= read -r -d '' lnk; do
470+
local lnk_dir; lnk_dir=$(dirname "$lnk")
471+
[[ -n "${_seen[$lnk_dir]:-}" ]] && continue
472+
local lnk_name; lnk_name=$(basename "$lnk" .lnk)
473+
case "${lnk_name,,}" in
474+
"gog galaxy"|"gog launcher"|"gog galaxy updater") continue ;;
475+
esac
476+
print_info "LNK: $lnk_name"
477+
create_external_shortcut "$lnk" "$lnk_name" && ((created++)) || ((skipped++))
478+
done < <(find "${roots[@]}" -name "*.lnk" -print0 2>/dev/null)
479+
480+
if (( created + skipped == 0 )); then
481+
print_warning "No games found. Try specifying the games directory: wig scan-shortcuts /path/to/games/"
482+
else
483+
print_success "Scan complete — created: $created skipped/failed: $skipped"
484+
fi
485+
}

setup

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ SHORTCUT MANAGEMENT:
6868
install-shortcut <key|all> Create .desktop shortcut for a registered launcher
6969
install-shortcut --profile <p> <key> Create profile-specific shortcut (key-p.desktop)
7070
install-shortcut /path/to/Game.exe Create shortcut for any .exe or .lnk (auto-detects icon)
71+
scan-shortcuts [path] Scan for GOG games + Windows .lnk files; create all shortcuts
72+
(default: prefix desktop/start-menu + ~/Games)
7173
remove-shortcut <key|all> Remove desktop shortcut (or all)
7274
7375
PROFILE MANAGEMENT (per-app Proton/DXVK tuning):
@@ -174,6 +176,7 @@ main() {
174176
remove-shortcut)
175177
if [ "$2" = "all" ]; then remove_all_shortcuts
176178
else remove_shortcut "$2"; fi ;;
179+
scan-shortcuts) shift; scan_shortcuts "${1:-}" ;;
177180

178181
# Profiles
179182
profile) shift; profile_dispatch "$@" ;;

0 commit comments

Comments
 (0)