├── .gitignore ├── .vscode └── settings.json ├── README.md ├── extension.yml ├── package.json ├── utils.js ├── LICENSE └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # steam-launcher 2 | Deckboard extension for launching installed Steam games https://deckboard.app 3 | 4 | The game listed from Steam installation directory [DRIVE]:\\Program Files (x86)\\Steam\\steamapps 5 | -------------------------------------------------------------------------------- /extension.yml: -------------------------------------------------------------------------------- 1 | name: Steam Launcher 2 | package: steam-launcher 3 | version: 1.3.0 4 | description: Launch installed Steam games 5 | author: Riva Farabi 6 | license: MIT 7 | repository: "https://github.com/rivafarabi/steam-launcher" -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "steam-launcher", 3 | "version": "1.3.0", 4 | "description": "Launch installed Steam games", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "deckboard-kit --build", 8 | "test": "mocha" 9 | }, 10 | "author": "Riva Farabi", 11 | "license": "MIT", 12 | "dependencies": { 13 | "deckboard-kit": "^0.1.11", 14 | "fs-extra": "^8.1.0", 15 | "opn": "^6.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | const acfToJson = raw => { 2 | return JSON.parse( 3 | raw 4 | .toString() 5 | .split('LastUpdated')[0] 6 | .replace(/AppState/g, '') 7 | .replace(/"/g, '') 8 | .replace(/\t\t/g, '": "') 9 | .replace(/\n/g, '", "') 10 | .replace(/\t/g, ' ') 11 | .replace(/ " /g, ' "') 12 | .replace('", "{", ', '{ ') 13 | .slice(0, -3) + '}' 14 | ); 15 | }; 16 | 17 | module.exports = { 18 | acfToJson 19 | }; 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Riva Farabi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { Extension, INPUT_METHOD, PLATFORMS, log } = require('deckboard-kit'); 2 | const fs = require('fs-extra'); 3 | const path = require('path'); 4 | const opn = require('opn'); 5 | const { acfToJson } = require('./utils'); 6 | 7 | class SteamLauncherExtension extends Extension { 8 | constructor() { 9 | super(); 10 | this.name = 'Steam Launcher'; 11 | this.platforms = [PLATFORMS.WINDOWS]; 12 | this.configs = { 13 | steamPaths: { 14 | type: 'array', 15 | name: 'Paths', 16 | descriptions: '', 17 | value: [ 18 | path.join( 19 | 'C:', 20 | 'Program Files (x86)', 21 | 'Steam', 22 | 'steamapps' 23 | ), 24 | path.join('D:', 'Program Files (x86)', 'Steam', 'steamapps') 25 | ] 26 | } 27 | }; 28 | this.initExtension(); 29 | } 30 | 31 | initExtension() { 32 | this.setInputOptions(); 33 | } 34 | 35 | update() { 36 | this.setInputOptions(); 37 | } 38 | 39 | setInputOptions() { 40 | this.inputs = [ 41 | { 42 | label: 'Launch Game', 43 | value: 'steam-launch-games', 44 | icon: 'steam', 45 | fontIcon: 'fab', 46 | color: '#171A21', 47 | input: [ 48 | { 49 | label: 'Game', 50 | ref: 'appid', 51 | type: INPUT_METHOD.INPUT_SELECT, 52 | items: this.getGameList() 53 | } 54 | ] 55 | } 56 | ]; 57 | } 58 | 59 | getGameList() { 60 | let input = []; 61 | this.configs.steamPaths.value.forEach(steamPath => { 62 | try { 63 | const steamappsdir = fs.readdirSync(steamPath); 64 | if (steamappsdir) { 65 | const acfFiles = steamappsdir.filter( 66 | x => x.split('.').pop() === 'acf' 67 | ); 68 | const gamesObject = acfFiles.map(x => { 69 | const raw = fs.readFileSync(path.join(steamPath, x)); 70 | const { appid, name } = acfToJson(raw); 71 | return { value: appid, label: name }; 72 | }); 73 | input = [...input, ...gamesObject]; 74 | } 75 | } catch (err) { 76 | log.error( 77 | 'no Steam installation in the directory ' + steamPath 78 | ); 79 | } 80 | }); 81 | return input.sort((a, b) => a.label - b.label); 82 | } 83 | 84 | execute(action, { appid }) { 85 | switch (action) { 86 | case 'steam-launch-games': 87 | opn('steam://rungameid/' + appid); 88 | break; 89 | default: 90 | break; 91 | } 92 | } 93 | } 94 | 95 | module.exports = new SteamLauncherExtension(); 96 | --------------------------------------------------------------------------------