'use strict'; /* * streamdeckplugin.js – das AeroMC-Plugin in die Stream-Deck-Software kopieren * ----------------------------------------------------------------------------- * Das Plugin (Ordner streamdeck-plugin/com.aeromc.launcher.sdPlugin) liegt im * Launcher mit dabei. Schaltet jemand "Stream Deck erlauben" ein – und bei jedem * Start, solange es an ist – legt AeroMC es in den Plugin-Ordner der Stream-Deck- * Software, falls es dort fehlt oder von einer anderen Fassung stammt. Nach dem * Kopieren muss die Stream-Deck-Software einmal neu gestartet werden, damit sie * das Plugin lädt. */ const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const PLUGIN_NAME = 'com.aeromc.launcher.sdPlugin'; // Ordner mit dem mitgelieferten Plugin; null, wenn er in dieser Fassung fehlt function quelle(istPaketiert, ressourcenOrdner) { const kandidat = istPaketiert ? path.join(ressourcenOrdner, 'streamdeck-plugin', PLUGIN_NAME) : path.join(__dirname, '..', 'streamdeck-plugin', PLUGIN_NAME); return fs.existsSync(path.join(kandidat, 'manifest.json')) ? kandidat : null; } // Plugin-Ordner der Stream-Deck-Software; null, wenn sie nie installiert war function pluginOrdner() { const appdata = process.env.APPDATA; if (!appdata) return null; const ordner = path.join(appdata, 'Elgato', 'StreamDeck', 'Plugins'); return fs.existsSync(ordner) ? ordner : null; } // Was die Stream-Deck-Software selbst im Plugin-Ordner anlegt (Protokolle), zählt nicht mit const IGNORIERT = new Set(['logs']); function dateien(basis, rel = '') { const ergebnis = []; for (const e of fs.readdirSync(path.join(basis, rel), { withFileTypes: true })) { if (!rel && IGNORIERT.has(e.name)) continue; const r = rel ? rel + '/' + e.name : e.name; if (e.isDirectory()) ergebnis.push(...dateien(basis, r)); else ergebnis.push(r); } return ergebnis.sort(); } // Prüfsumme über Dateinamen und -inhalt - gleiche Prüfsumme = gleicher Stand function fingerabdruck(ordner) { const h = crypto.createHash('sha1'); for (const rel of dateien(ordner)) { h.update(rel + '\0'); h.update(fs.readFileSync(path.join(ordner, ...rel.split('/')))); } return h.digest('hex'); } /* * -> { ok: true, status: 'installiert' | 'aktualisiert' | 'aktuell', neustart } * { ok: false, grund: 'quelle-fehlt' | 'kein-streamdeck' | 'kopieren', message } */ function installiere(opt) { const o = opt || {}; if (!o.quelle) return { ok: false, grund: 'quelle-fehlt', message: 'Das Plugin ist in dieser Fassung nicht enthalten.' }; const plugins = o.pluginOrdner !== undefined ? o.pluginOrdner : pluginOrdner(); if (!plugins || !fs.existsSync(plugins)) { return { ok: false, grund: 'kein-streamdeck', message: 'Die Stream-Deck-Software wurde nicht gefunden.' }; } const ziel = path.join(plugins, PLUGIN_NAME); try { const vorhanden = fs.existsSync(ziel); if (vorhanden && fingerabdruck(ziel) === fingerabdruck(o.quelle)) return { ok: true, status: 'aktuell', neustart: false }; fs.cpSync(o.quelle, ziel, { recursive: true, force: true, filter: (src) => !IGNORIERT.has(path.basename(src)) || src === o.quelle }); return { ok: true, status: vorhanden ? 'aktualisiert' : 'installiert', neustart: true }; } catch (err) { return { ok: false, grund: 'kopieren', message: 'Das Plugin konnte nicht kopiert werden (' + err.message + '). Bitte die Stream-Deck-Software beenden und es erneut versuchen.' }; } } module.exports = { PLUGIN_NAME, quelle, pluginOrdner, installiere, fingerabdruck };