galactic-bot/structure/client/Resolver.js

321 lines
11 KiB
JavaScript

/* eslint-disable no-useless-escape */
class Resolver {
constructor(client) {
this.client = client;
}
components(str = '', type, exact = true) { //used for CommandHandler
const string = str.toLowerCase();
const components = this.client.registry.components
.filter(c => c.type === type)
.filter(exact ? filterExact(string) : filterInexact(string))
.array();
return components || [];
}
resolveBoolean(input) {
input = input.toLowerCase();
const truthy = [ 'on', 'true', 'yes', 'enable', 'y' ];
const falsey = [ 'off', 'false', 'no', 'disable', 'n' ];
if(truthy.includes(input)) {
return true;
} else if (falsey.includes(input)) {
return false;
} else {
return null;
}
}
// resolveTrue(input) {
// return [ 'on', 'true' ].includes(input.toLowerCase());
// }
// resolveFalse(input) {
// return [].includes(input.toLowerCase());
// }
async resolveMemberAndUser(string, guild) {
const str = string.toLowerCase();
const index = guild ? guild.members : this.client.users;
let member = null;
if(/<@!?(\d{17,21})>/iy.test(str)) { //mentions
const matches = /<@!?(\d{17,21})>/iy.exec(str);
member = index.get(matches[1]);
if(!member) {
try {
member = await index.fetch(matches[1]);
} catch(e) {
try {
member = await this.client.users.fetch(matches[1]);
} catch(e) {} //eslint-disable-line no-empty
} //eslint-disable-line no-empty
}
} else if(/\d{17,21}/iy.test(str)) { //id
const matches = /(\d{17,21})/iy.exec(str);
member = index.get(matches[1]);
if(!member) {
try {
member = await index.fetch(matches[1]);
} catch(e) {
try {
member = await this.client.users.fetch(matches[1]);
} catch(e) {} //eslint-disable-line no-empty
} //eslint-disable-line no-empty
}
} else if(/(.{2,32})#(\d{4})/iy.test(str)) { //username#discrim
const matches = /(.{2,32})#(\d{4})/iy.exec(str);
member = guild
? guild.members.filter(m=>m.user.username === matches[1] && m.user.discriminator === matches[2]).first()
: this.client.users.filter(u=>u.username === matches[1] && u.discriminator === matches[2]).first();
}
return member || null;
}
/**
* Resolve several user resolveables
*
* @param {array<string>} [resolveables=[]] an array of user resolveables (name, id, tag)
* @param {boolean} [strict=false] whether or not to attempt resolving by partial usernames
* @returns {array || boolean} Array of resolved users or false if none were resolved
* @memberof Resolver
*/
async resolveUsers(resolveables = [], strict = false) {
if(typeof resolveables === 'string') resolveables = [ resolveables ];
if(resolveables.length === 0) return false;
let users = this.client.users;
let resolved = [];
for(let resolveable of resolveables) {
if(/<@!?([0-9]{17,21})>/.test(resolveable)) {
let id = resolveable.match(/<@!?([0-9]{17,21})>/)[1];
let user = await users.fetch(id).catch(err => { if(err.code === 10013) return false; else { console.warn(err); return false; } });
if(user) resolved.push(user);
} else if(/(id\:)?([0-9]{17,21})/.test(resolveable)) {
let id = resolveable.match(/(id\:)?([0-9]{17,21})/)[2];
let user = await users.fetch(id).catch(err => { if(err.code === 10013) return false; else { console.warn(err); return false; } });
if(user) resolved.push(user);
} else if(/^\@?([\S\s]{1,32})\#([0-9]{4})/.test(resolveable)) {
let m = resolveable.match(/^\@?([\S\s]{1,32})\#([0-9]{4})/);
let username = m[1].toLowerCase();
let discrim = m[2].toLowerCase();
let [ user ] = users.cache.filter(u => {
return u.username.toLowerCase() === username && u.discriminator === discrim;
}).first(1);
if(user) resolved.push(user);
} else if(!strict) {
let name = resolveable.toLowerCase();
let [ user ] = users.cache.filter(u => {
return u.username.toLowerCase().includes(name);
}).first(1);
if(user) resolved.push(user);
}
}
return resolved.length > 0 ? resolved : false;
}
async resolveUser(resolveable, strict) {
let [ result ] = await this.resolveUsers([ resolveable ], strict);
return result;
}
/**
* Resolve multiple member resolveables
*
* @param {array<string>} [resolveables=[]] an array of member resolveables (name, nickname, tag, id)
* @param {boolean} [strict=false] whether or not to attempt resolving by partial matches
* @param {Guild} guild the guild in which to look for members
* @returns {array<GuildMember> || boolean} an array of resolved members or false if none were resolved
* @memberof Resolver
*/
async resolveMembers(resolveables = [], guild, strict = false) {
if(typeof resolveables === 'string') resolveables = [ resolveables ];
if(resolveables.length === 0) return false;
let members = guild.members;
let resolved = [];
for(let resolveable of resolveables) {
if(/<@!?([0-9]{17,21})>/.test(resolveable)) {
let id = resolveable.match(/<@!?([0-9]{17,21})>/)[1];
let member = await members.fetch(id).catch(err => { if(err.code === 10007) return false; else { console.warn(err); return false; } });
if(member) resolved.push(member);
} else if(/(id\:)?([0-9]{17,21})/.test(resolveable)) {
let id = resolveable.match(/(id\:)?([0-9]{17,21})/)[2];
let member = await members.fetch(id).catch(err => { if(err.code === 10007) return false; else { console.warn(err); return false; } });
if(member) resolved.push(member);
} else if(/^\@?([\S\s]{1,32})\#([0-9]{4})/.test(resolveable)) {
let m = resolveable.match(/^\@?([\S\s]{1,32})\#([0-9]{4})/);
let username = m[1].toLowerCase();
let discrim = m[2].toLowerCase();
let [ member ] = members.cache.filter(m => {
return m.user.username.toLowerCase() === username && m.user.discriminator === discrim;
}).first(1);
if(member) resolved.push(member);
} else if(/^\@?([\S\s]{1,32})/.test(resolveable) && guild && !strict) {
let nickname = resolveable.match(/^\@?([\S\s]{1,32})/)[0].toLowerCase();
let [ member ] = members.cache.filter((m) => {
return (m && m.user) &&
((!m.nickname ? false : m.nickname.toLowerCase() == nickname ) ||
(!m.nickname ? false : m.nickname.toLowerCase().includes(nickname)) ||
m.user.username.toLowerCase().includes(nickname) ||
m.user.username.toLowerCase() == nickname);
}).first(1);
if(member) resolved.push(member);
}
}
return resolved.length > 0 ? resolved : false;
}
/**
* Resolve multiple channels
*
* @param {array<string>} [resolveables=[]] an array of channel resolveables (name, id)
* @param {guild} guild the guild in which to look for channels
* @param {boolean} [strict=false] whether or not partial names are resolved
* @returns {array<GuildChannel> || false} an array of guild channels or false if none were resolved
* @memberof Resolver
*/
async resolveChannels(resolveables = [], guild, strict = false) {
if(typeof resolveables === 'string') resolveables = [ resolveables ];
if(resolveables.length === 0) return false;
let channels = guild.channels;
let resolved = [];
for(let resolveable of resolveables) {
let channel = channels.resolve(resolveable);
if(channel) {
resolved.push(channel);
continue;
}
let name = /^\#?([a-z0-9\-\_0]*)/i;
let id = /^\<\#([0-9]*)\>/i;
if(name.test(resolveable)) {
let match = resolveable.match(name);
let ch = match[1].toLowerCase();
let channel = channels.cache.filter(c => {
if(!strict) return c.name.toLowerCase().includes(ch);
return c.name.toLowerCase() === ch;
}).first(1);
if(channel) resolved.push(channel);
} else if(id.test(resolveable)) {
let match = resolveable.match(id);
let ch = match[1];
let channel = channels.resolve(ch);
if(channel) resolved.push(channel);
}
}
return resolved.length > 0 ? resolved : false;
}
/**
* Resolve multiple roles
*
* @param {array<string>} [resolveables=[]] an array of roles resolveables (name, id)
* @param {Guild} guild the guild in which to look for roles
* @param {boolean} [strict=false] whether or not partial names are resolved
* @returns {array<GuildRole> || false} an array of roles or false if none were resolved
* @memberof Resolver
*/
async resolveRoles(resolveables = [], guild, strict = false) {
if(typeof resolveables === 'string') resolveables = [ resolveables ];
if(resolveables.length === 0) return false;
let roles = guild.roles;
let resolved = [];
for(let resolveable of resolveables) {
let id = /^(<@&)?([0-9]{16,22})>?/i;
if(id.test(resolveable)) {
let match = resolveable.match(id);
let r_id = match[2];
let role = await roles.fetch(r_id).catch(console.error);
if(role) resolved.push(role);
} else {
let role = roles.cache.filter(r => {
if(!strict) return r.name.toLowerCase().includes(resolveable.toLowerCase());
return r.name.toLowerCase() === resolveable.toLowerCase();
}).first(1);
if(role) resolved.push(role);
}
}
return resolved.length > 0 ? resolved : false;
}
}
module.exports = Resolver;
const filterExact = (search) => {
return comp => comp.id.toLowerCase() === search ||
comp.resolveable.toLowerCase() === search ||
(comp.aliases && (comp.aliases.some(ali => `${comp.type}:${ali}`.toLowerCase() === search) ||
comp.aliases.some(ali => ali.toLowerCase() === search)));
};
const filterInexact = (search) => {
return comp => comp.id.toLowerCase().includes(search) ||
comp.resolveable.toLowerCase().includes(search) ||
(comp.aliases && (comp.aliases.some(ali => `${comp.type}:${ali}`.toLowerCase().includes(search)) ||
comp.aliases.some(ali => ali.toLowerCase().includes(search))));
};