Add multi-server support and more thread header information

Fixes #63. Multi-server support allows you to set an array of ids in
mainGuildId. If there are more than 1 main guild, the thread header will
display nickname and join date for each main guild the user is in.

Thread header information now also includes how long it's been since the
user joined the guild(s).

The commit also includes some minor code cleanup.
master
Dragory 2018-04-21 15:38:21 +03:00
parent 1fc32f71d0
commit e5b29a235e
3 changed files with 71 additions and 22 deletions

View File

@ -60,6 +60,7 @@ for (const [prop, value] of Object.entries(userConfig)) {
finalConfig[prop] = value; finalConfig[prop] = value;
} }
// Default knex config
if (! finalConfig['knex']) { if (! finalConfig['knex']) {
finalConfig['knex'] = { finalConfig['knex'] = {
client: 'sqlite', client: 'sqlite',
@ -70,12 +71,14 @@ if (! finalConfig['knex']) {
}; };
} }
// Make sure migration settings are always present in knex config
Object.assign(finalConfig['knex'], { Object.assign(finalConfig['knex'], {
migrations: { migrations: {
directory: path.join(finalConfig.dbDir, 'migrations') directory: path.join(finalConfig.dbDir, 'migrations')
} }
}); });
// Make sure all of the required config options are present
for (const opt of required) { for (const opt of required) {
if (! finalConfig[opt]) { if (! finalConfig[opt]) {
console.error(`Missing required config.json value: ${opt}`); console.error(`Missing required config.json value: ${opt}`);
@ -83,4 +86,9 @@ for (const opt of required) {
} }
} }
// Make sure mainGuildId is internally always an array
if (! Array.isArray(finalConfig['mainGuildId'])) {
finalConfig['mainGuildId'] = [finalConfig['mainGuildId']];
}
module.exports = finalConfig; module.exports = finalConfig;

View File

@ -4,7 +4,6 @@ const moment = require('moment');
const uuid = require('uuid'); const uuid = require('uuid');
const humanizeDuration = require('humanize-duration'); const humanizeDuration = require('humanize-duration');
const bot = require('../bot');
const knex = require('../knex'); const knex = require('../knex');
const config = require('../config'); const config = require('../config');
const utils = require('../utils'); const utils = require('../utils');
@ -37,6 +36,13 @@ async function findOpenThreadByUserId(userId) {
return (thread ? new Thread(thread) : null); return (thread ? new Thread(thread) : null);
} }
function getHeaderGuildInfo(member) {
return {
nickname: member.nick || member.user.username,
joinDate: humanizeDuration(Date.now() - member.joinedAt, {largest: 2, round: true})
};
}
/** /**
* Creates a new modmail thread for the specified user * Creates a new modmail thread for the specified user
* @param {Eris.User} user * @param {Eris.User} user
@ -96,20 +102,45 @@ async function createNewThreadForUser(user, quiet = false) {
} }
// Post some info to the beginning of the new thread // Post some info to the beginning of the new thread
const mainGuild = utils.getMainGuild(); const infoHeaderItems = [];
const member = (mainGuild ? mainGuild.members.get(user.id) : null);
if (! member) console.log(`[INFO] Member ${user.id} not found in main guild ${config.mainGuildId}`);
let mainGuildNickname = null; // Account age
if (member && member.nick) mainGuildNickname = member.nick; const accountAge = humanizeDuration(Date.now() - user.createdAt, {largest: 2, round: true});
else if (member && member.user) mainGuildNickname = member.user.username; infoHeaderItems.push(`ACCOUNT AGE **${accountAge}**`);
else if (member == null) mainGuildNickname = 'NOT ON SERVER';
if (mainGuildNickname == null) mainGuildNickname = 'UNKNOWN'; // User id
infoHeaderItems.push(`ID **${user.id}**`);
let infoHeader = infoHeaderItems.join(', ');
// Guild info
const guildInfoHeaderItems = new Map();
utils.getMainGuilds().forEach(guild => {
const member = guild.members.get(user.id);
if (! member) return;
const {nickname, joinDate} = getHeaderGuildInfo(member);
guildInfoHeaderItems.set(guild.name, [
`NICKNAME **${nickname}**`,
`JOINED **${joinDate}** ago`
]);
});
guildInfoHeaderItems.forEach((items, guildName) => {
if (guildInfoHeaderItems.size === 1) {
infoHeader += `\n${items.join(', ')}`;
} else {
infoHeader += `\n**[${guildName}]** ${items.join(', ')}`;
}
});
const userLogCount = await getClosedThreadCountByUserId(user.id); const userLogCount = await getClosedThreadCountByUserId(user.id);
const accountAge = humanizeDuration(Date.now() - user.createdAt, {largest: 2}); if (userLogCount > 0) {
const infoHeader = `ACCOUNT AGE **${accountAge}**, ID **${user.id}**, NICKNAME **${mainGuildNickname}**, LOGS **${userLogCount}**\n-------------------------------`; infoHeader += `\n\nThis user has **${userLogCount}** previous modmail threads. Use \`${config.prefix}logs\` to see them.`;
}
infoHeader += '\n────────────────';
await newThread.postSystemMessage(infoHeader); await newThread.postSystemMessage(infoHeader);

View File

@ -7,10 +7,10 @@ const config = require('./config');
class BotError extends Error {} class BotError extends Error {}
const userMentionRegex = /^<@\!?([0-9]+?)>$/; const userMentionRegex = /^<@!?([0-9]+?)>$/;
let inboxGuild = null; let inboxGuild = null;
let mainGuild = null; let mainGuilds = [];
let logChannel = null; let logChannel = null;
/** /**
@ -23,17 +23,26 @@ function getInboxGuild() {
} }
/** /**
* @returns {Eris~Guild} * @returns {Eris~Guild[]}
*/ */
function getMainGuild() { function getMainGuilds() {
if (! mainGuild) mainGuild = bot.guilds.find(g => g.id === config.mainGuildId); if (mainGuilds.length === 0) {
if (! mainGuild) console.warn('[WARN] The bot is not on the main server! If this is intentional, you can ignore this warning.'); mainGuilds = bot.guilds.filter(g => config.mainGuildId.includes(g.id));
return mainGuild; }
if (mainGuilds.length !== config.mainGuildId.length) {
if (config.mainGuildId.length === 1) {
console.warn(`[WARN] The bot hasn't joined the main guild!`);
} else {
console.warn(`[WARN] The bot hasn't joined one or more main guilds!`);
}
}
return mainGuilds;
} }
/** /**
* Returns the designated log channel, or the default channel if none is set * Returns the designated log channel, or the default channel if none is set
* @param bot
* @returns {Eris~TextChannel} * @returns {Eris~TextChannel}
*/ */
function getLogChannel() { function getLogChannel() {
@ -91,8 +100,9 @@ function messageIsOnInboxServer(msg) {
*/ */
function messageIsOnMainServer(msg) { function messageIsOnMainServer(msg) {
if (! msg.channel.guild) return false; if (! msg.channel.guild) return false;
if (msg.channel.guild.id !== getMainGuild().id) return false;
return true; return getMainGuilds()
.some(g => msg.channel.guild.id === g.id);
} }
/** /**
@ -268,7 +278,7 @@ module.exports = {
BotError, BotError,
getInboxGuild, getInboxGuild,
getMainGuild, getMainGuilds,
getLogChannel, getLogChannel,
postError, postError,
postLog, postLog,