Wo der Bot nicht hinkommt, fragt das Panel -- Typ panel
Bisher entschied `x.gamedig` darueber, ob aus einem Panel-Server ein
Monitor-Eintrag wird: "kennt unsere Bibliothek dieses Spiel?" Das hat
einen Fall ausgesperrt, den es wirklich gibt -- TeamSpeak.
UND ZWAR NICHT, WEIL GAMEDIG ES NICHT KOENNTE. Am 16.08.2026
nachgeschlagen, nachdem die Annahme "gamedig kennt TeamSpeak nicht"
sich als falsch erwies: gamedig 5.3.3 hat `teamspeak3`, DiscordGSM
fuehrt es ebenfalls. Der Grund ist ein anderer und ein besserer:
node_modules/gamedig/protocols/teamspeak3.js
queryPort = options.teamspeakQueryPort || 10011
'use port=<voice>' -> 'serverinfo' -> 'clientlist'
Es braucht den SERVERQUERY-Port. Beim Betreiber liegt der hier:
9987/udp -> 0.0.0.0:9987 Sprache, oeffentlich
10011/tcp -> 127.0.0.1:9988 ServerQuery, NUR localhost
30033/tcp -> 0.0.0.0:9989 Dateien, oeffentlich
Der Bot laeuft im Container und erreicht 127.0.0.1 des Hosts nie. Zwei
Gegenproben vom Host aus, beide gescheitert (die zweite auch deshalb,
weil gamedig ohne `teamspeakQueryPort` stur 10011 nimmt -- den es dort
gar nicht gibt). Eine Kennung einzutragen brauechte also einen OFFENEN
Verwaltungsport, und das ist genau das, was die Regel "kein Port geht
ohne Eintrag ins Netz" verhindert.
Das Panel dagegen laeuft auf dem Host, darf hin und hat die
Zugangsdaten -- und schickt seine eigene Messung seit heute im
Statusbericht mit. Also:
- `taugt` fragt `zeigbar` statt `gamedig`: "kann UEBERHAUPT JEMAND
diesen Server abfragen -- wir oder das Panel fuer uns?" Mit
Rueckfall auf `gamedig` fuer ein aelteres Panel; ohne den
verschwaenden nach diesem Update alle Eintraege, und zwar lautlos.
- Neuer eigener Typ `panel` neben `fivem` und `http`. Er ersetzt
nichts: wo gamedig kann, bleibt es bei gamedig -- dessen Antwort
bringt Karte, Fassung und Ping mit, die das Panel nicht liefert.
- `spieler === null` heisst KEINE ANTWORT, nicht null Spieler. Das
Panel sichert dazu einen Grund zu; wir werfen damit und landen im
selben Zweig wie ein gescheiterter gamedig-Query, statt eine 0 zu
erfinden. Und kein Ping: die Zahl ist eine gespeicherte Messung des
Panels, keine Antwortzeit von hier.
EINE FALLE BEIM ZWEITEN PARAMETER: `servers.map(queryServer)` haette
`panelItems` den INDEX untergeschoben -- der erste Server saehe null,
alle weiteren eine Zahl, an der `panelEintrag` still scheitert. Also
`map((s) => queryServer(s, panelItems))`.
Probe erweitert und im neu gebauten Abbild gelaufen, alles gruen --
einschliesslich "null Spieler sind eine Antwort, kein Ausfall".
This commit is contained in:
@@ -49,6 +49,42 @@ zeig(taugt(panel({ adresse: '' })) === false, 'ohne Adresse für Spieler -> nein
|
||||
zeig(taugt(panel({ port: null })) === false, 'ohne Port -> nein');
|
||||
zeig(taugt(undefined) === false, 'gar nichts -> nein');
|
||||
|
||||
console.log('');
|
||||
console.log('=== Was das Panel selbst abfragen kann (seit 16.08.2026)');
|
||||
//
|
||||
// DER FALL, UM DEN ES GEHT: TeamSpeak. gamedig KANN es -- das Protokoll
|
||||
// `teamspeak3` gibt es, DiscordGSM fuehrt es ebenfalls. Es braucht dafuer
|
||||
// aber den ServerQuery-Port, und der liegt beim Betreiber absichtlich auf
|
||||
// 127.0.0.1 (gemessen: 10011/tcp -> 127.0.0.1:9988). Der Bot im Container
|
||||
// kommt dort nie hin, das Panel auf dem Host schon -- und es hat die
|
||||
// Zugangsdaten. Also sagt das Panel `zeigbar: true` OHNE gamedig-Kennung,
|
||||
// und wir lesen seine Zahl ab, statt einen Verwaltungsport zu oeffnen.
|
||||
zeig(taugt(panel({ gamedig: null, zeigbar: true })) === true, 'ohne gamedig, aber das Panel kann fragen -> ja');
|
||||
zeig(taugt(panel({ gamedig: 'minecraft', zeigbar: false })) === false, 'Panel sagt nein -> nein, auch mit gamedig-Kennung');
|
||||
// DER RUECKFALL FUER EIN AELTERES PANEL. Ohne ihn verschwaenden nach einem
|
||||
// Bot-Update schlagartig alle Eintraege, und zwar lautlos.
|
||||
zeig(taugt(panel({ gamedig: 'minecraft' })) === true, 'aelteres Panel ohne `zeigbar` -> weiterhin ja');
|
||||
zeig(taugt(panel({ gamedig: null })) === false, 'aelteres Panel, kein gamedig -> weiterhin nein');
|
||||
|
||||
console.log('');
|
||||
console.log('=== Und welcher Typ dabei entsteht');
|
||||
{
|
||||
const vorher = db.listGameservers().length;
|
||||
const b = abgleichen([panel({ name: 'ts3', gamedig: null, zeigbar: true, port: 9987 })]);
|
||||
zeig(b.angelegt.includes('ts3'), 'ein Server ohne gamedig-Kennung wird angelegt', b.angelegt.join());
|
||||
const t = db.listGameservers().find((s) => s.name === 'ts3');
|
||||
zeig(t?.type === 'panel', 'und zwar mit dem Typ `panel` -- da fragt der Bot nicht selbst', t?.type);
|
||||
// Wo gamedig kann, bleibt es bei gamedig: dessen Antwort bringt Karte,
|
||||
// Fassung und Ping mit, die das Panel nicht liefert.
|
||||
abgleichen([panel({ name: 'ts3', gamedig: null, zeigbar: true, port: 9987 }), panel()]);
|
||||
zeig(db.listGameservers().find((s) => s.name === 'p1')?.type === 'minecraft', 'mit Kennung bleibt es bei gamedig -- der neue Typ ersetzt nichts');
|
||||
// Aufraeumen, damit die folgenden Abschnitte auf dem Stand von vorher
|
||||
// rechnen. Eine Probe, die den Stand veraendert, macht die naechste Zeile
|
||||
// unlesbar.
|
||||
abgleichen([]);
|
||||
zeig(db.listGameservers().length === vorher, 'und danach ist wieder aufgeraeumt');
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('=== Anlegen');
|
||||
let a = abgleichen([panel()]);
|
||||
@@ -111,6 +147,39 @@ zeig(danach.image_url === 'https://neu', 'und die Änderung ist drin');
|
||||
abgleichen([panel()]);
|
||||
zeig(db.getGameserver(p1.id).image_url === 'https://neu', 'der nächste Durchlauf plättet sie nicht');
|
||||
|
||||
console.log('');
|
||||
console.log('=== Der Typ `panel`: was der Bot daraus macht');
|
||||
{
|
||||
const { queryServer } = await import('../src/bot/server-monitor.js');
|
||||
const eintrag = { id: 99, name: 'ts3', type: 'panel', host: '1.2.3.4', port: 9987 };
|
||||
const bericht = (o) => [{
|
||||
name: 'ts3', port: 9987, spiel: 'TeamSpeak 3', zeigbar: true, gamedig: null,
|
||||
spieler: 3, spieler_max: 32, spieler_grund: null, ...o,
|
||||
}];
|
||||
|
||||
const r = await queryServer(eintrag, bericht());
|
||||
zeig(r.online === true && r.players === 3 && r.max === 32, 'die Zahl des Panels wird uebernommen', `${r.players}/${r.max}`);
|
||||
zeig(r.spielname === 'TeamSpeak 3', 'samt Spielname aus dem Bericht', r.spielname);
|
||||
// KEIN ERFUNDENER PING. Die Zahl ist eine gespeicherte Messung des Panels
|
||||
// und keine Antwortzeit von hier.
|
||||
zeig(r.ping === null, 'aber KEIN Ping -- den haben wir nicht gemessen', String(r.ping));
|
||||
|
||||
// null HEISST KEINE ANTWORT, NICHT NULL SPIELER. Das ist der ganze Punkt:
|
||||
// ein leerer Server und ein unerreichbarer duerfen nicht gleich aussehen.
|
||||
const ohne = await queryServer(eintrag, bericht({ spieler: null, spieler_grund: 'Der Server läuft nicht.' }));
|
||||
zeig(ohne.online === false, 'ohne Zahl: offline, statt eine 0 zu erfinden');
|
||||
zeig(ohne.players === null, 'und die Spielerzahl bleibt null', String(ohne.players));
|
||||
|
||||
// NULL SPIELER SIND EINE ANTWORT. Der haeufigste Zustand ueberhaupt --
|
||||
// wer ihn als "offline" liest, faerbt einen laufenden Server rot.
|
||||
const leer = await queryServer(eintrag, bericht({ spieler: 0 }));
|
||||
zeig(leer.online === true && leer.players === 0, 'null Spieler sind eine Antwort, kein Ausfall');
|
||||
|
||||
// Und die Faelle, in denen gar nichts da ist.
|
||||
zeig((await queryServer(eintrag, null)).online === false, 'ohne Panel-Bericht: offline statt Absturz');
|
||||
zeig((await queryServer(eintrag, [])).online === false, 'leerer Bericht: offline statt Absturz');
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log('=== Kaputte Berichte');
|
||||
zeig(abgleichen(null).angelegt.length === 0, 'null -> nichts passiert');
|
||||
|
||||
Reference in New Issue
Block a user