|
@@ -0,0 +1,146 @@
|
|
|
+import { ICommand } from "./command";
|
|
|
+import { Dict, NeighBuilder } from "src/util";
|
|
|
+import { ReactionCollector, Message } from "discord.js";
|
|
|
+import yaml from "yaml";
|
|
|
+import { client } from "src/client";
|
|
|
+import { getRepository } from "typeorm";
|
|
|
+import { Contest } from "@db/entity/Contest";
|
|
|
+import { isNumber } from "util";
|
|
|
+import emoji_regex from "emoji-regex";
|
|
|
+
|
|
|
+
|
|
|
+const CHANNEL_ID_PATTERN = /<#(\d+)>/;
|
|
|
+
|
|
|
+let pendingReactors : Dict<ReactionCollector> = {};
|
|
|
+
|
|
|
+async function init() {
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+interface ContestCreationOptions {
|
|
|
+ in?: string;
|
|
|
+ duration?: string;
|
|
|
+ announce_winners?: boolean;
|
|
|
+ vote_reaction?: string;
|
|
|
+}
|
|
|
+
|
|
|
+const CONTEST_DEFAULTS : ContestCreationOptions = {
|
|
|
+ duration: "1d",
|
|
|
+ announce_winners: false,
|
|
|
+ vote_reaction: "❤️"
|
|
|
+};
|
|
|
+
|
|
|
+const DURATION_MULTIPLIERS : Dict<number> = {
|
|
|
+ "s" : 1000,
|
|
|
+ "min": 60 * 1000,
|
|
|
+ "h": 60 * 60 * 1000,
|
|
|
+ "d": 24 * 60 * 60 * 1000,
|
|
|
+ "mon": 30 * 24 * 60 * 60 * 1000,
|
|
|
+ "y": 365 * 24 * 60 * 60 * 1000
|
|
|
+};
|
|
|
+
|
|
|
+function parseDuration(duration: string) : number | undefined {
|
|
|
+ let numNB = new NeighBuilder();
|
|
|
+
|
|
|
+ let chIndex = 0;
|
|
|
+ for(; chIndex < duration.length; chIndex++) {
|
|
|
+ let c = duration.charAt(chIndex);
|
|
|
+ if(isNumber(c))
|
|
|
+ numNB.append(c);
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ let unit = duration.substr(chIndex).trim().toLowerCase();
|
|
|
+
|
|
|
+ if(!(unit in DURATION_MULTIPLIERS))
|
|
|
+ return undefined;
|
|
|
+
|
|
|
+ return +numNB * DURATION_MULTIPLIERS[unit];
|
|
|
+}
|
|
|
+
|
|
|
+async function createContest(msg: Message, info: ContestCreationOptions) {
|
|
|
+ let dur = parseDuration(info.duration);
|
|
|
+ if(!dur) {
|
|
|
+ await msg.channel.send(`${msg.author.toString()} Duration format is invalid!`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!msg.guild.emojis.find(e => e.toString() == info.vote_reaction) && !emoji_regex().exec(info.vote_reaction)) {
|
|
|
+ await msg.channel.send(`${msg.author.toString()} The vote emote must be accessible by everyone on the server!`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let repo = getRepository(Contest);
|
|
|
+
|
|
|
+ let contest = await repo.findOne({
|
|
|
+ where: { channel: info.in }
|
|
|
+ });
|
|
|
+
|
|
|
+ if(contest) {
|
|
|
+ await msg.channel.send(`${msg.author.toString()} The channel already has a contest running!`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ contest = repo.create({
|
|
|
+ channel: info.in,
|
|
|
+ startDate: new Date(),
|
|
|
+ endDate: new Date(Date.now() + dur),
|
|
|
+ announceWinners: info.announce_winners
|
|
|
+ });
|
|
|
+
|
|
|
+ await repo.save(contest);
|
|
|
+ await msg.channel.send(`${msg.author.toString()} Started contest (ID: ${contest.id})`);
|
|
|
+}
|
|
|
+
|
|
|
+export default <ICommand>{
|
|
|
+ commands: [
|
|
|
+ {
|
|
|
+ //\s+in:\s*([^\s]+)\s+duration:\s(\d+ ?(s|d|m|y))\s+announce_winners:\s*(true|false)\s+vote_reaction:\s*([^\s])
|
|
|
+ pattern: "create contest",
|
|
|
+ action: async (m, contents) => {
|
|
|
+ let message = contents.substr("create contest".length);
|
|
|
+ let contestData : ContestCreationOptions = { ...CONTEST_DEFAULTS, ...yaml.parse(message) };
|
|
|
+
|
|
|
+ if(!contestData.in)
|
|
|
+ contestData.in = m.channel.id;
|
|
|
+ else {
|
|
|
+ let matches = CHANNEL_ID_PATTERN.exec(contestData.in);
|
|
|
+ if(matches.length == 0) {
|
|
|
+ await m.channel.send(`${m.author.toString()} I can't see such a channel!`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let channelId = matches[1];
|
|
|
+ if(!m.guild.channels.exists("id", channelId)) {
|
|
|
+ await m.channel.send(`${m.author.toString()} This channel is not in the current guild!`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ contestData.in = channelId;
|
|
|
+ }
|
|
|
+
|
|
|
+ await createContest(m, contestData);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ pattern: "contests",
|
|
|
+ action: async (m) => {
|
|
|
+ await m.channel.send("Heck");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ pattern: /end contest( (\d*))?/,
|
|
|
+ action: async (m, contents, matches) => {
|
|
|
+ await m.channel.send("Heck");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ pattern: "announce winners",
|
|
|
+ action: async (m, contents, matches) => {
|
|
|
+ await m.channel.send("Heck");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ onStart: init,
|
|
|
+};
|