diff --git a/README.md b/README.md index d5b7cc9..39dbcc1 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ These go in `config.json`. See also `config.example.json`. |greetingMessage|None|Text content of the welcome message| |ignoreAccidentalThreads|false|If set to true, the bot attempts to ignore common "accidental" messages that would start a new thread, such as "ok", "thanks", etc.| |inboxServerPermission|None|Permission required to use bot commands on the inbox server| +|joinedAtDeniedMessage|None|"You haven't been a member of the server for enough time to contact modmail"|See `requiredJoinedAt` below| |mentionRole|"here"|Role that is mentioned when new threads are created or the bot is mentioned. Accepted values are "here", "everyone", or a role id as a string. Set to null to disable these pings entirely.| |mentionUserInThreadHeader|false|If set to true, mentions the thread's user in the thread header| |newThreadCategoryId|None|ID of the category where new modmail thread channels should be placed| @@ -89,6 +90,7 @@ These go in `config.json`. See also `config.example.json`. |prefix|"!"|Prefix for bot commands| |relaySmallAttachmentsAsAttachments|false|Whether to relay small attachments from users as native attachments rather than links in modmail threads| |requiredAccountAge|None|Required account age for contacting modmail (in hours). If the account is not old enough, a new thread will not be created and the bot will reply with `accountAgeDeniedMessage` (if set) instead.| +|requiredJoinedAt|None|Required amount of time (in hours) the user must be a member of the server before being able to contact modmail. If the user hasn't been a member of the server for the specified time, a new thread will not be created and the bot will reply with `joinedAtDeniedMessage` (if set) instead.| |responseMessage|"Thank you for your message! Our mod team will reply to you here as soon as possible."|The bot's response to DMs that start a new thread| |smallAttachmentLimit|2097152|Size limit of `relaySmallAttachmentsAsAttachments`, in bytes (default is 2MB)| |snippetPrefix|"!!"|Prefix to use snippets| diff --git a/src/config.js b/src/config.js index 411e527..1f9f17a 100644 --- a/src/config.js +++ b/src/config.js @@ -78,6 +78,9 @@ const defaultConfig = { "requiredAccountAge": null, // In hours "accountAgeDeniedMessage": "Your Discord account is not old enough to contact modmail.", + "requiredJoinedAt": null, // In hours too + "joinedAtDeniedMessage": "You haven't been a member of the server for enough time to contact modmail", + "relaySmallAttachmentsAsAttachments": false, "smallAttachmentLimit": 1024 * 1024 * 2, "attachmentStorage": "local", diff --git a/src/data/threads.js b/src/data/threads.js index 2716c84..19b6622 100644 --- a/src/data/threads.js +++ b/src/data/threads.js @@ -51,12 +51,24 @@ function getHeaderGuildInfo(member) { * @returns {Promise} * @throws {Error} */ -async function createNewThreadForUser(user, quiet = false) { +async function createNewThreadForUser(user, member, quiet = false) { const existingThread = await findOpenThreadByUserId(user.id); if (existingThread) { throw new Error('Attempted to create a new thread for a user with an existing open thread!'); } + // Check the config for a requirement of a minimum time the user must be a member of the guild to contact modmail, + // if the user hasn't been a member of the guild for the specified time, return an optional message without making a new thread + if (config.requiredJoinedAt && member) { + if (member.joinedAt > moment() - config.requiredJoinedAt) { + if (config.joinedAtDeniedMessage) { + const privateChannel = await user.getDMChannel(); + await privateChannel.createMessage(config.joinedAtDeniedMessage); + } + return; + } + } + // Check the config for a requirement of account age to contact modmail, // if the account is too young, return an optional message without making a new thread if (config.requiredAccountAge) { diff --git a/src/main.js b/src/main.js index 65667cd..43fa9fa 100644 --- a/src/main.js +++ b/src/main.js @@ -74,12 +74,25 @@ bot.on('messageCreate', async msg => { messageQueue.add(async () => { let thread = await threads.findOpenThreadByUserId(msg.author.id); + // Due the way discord works, private channels don't have a member property as they are a guild only property, + // if more than one main guild have been set, we just ignore the requiredJoinedAt config option + let member; + const mainGuilds = utils.getMainGuilds(); + if (mainGuilds.length === 1) { + member = bot.guilds.get(mainGuilds[0]).members.get(msg.author.id); + if (! member) { + member = false; + } + } else { + member = false; + } + // New thread if (! thread) { // Ignore messages that shouldn't usually open new threads, such as "ok", "thanks", etc. if (config.ignoreAccidentalThreads && msg.content && ACCIDENTAL_THREAD_MESSAGES.includes(msg.content.trim().toLowerCase())) return; - thread = await threads.createNewThreadForUser(msg.author); + thread = await threads.createNewThreadForUser(msg.author, member); } if (thread) await thread.receiveUserReply(msg); diff --git a/src/modules/newthread.js b/src/modules/newthread.js index ca3431d..ac17951 100644 --- a/src/modules/newthread.js +++ b/src/modules/newthread.js @@ -17,13 +17,24 @@ module.exports = bot => { return; } + let member; + const mainGuilds = utils.getMainGuilds(); + if (mainGuilds.length === 1) { + member = bot.guilds.get(mainGuilds[0]).members.get(msg.author.id); + if (! member) { + member = false; + } + } else { + member = false; + } + const existingThread = await threads.findOpenThreadByUserId(user.id); if (existingThread) { utils.postSystemMessageWithFallback(msg.channel, thread, `Cannot create a new thread; there is another open thread with this user: <#${existingThread.channel_id}>`); return; } - const createdThread = await threads.createNewThreadForUser(user, true); + const createdThread = await threads.createNewThreadForUser(user, member, true); createdThread.postSystemMessage(`Thread was opened by ${msg.author.username}#${msg.author.discriminator}`); if (thread) { diff --git a/src/utils.js b/src/utils.js index fddb719..3b93ce8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -78,7 +78,7 @@ function postError(str) { * @returns {boolean} */ function isStaff(member) { - if (!member) return false; + if (! member) return false; if (config.inboxServerPermission.length === 0) return true; return config.inboxServerPermission.some(perm => {