Playtester werden jetzt beworben, nicht angeklickt
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:
@@ -5,7 +5,7 @@ import {
|
||||
ModalBuilder, TextInputBuilder, TextInputStyle,
|
||||
} from 'discord.js';
|
||||
import {
|
||||
getAppForm, setAppFormMessage,
|
||||
getAppForm, setAppFormMessage, addPlaytester,
|
||||
createApplication, getApplication, openApplicationOf, setApplicationStatus,
|
||||
} from '../db.js';
|
||||
import { brandColor, brandColor2, brandFooter } from '../runtime-settings.js';
|
||||
@@ -172,6 +172,11 @@ export async function handleReviewButton(interaction) {
|
||||
console.error(`[bewerbung] Rolle fehlgeschlagen: ${e.message}`)
|
||||
);
|
||||
}
|
||||
// Playtester-Formular: Annahme trägt zusätzlich in die Liste ein, damit die
|
||||
// Schlüssel-Verteilung denjenigen kennt
|
||||
if (approved && form?.playtester) {
|
||||
addPlaytester(application.user_id, application.username ?? application.user_id);
|
||||
}
|
||||
// DM an den Bewerber
|
||||
const user = await interaction.client.users.fetch(application.user_id).catch(() => null);
|
||||
await user?.send(renderTemplate(approved ? 'application.approved' : 'application.denied', {
|
||||
|
||||
+16
-10
@@ -22,7 +22,7 @@ import {
|
||||
import { handleRoleMenuButton } from './role-menus.js';
|
||||
import { handleGiveawayAdminButton } from './giveaways.js';
|
||||
import {
|
||||
addPlaytester, removePlaytester, isWish, bumpWish,
|
||||
removePlaytester, playtesterForm, isWish, bumpWish,
|
||||
getGiveaway, toggleGiveawayEntry, giveawayEntries,
|
||||
} from '../db.js';
|
||||
import * as ping from './commands/ping.js';
|
||||
@@ -309,22 +309,28 @@ export async function startBot() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 🧪-Button: Playtester-Rolle + Liste togglen
|
||||
// 🧪-Button aus älteren Posts. Aufgenommen wird hier niemand mehr —
|
||||
// das läuft über das Playtester-Formular mit Prüfung durch das Team.
|
||||
// Austreten bleibt Selbstbedienung: dafür braucht es keine Freigabe.
|
||||
if (interaction.isButton() && interaction.customId === 'playtester_toggle') {
|
||||
const roleId = playtesterRoleId();
|
||||
try {
|
||||
if (!roleId || !interaction.inGuild()) throw new Error('Keine Playtester-Rolle konfiguriert');
|
||||
const member = interaction.member;
|
||||
const hasRole = member.roles.cache.has(roleId);
|
||||
if (hasRole) {
|
||||
await member.roles.remove(roleId);
|
||||
removePlaytester(interaction.user.id);
|
||||
} else {
|
||||
await member.roles.add(roleId);
|
||||
addPlaytester(interaction.user.id, interaction.user.username);
|
||||
if (!member.roles.cache.has(roleId)) {
|
||||
const form = playtesterForm();
|
||||
await interaction.reply({
|
||||
content: form
|
||||
? '❕ Dieser Knopf ist veraltet. Bewirb dich über den Playtester-Aufruf — dort füllst du ein kurzes Formular aus, das Team meldet sich.'
|
||||
: '❕ Bewerbungen laufen gerade nicht über diesen Knopf. Melde dich beim Team.',
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await member.roles.remove(roleId);
|
||||
removePlaytester(interaction.user.id);
|
||||
await interaction.reply({
|
||||
content: renderTemplate(hasRole ? 'playtester.left' : 'playtester.joined', {
|
||||
content: renderTemplate('playtester.left', {
|
||||
user: member.displayName ?? interaction.user.username,
|
||||
mention: `<@${interaction.user.id}>`,
|
||||
}),
|
||||
|
||||
@@ -1,20 +1,52 @@
|
||||
// /playtester-setup — postet das Bewerbungs-Embed mit Button in den aktuellen Kanal (Admin)
|
||||
// /playtester-setup — postet den Playtester-Aufruf in den aktuellen Kanal (Admin)
|
||||
//
|
||||
// Ist ein Bewerbungs-Formular als Playtester-Formular markiert, führt der Knopf
|
||||
// dorthin: ausfüllen, das Team entscheidet. Ohne Formular gäbe es nur den alten
|
||||
// Selbstbedienungs-Knopf — und der macht jeden zum Playtester, der draufdrückt.
|
||||
// Deshalb sagt der Befehl dann, was zu tun ist, statt ihn zu posten.
|
||||
import {
|
||||
SlashCommandBuilder, PermissionFlagsBits, MessageFlags,
|
||||
ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder,
|
||||
} from 'discord.js';
|
||||
import { playtesterRoleId, brandColor, brandFooter } from '../../runtime-settings.js';
|
||||
import { renderTemplate } from '../../templates.js';
|
||||
import { playtesterForm } from '../../db.js';
|
||||
|
||||
export const data = new SlashCommandBuilder()
|
||||
.setName('playtester-setup')
|
||||
.setDescription('Postet das Playtester-Bewerbungs-Embed in diesen Kanal')
|
||||
.setDescription('Postet den Playtester-Aufruf in diesen Kanal')
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator);
|
||||
|
||||
export async function execute(interaction) {
|
||||
if (!playtesterRoleId()) {
|
||||
await interaction.reply({
|
||||
content: '❌ Erst auf der Config-Seite eine Playtester-Rolle wählen.',
|
||||
content: '❌ Erst in der Config eine Playtester-Rolle wählen.',
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const form = playtesterForm();
|
||||
if (!form) {
|
||||
await interaction.reply({
|
||||
content: '❌ Kein Playtester-Formular gesetzt.\n'
|
||||
+ 'Config → **Bewerbungen**: ein Formular anlegen und dort '
|
||||
+ '„Annahme trägt als Playtester ein" ankreuzen. Dann kann sich '
|
||||
+ 'niemand mehr per Knopfdruck selbst aufnehmen.',
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (JSON.parse(form.questions || '[]').length === 0) {
|
||||
await interaction.reply({
|
||||
content: `❌ Das Formular „${form.title}" hat noch keine Fragen.`,
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!form.review_channel_id) {
|
||||
await interaction.reply({
|
||||
content: `❌ Für „${form.title}" fehlt der Review-Kanal — sonst sieht niemand die Bewerbungen.`,
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
return;
|
||||
@@ -26,14 +58,19 @@ export async function execute(interaction) {
|
||||
.setDescription(renderTemplate('playtester.panel_text'))
|
||||
.setFooter({ text: brandFooter('PLAYTEST') });
|
||||
|
||||
// Derselbe Knopf wie beim Bewerbungs-Formular — das Formular, die Prüfung
|
||||
// und die Antwort-DMs sind dieselbe Maschinerie, nur ein anderer Aufhänger.
|
||||
const row = new ActionRowBuilder().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId('playtester_toggle')
|
||||
.setCustomId(`apply:${form.id}`)
|
||||
.setStyle(ButtonStyle.Success)
|
||||
.setLabel('Als Playtester bewerben')
|
||||
.setEmoji('🧪')
|
||||
);
|
||||
|
||||
await interaction.channel.send({ embeds: [embed], components: [row] });
|
||||
await interaction.reply({ content: '✅ Bewerbungs-Post erstellt.', flags: MessageFlags.Ephemeral });
|
||||
await interaction.reply({
|
||||
content: `✅ Aufruf gepostet — Bewerbungen laufen über „${form.title}".`,
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user