summaryrefslogtreecommitdiff
path: root/dist/utils
diff options
context:
space:
mode:
Diffstat (limited to 'dist/utils')
-rw-r--r--dist/utils/Util.js199
-rw-r--r--dist/utils/gameDigHelper.js42
-rw-r--r--dist/utils/genCmdURL.js3
-rw-r--r--dist/utils/simpleFormat.js6
-rw-r--r--dist/utils/stripWebhookURL.js7
-rw-r--r--dist/utils/truncateText.js3
-rw-r--r--dist/utils/wait.js3
-rw-r--r--dist/utils/winPercentage.js5
8 files changed, 268 insertions, 0 deletions
diff --git a/dist/utils/Util.js b/dist/utils/Util.js
new file mode 100644
index 0000000..633c7da
--- /dev/null
+++ b/dist/utils/Util.js
@@ -0,0 +1,199 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ 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) : adopt(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 });
+const crypto_1 = __importDefault(require("crypto"));
+const yes = ['yes', 'y', 'ye', 'yeah', 'yup', 'yea', 'ya', 'hai', 'si', 'sí', 'oui', 'はい', 'correct'];
+const no = ['no', 'n', 'nah', 'nope', 'nop', 'iie', 'いいえ', 'non', 'fuck off'];
+module.exports = class Util {
+ static delay(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+ static shuffle(array) {
+ const arr = array.slice(0);
+ for (let i = arr.length - 1; i >= 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ const temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+ return arr;
+ }
+ static list(arr, conj = 'and') {
+ const len = arr.length;
+ if (len === 0)
+ return '';
+ if (len === 1)
+ return arr[0];
+ return `${arr.slice(0, -1).join(', ')}${len > 1 ? `${len > 2 ? ',' : ''} ${conj} ` : ''}${arr.slice(-1)}`;
+ }
+ static shorten(text, maxLen = 2000) {
+ return text.length > maxLen ? `${text.substr(0, maxLen - 3)}...` : text;
+ }
+ static randomRange(min, max) {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+ static trimArray(arr, maxLen = 10) {
+ if (arr.length > maxLen) {
+ const len = arr.length - maxLen;
+ arr = arr.slice(0, maxLen);
+ arr.push(`${len} more...`);
+ }
+ return arr;
+ }
+ static removeDuplicates(arr) {
+ if (arr.length === 0 || arr.length === 1)
+ return arr;
+ const newArr = [];
+ for (let i = 0; i < arr.length; i++) {
+ if (newArr.includes(arr[i]))
+ continue;
+ newArr.push(arr[i]);
+ }
+ return newArr;
+ }
+ static sortByName(arr, prop) {
+ return arr.sort((a, b) => {
+ if (prop)
+ return a[prop].toLowerCase() > b[prop].toLowerCase() ? 1 : -1;
+ return a.toLowerCase() > b.toLowerCase() ? 1 : -1;
+ });
+ }
+ static firstUpperCase(text, split = ' ') {
+ return text.split(split).map(word => `${word.charAt(0).toUpperCase()}${word.slice(1)}`).join(' ');
+ }
+ static formatNumber(number, minimumFractionDigits = 0) {
+ return Number.parseFloat(number).toLocaleString(undefined, {
+ minimumFractionDigits,
+ maximumFractionDigits: 2
+ });
+ }
+ static base64(text, mode = 'encode') {
+ if (mode === 'encode')
+ return Buffer.from(text).toString('base64');
+ if (mode === 'decode')
+ return Buffer.from(text, 'base64').toString('utf8') || null;
+ throw new TypeError(`${mode} is not a supported base64 mode.`);
+ }
+ static hash(text, algorithm) {
+ return crypto_1.default.createHash(algorithm).update(text).digest('hex');
+ }
+ static streamToArray(stream) {
+ if (!stream.readable)
+ return Promise.resolve([]);
+ return new Promise((resolve, reject) => {
+ const array = [];
+ function onData(data) {
+ array.push(data);
+ }
+ function onEnd(error) {
+ if (error)
+ reject(error);
+ else
+ resolve(array);
+ cleanup();
+ }
+ function onClose() {
+ resolve(array);
+ cleanup();
+ }
+ function cleanup() {
+ stream.removeListener('data', onData);
+ stream.removeListener('end', onEnd);
+ stream.removeListener('error', onEnd);
+ stream.removeListener('close', onClose);
+ }
+ stream.on('data', onData);
+ stream.on('end', onEnd);
+ stream.on('error', onEnd);
+ stream.on('close', onClose);
+ });
+ }
+ static percentColor(pct, percentColors) {
+ let i = 1;
+ for (i; i < percentColors.length - 1; i++) {
+ if (pct < percentColors[i].pct) {
+ break;
+ }
+ }
+ const lower = percentColors[i - 1];
+ const upper = percentColors[i];
+ const range = upper.pct - lower.pct;
+ const rangePct = (pct - lower.pct) / range;
+ const pctLower = 1 - rangePct;
+ const pctUpper = rangePct;
+ const color = {
+ r: Math.floor((lower.color.r * pctLower) + (upper.color.r * pctUpper)).toString(16).padStart(2, '0'),
+ g: Math.floor((lower.color.g * pctLower) + (upper.color.g * pctUpper)).toString(16).padStart(2, '0'),
+ b: Math.floor((lower.color.b * pctLower) + (upper.color.b * pctUpper)).toString(16).padStart(2, '0')
+ };
+ return `#${color.r}${color.g}${color.b}`;
+ }
+ static today(timeZone) {
+ const now = new Date();
+ now.setHours(0);
+ now.setMinutes(0);
+ now.setSeconds(0);
+ now.setMilliseconds(0);
+ if (timeZone)
+ now.setUTCHours(now.getUTCHours() + timeZone);
+ return now;
+ }
+ static tomorrow(timeZone) {
+ const today = Util.today(timeZone);
+ today.setDate(today.getDate() + 1);
+ return today;
+ }
+ static embedURL(title, url, display) {
+ return `[${title}](${url.replace(/\)/g, '%27')}${display ? ` "${display}"` : ''})`;
+ }
+ static verify(channel, user, { time = 30000, extraYes = [], extraNo = [] } = {}) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const filter = res => {
+ const value = res.content.toLowerCase();
+ return (user ? res.author.id === user.id : true)
+ && (yes.includes(value) || no.includes(value) || extraYes.includes(value) || extraNo.includes(value));
+ };
+ const verify = yield channel.awaitMessages(filter, {
+ max: 1,
+ time
+ });
+ if (!verify.size)
+ return 0;
+ const choice = verify.first().content.toLowerCase();
+ if (yes.includes(choice) || extraYes.includes(choice))
+ return true;
+ if (no.includes(choice) || extraNo.includes(choice))
+ return false;
+ return false;
+ });
+ }
+ static cleanAnilistHTML(html) {
+ let clean = html
+ .replace(/\r|\n|\f/g, '')
+ .replace(/<br>/g, '\n')
+ .replace(/&#039;/g, '\'')
+ .replace(/&quot;/g, '"')
+ .replace(/<\/?i>/g, '*')
+ .replace(/<\/?b>/g, '**')
+ .replace(/~!|!~/g, '||')
+ .replace(/&mdash;/g, '—');
+ if (clean.length > 2000)
+ clean = `${clean.substr(0, 1995)}...`;
+ const spoilers = (clean.match(/\|\|/g) || []).length;
+ if (spoilers !== 0 && (spoilers && (spoilers % 2)))
+ clean += '||';
+ return clean;
+ }
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9VdGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQTRCO0FBQzVCLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDdEcsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBRTlFLE1BQU0sQ0FBQyxPQUFPLEdBQUcsTUFBTSxJQUFJO0lBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUNkLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSztRQUNuQixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLEtBQUssSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN6QyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FB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 \ No newline at end of file
diff --git a/dist/utils/gameDigHelper.js b/dist/utils/gameDigHelper.js
new file mode 100644
index 0000000..7b80e82
--- /dev/null
+++ b/dist/utils/gameDigHelper.js
@@ -0,0 +1,42 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const ms_1 = __importDefault(require("ms"));
+const discord_js_1 = require("discord.js");
+module.exports = res => {
+ const playerCount = res.players.length;
+ const maxPlayers = res.maxPlayers;
+ const emb = new discord_js_1.MessageEmbed()
+ .setTitle(res.name)
+ .setFooter(`Took ${ms_1.default(res.ping)} to complete.`)
+ .addFields([
+ {
+ name: 'Connect',
+ value: `${res.connect}`
+ },
+ {
+ name: 'Online Players',
+ value: `${playerCount}/${maxPlayers} (${Math.round((playerCount / maxPlayers) * 100)}%)`
+ },
+ {
+ name: 'Map',
+ value: discord_js_1.Util.escapeMarkdown(res.map)
+ },
+ {
+ name: 'Password Required',
+ value: res.password ? 'Yes' : 'No'
+ }
+ ]);
+ const unconfirmedValues = new Map([
+ [res.raw.secure, secure => emb.addField('Vac Secured', secure ? 'Yes' : 'No')],
+ [res.raw.games, game => emb.addField('Game', discord_js_1.Util.escapeMarkdown(game))]
+ ]);
+ unconfirmedValues.forEach((val, key) => {
+ if (typeof key !== 'undefined')
+ val(key);
+ });
+ return emb;
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FtZURpZ0hlbHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9nYW1lRGlnSGVscGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNENBQW9CO0FBQ3BCLDJDQUErQztBQVEvQyxNQUFNLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxFQUFFO0lBQ25CLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFBO0lBQ3RDLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUE7SUFFakMsTUFBTSxHQUFHLEdBQUcsSUFBSSx5QkFBWSxFQUFFO1NBQ3pCLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO1NBQ2xCLFNBQVMsQ0FBQyxRQUFRLFlBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQztTQUM5QyxTQUFTLENBQUM7UUFDUDtZQUNJLElBQUksRUFBRSxTQUFTO1lBQ2YsS0FBSyxFQUFFLEdBQUcsR0FBRyxDQUFDLE9BQU8sRUFBRTtTQUMxQjtRQUNEO1lBQ0ksSUFBSSxFQUFFLGdCQUFnQjtZQUN0QixLQUFLLEVBQUUsR0FBRyxXQUFXLElBQUksVUFBVSxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUk7U0FDM0Y7UUFDRDtZQUNJLElBQUksRUFBRSxLQUFLO1lBQ1gsS0FBSyxFQUFFLGlCQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUM7U0FDdEM7UUFDRDtZQUNJLElBQUksRUFBRSxtQkFBbUI7WUFDekIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSTtTQUNyQztLQUNKLENBQUMsQ0FBQTtJQUVOLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQUM7UUFDOUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5RSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsaUJBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUMzRSxDQUFDLENBQUE7SUFFRixpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDbkMsSUFBSSxPQUFPLEdBQUcsS0FBSyxXQUFXO1lBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQzVDLENBQUMsQ0FBQyxDQUFBO0lBRUYsT0FBTyxHQUFHLENBQUE7QUFDZCxDQUFDLENBQUEifQ== \ No newline at end of file
diff --git a/dist/utils/genCmdURL.js b/dist/utils/genCmdURL.js
new file mode 100644
index 0000000..c063f3c
--- /dev/null
+++ b/dist/utils/genCmdURL.js
@@ -0,0 +1,3 @@
+"use strict";
+module.exports = cmd => `/commands/${cmd.group.name.toLowerCase().replace(/\s/g, "-")}/${cmd.name}`;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuQ21kVVJMLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2dlbkNtZFVSTC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLGFBQWEsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMifQ== \ No newline at end of file
diff --git a/dist/utils/simpleFormat.js b/dist/utils/simpleFormat.js
new file mode 100644
index 0000000..8813916
--- /dev/null
+++ b/dist/utils/simpleFormat.js
@@ -0,0 +1,6 @@
+"use strict";
+module.exports = value => {
+ const result = parseFloat(parseFloat(value).toFixed(2));
+ return result;
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlRm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3NpbXBsZUZvcm1hdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBS0EsTUFBTSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsRUFBRTtJQUNyQixNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUMsQ0FBQyJ9 \ No newline at end of file
diff --git a/dist/utils/stripWebhookURL.js b/dist/utils/stripWebhookURL.js
new file mode 100644
index 0000000..b788447
--- /dev/null
+++ b/dist/utils/stripWebhookURL.js
@@ -0,0 +1,7 @@
+"use strict";
+module.exports = url => {
+ const regex = /https:\/\/discordapp\.com\/api\/webhooks\/(\d{1,})\/([\w-_]{1,})/;
+ const matches = regex.exec(url);
+ return { id: matches[1], token: matches[2] };
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaXBXZWJob29rVVJMLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3N0cmlwV2ViaG9va1VSTC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBS0EsTUFBTSxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsRUFBRTtJQUNuQixNQUFNLEtBQUssR0FBRyxrRUFBa0UsQ0FBQztJQUNqRixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRWhDLE9BQU8sRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNqRCxDQUFDLENBQUMifQ== \ No newline at end of file
diff --git a/dist/utils/truncateText.js b/dist/utils/truncateText.js
new file mode 100644
index 0000000..5a10468
--- /dev/null
+++ b/dist/utils/truncateText.js
@@ -0,0 +1,3 @@
+"use strict";
+module.exports = (string, number = 2048) => (string.length > number ? `${string.substring(0, number - 3)}...` : string);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJ1bmNhdGVUZXh0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3RydW5jYXRlVGV4dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBS0EsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyJ9 \ No newline at end of file
diff --git a/dist/utils/wait.js b/dist/utils/wait.js
new file mode 100644
index 0000000..ff5442a
--- /dev/null
+++ b/dist/utils/wait.js
@@ -0,0 +1,3 @@
+"use strict";
+module.exports = delay => new Promise(resolve => setTimeout(resolve, delay));
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FpdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy93YWl0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFLQSxNQUFNLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMifQ== \ No newline at end of file
diff --git a/dist/utils/winPercentage.js b/dist/utils/winPercentage.js
new file mode 100644
index 0000000..ee31621
--- /dev/null
+++ b/dist/utils/winPercentage.js
@@ -0,0 +1,5 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+module.exports = (multiplier, user) => {
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2luUGVyY2VudGFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy93aW5QZXJjZW50YWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBT0EsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRTtBQVF0QyxDQUFDLENBQUMifQ== \ No newline at end of file