diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a2a0e..547845c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Fixed system messages like pins in DMs being relayed to the thread * Fixed channels sometimes being created without a category * Removed timestamps from threads by default. Logs will still have accurate timestamps. Can be re-enabled with the `threadTimestamps` config option. +* Added `!move` command to move threads between categories. Can be enabled with the `allowMove` config option, disabled by default. ## Sep 22, 2017 * Added `newThreadCategoryId` option. This option can be set to a category ID to place all new threads in that category. diff --git a/src/config.js b/src/config.js index 85535b2..2b93f55 100644 --- a/src/config.js +++ b/src/config.js @@ -28,6 +28,7 @@ const defaultConfig = { "useNicknames": false, "ignoreAccidentalThreads": false, "threadTimestamps": false, + "allowMove": false, "enableGreeting": false, "greetingMessage": null, diff --git a/src/main.js b/src/main.js index 19e6651..ea4f05e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,6 @@ const Eris = require('eris'); const moment = require('moment'); +const transliterate = require('transliteration'); const config = require('./config'); const bot = require('./bot'); @@ -255,6 +256,57 @@ addInboxServerCommand('logs', (msg, args, thread) => { } }); +addInboxServerCommand('move', async (msg, args, thread) => { + if (! config.allowMove) return; + + if (! thread) return; + + const searchStr = args[0]; + if (! searchStr || searchStr.trim() === '') return; + + const normalizedSearchStr = transliterate.slugify(searchStr); + + const categories = msg.channel.guild.channels.filter(c => { + // Filter to categories that are not the thread's current parent category + return (c instanceof Eris.CategoryChannel) && (c.id !== msg.channel.parentID); + }); + + if (categories.length === 0) return; + + // See if any category name contains a part of the search string + const containsRankings = categories.map(cat => { + const normalizedCatName = transliterate.slugify(cat.name); + + let i; + for (i = 1; i < normalizedSearchStr.length; i++) { + if (! normalizedCatName.includes(normalizedSearchStr.slice(0, i))) { + i--; + break; + } + } + + return [cat, i]; + }); + + // Sort by best match + containsRankings.sort((a, b) => { + return a[1] > b[1] ? -1 : 1; + }); + + if (containsRankings[0][1] === 0) { + thread.postNonLogMessage('No matching category'); + return; + } + + const targetCategory = containsRankings[0][0]; + + await bot.editChannel(thread.channel_id, { + parentID: targetCategory.id + }); + + thread.postSystemMessage(`Thread moved to ${targetCategory.name.toUpperCase()}`); +}); + module.exports = { async start() { // Load plugins