Fehlende Kanäle und Rollen aus dem Panel anlegen
Die Status-Seite listet Module, denen ein Kanal oder eine Rolle fehlt. Bisher hieß das: rüber zu Discord, Kanal anlegen, Rechte setzen, zurück ins Panel, auswählen, speichern. Jetzt steht daneben ein Knopf, der genau das in einem Schritt macht — inklusive Eintragen der Einstellung. Die Vorlagen hängen bei den Modulen (modules.js): Name, Thema und ob der Kanal privat sein soll. Private Kanäle bekommen @everyone entzogen und Bot plus alle Rollen mit Moderationsrecht eingetragen — sonst legt man einen Modmail-Kanal an, den das Team nicht sieht. Gibt es Kanal oder Rolle schon (bei Rollen unabhängig von Groß- und Kleinschreibung), werden sie verknüpft statt doppelt angelegt. Beim Temp-Voice-Hub entsteht ein Sprachkanal statt eines Textkanals. Fehlen dem Bot die Rechte, steht das im Panel im Klartext („Dem Bot fehlt das Recht Kanäle verwalten") statt einer Discord-Fehlernummer. Bewusst nur Anlegen: kein Löschen, kein Umbenennen. Ein Fehlklick beim Anlegen kostet einen überflüssigen Kanal, einer beim Löschen dessen Verlauf. Umbenennen wäre zusätzlich eine Falle, weil Discord es auf zwei Änderungen pro zehn Minuten und Kanal begrenzt. moduleMissing liefert dafür Objekte statt Beschriftungen, damit das Panel weiß, was sich anlegen lässt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
// Fehlende Kanäle und Rollen direkt aus dem Panel anlegen.
|
||||
//
|
||||
// Anlass: Die Status-Seite listet Module, denen ein Kanal oder eine Rolle
|
||||
// fehlt. Bisher hieß das: rüber zu Discord, Kanal anlegen, Rechte setzen,
|
||||
// zurück ins Panel, auswählen, speichern. Das hier macht daraus einen Klick.
|
||||
//
|
||||
// Bewusst nur Anlegen, kein Löschen und kein Umbenennen: ein Fehlklick beim
|
||||
// Anlegen kostet einen überflüssigen Kanal, ein Fehlklick beim Löschen kostet
|
||||
// dessen Verlauf.
|
||||
import { ChannelType, PermissionFlagsBits } from 'discord.js';
|
||||
import { setSetting } from '../db.js';
|
||||
import { creationPlan } from '../modules.js';
|
||||
import { discordGuildId } from '../runtime-settings.js';
|
||||
|
||||
/** Server, auf dem gearbeitet wird — konfigurierter, sonst der erste */
|
||||
function targetGuild(client) {
|
||||
const id = discordGuildId();
|
||||
return (id ? client.guilds.cache.get(id) : null) ?? [...client.guilds.cache.values()][0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kanal oder Rolle für eine Einstellung anlegen und diese gleich eintragen.
|
||||
*
|
||||
* @param {import('discord.js').Client} client
|
||||
* @param {string} setting — z. B. 'devlog_channel_id'
|
||||
* @returns {Promise<{ id: string, name: string, art: 'kanal'|'rolle' }>}
|
||||
* @throws {Error} mit einer Meldung, die im Panel angezeigt werden kann
|
||||
*/
|
||||
export async function createForSetting(client, setting) {
|
||||
const plan = creationPlan(setting);
|
||||
if (!plan) throw new Error('Dafür gibt es keine Vorlage — bitte von Hand anlegen.');
|
||||
|
||||
const guild = targetGuild(client);
|
||||
if (!guild) throw new Error('Kein Discord-Server gefunden.');
|
||||
|
||||
const me = guild.members.me ?? await guild.members.fetchMe().catch(() => null);
|
||||
if (!me) throw new Error('Der Bot findet sich selbst nicht auf dem Server.');
|
||||
|
||||
if (plan.rolle) {
|
||||
if (!me.permissions.has(PermissionFlagsBits.ManageRoles)) {
|
||||
throw new Error('Dem Bot fehlt das Recht „Rollen verwalten".');
|
||||
}
|
||||
// Vorhandene gleichnamige Rolle wiederverwenden statt ein Duplikat anlegen
|
||||
const vorhanden = [...guild.roles.cache.values()]
|
||||
.find((r) => r.name.toLowerCase() === plan.name.toLowerCase());
|
||||
const role = vorhanden ?? await guild.roles.create({
|
||||
name: plan.name,
|
||||
color: plan.farbe ?? undefined,
|
||||
mentionable: false,
|
||||
reason: 'Über das d4rkbot-Panel angelegt',
|
||||
});
|
||||
setSetting(setting, role.id);
|
||||
return { id: role.id, name: role.name, art: 'rolle', wiederverwendet: Boolean(vorhanden) };
|
||||
}
|
||||
|
||||
if (!me.permissions.has(PermissionFlagsBits.ManageChannels)) {
|
||||
throw new Error('Dem Bot fehlt das Recht „Kanäle verwalten".');
|
||||
}
|
||||
|
||||
const gewuenschterTyp = plan.sprache ? ChannelType.GuildVoice : ChannelType.GuildText;
|
||||
const vorhanden = [...guild.channels.cache.values()]
|
||||
.find((c) => c.name === plan.name && c.type === gewuenschterTyp);
|
||||
if (vorhanden) {
|
||||
setSetting(setting, vorhanden.id);
|
||||
return { id: vorhanden.id, name: vorhanden.name, art: 'kanal', wiederverwendet: true };
|
||||
}
|
||||
|
||||
// Private Kanäle: @everyone raus, Bot und Team-Rollen mit Moderationsrecht rein
|
||||
const overwrites = [];
|
||||
if (plan.privat) {
|
||||
overwrites.push({ id: guild.roles.everyone.id, deny: [PermissionFlagsBits.ViewChannel] });
|
||||
overwrites.push({ id: me.id, allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages] });
|
||||
for (const role of guild.roles.cache.values()) {
|
||||
if (role.permissions.has(PermissionFlagsBits.ManageMessages) && !role.managed) {
|
||||
overwrites.push({ id: role.id, allow: [PermissionFlagsBits.ViewChannel] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const channel = await guild.channels.create({
|
||||
name: plan.name,
|
||||
type: gewuenschterTyp,
|
||||
topic: plan.sprache ? undefined : plan.topic,
|
||||
permissionOverwrites: overwrites.length ? overwrites : undefined,
|
||||
reason: 'Über das d4rkbot-Panel angelegt',
|
||||
});
|
||||
|
||||
setSetting(setting, channel.id);
|
||||
return { id: channel.id, name: channel.name, art: 'kanal', wiederverwendet: false };
|
||||
}
|
||||
Reference in New Issue
Block a user