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;
}
// Default knex config
if (! finalConfig['knex']) {
finalConfig['knex'] = {
client: 'sqlite',
@ -70,12 +71,14 @@ if (! finalConfig['knex']) {
};
}
// Make sure migration settings are always present in knex config
Object.assign(finalConfig['knex'], {
migrations: {
directory: path.join(finalConfig.dbDir, 'migrations')
}
});
// Make sure all of the required config options are present
for (const opt of required) {
if (! finalConfig[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;

View File

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

View File

@ -7,10 +7,10 @@ const config = require('./config');
class BotError extends Error {}
const userMentionRegex = /^<@\!?([0-9]+?)>$/;
const userMentionRegex = /^<@!?([0-9]+?)>$/;
let inboxGuild = null;
let mainGuild = null;
let mainGuilds = [];
let logChannel = null;
/**
@ -23,17 +23,26 @@ function getInboxGuild() {
}
/**
* @returns {Eris~Guild}
* @returns {Eris~Guild[]}
*/
function getMainGuild() {
if (! mainGuild) mainGuild = bot.guilds.find(g => g.id === config.mainGuildId);
if (! mainGuild) console.warn('[WARN] The bot is not on the main server! If this is intentional, you can ignore this warning.');
return mainGuild;
function getMainGuilds() {
if (mainGuilds.length === 0) {
mainGuilds = bot.guilds.filter(g => config.mainGuildId.includes(g.id));
}
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
* @param bot
* @returns {Eris~TextChannel}
*/
function getLogChannel() {
@ -91,8 +100,9 @@ function messageIsOnInboxServer(msg) {
*/
function messageIsOnMainServer(msg) {
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,
getInboxGuild,
getMainGuild,
getMainGuilds,
getLogChannel,
postError,
postLog,