Linked Roles: Rollen, die an geprueften Werten haengen
Neues Modul, standardmaessig aus. Ein Mitglied klickt in Discord auf "Rolle holen", landet auf /linked-roles, bestaetigt den OAuth-Dialog — und der Bot schiebt ihm drei Kennzahlen zu, die Discord dann gegen die Rollen-Einstellung prueft: level Zahl >= eingestelltem Wert dabei_seit Datum <= "vor X Tagen", also Mitglied seit mindestens X Tagen playtester Wahrheitswert Der Bot vergibt dabei keine Rollen. Er liefert nur die Zahlen; was daraus wird, entscheidet die Rollen-Einstellung im Server. Die Daten kommen aus dem, was ohnehin da ist: Level-Tabelle, Playtester-Liste, Discords Beitrittsdatum. Eigener OAuth-Weg statt /auth/login, weil die Berechtigungen andere sind — role_connections.write hat der normale Login nicht. Die Tokens werden gespeichert, und das ist keine Bequemlichkeit: ohne Refresh-Token bliebe jede Rolle auf dem Stand des Verknuepfungs-Tages stehen, ein Level-Up kaeme nie an. Discords eigene Anleitung sagt dasselbe. Der Umfang ist eng (nur identify + role_connections.write), beim Widerruf oder Entkoppeln fliegt der Datensatz sofort raus. Steht so auch als Kommentar an der Tabelle. Abgeglichen wird alle 6 Stunden, einstellbar. Dafuer kann everyTuned jetzt auch Stunden — und wirft bei einer unbekannten Einheit, statt den Abstand still um Faktor 60 oder 3600 danebenzulegen. Beim Bauen gefunden: moduleEnabled fehlte im Import von client.js. Der Bot waere beim ClientReady mit ReferenceError gestorben. Geprueft: alle drei Kennzahlen gegen Discords Formatgrenzen (Schluessel-Regex, Laengen, gueltige Typ-Codes), Modul- und Stellwert-Register, die Stunden-Umrechnung (6 h = 21600000 ms), Speichern und Loeschen einer Verknuepfung, dazu 186 SQL-Abfragen und alle Routen auf Rechtepruefung. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1074,6 +1074,42 @@ export function setSetting(key, value) {
|
||||
setSettingStmt.run(key, value);
|
||||
}
|
||||
|
||||
// Linked Roles: OAuth-Tokens der Mitglieder, die ihr Konto verknüpft haben.
|
||||
//
|
||||
// Das Speichern ist nicht optional — ohne Refresh-Token bliebe die verknüpfte
|
||||
// Rolle für immer auf dem Stand des Verknüpfungs-Tages stehen, ein Level-Up
|
||||
// käme nie an. Discords eigene Anleitung sagt dasselbe.
|
||||
//
|
||||
// Die Tokens gelten NUR für role_connections.write und identify. Damit kann
|
||||
// man weder Nachrichten lesen noch im Namen des Users handeln. Trotzdem:
|
||||
// wer die Datenbank hat, hat diese Tokens — sie liegen im selben Volume wie
|
||||
// alles andere und werden beim Entkoppeln sofort gelöscht.
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS role_connections (
|
||||
user_id TEXT PRIMARY KEY,
|
||||
username TEXT,
|
||||
access_token TEXT NOT NULL,
|
||||
refresh_token TEXT NOT NULL,
|
||||
expires_at INTEGER NOT NULL,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
`);
|
||||
const upsertRoleConnStmt = db.prepare(`
|
||||
INSERT INTO role_connections (user_id, username, access_token, refresh_token, expires_at, updated_at)
|
||||
VALUES (@user_id, @username, @access_token, @refresh_token, @expires_at, datetime('now'))
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
username = excluded.username, access_token = excluded.access_token,
|
||||
refresh_token = excluded.refresh_token, expires_at = excluded.expires_at,
|
||||
updated_at = datetime('now')
|
||||
`);
|
||||
const getRoleConnStmt = db.prepare('SELECT * FROM role_connections WHERE user_id = ?');
|
||||
const allRoleConnStmt = db.prepare('SELECT * FROM role_connections');
|
||||
const deleteRoleConnStmt = db.prepare('DELETE FROM role_connections WHERE user_id = ?');
|
||||
export const saveRoleConnection = (r) => upsertRoleConnStmt.run(r);
|
||||
export const getRoleConnection = (userId) => getRoleConnStmt.get(userId) ?? null;
|
||||
export const allRoleConnections = () => allRoleConnStmt.all();
|
||||
export const deleteRoleConnection = (userId) => deleteRoleConnStmt.run(userId).changes > 0;
|
||||
|
||||
// Einmalige Übernahme der alten kommagetrennten Watchdog-Liste in die
|
||||
// Dienst-Tabelle. Muss hier unten stehen, weil sie getSetting() braucht.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user