2019-04-13 01:44:18 +03:00
|
|
|
import { IBasePluginConfig, IPluginOptions, Plugin } from "knub";
|
2018-11-25 17:04:26 +02:00
|
|
|
import { PluginRuntimeError } from "../PluginRuntimeError";
|
2019-01-19 15:39:04 +02:00
|
|
|
import Ajv, { ErrorObject } from "ajv";
|
2019-04-20 17:36:28 +03:00
|
|
|
import { createUnknownUser, isSnowflake, isUnicodeEmoji, UnknownUser } from "../utils";
|
|
|
|
import { Member, User } from "eris";
|
2018-11-25 17:04:26 +02:00
|
|
|
|
2019-04-13 01:44:18 +03:00
|
|
|
export class ZeppelinPlugin<TConfig extends {} = IBasePluginConfig> extends Plugin<TConfig> {
|
2019-01-19 15:39:04 +02:00
|
|
|
protected configSchema: any;
|
|
|
|
protected permissionsSchema: any;
|
|
|
|
|
2019-04-20 17:36:28 +03:00
|
|
|
public static dependencies = [];
|
|
|
|
|
2018-11-25 17:04:26 +02:00
|
|
|
protected throwPluginRuntimeError(message: string) {
|
2019-01-03 06:17:39 +02:00
|
|
|
throw new PluginRuntimeError(message, this.runtimePluginName, this.guildId);
|
2018-11-25 17:04:26 +02:00
|
|
|
}
|
2018-12-15 17:24:09 +02:00
|
|
|
|
|
|
|
protected canActOn(member1, member2) {
|
|
|
|
if (member1.id === member2.id) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ourLevel = this.getMemberLevel(member1);
|
|
|
|
const memberLevel = this.getMemberLevel(member2);
|
|
|
|
return ourLevel > memberLevel;
|
|
|
|
}
|
2019-01-19 15:39:04 +02:00
|
|
|
|
|
|
|
public validateOptions(options: IPluginOptions): ErrorObject[] | null {
|
|
|
|
// Validate config values
|
|
|
|
if (this.configSchema) {
|
|
|
|
const ajv = new Ajv();
|
|
|
|
const validate = ajv.compile(this.configSchema);
|
|
|
|
|
|
|
|
if (options.config) {
|
|
|
|
const isValid = validate(options.config);
|
|
|
|
if (!isValid) return validate.errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options.overrides) {
|
|
|
|
for (const override of options.overrides) {
|
|
|
|
if (override.config) {
|
|
|
|
const isValid = validate(override.config);
|
|
|
|
if (!isValid) return validate.errors;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No errors, return null
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async runLoad(): Promise<any> {
|
|
|
|
const mergedOptions = this.getMergedOptions();
|
|
|
|
const validationErrors = this.validateOptions(mergedOptions);
|
|
|
|
if (validationErrors) {
|
|
|
|
throw new Error(`Invalid options:\n${validationErrors.join("\n")}`);
|
|
|
|
}
|
|
|
|
|
2019-02-06 20:05:48 +02:00
|
|
|
return super.runLoad();
|
2019-01-19 15:39:04 +02:00
|
|
|
}
|
2019-02-09 14:34:42 +02:00
|
|
|
|
|
|
|
public canUseEmoji(snowflake): boolean {
|
|
|
|
if (isUnicodeEmoji(snowflake)) {
|
|
|
|
return true;
|
|
|
|
} else if (isSnowflake(snowflake)) {
|
|
|
|
for (const guild of this.bot.guilds.values()) {
|
|
|
|
if (guild.emojis.some(e => (e as any).id === snowflake)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new PluginRuntimeError(`Invalid emoji: ${snowflake}`, this.runtimePluginName, this.guildId);
|
|
|
|
}
|
|
|
|
}
|
2019-04-13 03:54:36 +03:00
|
|
|
|
|
|
|
public getRegisteredCommands() {
|
|
|
|
return this.commands.commands;
|
|
|
|
}
|
2019-04-20 17:36:28 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves a user from the passed string. The passed string can be a user id, a user mention, a full username (with discrim), etc.
|
|
|
|
*/
|
|
|
|
async resolveUser(userResolvable: string): Promise<User | UnknownUser> {
|
|
|
|
if (userResolvable == null) {
|
|
|
|
return createUnknownUser();
|
|
|
|
}
|
|
|
|
|
|
|
|
let userId;
|
|
|
|
|
|
|
|
// A user mention?
|
|
|
|
const mentionMatch = userResolvable.match(/^<@!?(\d+)>$/);
|
|
|
|
if (mentionMatch) {
|
|
|
|
userId = mentionMatch[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
// A non-mention, full username?
|
|
|
|
if (!userId) {
|
|
|
|
const usernameMatch = userResolvable.match(/^@?([^#]+)#(\d{4})$/);
|
|
|
|
if (usernameMatch) {
|
|
|
|
const user = this.bot.users.find(u => u.username === usernameMatch[1] && u.discriminator === usernameMatch[2]);
|
|
|
|
userId = user.id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just a user ID?
|
|
|
|
if (!userId) {
|
|
|
|
const idMatch = userResolvable.match(/^\d+$/);
|
|
|
|
if (!idMatch) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
userId = userResolvable;
|
|
|
|
}
|
|
|
|
|
|
|
|
const cachedUser = this.bot.users.find(u => u.id === userId);
|
|
|
|
if (cachedUser) return cachedUser;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const freshUser = await this.bot.getRESTUser(userId);
|
|
|
|
return freshUser;
|
|
|
|
} catch (e) {} // tslint:disable-line
|
|
|
|
|
|
|
|
return createUnknownUser({ id: userId });
|
|
|
|
}
|
|
|
|
|
|
|
|
async getMember(userId: string): Promise<Member> {
|
|
|
|
// See if we have the member cached...
|
|
|
|
let member = this.guild.members.get(userId);
|
|
|
|
|
|
|
|
// If not, fetch it from the API
|
|
|
|
if (!member) {
|
|
|
|
try {
|
|
|
|
member = await this.bot.getRESTGuildMember(this.guildId, userId);
|
|
|
|
} catch (e) {} // tslint:disable-line
|
|
|
|
}
|
|
|
|
|
|
|
|
return member;
|
|
|
|
}
|
2018-11-25 17:04:26 +02:00
|
|
|
}
|