[Linux-only] basically bloxstap for sober
at dev 99 lines 2.6 kB view raw
1import { $ } from "bun"; 2import { writeFileSync } from "fs"; 3import { homedir } from "os"; 4import { join } from "path"; 5import { isCompiled } from "../constants"; 6 7type DesktopEntry = { 8 name: string; 9 genericName: string; 10 comment: string; 11 keywords?: string[]; 12 executable: string; 13 type: "Application"; 14 noDisplay: boolean; 15 categories: string[]; 16 icon?: string; 17 mimeTypes: string[]; 18}; 19 20/** tuxstrap.desktop */ 21export const tuxstrapDesktopEntry: DesktopEntry = { 22 name: "TuxStrap", 23 genericName: "Roblox Player", 24 comment: "Basically just Bloxstrap, but for Linux!", 25 keywords: [ 26 "roblox", 27 "vinegar", 28 "game", 29 "gaming", 30 "social", 31 "experience", 32 "launcher" 33 ], 34 type: "Application", 35 noDisplay: false, 36 icon: "org.vinegarhq.Sober", 37 mimeTypes: ["x-scheme-handler/roblox", "x-scheme-handler/roblox-player"], 38 categories: ["GNOME", "GTK", "Game"], 39 executable: `${process.argv.filter((a) => !a.includes("roblox")).join(" ")} -- @@u %u @@` 40}; 41 42export function createDesktopEntry(d: DesktopEntry, realPath?: string) { 43 return `[Desktop Entry] 44 Type=${d.type} 45 Name=${d.name} 46 GenericName=${d.genericName} 47 Comment=${d.comment} 48 ${d.keywords && `Keywords=${d.keywords.join(";")};`} 49 ${d.icon && `Icon=${d.icon}`} 50 NoDisplay=${d.noDisplay} 51 Categories=${d.categories.join(";")}; 52 Exec=${realPath ? realPath + " -- @@u %u @@" : d.executable} 53 MimeType=${d.mimeTypes.join(";")}; 54 ` 55 .replace(/^\t+/gm, "") 56 .replaceAll("\n\n", "\n"); 57} 58 59export async function registerXDG(fileName: string) { 60 if ( 61 isCompiled 62 ) { 63 for (const mimeType of tuxstrapDesktopEntry.mimeTypes) { 64 const r = await $`xdg-mime default ${fileName} ${mimeType}` 65 .nothrow() 66 .quiet(); 67 if (r.exitCode === 0) { 68 console.log( 69 `Registered Default XDG Mime ${mimeType} -> ${fileName}` 70 ); 71 } else { 72 console.error( 73 `Failed to Register Default XDG Mime ${mimeType} -> ${fileName} (Exit code ${r.exitCode})` 74 ); 75 } 76 } 77 return; 78 } 79 const desktopEntry = createDesktopEntry(tuxstrapDesktopEntry); 80 const dir = join(homedir(), ".local", "share", "applications"); 81 try { 82 writeFileSync(join(dir, fileName), desktopEntry); 83 console.log(`Placed ${fileName} in ${dir}`); 84 for (const mimeType of tuxstrapDesktopEntry.mimeTypes) { 85 const r = await $`xdg-mime default ${fileName} ${mimeType}` 86 .nothrow() 87 .quiet(); 88 if (r.exitCode === 0) { 89 console.log( 90 `Registered Default XDG Mime ${mimeType} -> ${fileName}` 91 ); 92 } else { 93 console.error( 94 `Failed to Register Default XDG Mime ${mimeType} -> ${fileName} (Exit code ${r.exitCode})` 95 ); 96 } 97 } 98 } catch {} 99}