Playtester werden jetzt beworben, nicht angeklickt
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Der Knopf unter dem Playtester-Aufruf hat jeden aufgenommen, der ihn gedrueckt
hat — ohne Frage, ohne Pruefung. Fuer ein Programm, dessen Teilnehmer Zugang
und Alpha-Keys bekommen, ist das die falsche Tuer.

Statt einen zweiten Pruef-Ablauf danebenzustellen, laeuft die Aufnahme jetzt
ueber die Bewerbungs-Formulare, die es laengst gibt: Modal ausfuellen,
Review-Embed im Staff-Kanal,  oder , Rolle und Antwort-DM bei Zusage. Das
ist dieselbe Maschinerie, nur ein anderer Aufhaenger — und damit auch nur eine
Stelle, an der spaeter etwas kaputtgehen kann.

Ein Formular laesst sich als Playtester-Formular markieren ("Annahme traegt als
Playtester ein"). Wer dort angenommen wird, landet zusaetzlich in der
Playtester-Liste, damit die Schluessel-Verteilung ihn kennt. Nur eines kann es
sein — sonst wuesste /playtester-setup nicht, welches es posten soll.

/playtester-setup postet jetzt den Knopf dieses Formulars. Fehlt das Formular,
fehlen Fragen oder fehlt der Review-Kanal, sagt der Befehl das, statt einen
Aufruf zu posten, der ins Leere fuehrt.

Der alte Knopf in bereits geposteten Nachrichten nimmt niemanden mehr auf: er
verweist auf den Aufruf. Austreten bleibt Selbstbedienung — dafuer braucht es
keine Freigabe.

Im Panel steht im Playtester-Bereich, ueber welches Formular die Aufnahme
laeuft, ob es schon gepostet ist, und ein Weg dorthin. Ohne markiertes Formular
steht dort, dass gerade niemand hereinkommt — das ist sonst der Grund, warum
sich tagelang niemand bewirbt.

Geprueft: Routen, SQL gegen das Schema, und im Browser beide Zustaende des
Hinweises sowie der neue Schalter — beim Wechsel zwischen zwei Formularen
folgt er dem richtigen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 10:04:16 +02:00
co-authored by Claude Opus 5
parent ddd7610d6c
commit 1c5c7d2470
8 changed files with 139 additions and 31 deletions
+11 -3
View File
@@ -9,7 +9,7 @@ import {
topLevels, saveTag, listTags, deleteTag,
createScheduledPost, listScheduledPosts, deleteScheduledPost,
addAlphaKeys, freeAlphaKeyCount, assignedAlphaKeys, alphaKeyOf, reserveAlphaKey, unreserveAlphaKey,
createAppForm, updateAppForm, getAppForm, listAppForms, deleteAppForm,
createAppForm, updateAppForm, getAppForm, listAppForms, deleteAppForm, clearOtherPlaytesterForms,
saveTrigger, listTriggers, deleteTrigger, activityRange,
createGameserver, updateGameserver, listGameservers, getGameserver, deleteGameserver,
saveWebAdmin, webAdminScopes, listWebAdmins, deleteWebAdmin,
@@ -1446,9 +1446,15 @@ ${rssItems}
approve_role_id: roleId || null,
post_channel_id: String(body.post_channel_id ?? '') || null,
questions: JSON.stringify(questions),
playtester: body.playtester ? 1 : 0,
};
}
/** Nur ein Formular kann das Playtester-Formular sein */
function playtesterExklusiv(form, id) {
if (form.playtester) clearOtherPlaytesterForms(id);
}
app.get('/api/appforms', async (request, reply) => {
if (requireScope(request, reply, 'bewerbungen')) return;
return { forms: listAppForms().map(formToJson) };
@@ -1459,7 +1465,8 @@ ${rssItems}
const form = parseFormBody(request, reply);
if (!form) return;
const id = createAppForm(form);
return { ok: true, form: formToJson(getAppForm(id)) };
playtesterExklusiv(form, id);
return { ok: true, form: formToJson(getAppForm(id)), forms: listAppForms().map(formToJson) };
});
app.put('/api/appforms/:id', async (request, reply) => {
@@ -1469,12 +1476,13 @@ ${rssItems}
const form = parseFormBody(request, reply);
if (!form) return;
updateAppForm({ ...form, id });
playtesterExklusiv(form, id);
if (getAppForm(id).message_id) {
await publishAppForm(client, id).catch((e) =>
request.log.warn(`Formular ${id}: Discord-Update fehlgeschlagen: ${e.message}`)
);
}
return { ok: true, form: formToJson(getAppForm(id)) };
return { ok: true, form: formToJson(getAppForm(id)), forms: listAppForms().map(formToJson) };
});
app.post('/api/appforms/:id/publish', async (request, reply) => {