103 lines
3.6 KiB
JavaScript
103 lines
3.6 KiB
JavaScript
'use strict';
|
||
|
||
/*
|
||
* discordpresence.js – Discord Rich Presence ("Spielt Minecraft über AeroMC")
|
||
* -----------------------------------------------------------------------------
|
||
* Verbindet sich rein lokal über die IPC-Pipe des laufenden Discord-Clients.
|
||
* SET_ACTIVITY braucht dafür bewusst KEINE Authentifizierung/OAuth (anders als
|
||
* der Rest der RPC-API) – daher hier absichtlich client.request(...) direkt
|
||
* statt client.user.setActivity(...), das erst nach einem Login funktioniert.
|
||
*
|
||
* Immer aktiv, ohne eigene Einstellung – braucht also keine Zustimmung/kein
|
||
* Häkchen. Läuft trotzdem komplett unauffällig: ist Discord nicht installiert
|
||
* oder nicht gestartet, bleibt es einfach inaktiv, ohne den Launcher oder den
|
||
* Spielstart zu stören – jeder Fehler hier wird bewusst verschluckt.
|
||
*/
|
||
|
||
const { Client } = require('@xhayper/discord-rpc');
|
||
|
||
// Von M_Viper unter discord.com/developers/applications angelegte AeroMC-App.
|
||
// Öffentliche Anwendungs-ID, kein Geheimnis (genau wie DEFAULT_CLIENT_ID bei
|
||
// der Microsoft-Anmeldung in auth.js) – gilt für alle AeroMC-Nutzer gleich.
|
||
const DEFAULT_CLIENT_ID = '1538173087730630686';
|
||
|
||
const LAUNCHER_WEBSITE = 'https://aeromc.viper.ipv64.net/';
|
||
|
||
let clientId = DEFAULT_CLIENT_ID;
|
||
let client = null;
|
||
let connecting = null;
|
||
|
||
function resolveClientId() {
|
||
return (clientId && String(clientId).trim()) || DEFAULT_CLIENT_ID;
|
||
}
|
||
|
||
async function connect() {
|
||
if (client && client.isConnected) return client;
|
||
if (connecting) return connecting;
|
||
|
||
const id = resolveClientId();
|
||
const c = new Client({ clientId: id });
|
||
c.on('disconnected', () => { if (client === c) client = null; });
|
||
connecting = c.connect()
|
||
.then(() => { client = c; connecting = null; return c; })
|
||
.catch((err) => { connecting = null; throw err; });
|
||
return connecting;
|
||
}
|
||
|
||
/*
|
||
* activity: { details, state, startTimestamp }
|
||
* details/state -> die beiden Zeilen unter dem Profilbild in Discord
|
||
* startTimestamp -> Discord zeigt die Spielzeit dann selbst laufend an
|
||
*/
|
||
async function setActivity(activity) {
|
||
try {
|
||
const c = await connect();
|
||
await c.request('SET_ACTIVITY', {
|
||
pid: process.pid,
|
||
activity: {
|
||
details: activity.details,
|
||
state: activity.state,
|
||
timestamps: activity.startTimestamp ? { start: activity.startTimestamp } : undefined,
|
||
assets: { large_image: 'aeromc_logo', large_text: 'AeroMC Launcher' },
|
||
// Discord zeigt Buttons Betrachtern des Profils an (nicht sich selbst) -
|
||
// maximal 2 sind erlaubt, hier reicht einer.
|
||
buttons: [{ label: 'AeroMC herunterladen', url: LAUNCHER_WEBSITE }],
|
||
instance: false,
|
||
},
|
||
});
|
||
} catch {
|
||
// Discord nicht installiert/nicht gestartet o. Ä. - bewusst lautlos
|
||
}
|
||
}
|
||
|
||
async function clearActivity() {
|
||
try {
|
||
if (!client || !client.isConnected) return;
|
||
await client.request('SET_ACTIVITY', { pid: process.pid });
|
||
} catch { /* egal */ }
|
||
}
|
||
|
||
async function shutdown() {
|
||
const c = client;
|
||
client = null;
|
||
connecting = null;
|
||
if (!c) return;
|
||
try { await c.destroy(); } catch { /* egal */ }
|
||
}
|
||
|
||
/*
|
||
* Verbindet direkt beim Start. settings.discordClientId erlaubt weiterhin
|
||
* (rein optional, per Hand in settings.json) eine eigene App-ID zu setzen -
|
||
* ohne eigenes Einstellungsfeld, ohne dass es dafür einen Schalter braucht.
|
||
*/
|
||
function configure(settings) {
|
||
const nextId = (settings && settings.discordClientId) || DEFAULT_CLIENT_ID;
|
||
const idChanged = nextId !== clientId;
|
||
clientId = nextId;
|
||
|
||
if (idChanged) { shutdown().then(() => connect().catch(() => {})); }
|
||
else if (!client) { connect().catch(() => {}); }
|
||
}
|
||
|
||
module.exports = { configure, setActivity, clearActivity, shutdown, DEFAULT_CLIENT_ID };
|