UNPKG

webpresence

Version:

Discord Rich Presence for websites - Show your browsing activity in Discord

597 lines (586 loc) 20.1 kB
import fs from 'fs'; import path from 'path'; import os from 'os'; import { execSync, exec } from 'child_process'; import chalk from 'chalk'; var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); function formatTimestamp() { return (/* @__PURE__ */ new Date()).toISOString(); } __name(formatTimestamp, "formatTimestamp"); function formatLogMessage(level, message, meta) { const timestamp = formatTimestamp(); let logMessage = `[${timestamp}] [${level}] ${message}`; if (meta) { try { if (typeof meta === "string") { logMessage += ` - ${meta}`; } else { logMessage += ` - ${JSON.stringify(meta)}`; } } catch (error) { logMessage += ` - [Error serializing metadata: ${error}]`; } } return logMessage; } __name(formatLogMessage, "formatLogMessage"); var isRunningAsCLI = process.argv.length > 1 && process.argv[1].includes("cli"); var verbose = !isRunningAsCLI; var logger = { error: /* @__PURE__ */ __name((message, meta) => { if (isRunningAsCLI) { console.error(chalk.red(`ERROR: ${message}`)); if (verbose && meta) { console.error(chalk.gray(JSON.stringify(meta, null, 2))); } } else { console.error(formatLogMessage("ERROR" /* ERROR */, message, meta)); } }, "error"), warn: /* @__PURE__ */ __name((message, meta) => { if (isRunningAsCLI) { if (verbose || message.includes("Discord") || message.includes("connection")) { console.warn(chalk.yellow(`WARNING: ${message}`)); if (verbose && meta) { console.warn(chalk.gray(JSON.stringify(meta, null, 2))); } } } else { console.warn(formatLogMessage("WARN" /* WARN */, message, meta)); } }, "warn"), info: /* @__PURE__ */ __name((message, meta) => { if (isRunningAsCLI) { const isImportant = message.includes("Server") || message.includes("Discord") || message.includes("connected") || message.includes("presence"); if (verbose || isImportant) { console.log(chalk.blue(message)); if (verbose && meta) { console.log(chalk.gray(JSON.stringify(meta, null, 2))); } } } else { console.log(formatLogMessage("INFO" /* INFO */, message, meta)); } }, "info"), debug: /* @__PURE__ */ __name((message, meta) => { if (process.env.DEBUG) { if (isRunningAsCLI && verbose) { console.log(chalk.gray(`DEBUG: ${message}`)); if (meta) { console.log(chalk.gray(JSON.stringify(meta, null, 2))); } } else if (!isRunningAsCLI) { console.log(formatLogMessage("DEBUG" /* DEBUG */, message, meta)); } } }, "debug"), // CLI-specific methods for better UX success: /* @__PURE__ */ __name((message) => { console.log(chalk.green(message)); }, "success"), important: /* @__PURE__ */ __name((message) => { console.log(chalk.cyan(message)); }, "important"), // Control verbosity setVerbose: /* @__PURE__ */ __name((v) => { verbose = v; }, "setVerbose"), isVerbose: /* @__PURE__ */ __name(() => verbose, "isVerbose") }; // src/utils/autostart.ts var HOME_DIR = os.homedir(); var AUTOSTART_DIR_LINUX = path.join(HOME_DIR, ".config", "autostart"); var AUTOSTART_FILE_LINUX = path.join(AUTOSTART_DIR_LINUX, "webpresence.desktop"); var SYSTEMD_USER_DIR = path.join(HOME_DIR, ".config", "systemd", "user"); var SYSTEMD_SERVICE_FILE = path.join(SYSTEMD_USER_DIR, "webpresence.service"); var LAUNCH_AGENTS_DIR_MAC = path.join(HOME_DIR, "Library", "LaunchAgents"); var LAUNCH_AGENT_FILE_MAC = path.join(LAUNCH_AGENTS_DIR_MAC, "com.utkarsh.webpresence.plist"); var WEBPRESENCE_DIR = path.join(HOME_DIR, ".webpresence"); var STARTUP_SCRIPT_PATH = path.join(WEBPRESENCE_DIR, "startup.sh"); var AUTOSTART_LOG_PATH = path.join(WEBPRESENCE_DIR, "autostart.log"); function detectLinuxDistribution() { try { const hasSystemd = fs.existsSync("/usr/bin/systemctl") || fs.existsSync("/bin/systemctl"); let isArch = fs.existsSync("/etc/arch-release"); let distroName = "Unknown Linux"; if (fs.existsSync("/etc/os-release")) { const osRelease = execSync("cat /etc/os-release", { encoding: "utf8" }); if (!isArch) { isArch = osRelease.toLowerCase().includes("arch") || osRelease.toLowerCase().includes("manjaro") || osRelease.toLowerCase().includes("endeavour"); } const nameMatch = osRelease.match(/NAME="([^"]+)"/); if (nameMatch && nameMatch[1]) { distroName = nameMatch[1]; } } return { isArch, isSystemd: hasSystemd, name: distroName }; } catch (error) { return { isArch: false, isSystemd: true, name: "Unknown Linux" }; } } __name(detectLinuxDistribution, "detectLinuxDistribution"); function getBestAutostartMethod(preferredMethod) { const platform = process.platform; if (preferredMethod && preferredMethod !== "auto") { return preferredMethod; } if (platform !== "linux") { return "auto"; } const distro = detectLinuxDistribution(); logger.info(`Detected Linux distribution: ${distro.name}`); if (distro.isArch && distro.isSystemd) { logger.info("Using systemd autostart method (recommended for Arch Linux)"); return "systemd"; } else if (distro.isSystemd) { logger.info("Using systemd autostart method"); return "systemd"; } else { logger.info("Using XDG autostart method"); return "xdg"; } } __name(getBestAutostartMethod, "getBestAutostartMethod"); function getWebPresencePath() { const platform = process.platform; try { return execSync("which webpresence", { encoding: "utf8" }).trim(); } catch (e) { if (platform === "win32") { try { return execSync("where webpresence", { encoding: "utf8" }).trim().split("\n")[0]; } catch (whereError) { if (process.env.APPDATA) { return path.join(process.env.APPDATA, "npm", "webpresence.cmd"); } } } const npmGlobalLocations = [ path.join(HOME_DIR, ".npm-global", "bin", "webpresence"), path.join(HOME_DIR, "node_modules", ".bin", "webpresence"), path.join(HOME_DIR, ".local", "bin", "webpresence"), "/usr/local/bin/webpresence", "/usr/bin/webpresence" ]; for (const location of npmGlobalLocations) { if (fs.existsSync(location)) { return location; } } return "webpresence"; } } __name(getWebPresencePath, "getWebPresencePath"); function createLinuxStartupScript(webpresencePath) { if (!fs.existsSync(WEBPRESENCE_DIR)) { fs.mkdirSync(WEBPRESENCE_DIR, { recursive: true }); } const startupScript = `#!/bin/bash # WebPresence Startup Script (BETA) # Created: $(new Date().toISOString()) # Wait for desktop environment to fully load sleep 10 # Ensure PATH includes npm global bin directories export PATH="$PATH:$HOME/.npm-global/bin:$HOME/.local/bin:/usr/local/bin" # Log startup attempt echo "[$(date)] Starting WebPresence..." >> "${AUTOSTART_LOG_PATH}" # Check if Discord is running if pgrep -x "Discord" > /dev/null || pgrep -x "discord" > /dev/null; then echo "[$(date)] Discord is running, starting WebPresence..." >> "${AUTOSTART_LOG_PATH}" else echo "[$(date)] Discord is not running, waiting 30 seconds..." >> "${AUTOSTART_LOG_PATH}" sleep 30 fi # Start WebPresence ${webpresencePath} start -d >> "${AUTOSTART_LOG_PATH}" 2>&1 # Log completion echo "[$(date)] Startup script completed" >> "${AUTOSTART_LOG_PATH}" `; fs.writeFileSync(STARTUP_SCRIPT_PATH, startupScript); try { execSync(`chmod +x ${STARTUP_SCRIPT_PATH}`); } catch (chmodError) { logger.warn(`Could not make startup script executable: ${chmodError}`); } return STARTUP_SCRIPT_PATH; } __name(createLinuxStartupScript, "createLinuxStartupScript"); async function enableSystemdAutostart(webpresencePath) { try { if (!fs.existsSync(SYSTEMD_USER_DIR)) { fs.mkdirSync(SYSTEMD_USER_DIR, { recursive: true }); } const serviceContent = `[Unit] Description=WebPresence Discord Rich Presence Server After=network.target graphical-session.target [Service] ExecStart=${webpresencePath} start Restart=on-failure RestartSec=10 Environment=PATH=${process.env.PATH}:${HOME_DIR}/.npm-global/bin:${HOME_DIR}/.local/bin:/usr/local/bin [Install] WantedBy=default.target `; fs.writeFileSync(SYSTEMD_SERVICE_FILE, serviceContent); try { execSync("systemctl --user daemon-reload"); execSync(`systemctl --user enable webpresence.service`); execSync(`systemctl --user start webpresence.service`); logger.success("Enabled autostart on Linux using systemd user service"); return { success: true, message: "Autostart enabled using systemd. WebPresence will start automatically when you log in." }; } catch (systemdError) { logger.warn(`Could not enable systemd service: ${systemdError.message}`); return { success: false, message: `Failed to enable systemd service: ${systemdError.message}` }; } } catch (error) { logger.error(`Error enabling systemd autostart: ${error.message}`, { error: error.stack }); return { success: false, message: `Failed to enable systemd autostart: ${error.message}` }; } } __name(enableSystemdAutostart, "enableSystemdAutostart"); async function enableXdgAutostart(webpresencePath) { try { const startupScriptPath = createLinuxStartupScript(webpresencePath); if (!fs.existsSync(AUTOSTART_DIR_LINUX)) { fs.mkdirSync(AUTOSTART_DIR_LINUX, { recursive: true }); } const desktopEntryContent = `[Desktop Entry] Type=Application Name=WebPresence Exec=${startupScriptPath} Terminal=false X-GNOME-Autostart-enabled=true StartupNotify=false Hidden=false NoDisplay=false Comment=Discord Rich Presence for websites `; fs.writeFileSync(AUTOSTART_FILE_LINUX, desktopEntryContent); try { execSync(`chmod +x ${AUTOSTART_FILE_LINUX}`); } catch (chmodError) { logger.warn(`Could not make desktop entry executable: ${chmodError}`); } logger.success("Enabled autostart on Linux using XDG autostart"); return { success: true, message: "Autostart enabled using XDG autostart. WebPresence will start automatically when you log in." }; } catch (error) { logger.error(`Error enabling XDG autostart: ${error.message}`, { error: error.stack }); return { success: false, message: `Failed to enable XDG autostart: ${error.message}` }; } } __name(enableXdgAutostart, "enableXdgAutostart"); async function disableSystemdAutostart() { try { let wasEnabled = false; if (fs.existsSync(SYSTEMD_SERVICE_FILE)) { try { execSync(`systemctl --user stop webpresence.service`); } catch (stopError) { } try { execSync(`systemctl --user disable webpresence.service`); } catch (disableError) { } fs.unlinkSync(SYSTEMD_SERVICE_FILE); wasEnabled = true; try { execSync("systemctl --user daemon-reload"); } catch (reloadError) { } } if (wasEnabled) { logger.success("Disabled autostart on Linux (systemd)"); return { success: true, message: "Autostart disabled. WebPresence will no longer start automatically when you log in." }; } return { success: true, message: "Autostart was not enabled with systemd." }; } catch (error) { logger.error(`Error disabling systemd autostart: ${error.message}`, { error: error.stack }); return { success: false, message: `Failed to disable systemd autostart: ${error.message}` }; } } __name(disableSystemdAutostart, "disableSystemdAutostart"); async function disableXdgAutostart() { try { let wasEnabled = false; if (fs.existsSync(AUTOSTART_FILE_LINUX)) { fs.unlinkSync(AUTOSTART_FILE_LINUX); wasEnabled = true; } if (fs.existsSync(STARTUP_SCRIPT_PATH)) { fs.unlinkSync(STARTUP_SCRIPT_PATH); wasEnabled = true; } if (wasEnabled) { logger.success("Disabled autostart on Linux (XDG)"); return { success: true, message: "Autostart disabled. WebPresence will no longer start automatically when you log in." }; } return { success: true, message: "Autostart was not enabled with XDG autostart." }; } catch (error) { logger.error(`Error disabling XDG autostart: ${error.message}`, { error: error.stack }); return { success: false, message: `Failed to disable XDG autostart: ${error.message}` }; } } __name(disableXdgAutostart, "disableXdgAutostart"); function isAutostartEnabled(method) { try { const platform = process.platform; if (platform === "win32") { try { const output = execSync("schtasks /query /tn WebPresence", { stdio: ["ignore", "pipe", "ignore"], encoding: "utf8" }); return output.includes("WebPresence"); } catch (e) { return false; } } else if (platform === "darwin") { return fs.existsSync(LAUNCH_AGENT_FILE_MAC); } else if (platform === "linux") { const bestMethod = getBestAutostartMethod(method); if (bestMethod === "systemd") { try { const output = execSync("systemctl --user is-enabled webpresence.service", { stdio: ["ignore", "pipe", "ignore"], encoding: "utf8" }); return output.trim() === "enabled"; } catch (e) { return false; } } else { return fs.existsSync(AUTOSTART_FILE_LINUX); } } return false; } catch (error) { logger.error(`Error checking autostart status: ${error.message}`, { error: error.stack }); return false; } } __name(isAutostartEnabled, "isAutostartEnabled"); async function enableAutostart(method) { try { const platform = process.platform; const webpresencePath = getWebPresencePath(); if (platform === "win32") { const command = `schtasks /create /tn WebPresence /sc onlogon /rl highest /tr "${webpresencePath} start -d" /f`; return new Promise((resolve) => { exec(command, (error, stdout, stderr) => { if (error) { logger.error(`Error enabling autostart on Windows: ${error.message}`); resolve({ success: false, message: `Failed to enable autostart: ${error.message}. Try running as administrator.` }); return; } logger.success("Enabled autostart on Windows using Task Scheduler"); resolve({ success: true, message: "Autostart enabled. WebPresence will start automatically when you log in." }); }); }); } else if (platform === "darwin") { if (!fs.existsSync(LAUNCH_AGENTS_DIR_MAC)) { fs.mkdirSync(LAUNCH_AGENTS_DIR_MAC, { recursive: true }); } const plistContent = `<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.utkarsh.webpresence</string> <key>ProgramArguments</key> <array> <string>${webpresencePath}</string> <string>start</string> <string>-d</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <false/> <key>StandardOutPath</key> <string>${path.join(HOME_DIR, ".webpresence", "launchd.log")}</string> <key>StandardErrorPath</key> <string>${path.join(HOME_DIR, ".webpresence", "launchd.log")}</string> </dict> </plist>`; fs.writeFileSync(LAUNCH_AGENT_FILE_MAC, plistContent); try { execSync(`launchctl load ${LAUNCH_AGENT_FILE_MAC}`); logger.success("Enabled autostart on macOS using LaunchAgents"); return { success: true, message: "Autostart enabled. WebPresence will start automatically when you log in." }; } catch (loadError) { logger.warn(`Could not load launch agent: ${loadError.message}`); return { success: true, message: "Autostart configuration created, but you may need to restart your computer for it to take effect." }; } } else if (platform === "linux") { const bestMethod = getBestAutostartMethod(method); if (bestMethod === "systemd") { return enableSystemdAutostart(webpresencePath); } else { return enableXdgAutostart(webpresencePath); } } return { success: false, message: `Autostart is not supported on platform: ${platform}` }; } catch (error) { logger.error(`Error enabling autostart: ${error.message}`, { error: error.stack }); return { success: false, message: `Failed to enable autostart: ${error.message}` }; } } __name(enableAutostart, "enableAutostart"); async function disableAutostart(method) { try { const platform = process.platform; if (platform === "win32") { const command = "schtasks /delete /tn WebPresence /f"; return new Promise((resolve) => { exec(command, (error, stdout, stderr) => { if (error) { if (error.message.includes("The system cannot find the file specified")) { resolve({ success: true, message: "Autostart was not enabled." }); return; } logger.error(`Error disabling autostart on Windows: ${error.message}`); resolve({ success: false, message: `Failed to disable autostart: ${error.message}. Try running as administrator.` }); return; } logger.success("Disabled autostart on Windows"); resolve({ success: true, message: "Autostart disabled. WebPresence will no longer start automatically when you log in." }); }); }); } else if (platform === "darwin") { if (fs.existsSync(LAUNCH_AGENT_FILE_MAC)) { try { execSync(`launchctl unload ${LAUNCH_AGENT_FILE_MAC}`); } catch (unloadError) { } fs.unlinkSync(LAUNCH_AGENT_FILE_MAC); logger.success("Disabled autostart on macOS"); return { success: true, message: "Autostart disabled. WebPresence will no longer start automatically when you log in." }; } return { success: true, message: "Autostart was not enabled." }; } else if (platform === "linux") { const bestMethod = getBestAutostartMethod(method); if (method === "auto" || !method) { const systemdResult = await disableSystemdAutostart(); const xdgResult = await disableXdgAutostart(); if (systemdResult.success && systemdResult.message.includes("disabled") || xdgResult.success && xdgResult.message.includes("disabled")) { return { success: true, message: "Autostart disabled. WebPresence will no longer start automatically when you log in." }; } return { success: true, message: "Autostart was not enabled." }; } else if (bestMethod === "systemd") { return disableSystemdAutostart(); } else { return disableXdgAutostart(); } } return { success: false, message: `Autostart is not supported on platform: ${platform}` }; } catch (error) { logger.error(`Error disabling autostart: ${error.message}`, { error: error.stack }); return { success: false, message: `Failed to disable autostart: ${error.message}` }; } } __name(disableAutostart, "disableAutostart"); export { disableAutostart, enableAutostart, isAutostartEnabled }; //# sourceMappingURL=autostart.js.map //# sourceMappingURL=autostart.js.map