[feature] we can now create launch shortcut in steam library

This commit is contained in:
MathieuG-P
2025-01-06 17:24:36 +01:00
parent 774c3a2954
commit 2a99c76d09
15 changed files with 210 additions and 182 deletions
+132 -4
View File
@@ -1,4 +1,4 @@
export enum SteamShortcutKey {
enum SteamShortcutKey {
AppName = "AppName",
Exe = "Exe",
StartDir = "StartDir",
@@ -16,13 +16,141 @@ export enum SteamShortcutKey {
tags = "tags"
}
type BaseShortcut = {
type BaseShortcutData = {
[K in SteamShortcutKey]: K extends "tags" ? string[] : string
};
export interface SteamShortcut extends Partial<BaseShortcut> {
// Mandatory fields
export interface SteamShortcutData extends Partial<BaseShortcutData> {
// Mandatory and specific values
AppName: string;
Exe: string;
StartDir: string;
OpenVR?: "\x01" | "\x00";
}
export class SteamShortcut {
public static parseShortcutsRawData(rawData: string): SteamShortcut[] {
// Code taken from: https://developer.valvesoftware.com/wiki/Steam_Library_Shortcuts#Reading_the_shortcuts.vdf
const startIndex = rawData.indexOf("\u0000shortcuts\u0000");
if (startIndex < 0) {
return [];
}
const start = startIndex + "\u0000shortcuts\u0000".length;
const end = rawData.lastIndexOf("\u0008\u0008");
if (end < 0 || end <= start) {
return [];
}
const shortcutsString = rawData.substring(start, end - start);
const result: SteamShortcutData[] = [];
let currentShortcut: SteamShortcutData | null = null;
let word = "";
let key = "";
let readingTags = false;
let tagId = -1;
const shortcutKeysRegex = new RegExp(`[\u0001\u0002](${Object.values(SteamShortcutKey).join("|")})`, "i");
for (const c of shortcutsString) {
if (c === "\u0000") {
if (word.endsWith(`\u0001${SteamShortcutKey.AppName}`)) {
if (currentShortcut) {
result.push(currentShortcut);
}
currentShortcut = {
AppName: "",
Exe: "",
StartDir: "",
icon: "",
LaunchOptions: "",
IsHidden: "\x00",
};
key = `\u0001${SteamShortcutKey.AppName}`;
} else if (shortcutKeysRegex.test(word)) {
key = word;
} else if (word === SteamShortcutKey.tags) {
readingTags = true;
} else if (key !== "") {
const currentKey = shortcutKeysRegex.exec(key).pop().replaceAll("\u0001", "").replaceAll("\u0002", "") as SteamShortcutKey;
if (currentShortcut && currentKey && currentKey !== SteamShortcutKey.tags) {
currentShortcut[currentKey] = word.replaceAll("\"", "") as string & ("\x01" | "\x00") // Make TS happy
}
key = "";
} else if (readingTags) {
if (word.startsWith("\u0001")) {
tagId = parseInt(word.substring(1), 10);
} else if (tagId >= 0 && currentShortcut) {
currentShortcut.tags.push(word);
tagId = -1;
} else {
readingTags = false;
}
}
word = "";
} else {
word += c;
}
}
if (currentShortcut) {
result.push(currentShortcut);
}
return result.map(shortcutData => new SteamShortcut(shortcutData));
}
public static getShortcutsString(shortcuts: SteamShortcut[]): string {
let shortcutsString = "\u0000shortcuts\u0000";
for (let i = 0; i < shortcuts.length; i++) {
const shortcut = shortcuts[i];
if(!shortcut.data?.AppName || !shortcut.data?.Exe || !shortcut.data?.StartDir) {
continue;
}
shortcutsString += `\u0000${i}\u0000`;
shortcutsString += shortcut.getStringBytes();
}
shortcutsString += "\u0008\u0008";
return shortcutsString;
}
private data: SteamShortcutData;
public constructor(shortcutData: SteamShortcutData) {
this.data = shortcutData;
}
public getStringBytes(): string {
const isHidden = this.data?.IsHidden === "\x01";
const allowDesktopConfig = this.data?.AllowDesktopConfig === "\x01";
const allowOverlay = this.data?.AllowDesktopConfig === "\x01";
const openVR = this.data?.OpenVR === "\x01";
const devkit = this.data?.Devkit === "\x01";
let strShortcut = "";
strShortcut += `\x02appid\x00${this.data?.appid || "\x00\x00\x00"}\x00`;
strShortcut += `\x01AppName\x00${this.data?.AppName ?? ""}\x00`;
strShortcut += `\x01Exe\x00\"${this.data?.Exe ?? ""}\"\x00`;
strShortcut += `\x01StartDir\x00\"${this.data?.StartDir ?? ""}\"\x00`;
strShortcut += `\x01icon\x00${this.data?.icon ?? ""}\x00`;
strShortcut += `\x01ShortcutPath\x00\x00`;
strShortcut += `\x01LaunchOptions\x00${this.data?.LaunchOptions ?? ""}\x00`;
strShortcut += `\x02IsHidden\x00${isHidden ? "\x01" : "\x00"}\x00\x00\x00`;
strShortcut += `\x02AllowDesktopConfig\x00${allowDesktopConfig ? "\x01" : "\x00"}\x00\x00\x00`;
strShortcut += `\x02AllowOverlay\x00${allowOverlay ? "\x01" : "\x00"}\x00\x00\x00`;
strShortcut += `\x02OpenVR\x00${openVR ? "\x01" : "\x00"}\x00\x00\x00`;
strShortcut += `\x02Devkit\x00${devkit ? "\x01" : "\x00"}\x00\x00\x00`;
strShortcut += `\x01DevkitGameID\x00${this.data?.DevkitGameID ?? ""}\x00`;
strShortcut += `\x02DevkitOverrideAppID\x00\x00\x00\x00\x00`;
strShortcut += `\x02LastPlayTime\x00\x00\x00\x00\x00`;
strShortcut += `\x00tags\x00${""}\x08\x08`;
return strShortcut;
}
}