webpresence
Version:
Discord Rich Presence for websites - Show your browsing activity in Discord
597 lines (586 loc) • 20.1 kB
JavaScript
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