more mvp strip

This commit is contained in:
2026-04-21 17:24:03 +00:00
parent 6d579207f3
commit f3ee27ed7a
17 changed files with 598 additions and 1088 deletions

View File

@@ -273,145 +273,49 @@ async function cleanupEmptyOverflowCategory(guild, categoryId, categoryName) {
}
async function createTicketChannel(guild, ticketNumber, userId, subject, creatorNickname) {
if (CONFIG.USE_THREADS && CONFIG.THREAD_PARENT_CHANNEL) {
const parentChannel = guild.channels.cache.get(CONFIG.THREAD_PARENT_CHANNEL);
if (!parentChannel) {
throw new Error('Thread parent channel not found');
}
let parentId;
try {
parentId = await getOrCreateTicketCategory(guild, CONFIG.TICKET_CATEGORY_ID, CONFIG.TICKET_CATEGORY_NAME);
} catch (e) {
console.error('getOrCreateTicketCategory (createTicketChannel):', e);
throw new Error('Ticket category not found or could not be allocated');
}
const thread = await parentChannel.threads.create({
name: `🎫・ticket-${ticketNumber}`,
autoArchiveDuration: 1440,
type: ChannelType.PrivateThread,
invitable: false,
reason: `Ticket #${ticketNumber}`
});
await thread.members.add(userId);
// Add all members with the support role so they can see and reply in the thread
if (CONFIG.ROLE_ID_TO_PING) {
const role = guild.roles.cache.get(CONFIG.ROLE_ID_TO_PING);
if (role?.members?.size) {
for (const [memberId] of role.members) {
if (memberId === userId) continue; // already added
await thread.members.add(memberId).catch(() => {});
let channel;
try {
channel = await guild.channels.create({
name: creatorNickname ? toDiscordSafeName(`unclaimed-${creatorNickname}-${ticketNumber}`) : `ticket-${ticketNumber}`,
type: ChannelType.GuildText,
parent: parentId,
permissionOverwrites: [
{
id: guild.id,
deny: [PermissionFlagsBits.ViewChannel]
},
{
id: userId,
allow: [
PermissionFlagsBits.ViewChannel,
PermissionFlagsBits.SendMessages,
PermissionFlagsBits.ReadMessageHistory
]
},
{
id: CONFIG.ROLE_ID_TO_PING,
allow: [
PermissionFlagsBits.ViewChannel,
PermissionFlagsBits.SendMessages,
PermissionFlagsBits.ReadMessageHistory
]
}
}
}
return thread;
} else {
let parentId;
try {
parentId = await getOrCreateTicketCategory(guild, CONFIG.TICKET_CATEGORY_ID, CONFIG.TICKET_CATEGORY_NAME);
} catch (e) {
console.error('getOrCreateTicketCategory (createTicketChannel):', e);
throw new Error('Ticket category not found or could not be allocated');
}
let channel;
try {
channel = await guild.channels.create({
name: creatorNickname ? toDiscordSafeName(`unclaimed-${creatorNickname}-${ticketNumber}`) : `ticket-${ticketNumber}`,
type: ChannelType.GuildText,
parent: parentId,
permissionOverwrites: [
{
id: guild.id,
deny: [PermissionFlagsBits.ViewChannel]
},
{
id: userId,
allow: [
PermissionFlagsBits.ViewChannel,
PermissionFlagsBits.SendMessages,
PermissionFlagsBits.ReadMessageHistory
]
},
{
id: CONFIG.ROLE_ID_TO_PING,
allow: [
PermissionFlagsBits.ViewChannel,
PermissionFlagsBits.SendMessages,
PermissionFlagsBits.ReadMessageHistory
]
}
]
});
} catch (e) {
console.error('guild.channels.create (createTicketChannel):', e);
throw e;
}
return channel;
]
});
} catch (e) {
console.error('guild.channels.create (createTicketChannel):', e);
throw e;
}
}
/**
* Create a private Discord ticket thread under DISCORD_THREAD_CHANNEL_ID.
* Adds creator and all members with ROLE_ID_TO_PING.
* @param {import('discord.js').Guild} guild
* @param {number} ticketNumber
* @param {string} creatorUserId
* @returns {Promise<import('discord.js').ThreadChannel>}
*/
async function createDiscordTicketAsThread(guild, ticketNumber, creatorUserId) {
const parentId = CONFIG.DISCORD_THREAD_CHANNEL_ID;
if (!parentId) throw new Error('DISCORD_THREAD_CHANNEL_ID is not set');
const parentChannel = guild.channels.cache.get(parentId);
if (!parentChannel) throw new Error('Discord thread parent channel not found');
const thread = await parentChannel.threads.create({
name: `🎫・ticket-${ticketNumber}`,
autoArchiveDuration: 1440,
type: ChannelType.PrivateThread,
invitable: false,
reason: `Ticket #${ticketNumber}`
});
await thread.members.add(creatorUserId);
if (CONFIG.ROLE_ID_TO_PING) {
const role = guild.roles.cache.get(CONFIG.ROLE_ID_TO_PING);
if (role?.members?.size) {
for (const [memberId] of role.members) {
if (memberId === creatorUserId) continue;
await thread.members.add(memberId).catch(() => {});
}
}
}
return thread;
}
/**
* Create a private email ticket thread under EMAIL_THREAD_CHANNEL_ID.
* Adds all members with ROLE_ID_TO_PING (no creator; email tickets have no Discord user).
* @param {import('discord.js').Guild} guild
* @param {number} ticketNumber
* @param {string} chanName
* @returns {Promise<import('discord.js').ThreadChannel>}
*/
async function createEmailTicketAsThread(guild, ticketNumber, chanName) {
const parentId = CONFIG.EMAIL_THREAD_CHANNEL_ID;
if (!parentId) throw new Error('EMAIL_THREAD_CHANNEL_ID is not set');
const parentChannel = guild.channels.cache.get(parentId);
if (!parentChannel) throw new Error('Email thread parent channel not found');
const thread = await parentChannel.threads.create({
name: chanName || `🎫・ticket-${ticketNumber}`,
autoArchiveDuration: 1440,
type: ChannelType.PrivateThread,
invitable: false,
reason: `Ticket #${ticketNumber}`
});
if (CONFIG.ROLE_ID_TO_PING) {
const role = guild.roles.cache.get(CONFIG.ROLE_ID_TO_PING);
if (role?.members?.size) {
for (const [memberId] of role.members) {
await thread.members.add(memberId).catch(() => {});
}
}
}
return thread;
return channel;
}
// --- LIMITS & PERMISSIONS ---
@@ -649,8 +553,6 @@ module.exports = {
getNextTicketNumber,
getOrCreateTicketCategory,
cleanupEmptyOverflowCategory,
createDiscordTicketAsThread,
createEmailTicketAsThread,
RENAME_WINDOW_MS,
RENAME_LIMIT,
getSenderLocal,