ramirez/src/utils.js

296 lines
6.9 KiB
JavaScript
Raw Normal View History

2017-02-09 23:36:47 -05:00
const Eris = require('eris');
2017-09-19 13:23:55 -04:00
const bot = require('./bot');
2017-02-09 21:56:36 -05:00
const moment = require('moment');
const publicIp = require('public-ip');
const attachments = require('./data/attachments');
2017-09-19 13:23:55 -04:00
const config = require('./config');
class BotError extends Error {}
const userMentionRegex = /^<@\!?([0-9]+?)>$/;
2017-02-09 21:56:36 -05:00
2017-09-19 10:38:37 -04:00
let inboxGuild = null;
let mainGuild = null;
2017-09-19 10:38:37 -04:00
let logChannel = null;
/**
* @returns {Eris~Guild}
*/
2017-09-19 13:23:55 -04:00
function getInboxGuild() {
2017-09-19 10:38:37 -04:00
if (! inboxGuild) inboxGuild = bot.guilds.find(g => g.id === config.mailGuildId);
2017-09-19 13:23:55 -04:00
if (! inboxGuild) throw new BotError('The bot is not on the modmail (inbox) server!');
2017-09-19 10:38:37 -04:00
return inboxGuild;
2017-02-09 21:56:36 -05:00
}
/**
* @returns {Eris~Guild}
*/
2017-09-19 13:23:55 -04:00
function getMainGuild() {
if (! mainGuild) mainGuild = bot.guilds.find(g => g.id === config.mainGuildId);
2017-09-19 13:23:55 -04:00
if (! mainGuild) console.warn('[WARN] The bot is not on the main server! If this is intentional, you can ignore this warning.');
return mainGuild;
}
2017-09-19 13:23:55 -04:00
/**
* Returns the designated log channel, or the default channel if none is set
* @param bot
* @returns {Eris~TextChannel}
2017-09-19 13:23:55 -04:00
*/
function getLogChannel() {
const inboxGuild = getInboxGuild();
2017-09-19 10:38:37 -04:00
if (! config.logChannelId) {
2017-09-19 13:23:55 -04:00
logChannel = inboxGuild.channels.get(inboxGuild.id);
} else if (! logChannel) {
logChannel = inboxGuild.channels.get(config.logChannelId);
2017-09-19 10:38:37 -04:00
}
if (! logChannel) {
2017-09-19 13:23:55 -04:00
throw new BotError('Log channel not found!');
2017-09-19 10:38:37 -04:00
}
return logChannel;
}
function postLog(...args) {
getLogChannel().createMessage(...args);
}
2017-09-19 13:23:55 -04:00
function postError(str) {
getLogChannel().createMessage({
content: `${getInboxMention()}**Error:** ${str.trim()}`,
2017-09-19 13:23:55 -04:00
disableEveryone: false
});
}
/**
* Returns whether the given member has permission to use modmail commands
* @param member
* @returns {boolean}
*/
function isStaff(member) {
if (! config.inboxServerPermission) return true;
return member.permission.has(config.inboxServerPermission);
}
/**
* Returns whether the given message is on the inbox server
* @param msg
* @returns {boolean}
*/
function messageIsOnInboxServer(msg) {
if (! msg.channel.guild) return false;
if (msg.channel.guild.id !== getInboxGuild().id) return false;
return true;
}
/**
* Returns whether the given message is on the main server
* @param msg
* @returns {boolean}
*/
function messageIsOnMainServer(msg) {
if (! msg.channel.guild) return false;
if (msg.channel.guild.id !== getMainGuild().id) return false;
return true;
}
/**
* @param attachment
* @returns {Promise<string>}
*/
async function formatAttachment(attachment) {
let filesize = attachment.size || 0;
filesize /= 1024;
const attachmentUrl = await attachments.getUrl(attachment.id, attachment.filename);
return `**Attachment:** ${attachment.filename} (${filesize.toFixed(1)}KB)\n${attachmentUrl}`;
}
2017-02-09 21:56:36 -05:00
2017-02-09 23:36:47 -05:00
/**
* Returns the user ID of the user mentioned in str, if any
* @param {String} str
* @returns {String|null}
*/
2017-02-09 21:56:36 -05:00
function getUserMention(str) {
str = str.trim();
if (str.match(/^[0-9]+$/)) {
// User ID
return str;
} else {
let mentionMatch = str.match(userMentionRegex);
if (mentionMatch) return mentionMatch[1];
}
return null;
}
2017-02-09 23:36:47 -05:00
/**
* Returns the current timestamp in an easily readable form
* @returns {String}
*/
function getTimestamp(...momentArgs) {
return moment.utc(...momentArgs).format('HH:mm');
2017-02-09 21:56:36 -05:00
}
2017-02-09 23:36:47 -05:00
/**
* Disables link previews in the given string by wrapping links in < >
* @param {String} str
* @returns {String}
*/
2017-02-09 21:56:36 -05:00
function disableLinkPreviews(str) {
return str.replace(/(^|[^<])(https?:\/\/\S+)/ig, '$1<$2>');
}
2017-02-09 23:36:47 -05:00
/**
* Returns a URL to the bot's web server
* @param {String} path
2017-12-31 19:16:05 -05:00
* @returns {Promise<String>}
2017-02-09 23:36:47 -05:00
*/
2017-12-31 19:16:05 -05:00
async function getSelfUrl(path = '') {
2017-02-09 21:56:36 -05:00
if (config.url) {
2017-12-31 19:16:05 -05:00
return `${config.url}/${path}`;
2017-02-09 21:56:36 -05:00
} else {
2017-02-09 23:36:47 -05:00
const port = config.port || 8890;
2017-12-31 19:16:05 -05:00
const ip = await publicIp.v4();
return `http://${ip}:${port}/${path}`;
2017-02-09 21:56:36 -05:00
}
}
2017-02-09 23:36:47 -05:00
/**
* Returns the highest hoisted role of the given member
* @param {Eris~Member} member
* @returns {Eris~Role}
2017-02-09 23:36:47 -05:00
*/
function getMainRole(member) {
const roles = member.roles.map(id => member.guild.roles.get(id));
roles.sort((a, b) => a.position > b.position ? -1 : 1);
return roles.find(r => r.hoist);
}
/**
* Splits array items into chunks of the specified size
* @param {Array} items
* @param {Number} chunkSize
* @returns {Array}
*/
function chunk(items, chunkSize) {
const result = [];
for (let i = 0; i < items.length; i += chunkSize) {
result.push(items.slice(i, i + chunkSize));
}
return result;
}
/**
* Trims every line in the string
* @param {String} str
* @returns {String}
*/
function trimAll(str) {
return str
.split('\n')
.map(str => str.trim())
.join('\n');
}
/**
* Turns a "delay string" such as "1h30m" to milliseconds
* @param {String} str
* @returns {Number}
*/
function convertDelayStringToMS(str) {
const regex = /^([0-9]+)\s*([dhms])?[a-z]*\s*/;
let match;
let ms = 0;
str = str.trim();
while (str !== '' && (match = str.match(regex)) !== null) {
if (match[2] === 'd') ms += match[1] * 1000 * 60 * 60 * 24;
else if (match[2] === 'h') ms += match[1] * 1000 * 60 * 60;
else if (match[2] === 'm') ms += match[1] * 1000 * 60;
else if (match[2] === 's' || ! match[2]) ms += match[1] * 1000;
str = str.slice(match[0].length);
}
// Invalid delay string
if (str !== '') {
return null;
}
return ms;
}
function getInboxMention() {
if (config.mentionRole == null) return '';
else if (config.mentionRole === 'here') return '@here ';
else if (config.mentionRole === 'everyone') return '@everyone ';
else return `<@&${config.mentionRole}> `;
}
function postSystemMessageWithFallback(channel, thread, text) {
if (thread) {
thread.postSystemMessage(text);
} else {
channel.createMessage(text);
}
}
/**
* A normalized way to set props in data models, fixing some inconsistencies between different DB drivers in knex
* @param {Object} target
* @param {Object} props
*/
function setDataModelProps(target, props) {
for (const prop in props) {
if (! props.hasOwnProperty(prop)) continue;
// DATETIME fields are always returned as Date objects in MySQL/MariaDB
if (props[prop] instanceof Date) {
// ...even when NULL, in which case the date's set to unix epoch
if (props[prop].getUTCFullYear() === 1970) {
target[prop] = null;
} else {
// Set the value as a string in the same format it's returned in SQLite
target[prop] = moment.utc(props[prop]).format('YYYY-MM-DD HH:mm:ss');
}
} else {
target[prop] = props[prop];
}
}
}
2017-02-09 21:56:36 -05:00
module.exports = {
2017-09-19 13:23:55 -04:00
BotError,
2017-09-19 10:38:37 -04:00
getInboxGuild,
getMainGuild,
2017-09-19 10:38:37 -04:00
getLogChannel,
2017-09-19 13:23:55 -04:00
postError,
postLog,
2017-09-19 13:23:55 -04:00
isStaff,
messageIsOnInboxServer,
messageIsOnMainServer,
formatAttachment,
2017-02-09 21:56:36 -05:00
getUserMention,
getTimestamp,
disableLinkPreviews,
getSelfUrl,
2017-02-09 23:36:47 -05:00
getMainRole,
convertDelayStringToMS,
getInboxMention,
postSystemMessageWithFallback,
chunk,
trimAll,
setDataModelProps,
2017-02-09 21:56:36 -05:00
};