UNPKG

willow-plugin-exp

Version:

A plugin for willow that allows users to collect exp, gain levels, and be assigned roles.

299 lines (298 loc) 13.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); require("reflect-metadata"); const command_line_args_1 = __importDefault(require("command-line-args")); const lodash_1 = __importDefault(require("lodash")); const moment_1 = __importDefault(require("moment")); const willow_models_1 = require("willow-models"); const typeorm_1 = require("typeorm"); exports.commandOptions = [ { name: 'exp', alias: 'e', type: Boolean }, { name: 'rank', alias: 'r', type: Boolean }, { name: 'help', alias: 'h', type: Boolean } ]; var CommandType; (function (CommandType) { CommandType[CommandType["Quote"] = 0] = "Quote"; CommandType[CommandType["Random"] = 1] = "Random"; })(CommandType = exports.CommandType || (exports.CommandType = {})); class PsyduckExampleOrm { constructor(options, announceLevelUp = false, minExp = 1, maxExp = 10) { this.connectionOptions = options; this.announceLevelUp = announceLevelUp; this.minExp = minExp; this.maxExp = maxExp; } /** * This method is to be called after instantiation to connect to the data store. This is intentional to allow for unit testing methods without requiring a connection. */ connect() { typeorm_1.createConnection({ type: this.connectionOptions.type, host: this.connectionOptions.host, port: this.connectionOptions.port, username: this.connectionOptions.username, password: this.connectionOptions.password, database: this.connectionOptions.database, synchronize: true, logging: false, entities: [ willow_models_1.PluginExpUser, willow_models_1.UserLevel, willow_models_1.UserExp, willow_models_1.UserRank ] }).then((connection) => __awaiter(this, void 0, void 0, function* () { this.users = connection.getRepository(willow_models_1.PluginExpUser); this.levels = connection.getRepository(willow_models_1.UserLevel); this.ranks = connection.getRepository(willow_models_1.UserRank); this.exps = connection.getRepository(willow_models_1.UserExp); this.buildLevels(); })).catch(error => console.log(error)); } buildLevels() { return __awaiter(this, void 0, void 0, function* () { const levels = yield this.levels.find(); if (!levels || levels.length < 1) { for (let i = 0; i < 100; i++) { const level = new willow_models_1.UserLevel(); level.level = i + 1; level.requiredExp = (i + 1) * 1993 - 1185; yield this.levels.save(level); } } }); } /** * This event is emitted from Psyduck when a message is recieved in a discord channel. From there you may do as you with with it in your plugin. */ onMessage(message) { // If the message came from a bot, ignore. if (message.author.bot) { return; } // If the message is too small to be a command, ignore. if (message.content.length <= 1) { this.gainExp(message, message.author.id, message.channel.name); return; } // If the message is a string of repeated characters, ignore. For example !!!!!!! const dupe = RegExp(/^(.)\1*$/gm); if (dupe.test(message.content)) { this.gainExp(message, message.author.id, message.channel.name); return; } // Extract the command code, if it is in the list of commands we want to handle, continue. if (message.content.startsWith('!')) { const commandCodes = ['level', 'lvl', 'l']; const baseCommand = message.content.slice(1); const commandWithArgs = message.content.slice(1, message.content.indexOf(' ')); if (lodash_1.default.includes(commandCodes, baseCommand)) { this.explainLevel(message, message.channel.name); } else if (lodash_1.default.includes(commandCodes, commandWithArgs)) { } } else { this.gainExp(message, message.author.id, message.channel.name); } } getUser(userId) { return __awaiter(this, void 0, void 0, function* () { return yield this.users.findOne({ user: { id: userId } }, { relations: ['exps', 'level'] }); }); } createUser(guildId, serverName, guildAvatarUrl, userId, userName, avatarUrl) { const user = new willow_models_1.PluginExpUser(); const guildUser = new willow_models_1.GuildUser(); guildUser.id = userId; guildUser.userName = userName; guildUser.avatarUrl = avatarUrl || ''; const guild = new willow_models_1.Guild(); guild.id = guildId; guild.serverName = serverName; guild.avatarUrl = guildAvatarUrl || ''; guildUser.guild = guild; user.user = guildUser; user.exps = []; return user; } explainLevel(discord, channelName) { return __awaiter(this, void 0, void 0, function* () { let user = yield this.getUser(discord.author.id); if (!user) { user = this.createUser(discord.guild.id, discord.guild.name, discord.guild.iconURL, discord.author.id, discord.author.username, discord.author.avatarURL); user.exps.push(this.buildExp(channelName)); yield this.users.save(user); } let users = yield this.users.find({ relations: ['level', 'exps'] }); users = lodash_1.default.orderBy(users, u => lodash_1.default.sum(u.exps.map(e => e.amount)), ['desc']); let currentExp = 0; user.exps.forEach(exp => currentExp += exp.amount); const nextLevel = yield this.levels.findOne({ level: user.level ? user.level.level + 1 : 1 }); const userIndex = users.findIndex(u => u.user.id === user.user.id); const nextPlaceUser = users[userIndex === 0 ? 0 : userIndex - 1]; let nextPlaceUserExp = 0; let nextPlaceUserName = undefined; if (nextPlaceUser) { try { const du = yield discord.guild.fetchMember(nextPlaceUser.user.id); nextPlaceUserName = du.user.username; } catch (error) { console.log(error); } nextPlaceUser.exps.forEach(exp => nextPlaceUserExp += exp.amount); } const embed = { 'color': 11812284, 'author': { 'name': '💯 Your Level Report' }, 'fields': [ { 'name': 'Overall Rank', 'value': `${userIndex + 1}/${users.length}`, 'inline': true }, { 'name': 'Current Exp', 'value': `${currentExp}`, 'inline': true }, { 'name': 'Current Level', 'value': `**${user.level ? user.level.level : 'None'}** (req. *${user.level ? user.level.requiredExp : 0} exp*)`, 'inline': true }, { 'name': 'Next Level', 'value': `**${nextLevel ? nextLevel.level : 'none'}** (req. *${nextLevel ? nextLevel.requiredExp : 0} exp*)`, 'inline': true }, { 'name': 'Exp To Next Level', 'value': `${nextLevel ? nextLevel.requiredExp - currentExp : 0}`, 'inline': true }, { 'name': 'Exp To Overtake', 'value': `${nextPlaceUserExp - currentExp} (*${nextPlaceUserName || nextPlaceUser.user.id}*)`, 'inline': true } ] }; discord.channel.send({ embed }); }); } buildExp(channel) { const exp = new willow_models_1.UserExp(); exp.channel = channel; exp.timeStamp = moment_1.default().format('ddd MMM DD YYYY h:mm A'); exp.amount = lodash_1.default.random(this.minExp, this.maxExp); return exp; } gainExp(discord, userId, channel) { return __awaiter(this, void 0, void 0, function* () { let user = yield this.getUser(userId); if (!user) { user = this.createUser(discord.guild.id, discord.guild.name, discord.guild.iconURL, discord.author.id, discord.author.username, discord.author.avatarURL); yield this.users.save(user); } user.exps.push(this.buildExp(channel)); yield this.users.save(user); this.checkGainLevel(discord, user); }); } checkGainLevel(discord, user) { return __awaiter(this, void 0, void 0, function* () { let currentExp = 0; let leveled = false; user.exps.forEach(exp => currentExp += exp.amount); const levels = yield this.levels.find({ requiredExp: typeorm_1.Between(1, currentExp) }); if (!user.level) { leveled = true; user.level = levels[0]; yield this.users.save(user); } else { for (let i = 0; i < levels.length; i++) { const level = levels[i]; if (level.id > user.level.id) { leveled = true; user.level = level; yield this.users.save(user); break; } } } yield this.users.save(user); if (leveled) { yield this.gainLevel(discord, user); if (this.announceLevelUp) { if (typeof (this.announceLevelUp) === 'boolean') { discord.channel.send(`Level 🆙 <@${user.user.id}> - You are now level ${user.level.level}`); } else { const channel = discord.guild.channels.find('id', this.announceLevelUp.announceChannel); if (channel) { channel.send(`Level 🆙 <@${user.user.id}> - You are now level ${user.level.level}`); } } } } }); } gainLevel(discord, user) { return __awaiter(this, void 0, void 0, function* () { const currentLevel = yield this.levels.findOne({ id: user.level.id }, { relations: ['ranks'] }); if (currentLevel) { currentLevel.ranks.forEach(r => { this.assignRole(discord, user.user.id, r.rankName); }); } }); } assignRole(discord, userId, roleName) { return __awaiter(this, void 0, void 0, function* () { try { const serverRole = discord.guild.roles.find('name', roleName); if (serverRole) { const guildUser = yield discord.guild.fetchMember(userId); if (guildUser && !guildUser.roles.get(serverRole.id)) { guildUser.addRole(serverRole); } } } catch (error) { } }); } parseParameters(messageContent) { const params = messageContent.match(/ (?=\S)[^'\s]*(?:'[^\\']*(?:\\[\s\S][^\\']*)*'[^'\s]*)*/g) || []; return params.map(p => p.trim()); } hydrateOptions(parameters) { return command_line_args_1.default(exports.commandOptions, { argv: parameters, partial: true }); } extractUserId(userId) { const matches = userId.match(/(?<=@|!)(.*)(?=>)/gm); if (matches && matches.length === 1) { return matches[0].replace('!', ''); } return undefined; } } exports.default = PsyduckExampleOrm;