Ticket-System, Web-Composer und Nachrichten-Bearbeitung
- Tickets: /ticket-setup postet 🎫-Button; Klick erstellt privaten Thread (ein offenes Ticket pro User), Schließen-Button sperrt + archiviert - Composer auf der Setup-Seite: Nachricht/Embed als Bot in beliebigen Kanal senden oder per Message-ID bearbeiten (nur eigene Bot-Posts) - API v1: PATCH /api/v1/message — Skripte können ihre Bot-Posts aktualisieren - Setting ticket_channel_id; README ergänzt Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+47
-1
@@ -212,6 +212,7 @@ ${rssItems}
|
||||
modlog_channel_id: getSetting('modlog_channel_id') ?? '',
|
||||
status_channel_id: getSetting('status_channel_id') ?? '',
|
||||
voting_channel_id: getSetting('voting_channel_id') ?? '',
|
||||
ticket_channel_id: getSetting('ticket_channel_id') ?? '',
|
||||
gameservers: getSetting('gameservers') ?? '',
|
||||
};
|
||||
}
|
||||
@@ -244,7 +245,7 @@ ${rssItems}
|
||||
const OPTIONAL_CHANNELS = [
|
||||
'release_channel_id', 'backup_channel_id', 'starboard_channel_id',
|
||||
'screenshot_channel_id', 'modmail_channel_id', 'welcome_channel_id',
|
||||
'modlog_channel_id', 'status_channel_id', 'voting_channel_id',
|
||||
'modlog_channel_id', 'status_channel_id', 'voting_channel_id', 'ticket_channel_id',
|
||||
];
|
||||
for (const key of ['commit_channel_id', 'devlog_channel_id', ...OPTIONAL_CHANNELS]) {
|
||||
if (body[key] === undefined) continue;
|
||||
@@ -312,6 +313,51 @@ ${rssItems}
|
||||
return { ok: true, settings: currentSettings() };
|
||||
});
|
||||
|
||||
// Composer (Admin): Nachricht/Embed als Bot senden oder eigene Posts bearbeiten
|
||||
app.post('/api/compose', async (request, reply) => {
|
||||
if (requireAdmin(request, reply)) return;
|
||||
|
||||
const { channel_id: channelId, message_id: messageId, content, embed_title: embedTitle } = request.body ?? {};
|
||||
const text = String(content ?? '').trim();
|
||||
if (!channelId || !text) {
|
||||
return reply.code(400).send({ error: 'channel_id und content nötig' });
|
||||
}
|
||||
const channel = await client.channels.fetch(String(channelId)).catch(() => null);
|
||||
if (!channel?.isTextBased()) {
|
||||
return reply.code(404).send({ error: 'Kanal nicht gefunden' });
|
||||
}
|
||||
|
||||
// Mit Embed-Titel → gebrandetes Embed, sonst Plaintext (Discord-Markdown)
|
||||
const payload = embedTitle?.trim()
|
||||
? {
|
||||
content: null,
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setColor(0xf5c518)
|
||||
.setTitle(String(embedTitle).slice(0, 200))
|
||||
.setDescription(text.slice(0, 4000))
|
||||
.setFooter({ text: 'D4RKST3R' })
|
||||
.setTimestamp(),
|
||||
],
|
||||
}
|
||||
: { content: text.slice(0, 2000), embeds: [] };
|
||||
|
||||
if (messageId) {
|
||||
const message = await channel.messages.fetch(String(messageId)).catch(() => null);
|
||||
if (!message) return reply.code(404).send({ error: 'Nachricht nicht gefunden' });
|
||||
if (message.author?.id !== client.user?.id) {
|
||||
return reply.code(403).send({ error: 'Nur eigene Bot-Nachrichten sind editierbar' });
|
||||
}
|
||||
await message.edit(payload);
|
||||
request.log.info(`Composer: Nachricht ${messageId} bearbeitet`);
|
||||
return { ok: true, edited: true, message_id: String(messageId) };
|
||||
}
|
||||
|
||||
const message = await channel.send(payload);
|
||||
request.log.info(`Composer: Nachricht ${message.id} gesendet`);
|
||||
return { ok: true, edited: false, message_id: message.id };
|
||||
});
|
||||
|
||||
// --- API-Keys (Admin) — für /api/v1/* ---
|
||||
|
||||
const VALID_SCOPES = ['message', 'dm', 'roles', 'read'];
|
||||
|
||||
Reference in New Issue
Block a user